diff --git a/js/qdreader_sign_autman.js b/js/qdreader_sign_autman.js index cb2724f..5fa926f 100644 --- a/js/qdreader_sign_autman.js +++ b/js/qdreader_sign_autman.js @@ -4,12 +4,12 @@ //[author: Hermes] //[service: BOSS] //[class: 工具类] -//[version: 2.10.9] +//[version: 2.11.0] //[platform: web,qq,wx,tg,tb,fs,we] //[public: false] //[price: 0] //[disable: false] -//[description: 启点读书(QDReader) Autman 签到插件:保存 QX 抓到的 H5 Cookie,支持手动“启点签到”;定时使用 `1 7 * * *` 每日 07:01 签到;每次签到运行结束后立即归档并清空最近运行日志,不再依赖单独归档定时;带独立 bucket、多用户隔离、请求重试、签名响应解析、结果摘要和安全脱敏。] +//[description: 启点读书(QDReader) Autman 签到插件:保存 QX 抓到的 H5 Cookie,支持手动“启点签到”;定时使用 `1 7 * * *` 每日 07:01 签到;完全体可选任务按上游原项目解密流程执行;每次签到运行结束后立即归档并清空最近运行日志,不再依赖单独归档定时;带独立 bucket、多用户隔离、请求重试、签名响应解析、结果摘要和安全脱敏。] //[rule: ^启点(账号|查询|ck|CK|cookie|Cookie|签到|读书|归档|日志归档)(.*)$] //[rule: ^qdreader(.*)$] //[admin: true] @@ -276,7 +276,7 @@ function contentText() { } function usage() { return [ - "启点读书签到插件 v2.10.9", + "启点读书签到插件 v2.11.0", "【一级菜单】", "账号管理:启点账号", "执行查询:启点查询", @@ -640,63 +640,65 @@ function doReceiveGifts(cookie) { } function doAdvTask(cookie) { var main = qdGet("/argus/api/v2/video/adv/mainPage", {}, cookie) - if (!taskResultOk(main)) return { name: "激励任务", ok: false, msg: resultMsg(main) || "获取任务失败", path: "/argus/api/v2/video/adv/mainPage" } - var tasks = firstArray(nested(main, ["Data", "VideoRewardTab", "TaskList"]), nested(main, ["data", "VideoRewardTab", "TaskList"]), nested(main, ["Data", "TaskList"]), nested(main, ["data", "TaskList"])) - if (!tasks.length) return { name: "激励任务", ok: false, msg: "未找到任务列表", path: "/argus/api/v2/video/adv/mainPage" } - if (taskFinished(tasks[tasks.length - 1])) return { name: "激励任务", ok: true, msg: "已完成", path: "/argus/api/v2/video/adv/mainPage" } + if (!taskResultOk(main)) return { name: "激励任务", ok: false, msg: resultMsg(main) || "获取任务列表失败", path: "/argus/api/v2/video/adv/mainPage" } + var tasks = firstArray(nested(main, ["Data", "DailyBenefitModule", "TaskList"]), nested(main, ["data", "DailyBenefitModule", "TaskList"])) + if (!tasks.length) return { name: "激励任务", ok: false, msg: "任务列表为空", path: "/argus/api/v2/video/adv/mainPage" } + if (taskFinished(tasks[tasks.length - 1])) return { name: "激励任务", ok: true, msg: "任务已完成", path: "/argus/api/v2/video/adv/mainPage" } var submittedCount = 0 for (var i = 0; i < tasks.length; i++) { var t = tasks[i] || {} if (taskFinished(t)) continue var tid = taskIdOf(t) if (!tid) continue - var fr = finishVideoTask(t, cookie, 1) + var fr = finishVideoTask(tid, cookie, 1) submittedCount += fr.ok - if (fr.ok < fr.total) return { name: "激励任务", ok: false, msg: resultMsg(fr.last) || ("第 " + (i + 1) + " 个视频任务失败"), path: "/argus/api/v1/video/adv/finishWatch" } + if (fr.ok < fr.total) return { name: "激励任务", ok: false, msg: resultMsg(fr.last) || ("第 " + (i + 1) + " 个任务失败"), path: "/argus/api/v1/video/adv/finishWatch" } } var verify = qdGet("/argus/api/v2/video/adv/mainPage", {}, cookie) - var after = firstArray(nested(verify, ["Data", "VideoRewardTab", "TaskList"]), nested(verify, ["data", "VideoRewardTab", "TaskList"]), nested(verify, ["Data", "TaskList"]), nested(verify, ["data", "TaskList"])) - var finished = !!(after && after.length && taskFinished(after[after.length - 1])) - return { name: "激励任务", ok: finished, msg: finished ? "已完成" : (submittedCount ? "任务未完成" : "未找到可提交任务"), path: "/argus/api/v2/video/adv/mainPage" } + var after = firstArray(nested(verify, ["Data", "DailyBenefitModule", "TaskList"]), nested(verify, ["data", "DailyBenefitModule", "TaskList"])) + var finished = !!(after && after.length && after.every(function (t) { return taskFinished(t) })) + return { name: "激励任务", ok: finished, msg: finished ? "任务已完成" : (submittedCount ? "部分任务未完成" : "未找到可提交任务"), path: "/argus/api/v2/video/adv/mainPage" } +} +function taskReceived(task) { + return Number(field(task, ["IsReceived", "Received", "Status", "status"], 0)) === 1 } function doDailyTask(cookie) { - var list = qdGet("/argus/api/v3/checkin/packagelist", {}, cookie) - if (!taskResultOk(list)) return { name: "每日任务", ok: false, msg: resultMsg(list) || "获取任务列表失败", path: "/argus/api/v3/checkin/packagelist" } - var data = list.Data || list.data || {} - var pre = field(data, ["Task", "SurpriseTask", "CurrentTask"], null) + var main = qdGet("/argus/api/v2/video/adv/mainPage", {}, cookie) + if (!taskResultOk(main)) return { name: "每日任务", ok: false, msg: resultMsg(main) || "获取任务列表失败", path: "/argus/api/v2/video/adv/mainPage" } + var data = main.Data || main.data || {} var done = 0 + var pre = data.SurpriseBenefit if (pre && !taskFinished(pre) && taskIdOf(pre)) { - var pr = finishVideoTask(pre, cookie, 1) + var pr = finishVideoTask(taskIdOf(pre), cookie, 1) done += pr.ok if (pr.ok < pr.total) return { name: "每日任务", ok: false, msg: resultMsg(pr.last) || "惊喜福利任务失败", path: "/argus/api/v1/video/adv/finishWatch" } } - var tasks = firstArray(nested(list, ["Data", "PackageList", "TaskList"]), nested(list, ["data", "PackageList", "TaskList"]), nested(list, ["Data", "TaskList"]), nested(list, ["data", "TaskList"]), nested(list, ["Data", "PackageList"]), nested(list, ["data", "PackageList"])) + var tasks = firstArray(nested(main, ["Data", "VideoRewardTab", "TaskList"]), nested(main, ["data", "VideoRewardTab", "TaskList"])) + if (!tasks.length) return { name: "每日任务", ok: false, msg: "任务列表为空", path: "/argus/api/v2/video/adv/mainPage" } var oneAd = null var target = null for (var i = 0; i < tasks.length; i++) { - var n = taskTitle(tasks[i]) - if (!oneAd && /完成\s*1\s*个广告任务|1个广告|one.?ad/i.test(n)) oneAd = tasks[i] - if (!target && n === "每日任务") target = tasks[i] + var title = taskTitle(tasks[i]) + if (!oneAd && title === "完成1个广告任务得奖励") oneAd = tasks[i] + if (!target && title === "完成3个广告任务得奖励") target = tasks[i] } - if (!target) for (var k = 0; k < tasks.length; k++) { var n2 = taskTitle(tasks[k]); if (/每日|daily/i.test(n2)) { target = tasks[k]; break } } - if (oneAd && oneAd !== target && !taskFinished(oneAd) && taskIdOf(oneAd)) { - var ar = finishVideoTask(oneAd, cookie, 1) + if (oneAd && !taskReceived(oneAd) && taskIdOf(oneAd)) { + var ar = finishVideoTask(taskIdOf(oneAd), cookie, 1) done += ar.ok if (ar.ok < ar.total) return { name: "每日任务", ok: false, msg: resultMsg(ar.last) || "完成1个广告任务失败", path: "/argus/api/v1/video/adv/finishWatch" } } - if (!target) return { name: "每日任务", ok: true, msg: done ? ("完成 " + done + " 次") : "无每日任务", path: "/argus/api/v3/checkin/packagelist" } - if (taskFinished(target)) return { name: "每日任务", ok: true, msg: "已完成", path: "/argus/api/v3/checkin/packagelist" } + if (!target) return { name: "每日任务", ok: false, msg: "未找到每日任务任务", path: "/argus/api/v2/video/adv/mainPage" } + if (taskReceived(target)) return { name: "每日任务", ok: true, msg: "任务已完成", path: "/argus/api/v2/video/adv/mainPage" } var tid = taskIdOf(target) - if (!tid) return { name: "每日任务", ok: true, msg: done ? ("完成 " + done + " 次") : "无每日任务", path: "/argus/api/v3/checkin/packagelist" } - var tr = finishVideoTask(target, cookie, taskRunCount(target, 3)) + if (!tid) return { name: "每日任务", ok: false, msg: "每日任务缺少 TaskId", path: "/argus/api/v2/video/adv/mainPage" } + var tr = finishVideoTask(tid, cookie, 3) done += tr.ok if (tr.ok < tr.total) return { name: "每日任务", ok: false, msg: resultMsg(tr.last) || "每日任务广告失败", path: "/argus/api/v1/video/adv/finishWatch" } var verify = qdGet("/argus/api/v2/video/adv/mainPage", {}, cookie) - var after = firstArray(nested(verify, ["Data", "VideoRewardTab", "TaskList"]), nested(verify, ["data", "VideoRewardTab", "TaskList"]), nested(verify, ["Data", "TaskList"]), nested(verify, ["data", "TaskList"])) + var after = firstArray(nested(verify, ["Data", "VideoRewardTab", "TaskList"]), nested(verify, ["data", "VideoRewardTab", "TaskList"])) var finished = false - for (var v = 0; v < after.length; v++) if (taskIdKey(taskIdOf(after[v])) === taskIdKey(tid) && taskFinished(after[v])) { finished = true; break } - if (!finished) for (var x = 0; x < after.length; x++) if (taskTitle(after[x]) === "每日任务" && taskFinished(after[x])) { finished = true; break } - return { name: "每日任务", ok: finished || done > 0, msg: finished ? "已完成" : (done > 0 ? ("完成 " + done + " 次") : "任务未完成"), path: "/argus/api/v3/checkin/packagelist" } + for (var v = 0; v < after.length; v++) if (taskTitle(after[v]) === "完成3个广告任务得奖励" && taskReceived(after[v])) { finished = true; break } + return { name: "每日任务", ok: finished, msg: finished ? "任务已完成" : "任务未完成", path: "/argus/api/v2/video/adv/mainPage" } } function doLotteryTask(cookie) { var detail = qdGet("/argus/api/v2/checkin/detail", {}, cookie) diff --git a/plugins/qdreader/qdreader_sign_autman.js b/plugins/qdreader/qdreader_sign_autman.js index cb2724f..5fa926f 100644 --- a/plugins/qdreader/qdreader_sign_autman.js +++ b/plugins/qdreader/qdreader_sign_autman.js @@ -4,12 +4,12 @@ //[author: Hermes] //[service: BOSS] //[class: 工具类] -//[version: 2.10.9] +//[version: 2.11.0] //[platform: web,qq,wx,tg,tb,fs,we] //[public: false] //[price: 0] //[disable: false] -//[description: 启点读书(QDReader) Autman 签到插件:保存 QX 抓到的 H5 Cookie,支持手动“启点签到”;定时使用 `1 7 * * *` 每日 07:01 签到;每次签到运行结束后立即归档并清空最近运行日志,不再依赖单独归档定时;带独立 bucket、多用户隔离、请求重试、签名响应解析、结果摘要和安全脱敏。] +//[description: 启点读书(QDReader) Autman 签到插件:保存 QX 抓到的 H5 Cookie,支持手动“启点签到”;定时使用 `1 7 * * *` 每日 07:01 签到;完全体可选任务按上游原项目解密流程执行;每次签到运行结束后立即归档并清空最近运行日志,不再依赖单独归档定时;带独立 bucket、多用户隔离、请求重试、签名响应解析、结果摘要和安全脱敏。] //[rule: ^启点(账号|查询|ck|CK|cookie|Cookie|签到|读书|归档|日志归档)(.*)$] //[rule: ^qdreader(.*)$] //[admin: true] @@ -276,7 +276,7 @@ function contentText() { } function usage() { return [ - "启点读书签到插件 v2.10.9", + "启点读书签到插件 v2.11.0", "【一级菜单】", "账号管理:启点账号", "执行查询:启点查询", @@ -640,63 +640,65 @@ function doReceiveGifts(cookie) { } function doAdvTask(cookie) { var main = qdGet("/argus/api/v2/video/adv/mainPage", {}, cookie) - if (!taskResultOk(main)) return { name: "激励任务", ok: false, msg: resultMsg(main) || "获取任务失败", path: "/argus/api/v2/video/adv/mainPage" } - var tasks = firstArray(nested(main, ["Data", "VideoRewardTab", "TaskList"]), nested(main, ["data", "VideoRewardTab", "TaskList"]), nested(main, ["Data", "TaskList"]), nested(main, ["data", "TaskList"])) - if (!tasks.length) return { name: "激励任务", ok: false, msg: "未找到任务列表", path: "/argus/api/v2/video/adv/mainPage" } - if (taskFinished(tasks[tasks.length - 1])) return { name: "激励任务", ok: true, msg: "已完成", path: "/argus/api/v2/video/adv/mainPage" } + if (!taskResultOk(main)) return { name: "激励任务", ok: false, msg: resultMsg(main) || "获取任务列表失败", path: "/argus/api/v2/video/adv/mainPage" } + var tasks = firstArray(nested(main, ["Data", "DailyBenefitModule", "TaskList"]), nested(main, ["data", "DailyBenefitModule", "TaskList"])) + if (!tasks.length) return { name: "激励任务", ok: false, msg: "任务列表为空", path: "/argus/api/v2/video/adv/mainPage" } + if (taskFinished(tasks[tasks.length - 1])) return { name: "激励任务", ok: true, msg: "任务已完成", path: "/argus/api/v2/video/adv/mainPage" } var submittedCount = 0 for (var i = 0; i < tasks.length; i++) { var t = tasks[i] || {} if (taskFinished(t)) continue var tid = taskIdOf(t) if (!tid) continue - var fr = finishVideoTask(t, cookie, 1) + var fr = finishVideoTask(tid, cookie, 1) submittedCount += fr.ok - if (fr.ok < fr.total) return { name: "激励任务", ok: false, msg: resultMsg(fr.last) || ("第 " + (i + 1) + " 个视频任务失败"), path: "/argus/api/v1/video/adv/finishWatch" } + if (fr.ok < fr.total) return { name: "激励任务", ok: false, msg: resultMsg(fr.last) || ("第 " + (i + 1) + " 个任务失败"), path: "/argus/api/v1/video/adv/finishWatch" } } var verify = qdGet("/argus/api/v2/video/adv/mainPage", {}, cookie) - var after = firstArray(nested(verify, ["Data", "VideoRewardTab", "TaskList"]), nested(verify, ["data", "VideoRewardTab", "TaskList"]), nested(verify, ["Data", "TaskList"]), nested(verify, ["data", "TaskList"])) - var finished = !!(after && after.length && taskFinished(after[after.length - 1])) - return { name: "激励任务", ok: finished, msg: finished ? "已完成" : (submittedCount ? "任务未完成" : "未找到可提交任务"), path: "/argus/api/v2/video/adv/mainPage" } + var after = firstArray(nested(verify, ["Data", "DailyBenefitModule", "TaskList"]), nested(verify, ["data", "DailyBenefitModule", "TaskList"])) + var finished = !!(after && after.length && after.every(function (t) { return taskFinished(t) })) + return { name: "激励任务", ok: finished, msg: finished ? "任务已完成" : (submittedCount ? "部分任务未完成" : "未找到可提交任务"), path: "/argus/api/v2/video/adv/mainPage" } +} +function taskReceived(task) { + return Number(field(task, ["IsReceived", "Received", "Status", "status"], 0)) === 1 } function doDailyTask(cookie) { - var list = qdGet("/argus/api/v3/checkin/packagelist", {}, cookie) - if (!taskResultOk(list)) return { name: "每日任务", ok: false, msg: resultMsg(list) || "获取任务列表失败", path: "/argus/api/v3/checkin/packagelist" } - var data = list.Data || list.data || {} - var pre = field(data, ["Task", "SurpriseTask", "CurrentTask"], null) + var main = qdGet("/argus/api/v2/video/adv/mainPage", {}, cookie) + if (!taskResultOk(main)) return { name: "每日任务", ok: false, msg: resultMsg(main) || "获取任务列表失败", path: "/argus/api/v2/video/adv/mainPage" } + var data = main.Data || main.data || {} var done = 0 + var pre = data.SurpriseBenefit if (pre && !taskFinished(pre) && taskIdOf(pre)) { - var pr = finishVideoTask(pre, cookie, 1) + var pr = finishVideoTask(taskIdOf(pre), cookie, 1) done += pr.ok if (pr.ok < pr.total) return { name: "每日任务", ok: false, msg: resultMsg(pr.last) || "惊喜福利任务失败", path: "/argus/api/v1/video/adv/finishWatch" } } - var tasks = firstArray(nested(list, ["Data", "PackageList", "TaskList"]), nested(list, ["data", "PackageList", "TaskList"]), nested(list, ["Data", "TaskList"]), nested(list, ["data", "TaskList"]), nested(list, ["Data", "PackageList"]), nested(list, ["data", "PackageList"])) + var tasks = firstArray(nested(main, ["Data", "VideoRewardTab", "TaskList"]), nested(main, ["data", "VideoRewardTab", "TaskList"])) + if (!tasks.length) return { name: "每日任务", ok: false, msg: "任务列表为空", path: "/argus/api/v2/video/adv/mainPage" } var oneAd = null var target = null for (var i = 0; i < tasks.length; i++) { - var n = taskTitle(tasks[i]) - if (!oneAd && /完成\s*1\s*个广告任务|1个广告|one.?ad/i.test(n)) oneAd = tasks[i] - if (!target && n === "每日任务") target = tasks[i] + var title = taskTitle(tasks[i]) + if (!oneAd && title === "完成1个广告任务得奖励") oneAd = tasks[i] + if (!target && title === "完成3个广告任务得奖励") target = tasks[i] } - if (!target) for (var k = 0; k < tasks.length; k++) { var n2 = taskTitle(tasks[k]); if (/每日|daily/i.test(n2)) { target = tasks[k]; break } } - if (oneAd && oneAd !== target && !taskFinished(oneAd) && taskIdOf(oneAd)) { - var ar = finishVideoTask(oneAd, cookie, 1) + if (oneAd && !taskReceived(oneAd) && taskIdOf(oneAd)) { + var ar = finishVideoTask(taskIdOf(oneAd), cookie, 1) done += ar.ok if (ar.ok < ar.total) return { name: "每日任务", ok: false, msg: resultMsg(ar.last) || "完成1个广告任务失败", path: "/argus/api/v1/video/adv/finishWatch" } } - if (!target) return { name: "每日任务", ok: true, msg: done ? ("完成 " + done + " 次") : "无每日任务", path: "/argus/api/v3/checkin/packagelist" } - if (taskFinished(target)) return { name: "每日任务", ok: true, msg: "已完成", path: "/argus/api/v3/checkin/packagelist" } + if (!target) return { name: "每日任务", ok: false, msg: "未找到每日任务任务", path: "/argus/api/v2/video/adv/mainPage" } + if (taskReceived(target)) return { name: "每日任务", ok: true, msg: "任务已完成", path: "/argus/api/v2/video/adv/mainPage" } var tid = taskIdOf(target) - if (!tid) return { name: "每日任务", ok: true, msg: done ? ("完成 " + done + " 次") : "无每日任务", path: "/argus/api/v3/checkin/packagelist" } - var tr = finishVideoTask(target, cookie, taskRunCount(target, 3)) + if (!tid) return { name: "每日任务", ok: false, msg: "每日任务缺少 TaskId", path: "/argus/api/v2/video/adv/mainPage" } + var tr = finishVideoTask(tid, cookie, 3) done += tr.ok if (tr.ok < tr.total) return { name: "每日任务", ok: false, msg: resultMsg(tr.last) || "每日任务广告失败", path: "/argus/api/v1/video/adv/finishWatch" } var verify = qdGet("/argus/api/v2/video/adv/mainPage", {}, cookie) - var after = firstArray(nested(verify, ["Data", "VideoRewardTab", "TaskList"]), nested(verify, ["data", "VideoRewardTab", "TaskList"]), nested(verify, ["Data", "TaskList"]), nested(verify, ["data", "TaskList"])) + var after = firstArray(nested(verify, ["Data", "VideoRewardTab", "TaskList"]), nested(verify, ["data", "VideoRewardTab", "TaskList"])) var finished = false - for (var v = 0; v < after.length; v++) if (taskIdKey(taskIdOf(after[v])) === taskIdKey(tid) && taskFinished(after[v])) { finished = true; break } - if (!finished) for (var x = 0; x < after.length; x++) if (taskTitle(after[x]) === "每日任务" && taskFinished(after[x])) { finished = true; break } - return { name: "每日任务", ok: finished || done > 0, msg: finished ? "已完成" : (done > 0 ? ("完成 " + done + " 次") : "任务未完成"), path: "/argus/api/v3/checkin/packagelist" } + for (var v = 0; v < after.length; v++) if (taskTitle(after[v]) === "完成3个广告任务得奖励" && taskReceived(after[v])) { finished = true; break } + return { name: "每日任务", ok: finished, msg: finished ? "任务已完成" : "任务未完成", path: "/argus/api/v2/video/adv/mainPage" } } function doLotteryTask(cookie) { var detail = qdGet("/argus/api/v2/checkin/detail", {}, cookie) diff --git a/tests/qdreader_plugin.test.mjs b/tests/qdreader_plugin.test.mjs index 21fe1bc..ad2db1a 100644 --- a/tests/qdreader_plugin.test.mjs +++ b/tests/qdreader_plugin.test.mjs @@ -88,7 +88,7 @@ test('README documents QDReader task schedule windows and required endpoints', ( 'receivegifts', 'mainPage', 'finishWatch', - 'packagelist', + 'mainPage', 'lottery', 'checkinexchangepage', 'exchangegoods', @@ -397,7 +397,6 @@ test('optional QDReader full tasks use upstream executable endpoints and sign ab qdreader_user_bind_json: JSON.stringify({ '12345': 'user-a' }), qdreader_task_pref_json: JSON.stringify({ '12345': { adv: true, extraAdv: true, lottery: true, weeklyExchange: true, chapterCard: true, messageBox: true } }), }; - const originalDate = Date; const sunday = fixedDateClass('2026-05-24T20:01:00.000+08:00'); const r = runPlugin({ content: '启点签到', @@ -410,13 +409,25 @@ test('optional QDReader full tasks use upstream executable endpoints and sign ab (req) => String(req.url).includes('/sign') ? { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } } : { statusCode: 200, body: { code: 0, msg: 'ok' } }, { statusCode: 200, body: { code: 0, msg: '奖励完成' } }, (req) => String(req.url).includes('/sign') ? { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } } : { statusCode: 200, body: { code: 0, msg: 'ok' } }, - { statusCode: 200, body: { code: 0, Data: { VideoRewardTab: { TaskList: [{ TaskId: 'adv-1', IsFinished: 0 }] } } } }, + { statusCode: 200, body: { code: 0, Data: { DailyBenefitModule: { TaskList: [{ TaskId: 'adv-1', Title: '激励碎片', IsFinished: 0 }] } } } }, (req) => String(req.url).includes('/sign') ? { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } } : { statusCode: 200, body: { code: 0, msg: 'ok' } }, { statusCode: 200, body: { code: 0, msg: '视频完成' } }, (req) => String(req.url).includes('/sign') ? { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } } : { statusCode: 200, body: { code: 0, msg: 'ok' } }, - { statusCode: 200, body: { code: 0, Data: { VideoRewardTab: { TaskList: [{ TaskId: 'adv-1', IsFinished: 1 }] } } } }, + { statusCode: 200, body: { code: 0, Data: { DailyBenefitModule: { TaskList: [{ TaskId: 'adv-1', Title: '激励碎片', IsFinished: 1 }] } } } }, (req) => String(req.url).includes('/sign') ? { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } } : { statusCode: 200, body: { code: 0, msg: 'ok' } }, - { statusCode: 200, body: { code: 0, Data: { TaskList: [{ TaskId: 'daily-1', TaskName: '每日任务', IsFinished: 1, NeedWatchCount: 1 }] } } }, + { statusCode: 200, body: { code: 0, Data: { SurpriseBenefit: { TaskId: 'surprise-1', IsFinished: 0 }, VideoRewardTab: { TaskList: [{ TaskId: 'one-ad', Title: '完成1个广告任务得奖励', IsReceived: 0 }, { TaskId: 'daily-3', Title: '完成3个广告任务得奖励', IsReceived: 0 }] } } } }, + (req) => String(req.url).includes('/sign') ? { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } } : { statusCode: 200, body: { code: 0, msg: 'ok' } }, + { statusCode: 200, body: { code: 0, msg: '惊喜福利完成' } }, + (req) => String(req.url).includes('/sign') ? { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } } : { statusCode: 200, body: { code: 0, msg: 'ok' } }, + { statusCode: 200, body: { code: 0, msg: '一个广告完成' } }, + (req) => String(req.url).includes('/sign') ? { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } } : { statusCode: 200, body: { code: 0, msg: 'ok' } }, + { statusCode: 200, body: { code: 0, msg: '每日广告1完成' } }, + (req) => String(req.url).includes('/sign') ? { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } } : { statusCode: 200, body: { code: 0, msg: 'ok' } }, + { statusCode: 200, body: { code: 0, msg: '每日广告2完成' } }, + (req) => String(req.url).includes('/sign') ? { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } } : { statusCode: 200, body: { code: 0, msg: 'ok' } }, + { statusCode: 200, body: { code: 0, msg: '每日广告3完成' } }, + (req) => String(req.url).includes('/sign') ? { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } } : { statusCode: 200, body: { code: 0, msg: 'ok' } }, + { statusCode: 200, body: { code: 0, Data: { VideoRewardTab: { TaskList: [{ TaskId: 'daily-3', Title: '完成3个广告任务得奖励', IsReceived: 1 }] } } } }, (req) => String(req.url).includes('/sign') ? { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } } : { statusCode: 200, body: { code: 0, msg: 'ok' } }, { statusCode: 200, body: { code: 0, Data: { HasVideoUrge: 0, LotteryCount: 1 } } }, (req) => String(req.url).includes('/sign') ? { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } } : { statusCode: 200, body: { code: 0, msg: 'ok' } }, @@ -435,7 +446,7 @@ test('optional QDReader full tasks use upstream executable endpoints and sign ab assert.ok(urls.some(u => /argus\/api\/v3\/checkin\/receivegifts$/.test(u))); assert.ok(urls.some(u => /argus\/api\/v2\/video\/adv\/mainPage$/.test(u))); assert.ok(urls.some(u => /argus\/api\/v1\/video\/adv\/finishWatch$/.test(u))); - assert.ok(urls.some(u => /argus\/api\/v3\/checkin\/packagelist$/.test(u))); + assert.ok(!urls.some(u => /argus\/api\/v3\/checkin\/packagelist$/.test(u))); assert.ok(urls.some(u => /argus\/api\/v2\/checkin\/detail$/.test(u))); assert.ok(urls.some(u => /argus\/api\/v2\/checkin\/lottery$/.test(u))); assert.ok(urls.some(u => /argus\/api\/v3\/checkin\/checkinexchangepage$/.test(u))); @@ -444,6 +455,10 @@ test('optional QDReader full tasks use upstream executable endpoints and sign ab assert.ok(urls.some(u => /^https:\/\/magev6\.if\.qidian\.com\/argus\/api\/v2\/message\/pullmessage/.test(u))); const signed = r.calls.filter(c => /api\.120399\.xyz\/qdreader\/sign$/.test(c.url)).map(c => JSON.parse(c.body).url); assert.ok(signed.includes('https://magev6.if.qidian.com/argus/api/v2/message/pullmessage')); + + const finishCalls = r.calls.filter(c => /argus\/api\/v1\/video\/adv\/finishWatch$/.test(c.url)); + assert.equal(finishCalls.length, 6); + assert.deepEqual(finishCalls.map(c => new URLSearchParams(c.body).get('taskId')), ['adv-1', 'surprise-1', 'one-ad', 'daily-3', 'daily-3', 'daily-3']); assert.match(r.replies[0], /激励任务✅/); assert.match(r.replies[0], /每日任务✅/); assert.match(r.replies[0], /每日抽奖✅/); @@ -825,14 +840,14 @@ test('adv task treats upstream result 9 as accepted and verifies finished state' { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } }, { statusCode: 200, body: { code: 1, msg: '无可领取礼包' } }, { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } }, - { statusCode: 200, body: { code: 0, Data: { VideoRewardTab: { TaskList: [{ TaskId: 'old-done', Title: '已完成旧任务', IsFinished: 1 }, { TaskId: '1165585369246138372', Title: '看视频领福利', IsFinished: 0 }] } } } }, + { statusCode: 200, body: { code: 0, Data: { DailyBenefitModule: { TaskList: [{ TaskId: 'old-done', Title: '已完成旧任务', IsFinished: 1 }, { TaskId: '1165585369246138372', Title: '看视频领福利', IsFinished: 0 }] } } } }, { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } }, { statusCode: 200, body: { result: 9, message: '' } }, { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } }, - { statusCode: 200, body: { code: 0, Data: { VideoRewardTab: { TaskList: [{ TaskId: 'old-done', Title: '已完成旧任务', IsFinished: 1 }, { TaskId: '1165585369246138372', Title: '看视频领福利', IsFinished: 1 }] } } } }, + { statusCode: 200, body: { code: 0, Data: { DailyBenefitModule: { TaskList: [{ TaskId: 'old-done', Title: '已完成旧任务', IsFinished: 1 }, { TaskId: '1165585369246138372', Title: '看视频领福利', IsFinished: 1 }] } } } }, ], }); - assert.match(r.replies[0], /激励任务✅\(已完成\)/); + assert.match(r.replies[0], /激励任务✅\(任务已完成\)/); assert.match(r.replies[0], /汇总:成功 1 \/ 失败 0 \/ 总计 1/); assert.equal(r.calls.filter(c => /video\/adv\/finishWatch$/.test(c.url)).length, 1); assert.match(r.calls.find(c => /video\/adv\/finishWatch$/.test(c.url)).body, /1165585369246138372/); @@ -854,18 +869,18 @@ test('adv task does not report success when only unrelated task is finished afte { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } }, { statusCode: 200, body: { code: 1, msg: '无可领取礼包' } }, { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } }, - { statusCode: 200, body: { code: 0, Data: { VideoRewardTab: { TaskList: [{ TaskId: 'old-done', Title: '已完成旧任务', IsFinished: 1 }, { TaskId: '1165585369246138372', Title: '看视频领福利', IsFinished: 0 }] } } } }, + { statusCode: 200, body: { code: 0, Data: { DailyBenefitModule: { TaskList: [{ TaskId: 'old-done', Title: '已完成旧任务', IsFinished: 1 }, { TaskId: '1165585369246138372', Title: '看视频领福利', IsFinished: 0 }] } } } }, { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } }, { statusCode: 200, body: { result: 9, message: '' } }, { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } }, - { statusCode: 200, body: { code: 0, Data: { VideoRewardTab: { TaskList: [{ TaskId: 'old-done', Title: '已完成旧任务', IsFinished: 1 }, { TaskId: '1165585369246138372', Title: '看视频领福利', IsFinished: 0 }] } } } }, + { statusCode: 200, body: { code: 0, Data: { DailyBenefitModule: { TaskList: [{ TaskId: 'old-done', Title: '已完成旧任务', IsFinished: 1 }, { TaskId: '1165585369246138372', Title: '看视频领福利', IsFinished: 0 }] } } } }, ], }); - assert.match(r.replies[0], /激励任务❌\(任务未完成\)/); + assert.match(r.replies[0], /激励任务❌\(部分任务未完成\)/); assert.match(r.replies[0], /汇总:成功 0 \/ 失败 1 \/ 总计 1/); }); -test('adv task follows upstream final-item completion instead of submitted-id inference', () => { +test('adv task requires every upstream DailyBenefitModule entry finished after callbacks', () => { const store = { qdreader_cookie_json: JSON.stringify({ '12345': cookie }), qdreader_user_bind_json: JSON.stringify({ '12345': 'user-a' }), @@ -881,7 +896,7 @@ test('adv task follows upstream final-item completion instead of submitted-id in { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } }, { statusCode: 200, body: { code: 1, msg: '无可领取礼包' } }, { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } }, - { statusCode: 200, body: { code: 0, Data: { VideoRewardTab: { TaskList: [ + { statusCode: 200, body: { code: 0, Data: { DailyBenefitModule: { TaskList: [ { TaskId: 'target-a', Title: '看视频领福利A', IsFinished: 0 }, { TaskId: 'target-b', Title: '看视频领福利B', IsFinished: 0 }, { TaskId: '1165585369246138370', Title: '每日签到', IsFinished: 0 }, @@ -893,15 +908,15 @@ test('adv task follows upstream final-item completion instead of submitted-id in { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } }, { statusCode: 200, body: { result: 9, message: '' } }, { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } }, - { statusCode: 200, body: { code: 0, Data: { VideoRewardTab: { TaskList: [ + { statusCode: 200, body: { code: 0, Data: { DailyBenefitModule: { TaskList: [ { TaskId: 'target-a', Title: '看视频领福利A', IsFinished: 0 }, { TaskId: 'target-b', Title: '看视频领福利B', IsFinished: 0 }, { TaskId: '1165585369246138370', Title: '每日签到', IsFinished: 1 }, ] } } } }, ], }); - assert.match(r.replies[0], /激励任务✅\(已完成\)/); - assert.match(r.replies[0], /汇总:成功 1 \/ 失败 0 \/ 总计 1/); + assert.match(r.replies[0], /激励任务❌\(部分任务未完成\)/); + assert.match(r.replies[0], /汇总:成功 0 \/ 失败 1 \/ 总计 1/); }); test('adv task iterates every unfinished upstream entry without local non-ad filtering', () => { @@ -920,20 +935,22 @@ test('adv task iterates every unfinished upstream entry without local non-ad fil { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } }, { statusCode: 200, body: { code: 1, msg: '无可领取礼包' } }, { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } }, - { statusCode: 200, body: { code: 0, Data: { VideoRewardTab: { TaskList: [ + { statusCode: 200, body: { code: 0, Data: { DailyBenefitModule: { TaskList: [ { TaskId: '1165585369246138372', Title: '看视频领福利', IsFinished: 0 }, { TaskId: '1165585369246138370', Title: '每日签到', IsFinished: 0 } ] } } } }, { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } }, { statusCode: 200, body: { result: 9, message: '' } }, { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } }, - { statusCode: 200, body: { code: 0, Data: { VideoRewardTab: { TaskList: [ + { statusCode: 200, body: { result: 9, message: '' } }, + { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } }, + { statusCode: 200, body: { code: 0, Data: { DailyBenefitModule: { TaskList: [ { TaskId: '1165585369246138372', Title: '看视频领福利', IsFinished: 1 }, - { TaskId: '1165585369246138370', Title: '每日签到', IsFinished: 0 } + { TaskId: '1165585369246138370', Title: '每日签到', IsFinished: 1 } ] } } } }, ], }); - assert.match(r.replies[0], /激励任务❌\(任务未完成\)/); + assert.match(r.replies[0], /激励任务✅\(任务已完成\)/); assert.equal(r.calls.filter(c => /video\/adv\/finishWatch$/.test(c.url)).length, 2); assert.ok(r.calls.some(c => /video\/adv\/finishWatch$/.test(c.url) && /1165585369246138370/.test(c.body))); }); @@ -954,14 +971,14 @@ test('adv task accepts nested data result 9 with empty message from sign gateway { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } }, { statusCode: 200, body: { code: 1, msg: '无可领取礼包' } }, { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } }, - { statusCode: 200, body: { code: 0, Data: { VideoRewardTab: { TaskList: [{ TaskId: '1165585369246138372', Title: '看视频领福利', IsFinished: 0 }] } } } }, + { statusCode: 200, body: { code: 0, Data: { DailyBenefitModule: { TaskList: [{ TaskId: '1165585369246138372', Title: '看视频领福利', IsFinished: 0 }] } } } }, { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } }, { statusCode: 200, body: { code: 200, data: { result: 9, message: '' } } }, { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } }, - { statusCode: 200, body: { code: 0, Data: { VideoRewardTab: { TaskList: [{ TaskId: '1165585369246138372', Title: '看视频领福利', IsFinished: 1 }] } } } }, + { statusCode: 200, body: { code: 0, Data: { DailyBenefitModule: { TaskList: [{ TaskId: '1165585369246138372', Title: '看视频领福利', IsFinished: 1 }] } } } }, ], }); - assert.match(r.replies[0], /激励任务✅\(已完成\)/); + assert.match(r.replies[0], /激励任务✅\(任务已完成\)/); assert.doesNotMatch(r.replies[0], /任务 1165585369246138372 失败/); }); @@ -984,11 +1001,11 @@ test('finishWatch payload matches upstream lowercase taskId and full captcha fie { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } }, { statusCode: 200, body: { code: 1, msg: '无可领取礼包' } }, { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } }, - { statusCode: 200, body: { code: 0, Data: { VideoRewardTab: { TaskList: [{ TaskId: '1187767793786748928', Title: '激励碎片', IsFinished: 0 }] } } } }, + { statusCode: 200, body: { code: 0, Data: { DailyBenefitModule: { TaskList: [{ TaskId: '1187767793786748928', Title: '激励碎片', IsFinished: 0 }] } } } }, { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } }, { statusCode: 200, body: { result: 9, message: '' } }, { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } }, - { statusCode: 200, body: { code: 0, Data: { VideoRewardTab: { TaskList: [{ TaskId: '1187767793786748928', Title: '激励碎片', IsFinished: 1 }] } } } }, + { statusCode: 200, body: { code: 0, Data: { DailyBenefitModule: { TaskList: [{ TaskId: '1187767793786748928', Title: '激励碎片', IsFinished: 1 }] } } } }, ], }); const finishCall = r.calls.find(c => /video\/adv\/finishWatch$/.test(c.url)); @@ -1013,20 +1030,20 @@ test('adv task submits each unfinished upstream list item once before verificati { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } }, { statusCode: 200, body: { code: 1, msg: '无可领取礼包' } }, { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } }, - { statusCode: 200, body: { code: 0, Data: { VideoRewardTab: { TaskList: [{ TaskId: '1187767793786748928', Title: '激励碎片', IsFinished: 0, NeedCount: 3 }] } } } }, + { statusCode: 200, body: { code: 0, Data: { DailyBenefitModule: { TaskList: [{ TaskId: '1187767793786748928', Title: '激励碎片', IsFinished: 0, NeedCount: 3 }] } } } }, { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } }, { statusCode: 200, body: { result: 9, message: '' } }, { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } }, - { statusCode: 200, body: { code: 0, Data: { VideoRewardTab: { TaskList: [{ TaskId: '1187767793786748928', Title: '激励碎片', IsFinished: 1, NeedCount: 3 }] } } } }, + { statusCode: 200, body: { code: 0, Data: { DailyBenefitModule: { TaskList: [{ TaskId: '1187767793786748928', Title: '激励碎片', IsFinished: 1, NeedCount: 3 }] } } } }, ], }); - assert.match(r.replies[0], /激励任务✅\(已完成\)/); + assert.match(r.replies[0], /激励任务✅\(任务已完成\)/); const finishCalls = r.calls.filter(c => /video\/adv\/finishWatch$/.test(c.url)); assert.equal(finishCalls.length, 1); assert.ok(finishCalls.every(c => /1187767793786748928/.test(c.body))); }); -test('adv task follows upstream completion when final list item is finished after callbacks', () => { +test('adv task follows upstream completion when every upstream list item is finished after callbacks', () => { const store = { qdreader_cookie_json: JSON.stringify({ '12345': cookie }), qdreader_user_bind_json: JSON.stringify({ '12345': 'user-a' }), @@ -1042,7 +1059,7 @@ test('adv task follows upstream completion when final list item is finished afte { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } }, { statusCode: 200, body: { code: 1, msg: '无可领取礼包' } }, { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } }, - { statusCode: 200, body: { code: 0, Data: { VideoRewardTab: { TaskList: [ + { statusCode: 200, body: { code: 0, Data: { DailyBenefitModule: { TaskList: [ { TaskId: 'target-a', Title: '看视频领福利A', IsFinished: 0 }, { TaskId: 'target-b', Title: '看视频领福利B', IsFinished: 0 }, { TaskId: '1165585369246138370', Title: '每日签到', IsFinished: 0 }, @@ -1054,14 +1071,14 @@ test('adv task follows upstream completion when final list item is finished afte { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } }, { statusCode: 200, body: { result: 9, message: '' } }, { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } }, - { statusCode: 200, body: { code: 0, Data: { VideoRewardTab: { TaskList: [ - { TaskId: 'target-a', Title: '看视频领福利A', IsFinished: 0 }, - { TaskId: 'target-b', Title: '看视频领福利B', IsFinished: 0 }, + { statusCode: 200, body: { code: 0, Data: { DailyBenefitModule: { TaskList: [ + { TaskId: 'target-a', Title: '看视频领福利A', IsFinished: 1 }, + { TaskId: 'target-b', Title: '看视频领福利B', IsFinished: 1 }, { TaskId: '1165585369246138370', Title: '每日签到', IsFinished: 1 }, ] } } } }, ], }); - assert.match(r.replies[0], /激励任务✅\(已完成\)/); + assert.match(r.replies[0], /激励任务✅\(任务已完成\)/); assert.match(r.replies[0], /汇总:成功 1 \/ 失败 0 \/ 总计 1/); assert.equal(r.calls.filter(c => /video\/adv\/finishWatch$/.test(c.url)).length, 3); }); @@ -1082,14 +1099,14 @@ test('adv task ignores count metadata and submits each unfinished upstream task { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } }, { statusCode: 200, body: { code: 1, msg: '无可领取礼包' } }, { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } }, - { statusCode: 200, body: { code: 0, Data: { VideoRewardTab: { TaskList: [{ TaskId: 'partial-task', Title: '看视频领福利', IsFinished: 0, Count: 1, NeedCount: 3 }] } } } }, + { statusCode: 200, body: { code: 0, Data: { DailyBenefitModule: { TaskList: [{ TaskId: 'partial-task', Title: '看视频领福利', IsFinished: 0, Count: 1, NeedCount: 3 }] } } } }, { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } }, { statusCode: 200, body: { result: 9, message: '' } }, { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } }, - { statusCode: 200, body: { code: 0, Data: { VideoRewardTab: { TaskList: [{ TaskId: 'partial-task', Title: '看视频领福利', IsFinished: 1, Count: 3, NeedCount: 3 }] } } } }, + { statusCode: 200, body: { code: 0, Data: { DailyBenefitModule: { TaskList: [{ TaskId: 'partial-task', Title: '看视频领福利', IsFinished: 1, Count: 3, NeedCount: 3 }] } } } }, ], }); - assert.match(r.replies[0], /激励任务✅\(已完成\)/); + assert.match(r.replies[0], /激励任务✅\(任务已完成\)/); const finishCalls = r.calls.filter(c => /video\/adv\/finishWatch$/.test(c.url)); assert.equal(finishCalls.length, 1); assert.ok(finishCalls.every(c => /partial-task/.test(c.body))); @@ -1112,10 +1129,10 @@ test('daily task follows upstream sequence: surprise task, one-ad task, then thr { statusCode: 200, body: { code: 1, msg: '无可领取礼包' } }, { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } }, { statusCode: 200, body: { code: 0, Data: { - CurrentTask: { TaskId: '1209756598013788162', Title: '惊喜福利任务', IsFinished: 0 }, - PackageList: { TaskList: [ - { TaskId: '1165585369246138373', Title: '完成1个广告任务', IsFinished: 0 }, - { TaskId: '1165585369246138372', Title: '每日任务', IsFinished: 0, NeedCount: 3 }, + SurpriseBenefit: { TaskId: '1209756598013788162', Title: '惊喜福利任务', IsFinished: 0 }, + VideoRewardTab: { TaskList: [ + { TaskId: '1165585369246138373', Title: '完成1个广告任务得奖励', IsReceived: 0 }, + { TaskId: '1165585369246138372', Title: '完成3个广告任务得奖励', IsReceived: 0 }, ] } } } }, { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } }, @@ -1130,12 +1147,12 @@ test('daily task follows upstream sequence: surprise task, one-ad task, then thr { statusCode: 200, body: { result: 9, message: '' } }, { body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } }, { statusCode: 200, body: { code: 0, Data: { VideoRewardTab: { TaskList: [ - { TaskId: '1165585369246138373', Title: '完成1个广告任务', IsFinished: 1 }, - { TaskId: '1165585369246138372', Title: '每日任务', IsFinished: 1, NeedCount: 3 }, + { TaskId: '1165585369246138373', Title: '完成1个广告任务得奖励', IsReceived: 1 }, + { TaskId: '1165585369246138372', Title: '完成3个广告任务得奖励', IsReceived: 1 }, ] } } } }, ], }); - assert.match(r.replies[0], /每日任务✅\(已完成\)/); + assert.match(r.replies[0], /每日任务✅\(任务已完成\)/); const bodies = r.calls.filter(c => /video\/adv\/finishWatch$/.test(c.url)).map(c => c.body); assert.equal(bodies.length, 5); assert.match(bodies[0], /1209756598013788162/); @@ -1234,3 +1251,4 @@ test('stream uid message token matches upstream operator precedence and avoids p assert.equal(JSON.parse(firstMessageSign.body).data.token, '24QAcr'); assert.notEqual(JSON.parse(firstMessageSign.body).data.token, '1903903219'); }); +