From 7388cf8eb5da86887a371d583e7dc40756b62ba2 Mon Sep 17 00:00:00 2001 From: Hermes Agent Date: Sat, 23 May 2026 13:22:26 +0800 Subject: [PATCH] fix: detect fake imtype for qdreader cron --- docs/autman-plugin-rules.md | 2 +- js/qdreader_sign_autman.js | 17 +++++++++---- plugins/qdreader/qdreader_sign_autman.js | 17 +++++++++---- tests/qdreader_plugin.test.mjs | 32 +++++++++++++----------- 4 files changed, 42 insertions(+), 26 deletions(-) diff --git a/docs/autman-plugin-rules.md b/docs/autman-plugin-rules.md index 278418f..09562c5 100644 --- a/docs/autman-plugin-rules.md +++ b/docs/autman-plugin-rules.md @@ -103,7 +103,7 @@ Python 示例: - `rule` 支持正则,可写多行表示多个触发规则。 - `cron` 支持 5 位或 6 位 cron 表达式。 -- 定时入口必须按运行环境判断,而不是只靠“消息内容为空”。推荐先检测 `ImType()` / `GetImType()` 是否为 `cron`,命中后直接走定时分支;不要在主入口用 `input()` 兜底读取命令内容。`input()` 是交互等待函数,定时场景可能返回 `q`、阻塞或把空触发误判成普通命令,导致 cron 已触发但业务没跑。参考茅台插件模式:`ImType() === "cron" ? "fake" : ImType()` 后显式进入 `cronTask()`。 +- 定时入口必须按运行环境判断,而不是只靠“消息内容为空”。推荐先检测 `ImType()` / `GetImType()` 是否为 `cron` / `task` / `fake`,命中后直接走定时分支;BOSS 实测 Autman cron 触发时日志上下文为 `content: ""` 且 `ImType/GetImType: "fake"`。不要在主入口用 `input()` 兜底读取命令内容。`input()` 是交互等待函数,定时场景可能返回 `q`、阻塞或把空触发误判成普通命令,导致 cron 已触发但业务没跑。参考茅台插件模式:`ImType() === "cron" ? "fake" : ImType()` 后显式进入 `cronTask()`。 - cron 头注兼容性优先使用带空格格式 `// [cron: 1 7 * * *]`,避免不同 Autman 解析器只识别一种注释风格。 - `admin: true` 表示仅管理员可执行。 - `priority` 数字越大优先级越高。 diff --git a/js/qdreader_sign_autman.js b/js/qdreader_sign_autman.js index c887558..9d0e993 100644 --- a/js/qdreader_sign_autman.js +++ b/js/qdreader_sign_autman.js @@ -4,7 +4,7 @@ //[author: Hermes] //[service: BOSS] //[class: 工具类] -// [version: 2.15.1] +// [version: 2.15.2] // [platform: web,qq,wx,tg,tb,fs,we] // [public: false] // [price: 0] @@ -264,12 +264,19 @@ function maskUid(uid) { return uid.slice(0, 2) + "***" + uid.slice(-2) } -function contentText() { - var s = "" +function runtimeImType() { var im = "" try { if (typeof ImType === "function") im = ImType() || "" } catch (e) {} try { if (!im && typeof GetImType === "function") im = GetImType() || "" } catch (e2) {} - if (lower(trim(im)) === "cron") return "" + return lower(trim(im)) +} +function isSchedulerImType(im) { + im = lower(trim(im)) + return im === "cron" || im === "task" || im === "fake" +} +function contentText() { + var s = "" + if (isSchedulerImType(runtimeImType())) return "" try { if (typeof getContent === "function") s = getContent() || "" } catch (e3) {} try { if (!s && typeof GetContent === "function") s = GetContent() || "" } catch (e4) {} try { if (!s && typeof sender !== "undefined" && sender && sender.getContent) s = sender.getContent() || "" } catch (e5) {} @@ -279,7 +286,7 @@ function contentText() { } function usage() { return [ - "启点读书签到插件 v2.15.1", + "启点读书签到插件 v2.15.2", "【一级菜单】", "账号管理:启点账号", "执行查询:启点查询", diff --git a/plugins/qdreader/qdreader_sign_autman.js b/plugins/qdreader/qdreader_sign_autman.js index c887558..9d0e993 100644 --- a/plugins/qdreader/qdreader_sign_autman.js +++ b/plugins/qdreader/qdreader_sign_autman.js @@ -4,7 +4,7 @@ //[author: Hermes] //[service: BOSS] //[class: 工具类] -// [version: 2.15.1] +// [version: 2.15.2] // [platform: web,qq,wx,tg,tb,fs,we] // [public: false] // [price: 0] @@ -264,12 +264,19 @@ function maskUid(uid) { return uid.slice(0, 2) + "***" + uid.slice(-2) } -function contentText() { - var s = "" +function runtimeImType() { var im = "" try { if (typeof ImType === "function") im = ImType() || "" } catch (e) {} try { if (!im && typeof GetImType === "function") im = GetImType() || "" } catch (e2) {} - if (lower(trim(im)) === "cron") return "" + return lower(trim(im)) +} +function isSchedulerImType(im) { + im = lower(trim(im)) + return im === "cron" || im === "task" || im === "fake" +} +function contentText() { + var s = "" + if (isSchedulerImType(runtimeImType())) return "" try { if (typeof getContent === "function") s = getContent() || "" } catch (e3) {} try { if (!s && typeof GetContent === "function") s = GetContent() || "" } catch (e4) {} try { if (!s && typeof sender !== "undefined" && sender && sender.getContent) s = sender.getContent() || "" } catch (e5) {} @@ -279,7 +286,7 @@ function contentText() { } function usage() { return [ - "启点读书签到插件 v2.15.1", + "启点读书签到插件 v2.15.2", "【一级菜单】", "账号管理:启点账号", "执行查询:启点查询", diff --git a/tests/qdreader_plugin.test.mjs b/tests/qdreader_plugin.test.mjs index 9891bb1..ff8a1b4 100644 --- a/tests/qdreader_plugin.test.mjs +++ b/tests/qdreader_plugin.test.mjs @@ -752,25 +752,27 @@ test('manual sign replies per account first and summary separately for multi-acc assert.match(r.replies[2], /日志已归档/); }); -test('cron detection uses ImType cron and does not consume input as command text', () => { +test('cron detection uses ImType cron/fake and does not consume input as command text', () => { const store = { qdreader_cookie_json: JSON.stringify({ '12345': cookie }), qdreader_user_bind_json: JSON.stringify({ '12345': 'user-a' }), }; - const r = runPlugin({ - content: '', - store, - userId: 'cron', - globals: { - ImType: () => 'cron', - input: () => 'q', - Date: fixedDateClass('2026-05-19T07:01:00.000+08:00'), - }, - }); - assert.equal(r.calls.length, 4); - assert.equal(r.replies.length, 1); - assert.match(r.replies[0], /汇总:成功 1 \/ 失败 0 \/ 总计 1/); - assert.match(r.replies[0], /定时任务\/零点任务/); + for (const imType of ['cron', 'fake']) { + const r = runPlugin({ + content: imType === 'fake' ? 'q' : '', + store: { ...store }, + userId: 'cron', + globals: { + ImType: () => imType, + input: () => 'q', + Date: fixedDateClass('2026-05-19T07:01:00.000+08:00'), + }, + }); + assert.equal(r.calls.length, 4, imType); + assert.equal(r.replies.length, 1, imType); + assert.match(r.replies[0], /汇总:成功 1 \/ 失败 0 \/ 总计 1/, imType); + assert.match(r.replies[0], /定时任务\/零点任务/, imType); + } }); test('manual sign only runs current user accounts while cron runs all accounts', () => {