diff --git a/back/data/notify.ts b/back/data/notify.ts index 12c62e4f..ed52ba6c 100644 --- a/back/data/notify.ts +++ b/back/data/notify.ts @@ -21,6 +21,7 @@ export enum NotificationMode { 'webhook' = 'webhook', 'chronocat' = 'Chronocat', 'ntfy' = 'ntfy', + 'wxPusherBot' = 'wxPusherBot', } abstract class NotificationBaseInfo { @@ -150,6 +151,13 @@ export class NtfyNotification extends NotificationBaseInfo { public ntfyTopic = ''; public ntfyPriority = ''; } + +export class WxPusherBotNotification extends NotificationBaseInfo { + public wxPusherBotAppToken = ''; + public wxPusherBotTopicIds = ''; + public wxPusherBotUids = ''; +} + export interface NotificationInfo extends GoCqHttpBotNotification, GotifyNotification, @@ -170,5 +178,5 @@ export interface NotificationInfo WebhookNotification, ChronocatNotification, LarkNotification, - NtfyNotification {} - + NtfyNotification, + WxPusherBotNotification {} diff --git a/back/services/notify.ts b/back/services/notify.ts index 526121a5..17ea4586 100644 --- a/back/services/notify.ts +++ b/back/services/notify.ts @@ -36,6 +36,7 @@ export default class NotificationService { ['lark', this.lark], ['chronocat', this.chronocat], ['ntfy', this.ntfy], + ['wxPusherBot', this.wxPusherBot], ]); private title = ''; @@ -696,6 +697,51 @@ export default class NotificationService { } } + private async wxPusherBot() { + const { wxPusherBotAppToken, wxPusherBotTopicIds, wxPusherBotUids } = this.params; + // 处理 topicIds,将分号分隔的字符串转为数组 + const topicIds = wxPusherBotTopicIds ? wxPusherBotTopicIds.split(';') + .map(id => id.trim()) + .filter(id => id) + .map(id => parseInt(id)) : []; + + // 处理 uids,将分号分隔的字符串转为数组 + const uids = wxPusherBotUids ? wxPusherBotUids.split(';') + .map(uid => uid.trim()) + .filter(uid => uid) : []; + + // topic_ids 和 uids 至少要有一个 + if (!topicIds.length && !uids.length) { + throw new Error('wxPusher 服务的 TopicIds 和 Uids 至少配置一个才行'); + } + + const url = `https://wxpusher.zjiecode.com/api/send/message`; + try { + const res: any = await got + .post(url, { + ...this.gotOption, + json: { + appToken: wxPusherBotAppToken, + content: `

${this.title}


${this.content}
`, + summary: this.title, + contentType: 2, + topicIds: topicIds, + uids: uids, + verifyPayType: 0 + }, + }) + .json(); + + if (res.code === 1000) { + return true; + } else { + throw new Error(JSON.stringify(res)); + } + } catch (error: any) { + throw new Error(error.response ? error.response.body : error); + } + } + private async chronocat() { const { chronocatURL, chronocatQQ, chronocatToken } = this.params; diff --git a/sample/config.sample.sh b/sample/config.sample.sh index 7d2d0dde..1249ae6f 100644 --- a/sample/config.sample.sh +++ b/sample/config.sample.sh @@ -230,8 +230,17 @@ export NTFY_URL="" export NTFY_TOPIC="" export NTFY_PRIORITY="3" +## 21. wxPusher +## 官方文档: https://wxpusher.zjiecode.com/docs/ +## 管理后台: https://wxpusher.zjiecode.com/admin/ +## wxPusher 的 appToken +export WXPUSHER_APP_TOKEN="" +## wxPusher 的 topicIds,多个用英文分号;分隔 topic_ids 与 uids 至少配置一个才行 +export WXPUSHER_TOPIC_IDS="" +## wxPusher 的 用户ID,多个用英文分号;分隔 topic_ids 与 uids 至少配置一个才行 +export WXPUSHER_UIDS="" -## 21. 自定义通知 +## 22. 自定义通知 ## 自定义通知 接收回调的URL export WEBHOOK_URL="" ## WEBHOOK_BODY 和 WEBHOOK_HEADERS 多个参数时,直接换行或者使用 $'\n' 连接多行字符串,比如 export dd="line 1"$'\n'"line 2" diff --git a/sample/notify.js b/sample/notify.js index 77af6536..debd8b9b 100644 --- a/sample/notify.js +++ b/sample/notify.js @@ -105,6 +105,12 @@ const push_config = { NTFY_URL: '', // ntfy地址,如https://ntfy.sh,默认为https://ntfy.sh NTFY_TOPIC: '', // ntfy的消息应用topic NTFY_PRIORITY: '3', // 推送消息优先级,默认为3 + + // 官方文档: https://wxpusher.zjiecode.com/docs/ + // 管理后台: https://wxpusher.zjiecode.com/admin/ + WXPUSHER_APP_TOKEN: '', // wxpusher 的 appToken + WXPUSHER_TOPIC_IDS: '', // wxpusher 的 主题ID,多个用英文分号;分隔 topic_ids 与 uids 至少配置一个才行 + WXPUSHER_UIDS: '', // wxpusher 的 用户ID,多个用英文分号;分隔 topic_ids 与 uids 至少配置一个才行 }; for (const key in push_config) { @@ -1246,6 +1252,70 @@ function ntfyNotify(text, desp) { }); } +function wxPusherNotify(text, desp) { + return new Promise((resolve) => { + const { WXPUSHER_APP_TOKEN, WXPUSHER_TOPIC_IDS, WXPUSHER_UIDS } = push_config; + if (WXPUSHER_APP_TOKEN) { + // 处理topic_ids,将分号分隔的字符串转为数组 + const topicIds = WXPUSHER_TOPIC_IDS ? WXPUSHER_TOPIC_IDS.split(';') + .map(id => id.trim()) + .filter(id => id) + .map(id => parseInt(id)) : []; + + // 处理uids,将分号分隔的字符串转为数组 + const uids = WXPUSHER_UIDS ? WXPUSHER_UIDS.split(';') + .map(uid => uid.trim()) + .filter(uid => uid) : []; + + // topic_ids uids 至少有一个 + if (!topicIds.length && !uids.length) { + console.log("wxpusher 服务的 WXPUSHER_TOPIC_IDS 和 WXPUSHER_UIDS 至少设置一个!!\n取消推送"); + return resolve(); + } + + const body = { + appToken: WXPUSHER_APP_TOKEN, + content: `

${text}


${desp}
`, + summary: text, + contentType: 2, + topicIds: topicIds, + uids: uids, + verifyPayType: 0 + }; + + const options = { + url: 'https://wxpusher.zjiecode.com/api/send/message', + body: JSON.stringify(body), + headers: { + 'Content-Type': 'application/json' + }, + timeout + }; + + $.post(options, (err, resp, data) => { + try { + if (err) { + console.log('wxpusher发送通知消息失败!\n', err); + } else { + if (data.code === 1000) { + console.log('wxpusher发送通知消息完成!'); + } else { + console.log(`wxpusher发送通知消息异常:${data.msg}`); + } + } + } catch (e) { + $.logErr(e, resp); + } finally { + resolve(data); + } + }); + } else { + console.log('wxpusher 服务的 WXPUSHER_APP_TOKEN 未设置!!\n取消推送'); + resolve(); + } + }); +} + function parseString(input, valueFormatFn) { const regex = /(\w+):\s*((?:(?!\n\w+:).)*)/g; @@ -1376,6 +1446,7 @@ async function sendNotify(text, desp, params = {}) { webhookNotify(text, desp), // 自定义通知 qmsgNotify(text, desp), // 自定义通知 ntfyNotify(text, desp), // Ntfy + wxPusherNotify(text, desp), // wxpusher ]); } diff --git a/sample/notify.py b/sample/notify.py index 02fd5f0e..717d619e 100644 --- a/sample/notify.py +++ b/sample/notify.py @@ -126,6 +126,10 @@ push_config = { 'NTFY_URL': '', # ntfy地址,如https://ntfy.sh 'NTFY_TOPIC': '', # ntfy的消息应用topic 'NTFY_PRIORITY':'3', # 推送消息优先级,默认为3 + + 'WXPUSHER_APP_TOKEN': '', # wxpusher 的 appToken 官方文档: https://wxpusher.zjiecode.com/docs/ 管理后台: https://wxpusher.zjiecode.com/admin/ + 'WXPUSHER_TOPIC_IDS': '', # wxpusher 的 主题ID,多个用英文分号;分隔 topic_ids 与 uids 至少配置一个才行 + 'WXPUSHER_UIDS': '', # wxpusher 的 用户ID,多个用英文分号;分隔 topic_ids 与 uids 至少配置一个才行 } # fmt: on @@ -835,6 +839,57 @@ def ntfy(title: str, content: str) -> None: else: print("Ntfy 推送失败!错误信息:", response.text) + +def wxpusher_bot(title: str, content: str) -> None: + """ + 通过 wxpusher 推送消息。 + 支持的环境变量: + - WXPUSHER_APP_TOKEN: appToken + - WXPUSHER_TOPIC_IDS: 主题ID, 多个用英文分号;分隔 + - WXPUSHER_UIDS: 用户ID, 多个用英文分号;分隔 + """ + if not push_config.get("WXPUSHER_APP_TOKEN"): + print("wxpusher 服务的 WXPUSHER_APP_TOKEN 未设置!!\n取消推送") + return + + + url = "https://wxpusher.zjiecode.com/api/send/message" + + # 处理topic_ids和uids,将分号分隔的字符串转为数组 + topic_ids = [] + if push_config.get("WXPUSHER_TOPIC_IDS"): + topic_ids = [int(id.strip()) for id in push_config.get("WXPUSHER_TOPIC_IDS").split(";") if id.strip()] + + uids = [] + if push_config.get("WXPUSHER_UIDS"): + uids = [uid.strip() for uid in push_config.get("WXPUSHER_UIDS").split(";") if uid.strip()] + + # topic_ids uids 至少有一个 + if not topic_ids and not uids: + print("wxpusher 服务的 WXPUSHER_TOPIC_IDS 和 WXPUSHER_UIDS 至少设置一个!!\n取消推送") + return + + print("wxpusher 服务启动") + + data = { + "appToken": push_config.get("WXPUSHER_APP_TOKEN"), + "content": f"

{title}


{content}
", + "summary": title, + "contentType": 2, + "topicIds": topic_ids, + "uids": uids, + "verifyPayType": 0 + } + + headers = {"Content-Type": "application/json"} + response = requests.post(url=url, json=data, headers=headers).json() + + if response.get("code") == 1000: + print("wxpusher 推送成功!") + else: + print(f"wxpusher 推送失败!错误信息:{response.get('msg')}") + + def parse_headers(headers): if not headers: return {} @@ -997,6 +1052,8 @@ def add_notify_function(): notify_function.append(custom_notify) if push_config.get("NTFY_TOPIC"): notify_function.append(ntfy) + if push_config.get("WXPUSHER_APP_TOKEN") and (push_config.get("WXPUSHER_TOPIC_IDS") or push_config.get("WXPUSHER_UIDS")): + notify_function.append(wxpusher_bot) if not notify_function: print(f"无推送渠道,请检查通知变量是否正确") return notify_function diff --git a/src/locales/en-US.json b/src/locales/en-US.json index cb9951b0..19b7c78e 100644 --- a/src/locales/en-US.json +++ b/src/locales/en-US.json @@ -395,6 +395,9 @@ "自建的PushMeServer消息接口地址,例如:http://127.0.0.1:3010,不填则使用官方消息接口": "The self built PushMeServer message interface address, for example: http://127.0.0.1:3010 If left blank, use the official message interface", "ntfy的url地址,例如 https://ntfy.sh'": "The URL address of ntfy, for example, https://ntfy.sh.", "ntfy的消息应用topic": "The topic for ntfy's messaging application.", + "wxPusherBot的appToken": "wxPusherBot's appToken, obtain according to docs https://wxpusher.zjiecode.com/docs/", + "wxPusherBot的topicIds": "wxPusherBot's topicIds, at least one of topicIds or uids must be configured", + "wxPusherBot的uids": "wxPusherBot's uids, at least one of topicIds or uids must be configured", "请求方法": "Request Method", "请求头Content-Type": "Request Header Content-Type", "请求链接以http或者https开头。url或者body中必须包含$title,$content可选,对应api内容的位置": "Request URL should start with http or https. URL or body must contain $title, $content is optional and corresponds to the API content position.", diff --git a/src/locales/zh-CN.json b/src/locales/zh-CN.json index 1ca52233..c3ac7226 100644 --- a/src/locales/zh-CN.json +++ b/src/locales/zh-CN.json @@ -395,6 +395,9 @@ "自建的PushMeServer消息接口地址,例如:http://127.0.0.1:3010,不填则使用官方消息接口": "自建的PushMeServer消息接口地址,例如:http://127.0.0.1:3010,不填则使用官方消息接口", "ntfy的url地址,例如 https://ntfy.sh": "ntfy的url地址,例如 https://ntfy.sh", "ntfy的消息应用topic": "ntfy的消息应用topic", + "wxPusherBot的appToken": "wxPusherBot的appToken, 按照文档获取 https://wxpusher.zjiecode.com/docs/", + "wxPusherBot的topicIds": "wxPusherBot的topicIds, topicIds 和 uids 至少配置一个才行", + "wxPusherBot的uids": "wxPusherBot的uids, topicIds 和 uids 至少配置一个才行", "请求方法": "请求方法", "请求头Content-Type": "请求头Content-Type", "请求链接以http或者https开头。url或者body中必须包含$title,$content可选,对应api内容的位置": "请求链接以http或者https开头。url或者body中必须包含$title,$content可选,对应api内容的位置", diff --git a/src/utils/config.ts b/src/utils/config.ts index a5ca36f5..35ce3bae 100644 --- a/src/utils/config.ts +++ b/src/utils/config.ts @@ -97,6 +97,7 @@ export default { { value: 'iGot', label: 'IGot' }, { value: 'pushPlus', label: 'PushPlus' }, { value: 'wePlusBot', label: intl.get('微加机器人') }, + { value: 'wxPusherBot', label: 'wxPusher' }, { value: 'chat', label: intl.get('群晖chat') }, { value: 'email', label: intl.get('邮箱') }, { value: 'lark', label: intl.get('飞书机器人') }, @@ -378,6 +379,23 @@ export default { ), }, ], + wxPusherBot: [ + { + label: 'wxPusherBotAppToken', + tip: intl.get('wxPusherBot的appToken'), + required: true, + }, + { + label: 'wxPusherBotTopicIds', + tip: intl.get('wxPusherBot的topicIds'), + required: false, + }, + { + label: 'wxPusherBotUids', + tip: intl.get('wxPusherBot的uids'), + required: false, + }, + ], lark: [ { label: 'larkKey',