refactor(common): 通知实现搬进 common.js,所有脚本一行 require 即可用

上一版把 notify 内联在 qqmusic 脚本里,只解决了单个脚本。这次搬到仓库根的
common.js,后续任何脚本 require('../common') 就能发通知。

common.js 新增导出:
  notify(title, content, opts)   webhook + pushplus 双通道,任一成功即 ok,永不抛错
  notifyConfig(env)              读 env 并给默认值(可注入替身,方便测试)
  httpPost(url, headers, body)   通用 POST,http/https 自适应
  parseHookHeaders(raw)          一行一个 Key: Value
  buildHookBody(t, c, tpl, ct)   拼 body,JSON 不合法就重建
Env 保持原样未动(jd 与 xiequ 在用)。

顺带删掉第 1 行的 require('node-fetch') —— 它是死代码:Env 内部所有 HTTP 走的是
require('got') + require('tough-cookie'),fetch 只以 $task.fetch(...) 的形式出现在
QuantumultX 分支(宿主 API,不是 node-fetch)。留着它反而会在容器缺 node-fetch 时
让整个文件 require 抛错,连带 jd / xiequ 一起挂。

qqmusic 脚本从 125 行内联实现缩成一行 require('../common'),删掉重复的
httpPost / parseHookHeaders / buildHookBody / notify 四份副本。

测试从 qqmusic/test_notify.js 挪到仓库根 test_common_notify.js,断言从 38 加到 69:
  - parseHookHeaders 九种输入(新增重复 key 覆盖)
  - buildHookBody 五种(新增自定义模板 + urlencoded + text/plain)
  - notifyConfig 十项默认值与 trim
  - notify 八种状态(200/204/201/401/403/400/429/连不上)
  - 无配置、双通道互不牵连
  - Env 兼容性(确认 node-fetch 已移除、老接口都在)

端到端已验证:common.js 的 notify 发出的 content 与原始 desp 逐字相同(10 行完整),
title 正确,header 带 token,HTTP 204 判为成功。

README(根 + qqmusic)新增 common.js 公共库章节,列出 notify 支持的八个环境变量
与「为什么不能放 sendNotify.js」的 deps 覆盖原因。
This commit is contained in:
2026-11-07 02:10:23 +08:00
parent 6a64a7de6f
commit 23d35cd942
6 changed files with 452 additions and 300 deletions

View File

@@ -25,6 +25,45 @@
> **文件名约定**:订阅白名单是 `scrip_`,所有脚本文件必须带该前缀才会被拉取。
> 详见各目录下的 README。
## 公共库 `common.js`
仓库根的 `common.js` 是**依赖文件**(订阅「依赖文件」填 `common` 就会拉下来),
提供两样东西:
```js
const { Env, notify } = require('../common')
// 1. Env:四端环境封装(QuantumultX / Surge / Loon / Node),jd 与 xiequ 在用
const $ = new Env('我的脚本')
// 2. notify:发通知,webhook + pushplus 双通道,任一成功即 ok,永不抛错
const r = await notify('标题', '正文')
// → { ok: true, channels: [{name:'webhook', ok:true, detail:'HTTP 204'}, ...] }
```
`notify` 读的环境变量:
| 变量 | 说明 |
|---|---|
| `WEBHOOK_URL` | 自定义 webhook(如平台 `/api/hooks/ql`) |
| `WEBHOOK_METHOD` | 默认 `POST` |
| `WEBHOOK_CONTENT_TYPE` | 默认 `application/json` |
| `WEBHOOK_BODY` | 支持 `$title` / `$content` 占位;不填则按 Content-Type 给默认形状 |
| `WEBHOOK_HEADERS` | 一行一个 `Key: Value`,**必须是真换行** |
| `PUSH_PLUS_TOKEN` | pushplus 直发 |
| `PUSH_PLUS_USER` | pushplus 群组编码(一对多) |
| `PUSH_PLUS_TEMPLATE` | 默认 `txt`(不转义 html、不折叠) |
**为什么不放在 `sendNotify.js` 里**:青龙订阅复制文件时 `/ql/data/deps/*` 会**最后覆盖**,
而 `deps` 里正好有一份面板自带的 `sendNotify.js`。改那个文件永远不生效。
`common.js` 不在 `deps` 里,所以安全。详见 [qqmusic/README.md](qqmusic/README.md) 的「坑 0」。
自检:
```bash
node test_common_notify.js # 69 条断言,含八种 HTTP 状态码
```
## 安装使用