From 3d410602d628c46bb00d330ac7bab50a8303a73d Mon Sep 17 00:00:00 2001 From: chaos-zhu Date: Sat, 17 Aug 2024 16:10:17 +0800 Subject: [PATCH] =?UTF-8?q?:sparkles:=20=E5=AE=8C=E5=96=84=E9=80=9A?= =?UTF-8?q?=E7=9F=A5=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/.eslintrc.js | 2 + server/app/controller/notify.js | 6 +-- server/app/controller/user.js | 14 +++---- server/app/utils/notify.js | 74 +++++++++++++++++++++++++-------- 4 files changed, 68 insertions(+), 28 deletions(-) diff --git a/server/.eslintrc.js b/server/.eslintrc.js index 82f82c9..8551d51 100644 --- a/server/.eslintrc.js +++ b/server/.eslintrc.js @@ -31,7 +31,9 @@ module.exports = { 'no-redeclare': ['error', { builtinGlobals: true }], // 禁止重复对象声明 'no-multi-assign': 0, 'no-restricted-globals': 0, + 'no-case-declarations': 0, 'space-before-function-paren': 0, // 函数定义时括号前面空格 + 'no-async-promise-executor': 0, // 允许在回调中使用async函数 'one-var': 0, // 允许连续声明 // 'no-undef': 0, // 允许未定义的变量【会使env配置无效】 'linebreak-style': 0, // 检测CRLF/LF检测【默认LF】 diff --git a/server/app/controller/notify.js b/server/app/controller/notify.js index d1ac504..925b765 100644 --- a/server/app/controller/notify.js +++ b/server/app/controller/notify.js @@ -1,5 +1,5 @@ const { readNotifyConfig, writeNotifyConfig, readNotifyList, writeNotifyList } = require('../utils') -const { sctTest, emailTest } = require('../utils/notify') +const { sendServerChan, sendEmail } = require('../utils/notify') // const commonTemp = require('../template/commonTemp') async function getNotifyConfig({ res }) { @@ -13,10 +13,10 @@ async function updateNotifyConfig({ res, request }) { try { switch(type) { case 'sct': - await sctTest(noticeConfig[type]) + await sendServerChan(noticeConfig[type]['sendKey'], 'EasyNode通知测试', '这是一条测试通知') break case 'email': - await emailTest(noticeConfig[type]) + await sendEmail(noticeConfig[type], 'EasyNode通知测试', '这是一条测试通知') break } await writeNotifyConfig(noticeConfig) diff --git a/server/app/controller/user.js b/server/app/controller/user.js index 57cd392..b2f30e5 100644 --- a/server/app/controller/user.js +++ b/server/app/controller/user.js @@ -1,6 +1,7 @@ const jwt = require('jsonwebtoken') const axios = require('axios') -const { getNetIPInfo, readKey, writeKey, RSADecryptSync, AESEncryptSync, SHA1Encrypt, sendEmailToConfList, getNotifySwByType } = require('../utils') +const { getNetIPInfo, readKey, writeKey, RSADecryptSync, AESEncryptSync, SHA1Encrypt, getNotifySwByType } = require('../utils') +const { asyncSendNotice } = require('../utils/notify') const getpublicKey = async ({ res }) => { let { publicKey: data } = await readKey() @@ -24,9 +25,8 @@ const login = async ({ res, request }) => { loginErrTotal++ if (loginErrCount >= allowErrCount) { const { ip, country, city } = await getNetIPInfo(clientIp) - // 发送通知&禁止登录 - let sw = getNotifySwByType('err_login') - if (sw) sendEmailToConfList('登录错误提醒', `重新登录次数: ${ loginErrTotal }
地点:${ country + city }
IP: ${ ip }`) + // 异步发送通知&禁止登录 + asyncSendNotice('err_login', 'EasyNode登录错误提醒', `错误登录次数: ${ loginErrTotal }
地点:${ country + city }
IP: ${ ip }`) forbidLogin = true loginErrCount = 0 @@ -82,8 +82,7 @@ const beforeLoginHandler = async (clientIp, jwtExpires) => { consola.info('登录成功:', new Date(), { ip, country, city }) // 邮件登录通知 - let sw = getNotifySwByType('login') - if (sw) sendEmailToConfList('登录提醒', `地点:${ country + city }
IP: ${ ip }`) + asyncSendNotice('login', 'EasyNode登录提醒', `地点:${ country + city }
IP: ${ ip }`) global.loginRecord.unshift(clientIPInfo) if (global.loginRecord.length > 10) global.loginRecord = global.loginRecord.slice(0, 10) @@ -103,8 +102,7 @@ const updatePwd = async ({ res, request }) => { keyObj.pwd = newPwd await writeKey(keyObj) - let sw = getNotifySwByType('updatePwd') - if (sw) sendEmailToConfList(`登录信息修改提醒, 新用户名: ${ newLoginName }`) + asyncSendNotice('updatePwd', 'EasyNode用户密码修改提醒', `原用户名:${ user }
更新用户名: ${ newLoginName }`) res.success({ data: true, msg: 'success' }) } diff --git a/server/app/utils/notify.js b/server/app/utils/notify.js index be67a54..3785bbb 100644 --- a/server/app/utils/notify.js +++ b/server/app/utils/notify.js @@ -1,27 +1,34 @@ const nodemailer = require('nodemailer') const axios = require('axios') +const { getNotifySwByType, readNotifyConfig } = require('../utils') -module.exports.sctTest = function ({ sendKey }) { - // eslint-disable-next-line no-async-promise-executor +function sendServerChan(sendKey, title, content) { + if (!sendKey) return consola.error('发送server酱通知失败, sendKey 为空') return new Promise((async (resolve, reject) => { - consola.info('server酱通知测试: ', sendKey) try { - let { data } = await axios.get(`https://sctapi.ftqq.com/${ sendKey }.send?title=messagetitle`) + consola.info('server酱通知预发送: ', title) + const url = `https://sctapi.ftqq.com/${ sendKey }.send` + const params = new URLSearchParams({ text: title, desp: content }) + let { data } = await axios.post(url, params, { + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' + } + }) resolve(data) - consola.success('测试成功') + consola.info('server酱通知发送成功: ', title) } catch (error) { reject(error) - consola.error('测试失败: ', error) + consola.error('server酱通知发送失败: ', error) } })) + } -module.exports.emailTest = function (conf) { - // eslint-disable-next-line no-async-promise-executor +function sendEmail({ service, user, pass }, title, content) { + if (!service || !user || !pass) return consola.info('发送通知失败, 邮箱配置信息不完整: ', { service, user, pass }) return new Promise((async (resolve, reject) => { - consola.info('邮箱通知测试: ', conf) try { - const { service, user, pass } = conf + consola.info('邮箱通知预发送: ', title) let transporter = nodemailer.createTransport({ service, auth: { @@ -29,19 +36,52 @@ module.exports.emailTest = function (conf) { pass } }) - let info = await transporter.sendMail({ + await transporter.sendMail({ from: user, to: user, - subject: 'EasyNode: 测试邮件通知', - text: '测试邮件', - html: '测试邮件' + subject: title, + // text: '', // 纯文本版本内容,如果收件人的邮件客户端不支持HTML显示,就会显示这个文本 + html: content }) - consola.info('Message sent: %s', info.messageId) + consola.info('邮件通知发送成功: ', title) resolve() - consola.success('测试成功') } catch (error) { reject(error) - consola.error('测试失败: ', error) + consola.error('邮件通知发送失败: ', error) } })) } + +// 异步发送通知 +async function asyncSendNotice(noticeAction, title, content) { + try { + let sw = await getNotifySwByType(noticeAction) // 获取对应动作的通知开关 + if (!sw) return + let notifyConfig = await readNotifyConfig() + let { type } = notifyConfig + if (!type) return consola.error('通知类型不存在: ', type) + content += `
通知发送时间:${ new Date() }` + switch (type) { + case 'sct': + let { sendKey } = notifyConfig['sct'] + if (!sendKey) return consola.info('未发送server酱通知, sendKey 为空') + await sendServerChan(sendKey, title, content) + break + case 'email': + let { service, user, pass } = notifyConfig['email'] + if (!service || !user || !pass) return consola.info('未发送邮件通知通知, 未配置邮箱: ', { service, user, pass }) + await sendEmail({ service, user, pass }, title, content) + break + default: + break + } + } catch (error) { + consola.error('通知发送失败: ', error) + } +} + +module.exports = { + asyncSendNotice, + sendServerChan, + sendEmail +} \ No newline at end of file