From 2fae1f9fc26e9345c95396bf83d91414c0b3ffda Mon Sep 17 00:00:00 2001
From: smallfawn <101914820+smallfawn@users.noreply.github.com>
Date: Fri, 14 Jul 2023 09:17:33 +0800
Subject: [PATCH] Update sendNotify.js
---
sendNotify.js | 488 +++++++++++++++++++++++++++++++++++++-------------
1 file changed, 367 insertions(+), 121 deletions(-)
diff --git a/sendNotify.js b/sendNotify.js
index 437f13a..fbc450d 100644
--- a/sendNotify.js
+++ b/sendNotify.js
@@ -8,8 +8,6 @@
* @param desp 通知体
* @param params 某些推送通知方式点击弹窗可跳转, 例:{ url: 'https://abc.com' }
* @param author 作者仓库等信息 例:`本通知 By:https://github.com/whyour/qinglong`
- * @魔改:smallfawn https://github.com/smallfawn/QLScriptPublic 参考:ccwav https://github.com/ccwav/QLScript2
- * @魔改位置 sendNotify函数 黑白名单模式
*/
const querystring = require('querystring');
@@ -36,12 +34,23 @@ let GOBOT_QQ = ''; // 如果GOBOT_URL设置 /send_private_msg 则需要填入 us
//(环境变量名 PUSH_KEY)
let SCKEY = '';
+// =======================================PushDeer通知设置区域===========================================
+//此处填你申请的PushDeer KEY.
+//(环境变量名 DEER_KEY)
+let PUSHDEER_KEY = '';
+let PUSHDEER_URL = '';
+
+// =======================================Synology Chat通知设置区域===========================================
+//此处填你申请的CHAT_URL与CHAT_TOKEN
+//(环境变量名 CHAT_URL CHAT_TOKEN)
+let CHAT_URL = '';
+let CHAT_TOKEN = '';
+
// =======================================Bark App通知设置区域===========================================
//此处填你BarkAPP的信息(IP/设备码,例如:https://api.day.app/XXXXXXXX)
let BARK_PUSH = '';
//BARK app推送图标,自定义推送图标(需iOS15或以上)
-let BARK_ICON =
- 'https://img.gejiba.com/images/a3f551e09ac19add4c49ec16228729c5.png';
+let BARK_ICON = 'https://qn.whyour.cn/logo.png';
//BARK app推送铃声,铃声列表去APP查看复制填写
let BARK_SOUND = '';
//BARK app推送消息的分组, 默认为"QingLong"
@@ -67,6 +76,10 @@ let DD_BOT_TOKEN = '';
//密钥,机器人安全设置页面,加签一栏下面显示的SEC开头的字符串
let DD_BOT_SECRET = '';
+// =======================================企业微信基础设置===========================================
+// 企业微信反向代理地址
+//(环境变量名 QYWX_ORIGIN)
+let QYWX_ORIGIN = '';
// =======================================企业微信机器人通知设置区域===========================================
//此处填你企业微信机器人的 webhook(详见文档 https://work.weixin.qq.com/api/doc/90000/90136/91770),例如:693a91f6-7xxx-4bc4-97a0-0ec2sifa5aaa
//(环境变量名 QYWX_KEY)
@@ -95,6 +108,39 @@ let IGOT_PUSH_KEY = '';
let PUSH_PLUS_TOKEN = '';
let PUSH_PLUS_USER = '';
+// =======================================Cool Push设置区域=======================================
+//官方文档:https://cp.xuthus.cc/docs
+//QQ_SKEY: Cool Push登录授权后推送消息的调用代码Skey
+//QQ_MODE: 推送模式详情请登录获取QQ_SKEY后见https://cp.xuthus.cc/feat
+let QQ_SKEY = '';
+let QQ_MODE = '';
+
+// =======================================智能微秘书设置区域=======================================
+//官方文档:http://wechat.aibotk.com/docs/about
+//AIBOTK_KEY: 填写智能微秘书个人中心的apikey
+//AIBOTK_TYPE:填写发送的目标 room 或 contact, 填其他的不生效
+//AIBOTK_NAME: 填写群名或用户昵称,和上面的type类型要对应
+let AIBOTK_KEY = '';
+let AIBOTK_TYPE = '';
+let AIBOTK_NAME = '';
+
+// =======================================飞书机器人设置区域=======================================
+//官方文档:https://www.feishu.cn/hc/zh-CN/articles/360024984973
+//FSKEY 飞书机器人的 FSKEY
+let FSKEY = '';
+
+// =======================================SMTP 邮件设置区域=======================================
+// SMTP_SERVER: 填写 SMTP 发送邮件服务器,形如 smtp.exmail.qq.com:465
+// SMTP_SSL: 填写 SMTP 发送邮件服务器是否使用 SSL,内容应为 true 或 false
+// SMTP_EMAIL: 填写 SMTP 收发件邮箱,通知将会由自己发给自己
+// SMTP_PASSWORD: 填写 SMTP 登录密码,也可能为特殊口令,视具体邮件服务商说明而定
+// SMTP_NAME: 填写 SMTP 收发件人姓名,可随意填写
+let SMTP_SERVER = '';
+let SMTP_SSL = 'false';
+let SMTP_EMAIL = '';
+let SMTP_PASSWORD = '';
+let SMTP_NAME = '';
+
//==========================云端环境变量的判断与接收=========================
if (process.env.GOTIFY_URL) {
GOTIFY_URL = process.env.GOTIFY_URL;
@@ -120,6 +166,19 @@ if (process.env.PUSH_KEY) {
SCKEY = process.env.PUSH_KEY;
}
+if (process.env.DEER_KEY) {
+ PUSHDEER_KEY = process.env.DEER_KEY;
+ PUSHDEER_URL = process.env.DEER_URL;
+}
+
+if (process.env.CHAT_URL) {
+ CHAT_URL = process.env.CHAT_URL;
+}
+
+if (process.env.CHAT_TOKEN) {
+ CHAT_TOKEN = process.env.CHAT_TOKEN;
+}
+
if (process.env.QQ_SKEY) {
QQ_SKEY = process.env.QQ_SKEY;
}
@@ -175,6 +234,12 @@ if (process.env.DD_BOT_TOKEN) {
}
}
+if (process.env.QYWX_ORIGIN) {
+ QYWX_ORIGIN = process.env.QYWX_ORIGIN;
+} else {
+ QYWX_ORIGIN = 'https://qyapi.weixin.qq.com';
+}
+
if (process.env.QYWX_KEY) {
QYWX_KEY = process.env.QYWX_KEY;
}
@@ -193,12 +258,40 @@ if (process.env.PUSH_PLUS_TOKEN) {
if (process.env.PUSH_PLUS_USER) {
PUSH_PLUS_USER = process.env.PUSH_PLUS_USER;
}
+
+if (process.env.AIBOTK_KEY) {
+ AIBOTK_KEY = process.env.AIBOTK_KEY;
+}
+if (process.env.AIBOTK_TYPE) {
+ AIBOTK_TYPE = process.env.AIBOTK_TYPE;
+}
+if (process.env.AIBOTK_NAME) {
+ AIBOTK_NAME = process.env.AIBOTK_NAME;
+}
+
+if (process.env.FSKEY) {
+ FSKEY = process.env.FSKEY;
+}
+
+if (process.env.SMTP_SERVER) {
+ SMTP_SERVER = process.env.SMTP_SERVER;
+}
+if (process.env.SMTP_SSL) {
+ SMTP_SSL = process.env.SMTP_SSL;
+}
+if (process.env.SMTP_EMAIL) {
+ SMTP_EMAIL = process.env.SMTP_EMAIL;
+}
+if (process.env.SMTP_PASSWORD) {
+ SMTP_PASSWORD = process.env.SMTP_PASSWORD;
+}
+if (process.env.SMTP_NAME) {
+ SMTP_NAME = process.env.SMTP_NAME;
+}
//==========================云端环境变量的判断与接收=========================
/**
* sendNotify 推送通知功能
- * 魔改:smallfawn https://github.com/smallfawn 增加黑白名单模式
- * 变量值 smallfawnPushWhite白名单 smallfawnPushBlack黑名单 不写默认通知 黑白名单二选一
* @param text 通知头
* @param desp 通知体
* @param params 某些推送通知方式点击弹窗可跳转, 例:{ url: 'https://abc.com' }
@@ -281,6 +374,16 @@ async function sendNotify(
async function push() {
//提供6种通知
desp += author; //增加作者信息,防止被贩卖等
+
+ // 根据标题跳过一些消息推送,环境变量:SKIP_PUSH_TITLE 用回车分隔
+ let skipTitle = process.env.SKIP_PUSH_TITLE;
+ if (skipTitle) {
+ if (skipTitle.split('\n').includes(text)) {
+ console.info(text + '在SKIP_PUSH_TITLE环境变量内,跳过推送!');
+ return;
+ }
+ }
+
await Promise.all([
serverNotify(text, desp), //微信server酱
pushPlusNotify(text, desp), //pushplus(推送加)
@@ -296,14 +399,14 @@ async function sendNotify(
iGotNotify(text, desp, params), //iGot
gobotNotify(text, desp), //go-cqhttp
gotifyNotify(text, desp), //gotify
+ ChatNotify(text, desp), //synolog chat
+ PushDeerNotify(text, desp), //PushDeer
+ aibotkNotify(text, desp), //智能微秘书
+ fsBotNotify(text, desp), //飞书机器人
+ smtpNotify(text, desp), //SMTP 邮件
]);
}
-
-
-
-
-
}
function gotifyNotify(text, desp) {
@@ -343,7 +446,7 @@ function gotifyNotify(text, desp) {
});
}
-function gobotNotify(text, desp, time = 2100) {
+function gobotNotify(text, desp) {
return new Promise((resolve) => {
if (GOBOT_URL) {
const options = {
@@ -354,38 +457,34 @@ function gobotNotify(text, desp, time = 2100) {
},
timeout,
};
- setTimeout(() => {
- $.post(options, (err, resp, data) => {
- try {
- if (err) {
- console.log('发送go-cqhttp通知调用API失败!!\n');
- console.log(err);
+ $.post(options, (err, resp, data) => {
+ try {
+ if (err) {
+ console.log('发送go-cqhttp通知调用API失败!!\n');
+ console.log(err);
+ } else {
+ data = JSON.parse(data);
+ if (data.retcode === 0) {
+ console.log('go-cqhttp发送通知消息成功🎉\n');
+ } else if (data.retcode === 100) {
+ console.log(`go-cqhttp发送通知消息异常: ${data.errmsg}\n`);
} else {
- data = JSON.parse(data);
- if (data.retcode === 0) {
- console.log('go-cqhttp发送通知消息成功🎉\n');
- } else if (data.retcode === 100) {
- console.log(`go-cqhttp发送通知消息异常: ${data.errmsg}\n`);
- } else {
- console.log(
- `go-cqhttp发送通知消息异常\n${JSON.stringify(data)}`,
- );
- }
+ console.log(`go-cqhttp发送通知消息异常\n${JSON.stringify(data)}`);
}
- } catch (e) {
- $.logErr(e, resp);
- } finally {
- resolve(data);
}
- });
- }, time);
+ } catch (e) {
+ $.logErr(e, resp);
+ } finally {
+ resolve(data);
+ }
+ });
} else {
resolve();
}
});
}
-function serverNotify(text, desp, time = 2100) {
+function serverNotify(text, desp) {
return new Promise((resolve) => {
if (SCKEY) {
//微信server酱推送通知一个\n不会换行,需要两个\n才能换行,故做此替换
@@ -400,101 +499,63 @@ function serverNotify(text, desp, time = 2100) {
},
timeout,
};
- setTimeout(() => {
- $.post(options, (err, resp, data) => {
- try {
- if (err) {
- console.log('发送通知调用API失败!!\n');
- console.log(err);
+ $.post(options, (err, resp, data) => {
+ try {
+ if (err) {
+ console.log('发送通知调用API失败!!\n');
+ console.log(err);
+ } else {
+ data = JSON.parse(data);
+ //server酱和Server酱·Turbo版的返回json格式不太一样
+ if (data.errno === 0 || data.data.errno === 0) {
+ console.log('server酱发送通知消息成功🎉\n');
+ } else if (data.errno === 1024) {
+ // 一分钟内发送相同的内容会触发
+ console.log(`server酱发送通知消息异常: ${data.errmsg}\n`);
} else {
- data = JSON.parse(data);
- //server酱和Server酱·Turbo版的返回json格式不太一样
- if (data.errno === 0 || data.data.errno === 0) {
- console.log('server酱发送通知消息成功🎉\n');
- } else if (data.errno === 1024) {
- // 一分钟内发送相同的内容会触发
- console.log(`server酱发送通知消息异常: ${data.errmsg}\n`);
- } else {
- console.log(
- `server酱发送通知消息异常\n${JSON.stringify(data)}`,
- );
- }
+ console.log(`server酱发送通知消息异常\n${JSON.stringify(data)}`);
}
- } catch (e) {
- $.logErr(e, resp);
- } finally {
- resolve(data);
}
- });
- }, time);
+ } catch (e) {
+ $.logErr(e, resp);
+ } finally {
+ resolve(data);
+ }
+ });
} else {
resolve();
}
});
}
-function CoolPush(text, desp) {
+function PushDeerNotify(text, desp) {
return new Promise((resolve) => {
- if (QQ_SKEY) {
- let options = {
- url: `https://push.xuthus.cc/${QQ_MODE}/${QQ_SKEY}`,
+ if (PUSHDEER_KEY) {
+ // PushDeer 建议对消息内容进行 urlencode
+ desp = encodeURI(desp);
+ const options = {
+ url: PUSHDEER_URL || `https://api2.pushdeer.com/message/push`,
+ body: `pushkey=${PUSHDEER_KEY}&text=${text}&desp=${desp}&type=markdown`,
headers: {
- 'Content-Type': 'application/json',
+ 'Content-Type': 'application/x-www-form-urlencoded',
},
+ timeout,
};
-
- // 已知敏感词
- text = text.replace(/京豆/g, '豆豆');
- desp = desp.replace(/京豆/g, '');
- desp = desp.replace(/🐶/g, '');
- desp = desp.replace(/红包/g, 'H包');
-
- switch (QQ_MODE) {
- case 'email':
- options.json = {
- t: text,
- c: desp,
- };
- break;
- default:
- options.body = `${text}\n\n${desp}`;
- }
-
- let pushMode = function (t) {
- switch (t) {
- case 'send':
- return '个人';
- case 'group':
- return 'QQ群';
- case 'wx':
- return '微信';
- case 'ww':
- return '企业微信';
- case 'email':
- return '邮件';
- default:
- return '未知方式';
- }
- };
-
$.post(options, (err, resp, data) => {
try {
if (err) {
- console.log(`发送${pushMode(QQ_MODE)}通知调用API失败!!\n`);
+ console.log('发送通知调用API失败!!\n');
console.log(err);
} else {
data = JSON.parse(data);
- if (data.code === 200) {
- console.log(`酷推发送${pushMode(QQ_MODE)}通知消息成功🎉\n`);
- } else if (data.code === 400) {
- console.log(
- `QQ酷推(Cool Push)发送${pushMode(QQ_MODE)}推送失败:${data.msg
- }\n`,
- );
- } else if (data.code === 503) {
- console.log(`QQ酷推出错,${data.message}:${data.data}\n`);
+ // 通过返回的result的长度来判断是否成功
+ if (
+ data.content.result.length !== undefined &&
+ data.content.result.length > 0
+ ) {
+ console.log('PushDeer发送通知消息成功🎉\n');
} else {
- console.log(`酷推推送异常: ${JSON.stringify(data)}`);
+ console.log(`PushDeer发送通知消息异常\n${JSON.stringify(data)}`);
}
}
} catch (e) {
@@ -509,13 +570,50 @@ function CoolPush(text, desp) {
});
}
+function ChatNotify(text, desp) {
+ return new Promise((resolve) => {
+ if (CHAT_URL && CHAT_TOKEN) {
+ // 对消息内容进行 urlencode
+ desp = encodeURI(desp);
+ const options = {
+ url: `${CHAT_URL}${CHAT_TOKEN}`,
+ body: `payload={"text":"${text}\n${desp}"}`,
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ },
+ };
+ $.post(options, (err, resp, data) => {
+ try {
+ if (err) {
+ console.log('发送通知调用API失败!!\n');
+ console.log(err);
+ } else {
+ data = JSON.parse(data);
+ if (data.success) {
+ console.log('Chat发送通知消息成功🎉\n');
+ } else {
+ console.log(`Chat发送通知消息异常\n${JSON.stringify(data)}`);
+ }
+ }
+ } catch (e) {
+ $.logErr(e);
+ } finally {
+ resolve(data);
+ }
+ });
+ } else {
+ resolve();
+ }
+ });
+}
+
function BarkNotify(text, desp, params = {}) {
return new Promise((resolve) => {
if (BARK_PUSH) {
const options = {
url: `${BARK_PUSH}/${encodeURIComponent(text)}/${encodeURIComponent(
desp,
- )}?icon=${BARK_ICON}?sound=${BARK_SOUND}&group=${BARK_GROUP}&${querystring.stringify(
+ )}?icon=${BARK_ICON}&sound=${BARK_SOUND}&group=${BARK_GROUP}&${querystring.stringify(
params,
)}`,
headers: {
@@ -553,9 +651,13 @@ function tgBotNotify(text, desp) {
if (TG_BOT_TOKEN && TG_USER_ID) {
const options = {
url: `https://${TG_API_HOST}/bot${TG_BOT_TOKEN}/sendMessage`,
- body: `chat_id=${TG_USER_ID}&text=${text}\n\n${desp}&disable_web_page_preview=true`,
+ json: {
+ chat_id: `${TG_USER_ID}`,
+ text: `${text}\n\n${desp}`,
+ disable_web_page_preview: true,
+ },
headers: {
- 'Content-Type': 'application/x-www-form-urlencoded',
+ 'Content-Type': 'application/json',
},
timeout,
};
@@ -607,7 +709,7 @@ function ddBotNotify(text, desp) {
json: {
msgtype: 'text',
text: {
- content: ` ${text}\n\n${desp}`,
+ content: `${text}\n\n${desp}`,
},
},
headers: {
@@ -670,11 +772,11 @@ function ddBotNotify(text, desp) {
function qywxBotNotify(text, desp) {
return new Promise((resolve) => {
const options = {
- url: `https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=${QYWX_KEY}`,
+ url: `${QYWX_ORIGIN}/cgi-bin/webhook/send?key=${QYWX_KEY}`,
json: {
msgtype: 'text',
text: {
- content: ` ${text}\n\n${desp}`,
+ content: `${text}\n\n${desp}`,
},
},
headers: {
@@ -732,7 +834,7 @@ function qywxamNotify(text, desp) {
if (QYWX_AM) {
const QYWX_AM_AY = QYWX_AM.split(',');
const options_accesstoken = {
- url: `https://qyapi.weixin.qq.com/cgi-bin/gettoken`,
+ url: `${QYWX_ORIGIN}/cgi-bin/gettoken`,
json: {
corpid: `${QYWX_AM_AY[0]}`,
corpsecret: `${QYWX_AM_AY[1]}`,
@@ -743,9 +845,9 @@ function qywxamNotify(text, desp) {
timeout,
};
$.post(options_accesstoken, (err, resp, data) => {
- html = desp.replace(/\n/g, '
');
- var json = JSON.parse(data);
- accesstoken = json.access_token;
+ let html = desp.replace(/\n/g, '
');
+ let json = JSON.parse(data);
+ let accesstoken = json.access_token;
let options;
switch (QYWX_AM_AY[4]) {
@@ -797,7 +899,7 @@ function qywxamNotify(text, desp) {
};
}
options = {
- url: `https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=${accesstoken}`,
+ url: `${QYWX_ORIGIN}/cgi-bin/message/send?access_token=${accesstoken}`,
json: {
touser: `${ChangeUserId(desp)}`,
agentid: `${QYWX_AM_AY[3]}`,
@@ -938,6 +1040,150 @@ function pushPlusNotify(text, desp) {
});
}
+function aibotkNotify(text, desp) {
+ return new Promise((resolve) => {
+ if (AIBOTK_KEY && AIBOTK_TYPE && AIBOTK_NAME) {
+ let json = {};
+ let url = '';
+ switch (AIBOTK_TYPE) {
+ case 'room':
+ url = 'https://api-bot.aibotk.com/openapi/v1/chat/room';
+ json = {
+ apiKey: `${AIBOTK_KEY}`,
+ roomName: `${AIBOTK_NAME}`,
+ message: {
+ type: 1,
+ content: `【青龙快讯】\n\n${text}\n${desp}`,
+ },
+ };
+ break;
+ case 'contact':
+ url = 'https://api-bot.aibotk.com/openapi/v1/chat/contact';
+ json = {
+ apiKey: `${AIBOTK_KEY}`,
+ name: `${AIBOTK_NAME}`,
+ message: {
+ type: 1,
+ content: `【青龙快讯】\n\n${text}\n${desp}`,
+ },
+ };
+ break;
+ }
+ const options = {
+ url: url,
+ json,
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ timeout,
+ };
+ $.post(options, (err, resp, data) => {
+ try {
+ if (err) {
+ console.log('智能微秘书发送通知消息失败!!\n');
+ console.log(err);
+ } else {
+ data = JSON.parse(data);
+ if (data.code === 0) {
+ console.log('智能微秘书发送通知消息成功🎉。\n');
+ } else {
+ console.log(`${data.error}\n`);
+ }
+ }
+ } catch (e) {
+ $.logErr(e, resp);
+ } finally {
+ resolve(data);
+ }
+ });
+ } else {
+ resolve();
+ }
+ });
+}
+
+function fsBotNotify(text, desp) {
+ return new Promise((resolve) => {
+ if (FSKEY) {
+ const options = {
+ url: `https://open.feishu.cn/open-apis/bot/v2/hook/${FSKEY}`,
+ json: { msg_type: 'text', content: { text: `${text}\n\n${desp}` } },
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ timeout,
+ };
+ $.post(options, (err, resp, data) => {
+ try {
+ if (err) {
+ console.log('发送通知调用API失败!!\n');
+ console.log(err);
+ } else {
+ data = JSON.parse(data);
+ if (data.StatusCode === 0) {
+ console.log('飞书发送通知消息成功🎉\n');
+ } else {
+ console.log(`${data.msg}\n`);
+ }
+ }
+ } catch (e) {
+ $.logErr(e, resp);
+ } finally {
+ resolve(data);
+ }
+ });
+ } else {
+ resolve();
+ }
+ });
+}
+
+async function smtpNotify(text, desp) {
+ if (![SMTP_SERVER, SMTP_EMAIL, SMTP_PASSWORD].every(Boolean)) {
+ return;
+ }
+
+ try {
+ const nodemailer = require('nodemailer');
+ const transporter = nodemailer.createTransport(
+ `${SMTP_SSL === 'true' ? 'smtps:' : 'smtp:'}//${SMTP_SERVER}`,
+ {
+ auth: {
+ user: SMTP_EMAIL,
+ pass: SMTP_PASSWORD,
+ },
+ },
+ );
+
+ const addr = SMTP_NAME ? `"${SMTP_NAME}" <${SMTP_EMAIL}>` : SMTP_EMAIL;
+ const info = await transporter.sendMail({
+ from: addr,
+ to: addr,
+ subject: text,
+ text: desp,
+ });
+
+ if (!!info.messageId) {
+ console.log('SMTP发送通知消息成功🎉\n');
+ return true;
+ }
+ console.log('SMTP发送通知消息失败!!\n');
+ } catch (e) {
+ console.log('SMTP发送通知消息出现错误!!\n');
+ console.log(e);
+ }
+}
+
+function smtpNotify(text, desp) {
+ return new Promise((resolve) => {
+ if (SMTP_SERVER && SMTP_SSL && SMTP_EMAIL && SMTP_PASSWORD && SMTP_NAME) {
+ // todo: Node.js并没有内置的 smtp 实现,需要调用外部库,因为不清楚这个文件的模块依赖情况,所以留给有缘人实现
+ } else {
+ resolve();
+ }
+ });
+}
+
module.exports = {
sendNotify,
BARK_PUSH,