fix(qdreader): treat risk-conf as verification block

This commit is contained in:
2026-07-02 14:32:09 +08:00
parent 012c3a9cb1
commit 7ef173c6c7
3 changed files with 138 additions and 30 deletions
+39 -12
View File
@@ -4,7 +4,7 @@
//[author: Hermes] //[author: Hermes]
//[service: BOSS] //[service: BOSS]
//[class: 工具类] //[class: 工具类]
// [version: 2.15.6] // [version: 2.15.7]
// [platform: web,qq,wx,tg,tb,fs,we] // [platform: web,qq,wx,tg,tb,fs,we]
// [public: false] // [public: false]
// [price: 0] // [price: 0]
@@ -447,13 +447,27 @@ function resultOk(obj) {
if (String(status) === "401" || String(status) === "403") return false if (String(status) === "401" || String(status) === "403") return false
return code === undefined || code === 0 || code === "0" || code === 200 || code === "200" || status === "ok" || status === "success" return code === undefined || code === 0 || code === "0" || code === 200 || code === "200" || status === "ok" || status === "success"
} }
function isLoginExpiredMsg(msg) {
msg = String(msg || "")
return /登录状态已失效|登录已失效|登录状态.*过期|登录.*过期|用户未登录|未登录|请登录|重新登录|Cookie.*失效|CK.*失效|cookie.*expired|login.*expired|not\s*login/i.test(msg)
}
function resultMsg(obj) { function resultMsg(obj) {
obj = responseEnvelope(obj) obj = responseEnvelope(obj)
if (!obj) return "" if (!obj) return ""
var status = obj.status || obj.Status || obj.statusCode || obj.StatusCode var status = obj.status || obj.Status || obj.statusCode || obj.StatusCode
if (String(status) === "401") return "登录状态已失效,请更新 Cookie" if (String(status) === "401") return "登录状态已失效,请更新 Cookie"
if (String(status) === "403") return "接口鉴权失败,请更新 Cookie" if (String(status) === "403") return "接口鉴权失败,请更新 Cookie"
return obj.Message || obj.Msg || obj.message || obj.msg || obj.error || obj.toast || (obj.data && (obj.data.message || obj.data.msg || obj.data.error || obj.data.toast || obj.data.Message || obj.data.Msg)) || (obj.Data && (obj.Data.message || obj.Data.msg || obj.Data.error || obj.Data.toast || obj.Data.Message || obj.Data.Msg)) || "" var msg = obj.Message || obj.Msg || obj.message || obj.msg || obj.error || obj.toast || (obj.data && (obj.data.message || obj.data.msg || obj.data.error || obj.data.toast || obj.data.Message || obj.data.Msg)) || (obj.Data && (obj.Data.message || obj.Data.msg || obj.Data.error || obj.Data.toast || obj.Data.Message || obj.Data.Msg)) || ""
if (isLoginExpiredMsg(msg)) return "登录状态已失效,请更新 Cookie"
return msg
}
function isCookieExpiredResult(obj) {
var env = responseEnvelope(obj)
if (!env) return false
var status = env.status || env.Status || env.statusCode || env.StatusCode
if (String(status) === "401") return true
var rawMsg = env.Message || env.Msg || env.message || env.msg || env.error || env.toast || (env.data && (env.data.message || env.data.msg || env.data.error || env.data.toast || env.data.Message || env.data.Msg)) || (env.Data && (env.Data.message || env.Data.msg || env.Data.error || env.Data.toast || env.Data.Message || env.Data.Msg)) || ""
return isLoginExpiredMsg(rawMsg)
} }
function successLikeMsg(msg) { function successLikeMsg(msg) {
msg = String(msg || "") msg = String(msg || "")
@@ -708,12 +722,18 @@ function taskRunCount(task, def) {
if (n > 10) n = 10 if (n > 10) n = 10
return n return n
} }
function taskAccepted(res) { return taskResultOk(res) || Number(resultCode(res)) === 9 } function taskAccepted(res) { return (taskResultOk(res) || Number(resultCode(res)) === 9) && !riskConf(res) }
function riskConf(res) { function riskConf(res) {
res = responseEnvelope(res) res = responseEnvelope(res)
var data = res && (res.Data || res.data || res.ResultData || res.resultData) var data = res && (res.Data || res.data || res.ResultData || res.resultData)
return data && (data.RiskConf || data.riskConf || data.Risk || data.risk) return data && (data.RiskConf || data.riskConf || data.Risk || data.risk)
} }
function riskBlockedMsg(res) {
var rc = riskConf(res)
if (!rc) return ""
var url = rc.CaptchaURL || rc.captchaUrl || rc.Url || rc.url || ""
return url ? "触发风控验证,任务未确认完成" : "触发风控验证,任务未确认完成"
}
function finishVideoTask(taskOrId, cookie, repeat) { function finishVideoTask(taskOrId, cookie, repeat) {
var tid = typeof taskOrId === "object" ? taskIdOf(taskOrId || {}) : taskOrId var tid = typeof taskOrId === "object" ? taskIdOf(taskOrId || {}) : taskOrId
var n = repeat || (typeof taskOrId === "object" ? taskRunCount(taskOrId, 1) : 1) var n = repeat || (typeof taskOrId === "object" ? taskRunCount(taskOrId, 1) : 1)
@@ -758,13 +778,13 @@ function doAdvTask(cookie) {
var fr = finishVideoTask(tid, cookie, 1) var fr = finishVideoTask(tid, cookie, 1)
submittedCount += fr.ok submittedCount += fr.ok
if (riskConf(fr.last)) riskSubmitted = true if (riskConf(fr.last)) riskSubmitted = true
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: riskBlockedMsg(fr.last) || resultMsg(fr.last) || ("第 " + (i + 1) + " 个任务失败"), path: "/argus/api/v1/video/adv/finishWatch" }
} }
var verify = qdGet("/argus/api/v2/video/adv/mainPage", {}, cookie) var verify = qdGet("/argus/api/v2/video/adv/mainPage", {}, cookie)
var after = advTaskList(verify) var after = advTaskList(verify)
var finished = !!(after && after.length && after.every(function (t) { return taskFinished(t) })) var finished = !!(after && after.length && after.every(function (t) { return taskFinished(t) }))
if (finished) return { name: "激励任务", ok: true, msg: "任务已完成", path: "/argus/api/v2/video/adv/mainPage" } if (finished) return { name: "激励任务", ok: true, msg: "任务已完成", path: "/argus/api/v2/video/adv/mainPage" }
if (submittedCount > 0 && riskSubmitted) return { name: "激励任务", ok: true, msg: "已提交,状态待刷新", path: "/argus/api/v2/video/adv/mainPage" } if (submittedCount > 0 && riskSubmitted) return { name: "激励任务", ok: false, msg: "触发风控验证,任务未确认完成", path: "/argus/api/v2/video/adv/mainPage" }
return { name: "激励任务", ok: false, msg: submittedCount ? "部分任务未完成" : "未找到可提交任务", path: "/argus/api/v2/video/adv/mainPage" } return { name: "激励任务", ok: false, msg: submittedCount ? "部分任务未完成" : "未找到可提交任务", path: "/argus/api/v2/video/adv/mainPage" }
} }
function taskReceived(task) { function taskReceived(task) {
@@ -781,7 +801,7 @@ function doDailyTask(cookie) {
var pr = finishVideoTask(taskIdOf(pre), cookie, 1) var pr = finishVideoTask(taskIdOf(pre), cookie, 1)
done += pr.ok done += pr.ok
if (riskConf(pr.last)) riskSubmitted = true if (riskConf(pr.last)) riskSubmitted = true
if (pr.ok < pr.total) return { name: "每日任务", ok: false, msg: resultMsg(pr.last) || "惊喜福利任务失败", path: "/argus/api/v1/video/adv/finishWatch" } if (pr.ok < pr.total) return { name: "每日任务", ok: false, msg: riskBlockedMsg(pr.last) || resultMsg(pr.last) || "惊喜福利任务失败", path: "/argus/api/v1/video/adv/finishWatch" }
} }
var tasks = dailyTaskList(main) var tasks = dailyTaskList(main)
if (!tasks.length) return { name: "每日任务", ok: false, msg: "任务列表为空", path: "/argus/api/v2/video/adv/mainPage" } if (!tasks.length) return { name: "每日任务", ok: false, msg: "任务列表为空", path: "/argus/api/v2/video/adv/mainPage" }
@@ -796,7 +816,7 @@ function doDailyTask(cookie) {
var ar = finishVideoTask(taskIdOf(oneAd), cookie, 1) var ar = finishVideoTask(taskIdOf(oneAd), cookie, 1)
done += ar.ok done += ar.ok
if (riskConf(ar.last)) riskSubmitted = true if (riskConf(ar.last)) riskSubmitted = true
if (ar.ok < ar.total) return { name: "每日任务", ok: false, msg: resultMsg(ar.last) || "完成1个广告任务失败", path: "/argus/api/v1/video/adv/finishWatch" } if (ar.ok < ar.total) return { name: "每日任务", ok: false, msg: riskBlockedMsg(ar.last) || resultMsg(ar.last) || "完成1个广告任务失败", path: "/argus/api/v1/video/adv/finishWatch" }
} }
if (!target) return { name: "每日任务", ok: false, msg: "未找到每日任务任务", path: "/argus/api/v2/video/adv/mainPage" } 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" } if (taskReceived(target)) return { name: "每日任务", ok: true, msg: "任务已完成", path: "/argus/api/v2/video/adv/mainPage" }
@@ -805,13 +825,13 @@ function doDailyTask(cookie) {
var tr = finishVideoTask(tid, cookie, 3) var tr = finishVideoTask(tid, cookie, 3)
done += tr.ok done += tr.ok
if (riskConf(tr.last)) riskSubmitted = true if (riskConf(tr.last)) riskSubmitted = true
if (tr.ok < tr.total) return { name: "每日任务", ok: false, msg: resultMsg(tr.last) || "每日任务广告失败", path: "/argus/api/v1/video/adv/finishWatch" } if (tr.ok < tr.total) return { name: "每日任务", ok: false, msg: riskBlockedMsg(tr.last) || resultMsg(tr.last) || "每日任务广告失败", path: "/argus/api/v1/video/adv/finishWatch" }
var verify = qdGet("/argus/api/v2/video/adv/mainPage", {}, cookie) var verify = qdGet("/argus/api/v2/video/adv/mainPage", {}, cookie)
var after = dailyTaskList(verify) var after = dailyTaskList(verify)
var finished = false var finished = false
for (var v = 0; v < after.length; v++) if (taskTitle(after[v]) === "完成3个广告任务得奖励" && taskReceived(after[v])) { finished = true; break } for (var v = 0; v < after.length; v++) if (taskTitle(after[v]) === "完成3个广告任务得奖励" && taskReceived(after[v])) { finished = true; break }
if (finished) return { name: "每日任务", ok: true, msg: "任务已完成", path: "/argus/api/v2/video/adv/mainPage" } if (finished) return { name: "每日任务", ok: true, msg: "任务已完成", path: "/argus/api/v2/video/adv/mainPage" }
if (done > 0 && riskSubmitted) return { name: "每日任务", ok: true, msg: "已提交,状态待刷新", path: "/argus/api/v2/video/adv/mainPage" } if (done > 0 && riskSubmitted) return { name: "每日任务", ok: false, msg: "触发风控验证,任务未确认完成", path: "/argus/api/v2/video/adv/mainPage" }
return { name: "每日任务", ok: false, msg: "任务未完成", path: "/argus/api/v2/video/adv/mainPage" } return { name: "每日任务", ok: false, msg: "任务未完成", path: "/argus/api/v2/video/adv/mainPage" }
} }
function doLotteryTask(cookie) { function doLotteryTask(cookie) {
@@ -907,9 +927,9 @@ function doMessageBox(cookie) {
var bookId = data.BookId || "" var bookId = data.BookId || ""
if (data.Status !== undefined && Number(data.Status) !== 1) continue if (data.Status !== undefined && Number(data.Status) !== 1) continue
if (chance <= 0 && bookStatus !== 0 && bookStatus !== 1 && bookStatus !== 2) continue if (chance <= 0 && bookStatus !== 0 && bookStatus !== 1 && bookStatus !== 2) continue
if (chance > 0) { var cb = qdPost("/argus/api/v1/interaction/rewardcallback", { orderId: orderId, checkRisk: "1" }, cookie); if (taskResultOk(cb) || String(resultCode(cb)) === "0") handled++; continue } if (chance > 0) { var cb = qdPost("/argus/api/v1/interaction/rewardcallback", { orderId: orderId, checkRisk: "1" }, cookie); if (!riskConf(cb) && (taskResultOk(cb) || String(resultCode(cb)) === "0")) handled++; continue }
if (bookStatus === 0 || bookStatus === 1) { if (!bookId) continue; var add = qdPost("/argus/api/v1/interaction/rewardaddshelf", { orderId: orderId, bookId: bookId }, cookie); if (taskResultOk(add) || String(resultCode(add)) === "0") handled++; continue } if (bookStatus === 0 || bookStatus === 1) { if (!bookId) continue; var add = qdPost("/argus/api/v1/interaction/rewardaddshelf", { orderId: orderId, bookId: bookId }, cookie); if (!riskConf(add) && (taskResultOk(add) || String(resultCode(add)) === "0")) handled++; continue }
if (bookStatus === 2) { var rc = qdPost("/argus/api/v1/interaction/rewardcallback", { orderId: orderId, checkRisk: "1" }, cookie); if (!taskResultOk(rc) && String(resultCode(rc)) !== "0") continue; var r2 = qdPost("/argus/api/v1/interaction/rewardcallback", { orderId: orderId, checkRisk: "0" }, cookie); if (taskResultOk(r2) || String(resultCode(r2)) === "0") handled++ } if (bookStatus === 2) { var rc = qdPost("/argus/api/v1/interaction/rewardcallback", { orderId: orderId, checkRisk: "1" }, cookie); if (riskConf(rc) || (!taskResultOk(rc) && String(resultCode(rc)) !== "0")) continue; var r2 = qdPost("/argus/api/v1/interaction/rewardcallback", { orderId: orderId, checkRisk: "0" }, cookie); if (!riskConf(r2) && (taskResultOk(r2) || String(resultCode(r2)) === "0")) handled++ }
} }
} }
return { name: "大咖荐书", ok: true, msg: handled ? ("成功处理 " + handled + " 个荐书") : "无待处理荐书", path: "https://magev6.if.qidian.com/argus/api/v2/message/pullmessage" } return { name: "大咖荐书", ok: true, msg: handled ? ("成功处理 " + handled + " 个荐书") : "无待处理荐书", path: "https://magev6.if.qidian.com/argus/api/v2/message/pullmessage" }
@@ -932,6 +952,13 @@ function doTaskChain(uid, cookie, source, runId) {
var startedAt = nowIso() var startedAt = nowIso()
var details = [] var details = []
var checkin = qidianRequest(CHECKIN_PATH, "POST", {}, cookie) var checkin = qidianRequest(CHECKIN_PATH, "POST", {}, cookie)
if (isCookieExpiredResult(checkin)) {
var expiredMsg = resultMsg(checkin) || "登录状态已失效,请更新 Cookie"
var expiredDetail = { name: "签到结果", ok: false, msg: expiredMsg, path: CHECKIN_PATH, cookieExpired: true }
var expiredResult = { uid: String(uid), ok: false, msg: expiredMsg, time: nowIso(), startedAt: startedAt, source: source || "manual", runId: runId || "", tasks: [expiredDetail], cookieExpired: true }
setLastResult(uid, expiredResult)
return { uid: uid, ok: false, msg: expiredMsg, raw: checkin, log: expiredResult, cookieExpired: true }
}
var ok = taskResultOk(checkin) var ok = taskResultOk(checkin)
var msg = resultMsg(checkin) || (ok ? "签到请求成功" : ("签到失败" + (resultCode(checkin) !== undefined ? " code=" + resultCode(checkin) : ""))) var msg = resultMsg(checkin) || (ok ? "签到请求成功" : ("签到失败" + (resultCode(checkin) !== undefined ? " code=" + resultCode(checkin) : "")))
details.push({ name: "签到结果", ok: !!ok, msg: String(msg || ""), path: CHECKIN_PATH }) details.push({ name: "签到结果", ok: !!ok, msg: String(msg || ""), path: CHECKIN_PATH })
+39 -12
View File
@@ -4,7 +4,7 @@
//[author: Hermes] //[author: Hermes]
//[service: BOSS] //[service: BOSS]
//[class: 工具类] //[class: 工具类]
// [version: 2.15.6] // [version: 2.15.7]
// [platform: web,qq,wx,tg,tb,fs,we] // [platform: web,qq,wx,tg,tb,fs,we]
// [public: false] // [public: false]
// [price: 0] // [price: 0]
@@ -447,13 +447,27 @@ function resultOk(obj) {
if (String(status) === "401" || String(status) === "403") return false if (String(status) === "401" || String(status) === "403") return false
return code === undefined || code === 0 || code === "0" || code === 200 || code === "200" || status === "ok" || status === "success" return code === undefined || code === 0 || code === "0" || code === 200 || code === "200" || status === "ok" || status === "success"
} }
function isLoginExpiredMsg(msg) {
msg = String(msg || "")
return /登录状态已失效|登录已失效|登录状态.*过期|登录.*过期|用户未登录|未登录|请登录|重新登录|Cookie.*失效|CK.*失效|cookie.*expired|login.*expired|not\s*login/i.test(msg)
}
function resultMsg(obj) { function resultMsg(obj) {
obj = responseEnvelope(obj) obj = responseEnvelope(obj)
if (!obj) return "" if (!obj) return ""
var status = obj.status || obj.Status || obj.statusCode || obj.StatusCode var status = obj.status || obj.Status || obj.statusCode || obj.StatusCode
if (String(status) === "401") return "登录状态已失效,请更新 Cookie" if (String(status) === "401") return "登录状态已失效,请更新 Cookie"
if (String(status) === "403") return "接口鉴权失败,请更新 Cookie" if (String(status) === "403") return "接口鉴权失败,请更新 Cookie"
return obj.Message || obj.Msg || obj.message || obj.msg || obj.error || obj.toast || (obj.data && (obj.data.message || obj.data.msg || obj.data.error || obj.data.toast || obj.data.Message || obj.data.Msg)) || (obj.Data && (obj.Data.message || obj.Data.msg || obj.Data.error || obj.Data.toast || obj.Data.Message || obj.Data.Msg)) || "" var msg = obj.Message || obj.Msg || obj.message || obj.msg || obj.error || obj.toast || (obj.data && (obj.data.message || obj.data.msg || obj.data.error || obj.data.toast || obj.data.Message || obj.data.Msg)) || (obj.Data && (obj.Data.message || obj.Data.msg || obj.Data.error || obj.Data.toast || obj.Data.Message || obj.Data.Msg)) || ""
if (isLoginExpiredMsg(msg)) return "登录状态已失效,请更新 Cookie"
return msg
}
function isCookieExpiredResult(obj) {
var env = responseEnvelope(obj)
if (!env) return false
var status = env.status || env.Status || env.statusCode || env.StatusCode
if (String(status) === "401") return true
var rawMsg = env.Message || env.Msg || env.message || env.msg || env.error || env.toast || (env.data && (env.data.message || env.data.msg || env.data.error || env.data.toast || env.data.Message || env.data.Msg)) || (env.Data && (env.Data.message || env.Data.msg || env.Data.error || env.Data.toast || env.Data.Message || env.Data.Msg)) || ""
return isLoginExpiredMsg(rawMsg)
} }
function successLikeMsg(msg) { function successLikeMsg(msg) {
msg = String(msg || "") msg = String(msg || "")
@@ -708,12 +722,18 @@ function taskRunCount(task, def) {
if (n > 10) n = 10 if (n > 10) n = 10
return n return n
} }
function taskAccepted(res) { return taskResultOk(res) || Number(resultCode(res)) === 9 } function taskAccepted(res) { return (taskResultOk(res) || Number(resultCode(res)) === 9) && !riskConf(res) }
function riskConf(res) { function riskConf(res) {
res = responseEnvelope(res) res = responseEnvelope(res)
var data = res && (res.Data || res.data || res.ResultData || res.resultData) var data = res && (res.Data || res.data || res.ResultData || res.resultData)
return data && (data.RiskConf || data.riskConf || data.Risk || data.risk) return data && (data.RiskConf || data.riskConf || data.Risk || data.risk)
} }
function riskBlockedMsg(res) {
var rc = riskConf(res)
if (!rc) return ""
var url = rc.CaptchaURL || rc.captchaUrl || rc.Url || rc.url || ""
return url ? "触发风控验证,任务未确认完成" : "触发风控验证,任务未确认完成"
}
function finishVideoTask(taskOrId, cookie, repeat) { function finishVideoTask(taskOrId, cookie, repeat) {
var tid = typeof taskOrId === "object" ? taskIdOf(taskOrId || {}) : taskOrId var tid = typeof taskOrId === "object" ? taskIdOf(taskOrId || {}) : taskOrId
var n = repeat || (typeof taskOrId === "object" ? taskRunCount(taskOrId, 1) : 1) var n = repeat || (typeof taskOrId === "object" ? taskRunCount(taskOrId, 1) : 1)
@@ -758,13 +778,13 @@ function doAdvTask(cookie) {
var fr = finishVideoTask(tid, cookie, 1) var fr = finishVideoTask(tid, cookie, 1)
submittedCount += fr.ok submittedCount += fr.ok
if (riskConf(fr.last)) riskSubmitted = true if (riskConf(fr.last)) riskSubmitted = true
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: riskBlockedMsg(fr.last) || resultMsg(fr.last) || ("第 " + (i + 1) + " 个任务失败"), path: "/argus/api/v1/video/adv/finishWatch" }
} }
var verify = qdGet("/argus/api/v2/video/adv/mainPage", {}, cookie) var verify = qdGet("/argus/api/v2/video/adv/mainPage", {}, cookie)
var after = advTaskList(verify) var after = advTaskList(verify)
var finished = !!(after && after.length && after.every(function (t) { return taskFinished(t) })) var finished = !!(after && after.length && after.every(function (t) { return taskFinished(t) }))
if (finished) return { name: "激励任务", ok: true, msg: "任务已完成", path: "/argus/api/v2/video/adv/mainPage" } if (finished) return { name: "激励任务", ok: true, msg: "任务已完成", path: "/argus/api/v2/video/adv/mainPage" }
if (submittedCount > 0 && riskSubmitted) return { name: "激励任务", ok: true, msg: "已提交,状态待刷新", path: "/argus/api/v2/video/adv/mainPage" } if (submittedCount > 0 && riskSubmitted) return { name: "激励任务", ok: false, msg: "触发风控验证,任务未确认完成", path: "/argus/api/v2/video/adv/mainPage" }
return { name: "激励任务", ok: false, msg: submittedCount ? "部分任务未完成" : "未找到可提交任务", path: "/argus/api/v2/video/adv/mainPage" } return { name: "激励任务", ok: false, msg: submittedCount ? "部分任务未完成" : "未找到可提交任务", path: "/argus/api/v2/video/adv/mainPage" }
} }
function taskReceived(task) { function taskReceived(task) {
@@ -781,7 +801,7 @@ function doDailyTask(cookie) {
var pr = finishVideoTask(taskIdOf(pre), cookie, 1) var pr = finishVideoTask(taskIdOf(pre), cookie, 1)
done += pr.ok done += pr.ok
if (riskConf(pr.last)) riskSubmitted = true if (riskConf(pr.last)) riskSubmitted = true
if (pr.ok < pr.total) return { name: "每日任务", ok: false, msg: resultMsg(pr.last) || "惊喜福利任务失败", path: "/argus/api/v1/video/adv/finishWatch" } if (pr.ok < pr.total) return { name: "每日任务", ok: false, msg: riskBlockedMsg(pr.last) || resultMsg(pr.last) || "惊喜福利任务失败", path: "/argus/api/v1/video/adv/finishWatch" }
} }
var tasks = dailyTaskList(main) var tasks = dailyTaskList(main)
if (!tasks.length) return { name: "每日任务", ok: false, msg: "任务列表为空", path: "/argus/api/v2/video/adv/mainPage" } if (!tasks.length) return { name: "每日任务", ok: false, msg: "任务列表为空", path: "/argus/api/v2/video/adv/mainPage" }
@@ -796,7 +816,7 @@ function doDailyTask(cookie) {
var ar = finishVideoTask(taskIdOf(oneAd), cookie, 1) var ar = finishVideoTask(taskIdOf(oneAd), cookie, 1)
done += ar.ok done += ar.ok
if (riskConf(ar.last)) riskSubmitted = true if (riskConf(ar.last)) riskSubmitted = true
if (ar.ok < ar.total) return { name: "每日任务", ok: false, msg: resultMsg(ar.last) || "完成1个广告任务失败", path: "/argus/api/v1/video/adv/finishWatch" } if (ar.ok < ar.total) return { name: "每日任务", ok: false, msg: riskBlockedMsg(ar.last) || resultMsg(ar.last) || "完成1个广告任务失败", path: "/argus/api/v1/video/adv/finishWatch" }
} }
if (!target) return { name: "每日任务", ok: false, msg: "未找到每日任务任务", path: "/argus/api/v2/video/adv/mainPage" } 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" } if (taskReceived(target)) return { name: "每日任务", ok: true, msg: "任务已完成", path: "/argus/api/v2/video/adv/mainPage" }
@@ -805,13 +825,13 @@ function doDailyTask(cookie) {
var tr = finishVideoTask(tid, cookie, 3) var tr = finishVideoTask(tid, cookie, 3)
done += tr.ok done += tr.ok
if (riskConf(tr.last)) riskSubmitted = true if (riskConf(tr.last)) riskSubmitted = true
if (tr.ok < tr.total) return { name: "每日任务", ok: false, msg: resultMsg(tr.last) || "每日任务广告失败", path: "/argus/api/v1/video/adv/finishWatch" } if (tr.ok < tr.total) return { name: "每日任务", ok: false, msg: riskBlockedMsg(tr.last) || resultMsg(tr.last) || "每日任务广告失败", path: "/argus/api/v1/video/adv/finishWatch" }
var verify = qdGet("/argus/api/v2/video/adv/mainPage", {}, cookie) var verify = qdGet("/argus/api/v2/video/adv/mainPage", {}, cookie)
var after = dailyTaskList(verify) var after = dailyTaskList(verify)
var finished = false var finished = false
for (var v = 0; v < after.length; v++) if (taskTitle(after[v]) === "完成3个广告任务得奖励" && taskReceived(after[v])) { finished = true; break } for (var v = 0; v < after.length; v++) if (taskTitle(after[v]) === "完成3个广告任务得奖励" && taskReceived(after[v])) { finished = true; break }
if (finished) return { name: "每日任务", ok: true, msg: "任务已完成", path: "/argus/api/v2/video/adv/mainPage" } if (finished) return { name: "每日任务", ok: true, msg: "任务已完成", path: "/argus/api/v2/video/adv/mainPage" }
if (done > 0 && riskSubmitted) return { name: "每日任务", ok: true, msg: "已提交,状态待刷新", path: "/argus/api/v2/video/adv/mainPage" } if (done > 0 && riskSubmitted) return { name: "每日任务", ok: false, msg: "触发风控验证,任务未确认完成", path: "/argus/api/v2/video/adv/mainPage" }
return { name: "每日任务", ok: false, msg: "任务未完成", path: "/argus/api/v2/video/adv/mainPage" } return { name: "每日任务", ok: false, msg: "任务未完成", path: "/argus/api/v2/video/adv/mainPage" }
} }
function doLotteryTask(cookie) { function doLotteryTask(cookie) {
@@ -907,9 +927,9 @@ function doMessageBox(cookie) {
var bookId = data.BookId || "" var bookId = data.BookId || ""
if (data.Status !== undefined && Number(data.Status) !== 1) continue if (data.Status !== undefined && Number(data.Status) !== 1) continue
if (chance <= 0 && bookStatus !== 0 && bookStatus !== 1 && bookStatus !== 2) continue if (chance <= 0 && bookStatus !== 0 && bookStatus !== 1 && bookStatus !== 2) continue
if (chance > 0) { var cb = qdPost("/argus/api/v1/interaction/rewardcallback", { orderId: orderId, checkRisk: "1" }, cookie); if (taskResultOk(cb) || String(resultCode(cb)) === "0") handled++; continue } if (chance > 0) { var cb = qdPost("/argus/api/v1/interaction/rewardcallback", { orderId: orderId, checkRisk: "1" }, cookie); if (!riskConf(cb) && (taskResultOk(cb) || String(resultCode(cb)) === "0")) handled++; continue }
if (bookStatus === 0 || bookStatus === 1) { if (!bookId) continue; var add = qdPost("/argus/api/v1/interaction/rewardaddshelf", { orderId: orderId, bookId: bookId }, cookie); if (taskResultOk(add) || String(resultCode(add)) === "0") handled++; continue } if (bookStatus === 0 || bookStatus === 1) { if (!bookId) continue; var add = qdPost("/argus/api/v1/interaction/rewardaddshelf", { orderId: orderId, bookId: bookId }, cookie); if (!riskConf(add) && (taskResultOk(add) || String(resultCode(add)) === "0")) handled++; continue }
if (bookStatus === 2) { var rc = qdPost("/argus/api/v1/interaction/rewardcallback", { orderId: orderId, checkRisk: "1" }, cookie); if (!taskResultOk(rc) && String(resultCode(rc)) !== "0") continue; var r2 = qdPost("/argus/api/v1/interaction/rewardcallback", { orderId: orderId, checkRisk: "0" }, cookie); if (taskResultOk(r2) || String(resultCode(r2)) === "0") handled++ } if (bookStatus === 2) { var rc = qdPost("/argus/api/v1/interaction/rewardcallback", { orderId: orderId, checkRisk: "1" }, cookie); if (riskConf(rc) || (!taskResultOk(rc) && String(resultCode(rc)) !== "0")) continue; var r2 = qdPost("/argus/api/v1/interaction/rewardcallback", { orderId: orderId, checkRisk: "0" }, cookie); if (!riskConf(r2) && (taskResultOk(r2) || String(resultCode(r2)) === "0")) handled++ }
} }
} }
return { name: "大咖荐书", ok: true, msg: handled ? ("成功处理 " + handled + " 个荐书") : "无待处理荐书", path: "https://magev6.if.qidian.com/argus/api/v2/message/pullmessage" } return { name: "大咖荐书", ok: true, msg: handled ? ("成功处理 " + handled + " 个荐书") : "无待处理荐书", path: "https://magev6.if.qidian.com/argus/api/v2/message/pullmessage" }
@@ -932,6 +952,13 @@ function doTaskChain(uid, cookie, source, runId) {
var startedAt = nowIso() var startedAt = nowIso()
var details = [] var details = []
var checkin = qidianRequest(CHECKIN_PATH, "POST", {}, cookie) var checkin = qidianRequest(CHECKIN_PATH, "POST", {}, cookie)
if (isCookieExpiredResult(checkin)) {
var expiredMsg = resultMsg(checkin) || "登录状态已失效,请更新 Cookie"
var expiredDetail = { name: "签到结果", ok: false, msg: expiredMsg, path: CHECKIN_PATH, cookieExpired: true }
var expiredResult = { uid: String(uid), ok: false, msg: expiredMsg, time: nowIso(), startedAt: startedAt, source: source || "manual", runId: runId || "", tasks: [expiredDetail], cookieExpired: true }
setLastResult(uid, expiredResult)
return { uid: uid, ok: false, msg: expiredMsg, raw: checkin, log: expiredResult, cookieExpired: true }
}
var ok = taskResultOk(checkin) var ok = taskResultOk(checkin)
var msg = resultMsg(checkin) || (ok ? "签到请求成功" : ("签到失败" + (resultCode(checkin) !== undefined ? " code=" + resultCode(checkin) : ""))) var msg = resultMsg(checkin) || (ok ? "签到请求成功" : ("签到失败" + (resultCode(checkin) !== undefined ? " code=" + resultCode(checkin) : "")))
details.push({ name: "签到结果", ok: !!ok, msg: String(msg || ""), path: CHECKIN_PATH }) details.push({ name: "签到结果", ok: !!ok, msg: String(msg || ""), path: CHECKIN_PATH })
+60 -6
View File
@@ -306,6 +306,29 @@ test('manual sign also archives immediately after run', () => {
assert.deepEqual(JSON.parse(r.store.qdreader_last_result_json), {}); assert.deepEqual(JSON.parse(r.store.qdreader_last_result_json), {});
}); });
test('business login-expired responses prompt cookie update', () => {
const store = {
qdreader_cookie_json: JSON.stringify({ '12345': cookie }),
qdreader_user_bind_json: JSON.stringify({ '12345': 'user-a' }),
};
const r = runPlugin({
content: '启点签到',
store,
userId: 'user-a',
requests: [
{ body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } },
{ statusCode: 200, body: { Result: -100, Message: '用户未登录或登录状态已过期' } },
],
});
assert.match(r.replies[0], /12\*\*\*45/);
assert.match(r.replies[0], /登录状态已失效,请更新 Cookie/);
assert.doesNotMatch(r.replies[0], /部分任务失败/);
const archive = JSON.parse(r.store.qdreader_archive_json);
const item = Object.values(archive)[0].items[0];
assert.equal(item.ok, false);
assert.match(item.msg, /登录状态已失效,请更新 Cookie/);
});
test('logs and archive dates use Beijing time even when runtime date is UTC', () => { test('logs and archive dates use Beijing time even when runtime date is UTC', () => {
const store = { const store = {
qdreader_cookie_json: JSON.stringify({ '12345': cookie }), qdreader_cookie_json: JSON.stringify({ '12345': cookie }),
@@ -1273,7 +1296,7 @@ test('adv and daily tasks report auth failure instead of empty list on HTTP 401'
}); });
test('daily task treats accepted risk-conf callbacks as submitted when status does not refresh immediately', () => { test('daily task does not report risk-conf callbacks as completed when status does not refresh', () => {
const store = { const store = {
qdreader_cookie_json: JSON.stringify({ '12345': cookie }), qdreader_cookie_json: JSON.stringify({ '12345': cookie }),
qdreader_user_bind_json: JSON.stringify({ '12345': 'user-a' }), qdreader_user_bind_json: JSON.stringify({ '12345': 'user-a' }),
@@ -1311,8 +1334,8 @@ test('daily task treats accepted risk-conf callbacks as submitted when status do
{ statusCode: 200, body: unchanged }, { statusCode: 200, body: unchanged },
], ],
}); });
assert.match(r.replies[0], /每日任务\(已提交,状态待刷新\)/); assert.match(r.replies[0], /每日任务\(触发风控验证,任务未确认完成\)/);
assert.doesNotMatch(r.replies[0], /部分任务失败/); assert.match(r.replies[0], /部分任务失败/);
}); });
@@ -1408,7 +1431,7 @@ test('adv task accepts discovered task list when upstream module name changes',
}); });
test('adv task treats accepted risk-conf callback as submitted when status does not refresh immediately', () => { test('adv task does not report risk-conf callback as completed when status does not refresh', () => {
const store = { const store = {
qdreader_cookie_json: JSON.stringify({ '12345': cookie }), qdreader_cookie_json: JSON.stringify({ '12345': cookie }),
qdreader_user_bind_json: JSON.stringify({ '12345': 'user-a' }), qdreader_user_bind_json: JSON.stringify({ '12345': 'user-a' }),
@@ -1432,8 +1455,8 @@ test('adv task treats accepted risk-conf callback as submitted when status does
{ statusCode: 200, body: { code: 0, Data: { DailyBenefitModule: { TaskList: [unchanged] } } } }, { statusCode: 200, body: { code: 0, Data: { DailyBenefitModule: { TaskList: [unchanged] } } } },
], ],
}); });
assert.match(r.replies[0], /激励任务\(已提交,状态待刷新\)/); assert.match(r.replies[0], /激励任务\(触发风控验证,任务未确认完成\)/);
assert.doesNotMatch(r.replies[0], /部分任务失败/); assert.match(r.replies[0], /部分任务失败/);
}); });
@@ -1599,6 +1622,37 @@ test('message box uses upstream appappend/fromId/interaction reward chain instea
assert.ok(r.calls.some(c => /argus\/api\/v1\/interaction\/rewardcallback/.test(c.url) && /orderId=abcdef123456/.test(c.body))); assert.ok(r.calls.some(c => /argus\/api\/v1\/interaction\/rewardcallback/.test(c.url) && /orderId=abcdef123456/.test(c.body)));
}); });
test('message box does not count risk-conf reward callback as handled', () => {
const store = {
qdreader_cookie_json: JSON.stringify({ '12345': cookie }),
qdreader_user_bind_json: JSON.stringify({ '12345': 'user-a' }),
qdreader_task_pref_json: JSON.stringify({ '12345': { messageBox: true } }),
};
const now = fixedDateClass('2026-05-20T21:31:00.000+08:00');
const r = runPlugin({
content: '启点签到',
store,
userId: 'user-a',
globals: { Date: now },
requests: [
{ 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: 1, msg: '无可领取礼包' } },
{ body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } },
{ statusCode: 200, body: { code: 0, Data: { UserList: [{ RedPoint: 1, FromId: 'sender-1', Name: '大咖' }] } } },
{ body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } },
{ statusCode: 200, body: { code: 0, Data: { MsgList: [{ CreateTime: '2026-05-20T21:20:00+08:00', ActionUrl: 'https://example.com/?orderId=abcdef123456' }] } } },
{ body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } },
{ statusCode: 200, body: { code: 0, Data: { ChanceCount: 1, Status: 1, BookStatus: 3, RewardName: '经验' } } },
{ body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } },
{ statusCode: 200, body: { Result: '0', Message: '', Data: { RiskConf: { BanId: '3', CaptchaURL: 'https://aq.qidian.com/mobile/phoneverify' } } } },
],
});
assert.match(r.replies[0], /大咖荐书✅\(无待处理荐书\)/);
assert.doesNotMatch(r.replies[0], /成功处理 1 个荐书/);
});
test('stream uid message token matches upstream operator precedence and avoids parameter-error decimal token', () => { test('stream uid message token matches upstream operator precedence and avoids parameter-error decimal token', () => {
const streamQdheader = 'KG51bGwpfChudWxsKXwxMTc5fDI1NTZ8KG51bGwpfDE2LjEwfDB8aU9TL2lQaG9uZS8obnVsbCl8MHwobnVsbCl8KG51bGwpfDQ3NTcwMDk3NXwxNzc5MDA5MTM2MDAwfDB8KG51bGwpfHx8KG51bGwpfChudWxsKXww'; const streamQdheader = 'KG51bGwpfChudWxsKXwxMTc5fDI1NTZ8KG51bGwpfDE2LjEwfDB8aU9TL2lQaG9uZS8obnVsbCl8MHwobnVsbCl8KG51bGwpfDQ3NTcwMDk3NXwxNzc5MDA5MTM2MDAwfDB8KG51bGwpfHx8KG51bGwpfChudWxsKXww';
const streamCookie = `QDHeader=${streamQdheader}; ywguid=120098575768; qdh=qdh; sessionyw=s; appId=12`; const streamCookie = `QDHeader=${streamQdheader}; ywguid=120098575768; qdh=qdh; sessionyw=s; appId=12`;