真机故障(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)
同样提取正确
QQ音乐自动签到(scrip_qqmusic_checkin.js)
QQ音乐会员成长值任务 + 会员福利站 自动签到,青龙面板 Node 零依赖。
协议底座与 LDP924/auto-checkin(Python)逐字节同源:
u6.y.qq.com/cgi-bin/musics.fcg 网关 + zzc 签名(sha1 重组 + 置乱表 + b64 去尾)+ qm_keyst cookie。
文件名必须带
scrip_前缀:本仓库的青龙订阅规则白名单是scrip_, 不带前缀的文件不会被订阅拉取(脚本、测试、文档同一约定)。
环境变量
| 变量 | 必填 | 说明 |
|---|---|---|
SH_QQMUSIC_KEY |
✅ | 多账号:青龙同名 env 加多条(注入自动 & 连接)。单条格式 <uin>#<qm_keyst>,如 123456789#Q_H_L_xxxx。也接受整串 cookie(含 qm_keyst= 与 uin=o...) |
QM_KEY / QM_UIN |
备选 | 单账号兼容形态(SH_QQMUSIC_KEY 优先) |
QM_CACHE_DIR |
可选 | key 缓存目录,默认 /ql/data/qqmusic_cache(青龙)/ qqmusic/.cache(本地) |
QM_PLAY_REPORT |
可选 | on 才启用任务20播放上报(本版未实现模板,挂了开关占位) |
凭证获取(web 抓一次,之后无限续)
- 浏览器打开 y.qq.com 登录(QQ/微信均可)
- F12 → Application → Cookies →
https://y.qq.com→ 复制qm_keyst与uin(o123456789去掉o) - 青龙新建环境变量
SH_QQMUSIC_KEY,值uin#qm_keyst
为什么抓一次就够:签名/g_tk 全是本地算法(无盐、无设备绑定、无动态 token);
qm_keyst 名义 72h,但续期接口 QQConnectLogin.LoginServer.QQLogin 旧 key 不吊销——
脚本每次运行先续期,新 key 写缓存滚动,环境变量永远不用再动。
只有脚本断跑超 72h 且缓存丢失(推送出现 🔴 2000)才需要重新抓。
缓存与订阅安全
续期产物存 /ql/data/qqmusic_cache/qm_<uin>.json(订阅仓库之外)。
git 的 reset/clean 只动 tracked 文件,untracked 目录在 git pull 下天然安全;
且脚本读缓存优先、env 兜底,缓存丢失仅退化为"72h 内重新抓一次"。
定时
cron: 1 0,6 * * *
每天 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 注解独占一行
任务覆盖
| 层 | 内容 | 风险 |
|---|---|---|
| 任务中心 | 签到(15) / 挂件(5) / 装扮(5) / 听书(5) / 节目StartTask | 低(等价 App 点击) |
| 会员福利站 | 每日签到(15) / 礼券(+10心愿值) / 旅程激励 / 月里程碑 / 月度好礼 / 臻享抽奖 | 低(先探后做,无硬编码 ID) |
| 播放上报 | 任务20 完整 +10 需 App 正常收听(伪造统计默认关) | 中(默认关闭) |
| 支付流水任务 | 4/5/6/12/14/18/21 | 不可伪造,不碰 |
状态三态机:Y=已完成零请求(防风控)/ W=进行中直接领 / N=执行动作。
错误码处置:20020 冷却3s重领 · 30005 只读探测后补领 · 10006 写锁即停次日恢复 · 2000 登录态失效推送提示。
本地测试
node --check scrip_qqmusic_checkin.js # 语法
node scrip_qqmusic_checkin.js # 无 env 时优雅跳过
SH_QQMUSIC_KEY='123#Q_H_L_x' node -e "console.log(require('./scrip_qqmusic_checkin').parseAccounts())"