From 27c687b764a3f6bf69cd388259b3aebb54b36318 Mon Sep 17 00:00:00 2001 From: Chan Date: Mon, 2 Mar 2026 16:33:09 +0800 Subject: [PATCH 1/4] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=20=E4=BC=81?= =?UTF-8?q?=E4=B8=9A=E5=BE=AE=E4=BF=A1=E5=BA=94=E7=94=A8=E6=8E=A8=E9=80=81?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=EF=BC=88=E5=8F=AF=E9=80=89=EF=BC=8C=E9=9C=80?= =?UTF-8?q?=E8=A6=81=E5=88=99=E9=85=8D=E7=BD=AE=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 22 ++++++++++- sign_ninebot.js | 97 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 116 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index dd0a6c6..6ce0919 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ - ✅自动签到 (GitHub Actions & 青龙面板) - 👋单账号/多账号签到 - 🔔Bark 通知推送 +- 🔔企业微信应用推送 # 所需依赖 @@ -27,7 +28,17 @@ |`BARK_URL`|`https://api.day.app`(默认值)|❌|选填,自定义 BARK 服务器地址(默认官方地址)| |`BARK_GROUP`|`九号签到`(推送分组名称)|❌|选填,推送消息的分组标签| |`BARK_ICON`|`https://example.com/icon.png`(图标 URL)|❌|选填,推送消息显示的图标| -|`BARK_SOUND`|`chime`(铃声名称)|❌|选填,推送消息的铃声(默认 `bell`,支持 `chime`、`alarm` 等)| +|`BARK_SOUND`|`chime`(铃声名称)|❌|选填,推送消息的铃声(默认 `bell`,支持 `chime`、`alarm` 等)| +|`WECOM_CORP_ID`|`ww1234567890abcdef`(企业 ID)|❌|选填,企业微信管理后台「我的企业」页面获取| +|`WECOM_CORP_SECRET`|`xxxxxxxxxxxxxxxxxxxxxxxx`(应用 Secret)|❌|选填,企业微信管理后台对应应用的 Secret| +|`WECOM_AGENT_ID`|`1000002`(应用 AgentId)|❌|选填,企业微信管理后台对应应用的 AgentId| +|`WECOM_PROXY_URL`|`https://qyapi.weixin.qq.com`(默认值)|❌|选填,企业微信 API 代理地址(默认官方地址,可替换为自建代理)| +|`WECOM_TO_USER`|`UserID1\|UserID2` 或 `@all`(默认 `@all`)|❌|选填,消息接收人,默认发送给全体成员| +|`WECOM_TO_PARTY`|`1\|2`(部门 ID 列表)|❌|选填,发送给指定部门| +|`WECOM_TO_TAG`|`1\|2`(标签 ID 列表)|❌|选填,发送给指定标签下的成员| +|`WECOM_MSG_TYPE`|`text` / `textcard` / `markdown`(默认 `text`)|❌|选填,消息类型:纯文本 / 文本卡片 / Markdown| +|`WECOM_CARD_URL`|`https://h5-bj.ninebot.com`(默认值)|❌|选填,文本卡片消息点击后跳转的 URL(仅 `textcard` 类型生效)| +|`WECOM_CARD_BTN`|`查看详情`(默认值)|❌|选填,文本卡片消息按钮文字(仅 `textcard` 类型生效)| # 使用方法 @@ -76,6 +87,15 @@ BARK_URL=https://api.day.app # 默认使用 APP 自带服务器 # BARK_GROUP=九号签到通知 # 通知分组 # BARK_ICON=https://xxx.png # 通知图标URL # BARK_SOUND=bell # 通知铃声 + +# 企业微信应用推送相关(可选,需要则配置) + +# WECOM_CORP_ID=你的企业ID # 企业微信管理后台「我的企业」获取 +# WECOM_CORP_SECRET=你的应用Secret # 应用管理页面获取 +# WECOM_AGENT_ID=你的应用AgentId # 应用管理页面获取 +# WECOM_PROXY_URL=https://qyapi.weixin.qq.com # 企业微信API代理地址,默认官方地址 +# WECOM_TO_USER=@all # 接收人,默认@all +# WECOM_MSG_TYPE=text # 消息类型:text / textcard / markdown ``` 4. 运行脚本 diff --git a/sign_ninebot.js b/sign_ninebot.js index cf98ada..0b83641 100644 --- a/sign_ninebot.js +++ b/sign_ninebot.js @@ -280,6 +280,96 @@ async function sendBarkNotification(title, message) { } } +// 发送企业微信应用推送 +async function sendWeComNotification(title, message) { + // 从环境变量获取企业微信配置 + const corpId = process.env.WECOM_CORP_ID; // 企业ID + const corpSecret = process.env.WECOM_CORP_SECRET; // 应用Secret + const agentId = process.env.WECOM_AGENT_ID; // 应用AgentId + const toUser = process.env.WECOM_TO_USER || "@all"; // 接收人,默认@all全体 + const proxyUrl = (process.env.WECOM_PROXY_URL || "https://qyapi.weixin.qq.com").replace(/\/+$/, ""); // 代理地址,默认官方API + + // 缺少必要配置则跳过 + if (!corpId || !corpSecret || !agentId) { + console.log("未配置企业微信应用推送(WECOM_CORP_ID / WECOM_CORP_SECRET / WECOM_AGENT_ID),跳过企业微信通知"); + return false; + } + + try { + // 第一步:获取 access_token + console.log(`企业微信: 正在获取access_token...(API地址: ${proxyUrl})`); + const tokenUrl = `${proxyUrl}/cgi-bin/gettoken?corpid=${corpId}&corpsecret=${corpSecret}`; + const tokenRes = await axios.get(tokenUrl, { timeout: 5000 }); + + if (tokenRes.data.errcode !== 0) { + console.error("企业微信获取access_token失败:", tokenRes.data.errmsg); + return false; + } + + const accessToken = tokenRes.data.access_token; + console.log("企业微信: access_token获取成功"); + + // 第二步:构建消息体 + // 判断消息类型:支持文本卡片(textcard)或纯文本(text) + const msgType = process.env.WECOM_MSG_TYPE || "text"; // 默认文本消息 + + let msgBody = { + touser: toUser, + agentid: parseInt(agentId), + safe: 0, + }; + + // 如果配置了发送给指定部门 + if (process.env.WECOM_TO_PARTY) { + msgBody.toparty = process.env.WECOM_TO_PARTY; + } + + // 如果配置了发送给指定标签 + if (process.env.WECOM_TO_TAG) { + msgBody.totag = process.env.WECOM_TO_TAG; + } + + if (msgType === "textcard") { + // 文本卡片消息 + msgBody.msgtype = "textcard"; + msgBody.textcard = { + title: title, + description: message.replace(/\n/g, "
"), + url: process.env.WECOM_CARD_URL || "https://h5-bj.ninebot.com", + btntxt: process.env.WECOM_CARD_BTN || "查看详情" + }; + } else if (msgType === "markdown") { + // Markdown消息(仅企业微信内部支持,不支持微信插件) + msgBody.msgtype = "markdown"; + msgBody.markdown = { + content: `## ${title}\n${message}` + }; + } else { + // 默认纯文本消息 + msgBody.msgtype = "text"; + msgBody.text = { + content: `${title}\n\n${message}` + }; + } + + // 第三步:发送消息 + const sendUrl = `${proxyUrl}/cgi-bin/message/send?access_token=${accessToken}`; + console.log("企业微信: 正在发送消息..."); + const sendRes = await axios.post(sendUrl, msgBody, { timeout: 5000 }); + + if (sendRes.data.errcode === 0) { + console.log("企业微信应用推送发送成功"); + return true; + } else { + console.error("企业微信应用推送发送失败:", sendRes.data.errmsg); + return false; + } + } catch (error) { + console.error("发送企业微信通知异常:", error.message); + return false; + } +} + // 初始化并执行签到 async function init() { // 处理多账号配置 @@ -338,8 +428,11 @@ async function init() { return `${status} ${acc.name}\n${acc.logs.replace(/\n/g, "\n ")}`; }).join("\n\n"); - // 发送Bark通知 - await sendBarkNotification(title, message); + // 发送通知(并行发送,互不影响) + await Promise.allSettled([ + sendBarkNotification(title, message), + sendWeComNotification(title, message) + ]); } // 启动执行 From 1a794290052a70b9e7483bb997144847fd861ff5 Mon Sep 17 00:00:00 2001 From: Chan Date: Mon, 2 Mar 2026 16:40:09 +0800 Subject: [PATCH 2/4] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=20=E4=BC=81?= =?UTF-8?q?=E4=B8=9A=E5=BE=AE=E4=BF=A1=E5=BA=94=E7=94=A8=E6=8E=A8=E9=80=81?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=EF=BC=88=E5=8F=AF=E9=80=89=EF=BC=8C=E9=9C=80?= =?UTF-8?q?=E8=A6=81=E5=88=99=E9=85=8D=E7=BD=AE=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sign_ninebot.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sign_ninebot.js b/sign_ninebot.js index 0b83641..21500c8 100644 --- a/sign_ninebot.js +++ b/sign_ninebot.js @@ -425,7 +425,7 @@ async function init() { const title = "九号出行签到结果"; let message = allResults.map(acc => { const status = acc.success ? "✅" : "❌"; - return `${status} ${acc.name}\n${acc.logs.replace(/\n/g, "\n ")}`; + return `${status} ${acc.name}\n${acc.logs.replace(/\n/g, "\n")}`; }).join("\n\n"); // 发送通知(并行发送,互不影响) From ee06d30d5e2e90d26cbb0dbb800f3e9df1cd5ca2 Mon Sep 17 00:00:00 2001 From: Chan Date: Mon, 2 Mar 2026 16:46:25 +0800 Subject: [PATCH 3/4] edit readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6ce0919..ad90022 100644 --- a/README.md +++ b/README.md @@ -106,7 +106,7 @@ npm start ## 青龙面板 -1. 添加订阅 https://github.com/waistu/Ninebot.git +1. 添加订阅 [https://github.com/waistu/Ninebot.git](https://github.com/cheny95/Ninebot.git) 2. 安装NodeJs 依赖:axios、moment、dotenv 3. 添加环境变量 4. 修改任务定时 From 7c4efd491d5ee0ed6a6757c5cacc04dc4dde4ea0 Mon Sep 17 00:00:00 2001 From: Chan Date: Mon, 2 Mar 2026 16:48:49 +0800 Subject: [PATCH 4/4] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ad90022..5d6edfe 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # 九号出行自动签到脚本 -这是一个用于九号出行自动签到的 Node.js 脚本,基于 [wan-kong/ninebot-sign](https://github.com/wan-kong/ninebot-sign) 修改,新增了一些内容。 +这是一个用于九号出行自动签到的 Node.js 脚本,基于 [waistu/Ninebot][(https://github.com/waistu/Ninebot)](https://github.com/waistu/Ninebot) 修改,新增了一些内容。 # 功能特点