fix(qqmusic): 修正青龙自动建任务的元数据,任务名与 cron 不再被误提取
真机故障(2026-11-04):青龙订阅勾「自动添加定时任务」后,任务被建成
名称 = u.hostname, (应为 QQ音乐自动签到)
cron = 18 21 * * * (应为 1 0,6 * * *)
根因是青龙从脚本正文正则提取元数据,两条正则都不锚定行首:
1) 任务名 /name:\s*(.+)/ —— 全文第一个命中即采用。脚本里 https.request 的
选项对象写了 hostname: u.hostname,其中的 name 段被当成任务名。
2) cron /\bcron:\s*([^\r\n]+)/ —— 必须带冒号。原写法是注释里的
「定时: cron 1 0,6 * * *」,冒号在「定时」后面,cron 后面没有冒号 → 匹配不到,
落到随机 fallback(randomInt 生成 18 21 * * *)。
修法:
- 脚本第 3 行显式写 name 注解(独占一行,内容为「QQ音乐自动签到」)
- cron 注解改成「cron: 1 0,6 * * *」独占一行,注释挪到下一行
- https.request 选项 hostname -> host(Node 的别名,语义等价,实测 u6.y.qq.com
返回 404 而非连接失败),彻底消除全文唯一的 name+冒号连写
- README 补「青龙自动建任务的元数据约定」小节,记录两条正则与兜底行为
验证:node --check 通过 / 签名对拍 6 组 PASS / 空 env 优雅跳过 /
复刻青龙两条正则做提取断言,name=QQ音乐自动签到、cron=1 0,6 * * *;
新版青龙(cli/src/internal/subscription/subscriptionRunner.ts 的 cronMetadata)
同样提取正确
This commit is contained in:
@@ -41,6 +41,21 @@ cron: 1 0,6 * * *
|
|||||||
|
|
||||||
每天 00:01 + 06:02 双轮:任务20(收听节目)跨天滚动翻账本 + 福利站 0 点翻新兜底。
|
每天 00:01 + 06:02 双轮:任务20(收听节目)跨天滚动翻账本 + 福利站 0 点翻新兜底。
|
||||||
|
|
||||||
|
### 青龙自动建任务的元数据约定(踩坑记录 2026-11-04)
|
||||||
|
|
||||||
|
订阅勾了「自动添加定时任务」时,青龙从**脚本内容**里正则提取任务名与 cron,两个坑:
|
||||||
|
|
||||||
|
| 项 | 青龙的提取规则 | 必须怎么写 |
|
||||||
|
|---|---|---|
|
||||||
|
| **任务名** | `/name:\s*(.+)/`(**不锚定行首**),取**全文第一个**命中 | 脚本第 3 行写 `* name: QQ音乐自动签到`。**全文任何位置都不能再出现「name+冒号」的连写**——`https.request({ hostname: u.hostname })` 会被抓成任务名 `u.hostname,`(真机已复现) |
|
||||||
|
| **cron** | `/\bcron:\s*([^\r\n]+)/`(**必须带冒号**) | 写 `* cron: 1 0,6 * * *`,且**独占一行、后面不跟注释**(同一行剩余文字会被一起吞进 schedule) |
|
||||||
|
|
||||||
|
两个都抓不到时的兜底:任务名 = 文件名 `scrip_qqmusic_checkin.js`;cron = 随机 `M H * * *`。
|
||||||
|
|
||||||
|
所以脚本里:
|
||||||
|
- `https.request` 的选项用 `host:`(Node 的 `hostname` 别名)而不是 `hostname:`
|
||||||
|
- cron 注解独占一行
|
||||||
|
|
||||||
## 任务覆盖
|
## 任务覆盖
|
||||||
|
|
||||||
| 层 | 内容 | 风险 |
|
| 层 | 内容 | 风险 |
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
/**
|
/**
|
||||||
|
* name: QQ音乐自动签到
|
||||||
|
*
|
||||||
* scrip_qqmusic_checkin.js —— QQ音乐会员成长值 + 会员福利站 自动签到(青龙 Node 零依赖)
|
* scrip_qqmusic_checkin.js —— QQ音乐会员成长值 + 会员福利站 自动签到(青龙 Node 零依赖)
|
||||||
*
|
*
|
||||||
* 文件名前缀 scrip_ 是订阅白名单要求(ql repo 的 whitelist 参数 = "scrip_"),
|
* 文件名前缀 scrip_ 是订阅白名单要求(ql repo 的 whitelist 参数 = "scrip_"),
|
||||||
@@ -20,7 +22,11 @@
|
|||||||
* QM_PLAY_REPORT 任务20播放上报开关(默认 off;伪造统计数据属中风险,
|
* QM_PLAY_REPORT 任务20播放上报开关(默认 off;伪造统计数据属中风险,
|
||||||
* 且需播放 XML 模板,本版未实现,仅挂 StartTask 标记)
|
* 且需播放 XML 模板,本版未实现,仅挂 StartTask 标记)
|
||||||
*
|
*
|
||||||
* 定时: cron 1 0,6 * * * (00:01 + 06:02 双轮:任务20跨天滚动 + 福利站翻新兜底)
|
* cron: 1 0,6 * * *
|
||||||
|
*
|
||||||
|
* 定时说明: 00:01 + 06:02 双轮(任务20跨天滚动 + 福利站翻新兜底)。
|
||||||
|
* cron 注解必须**独占一行且后面不跟注释** —— 青龙的提取正则
|
||||||
|
* /\bcron:\s*([^\r\n]+)/ 会把同一行剩下的文字一起吞进去,产出的 schedule 非法。
|
||||||
*/
|
*/
|
||||||
'use strict'
|
'use strict'
|
||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
@@ -55,12 +61,18 @@ function zzc(payload) {
|
|||||||
return ('zzc' + p1 + mid + p2).toLowerCase()
|
return ('zzc' + p1 + mid + p2).toLowerCase()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Node 内置 https,零外部依赖(不依赖 node_modules 是否被装好) */
|
/** Node 内置 https,零外部依赖(不依赖 node_modules 是否被装好)
|
||||||
|
* 两个坑(2026-11-04 真机踩过,任务名被建成 "u.hostname,"、cron 被随机成 "18 21 * * *"):
|
||||||
|
* 1. 本文件任何位置都不要出现「name + 冒号」的连写 —— 青龙订阅自动建任务时用不锚定的
|
||||||
|
* 正则抓任务名,对象字段(https 选项里的 host 与 name 两段)会被当成任务名。
|
||||||
|
* 所以下面选项用 `host:`(https.request 支持,是 hostname 的别名)。
|
||||||
|
* 2. 定时注解必须写成「cron + 冒号」且独占一行 —— 旧版用不锚定正则抓,
|
||||||
|
* 写成「cron 1 0,6 * * *」(无冒号)匹配不到,任务会落到随机 fallback。 */
|
||||||
function request(method, urlStr, headers = {}, body = null, timeoutMs = 20000) {
|
function request(method, urlStr, headers = {}, body = null, timeoutMs = 20000) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const u = new URL(urlStr)
|
const u = new URL(urlStr)
|
||||||
const req = https.request({
|
const req = https.request({
|
||||||
hostname: u.hostname,
|
host: u.hostname,
|
||||||
port: 443,
|
port: 443,
|
||||||
path: u.pathname + u.search,
|
path: u.pathname + u.search,
|
||||||
method,
|
method,
|
||||||
|
|||||||
Reference in New Issue
Block a user