fix(qdreader): discover shifted task lists
This commit is contained in:
@@ -618,6 +618,61 @@ function nested(obj, path) {
|
||||
}
|
||||
return cur
|
||||
}
|
||||
function payloadData(obj) { return (obj && (obj.Data || obj.data)) || {} }
|
||||
function looksLikeVideoTask(task) { return isObject(task) && !!taskIdOf(task) && (task["IsFinished"] !== undefined || task["IsReceived"] !== undefined || task["Title"] !== undefined || task["TaskName"] !== undefined) }
|
||||
function taskArrayScore(list, kind) {
|
||||
if (!Array.isArray(list) || !list.length) return 0
|
||||
var score = 0
|
||||
for (var i = 0; i < list.length; i++) {
|
||||
var t = list[i] || {}
|
||||
if (!looksLikeVideoTask(t)) continue
|
||||
var title = taskTitle(t)
|
||||
score += 2
|
||||
if (kind === "daily" && (title === "完成1个广告任务得奖励" || title === "完成3个广告任务得奖励" || t["IsReceived"] !== undefined)) score += 5
|
||||
if (kind === "adv" && (t["IsFinished"] !== undefined || /激励|碎片|福利|广告/.test(title))) score += 3
|
||||
}
|
||||
return score
|
||||
}
|
||||
function findTaskListByShape(root, kind) {
|
||||
var best = []
|
||||
var bestScore = 0
|
||||
var seen = []
|
||||
function walk(node, depth) {
|
||||
if (!node || depth > 8) return
|
||||
if (Array.isArray(node)) {
|
||||
var score = taskArrayScore(node, kind)
|
||||
if (score > bestScore) { bestScore = score; best = node }
|
||||
for (var i = 0; i < node.length; i++) walk(node[i], depth + 1)
|
||||
return
|
||||
}
|
||||
if (!isObject(node) || seen.indexOf(node) >= 0) return
|
||||
seen.push(node)
|
||||
for (var k in node) walk(node[k], depth + 1)
|
||||
}
|
||||
walk(root, 0)
|
||||
return best
|
||||
}
|
||||
function advTaskList(main) {
|
||||
return firstArray(
|
||||
nested(main, ["Data", "DailyBenefitModule", "TaskList"]),
|
||||
nested(main, ["data", "DailyBenefitModule", "TaskList"]),
|
||||
nested(main, ["Data", "AdvTaskList"]),
|
||||
nested(main, ["data", "AdvTaskList"]),
|
||||
findTaskListByShape(payloadData(main), "adv")
|
||||
)
|
||||
}
|
||||
function dailyTaskList(main) {
|
||||
return firstArray(
|
||||
nested(main, ["Data", "VideoRewardTab", "TaskList"]),
|
||||
nested(main, ["data", "VideoRewardTab", "TaskList"]),
|
||||
nested(main, ["Data", "TaskList"]),
|
||||
nested(main, ["data", "TaskList"]),
|
||||
findTaskListByShape(payloadData(main), "daily")
|
||||
)
|
||||
}
|
||||
function surpriseBenefit(data) {
|
||||
return data.SurpriseBenefit || data.SurpriseTask || data.SurpriseBenefitTask || null
|
||||
}
|
||||
function makeVideoPayload(taskId) {
|
||||
return { taskId: String(taskId || ""), BanId: "0", BanMessage: "", CaptchaAId: "", CaptchaURL: "", CaptchaType: "0", Challenge: "", Gt: "", NewCaptcha: "0", Offline: "0", PhoneNumber: "", SessionKey: "" }
|
||||
}
|
||||
@@ -667,7 +722,7 @@ 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", "DailyBenefitModule", "TaskList"]), nested(main, ["data", "DailyBenefitModule", "TaskList"]))
|
||||
var tasks = advTaskList(main)
|
||||
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
|
||||
@@ -681,7 +736,7 @@ function doAdvTask(cookie) {
|
||||
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", "DailyBenefitModule", "TaskList"]), nested(verify, ["data", "DailyBenefitModule", "TaskList"]))
|
||||
var after = advTaskList(verify)
|
||||
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" }
|
||||
}
|
||||
@@ -691,15 +746,15 @@ function taskReceived(task) {
|
||||
function doDailyTask(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 data = main.Data || main.data || {}
|
||||
var data = payloadData(main)
|
||||
var done = 0
|
||||
var pre = data.SurpriseBenefit
|
||||
var pre = surpriseBenefit(data)
|
||||
if (pre && !taskFinished(pre) && taskIdOf(pre)) {
|
||||
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(main, ["Data", "VideoRewardTab", "TaskList"]), nested(main, ["data", "VideoRewardTab", "TaskList"]))
|
||||
var tasks = dailyTaskList(main)
|
||||
if (!tasks.length) return { name: "每日任务", ok: false, msg: "任务列表为空", path: "/argus/api/v2/video/adv/mainPage" }
|
||||
var oneAd = null
|
||||
var target = null
|
||||
@@ -721,7 +776,7 @@ function doDailyTask(cookie) {
|
||||
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"]))
|
||||
var after = dailyTaskList(verify)
|
||||
var finished = false
|
||||
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" }
|
||||
|
||||
@@ -618,6 +618,61 @@ function nested(obj, path) {
|
||||
}
|
||||
return cur
|
||||
}
|
||||
function payloadData(obj) { return (obj && (obj.Data || obj.data)) || {} }
|
||||
function looksLikeVideoTask(task) { return isObject(task) && !!taskIdOf(task) && (task["IsFinished"] !== undefined || task["IsReceived"] !== undefined || task["Title"] !== undefined || task["TaskName"] !== undefined) }
|
||||
function taskArrayScore(list, kind) {
|
||||
if (!Array.isArray(list) || !list.length) return 0
|
||||
var score = 0
|
||||
for (var i = 0; i < list.length; i++) {
|
||||
var t = list[i] || {}
|
||||
if (!looksLikeVideoTask(t)) continue
|
||||
var title = taskTitle(t)
|
||||
score += 2
|
||||
if (kind === "daily" && (title === "完成1个广告任务得奖励" || title === "完成3个广告任务得奖励" || t["IsReceived"] !== undefined)) score += 5
|
||||
if (kind === "adv" && (t["IsFinished"] !== undefined || /激励|碎片|福利|广告/.test(title))) score += 3
|
||||
}
|
||||
return score
|
||||
}
|
||||
function findTaskListByShape(root, kind) {
|
||||
var best = []
|
||||
var bestScore = 0
|
||||
var seen = []
|
||||
function walk(node, depth) {
|
||||
if (!node || depth > 8) return
|
||||
if (Array.isArray(node)) {
|
||||
var score = taskArrayScore(node, kind)
|
||||
if (score > bestScore) { bestScore = score; best = node }
|
||||
for (var i = 0; i < node.length; i++) walk(node[i], depth + 1)
|
||||
return
|
||||
}
|
||||
if (!isObject(node) || seen.indexOf(node) >= 0) return
|
||||
seen.push(node)
|
||||
for (var k in node) walk(node[k], depth + 1)
|
||||
}
|
||||
walk(root, 0)
|
||||
return best
|
||||
}
|
||||
function advTaskList(main) {
|
||||
return firstArray(
|
||||
nested(main, ["Data", "DailyBenefitModule", "TaskList"]),
|
||||
nested(main, ["data", "DailyBenefitModule", "TaskList"]),
|
||||
nested(main, ["Data", "AdvTaskList"]),
|
||||
nested(main, ["data", "AdvTaskList"]),
|
||||
findTaskListByShape(payloadData(main), "adv")
|
||||
)
|
||||
}
|
||||
function dailyTaskList(main) {
|
||||
return firstArray(
|
||||
nested(main, ["Data", "VideoRewardTab", "TaskList"]),
|
||||
nested(main, ["data", "VideoRewardTab", "TaskList"]),
|
||||
nested(main, ["Data", "TaskList"]),
|
||||
nested(main, ["data", "TaskList"]),
|
||||
findTaskListByShape(payloadData(main), "daily")
|
||||
)
|
||||
}
|
||||
function surpriseBenefit(data) {
|
||||
return data.SurpriseBenefit || data.SurpriseTask || data.SurpriseBenefitTask || null
|
||||
}
|
||||
function makeVideoPayload(taskId) {
|
||||
return { taskId: String(taskId || ""), BanId: "0", BanMessage: "", CaptchaAId: "", CaptchaURL: "", CaptchaType: "0", Challenge: "", Gt: "", NewCaptcha: "0", Offline: "0", PhoneNumber: "", SessionKey: "" }
|
||||
}
|
||||
@@ -667,7 +722,7 @@ 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", "DailyBenefitModule", "TaskList"]), nested(main, ["data", "DailyBenefitModule", "TaskList"]))
|
||||
var tasks = advTaskList(main)
|
||||
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
|
||||
@@ -681,7 +736,7 @@ function doAdvTask(cookie) {
|
||||
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", "DailyBenefitModule", "TaskList"]), nested(verify, ["data", "DailyBenefitModule", "TaskList"]))
|
||||
var after = advTaskList(verify)
|
||||
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" }
|
||||
}
|
||||
@@ -691,15 +746,15 @@ function taskReceived(task) {
|
||||
function doDailyTask(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 data = main.Data || main.data || {}
|
||||
var data = payloadData(main)
|
||||
var done = 0
|
||||
var pre = data.SurpriseBenefit
|
||||
var pre = surpriseBenefit(data)
|
||||
if (pre && !taskFinished(pre) && taskIdOf(pre)) {
|
||||
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(main, ["Data", "VideoRewardTab", "TaskList"]), nested(main, ["data", "VideoRewardTab", "TaskList"]))
|
||||
var tasks = dailyTaskList(main)
|
||||
if (!tasks.length) return { name: "每日任务", ok: false, msg: "任务列表为空", path: "/argus/api/v2/video/adv/mainPage" }
|
||||
var oneAd = null
|
||||
var target = null
|
||||
@@ -721,7 +776,7 @@ function doDailyTask(cookie) {
|
||||
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"]))
|
||||
var after = dailyTaskList(verify)
|
||||
var finished = false
|
||||
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" }
|
||||
|
||||
@@ -1245,6 +1245,43 @@ test('adv task ignores count metadata and submits each unfinished upstream task
|
||||
assert.ok(finishCalls.every(c => /partial-task/.test(c.body)));
|
||||
});
|
||||
|
||||
test('adv task accepts discovered task list when upstream module name changes', () => {
|
||||
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': { adv: true } }),
|
||||
};
|
||||
const r = runPlugin({
|
||||
content: '启点签到',
|
||||
store,
|
||||
userId: 'user-a',
|
||||
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: { WelfareCenter: { AdvTasks: [
|
||||
{ TaskId: 'new-adv-a', Title: '激励碎片', IsFinished: 0 },
|
||||
{ TaskId: 'new-adv-b', 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: { result: 9, message: '' } },
|
||||
{ body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } },
|
||||
{ statusCode: 200, body: { code: 0, Data: { WelfareCenter: { AdvTasks: [
|
||||
{ TaskId: 'new-adv-a', Title: '激励碎片', IsFinished: 1 },
|
||||
{ TaskId: 'new-adv-b', Title: '广告福利', IsFinished: 1 },
|
||||
] } } } },
|
||||
],
|
||||
});
|
||||
assert.match(r.replies[0], /激励任务✅\(任务已完成\)/);
|
||||
assert.doesNotMatch(r.replies[0], /任务列表为空/);
|
||||
assert.equal(r.calls.filter(c => /video\/adv\/finishWatch$/.test(c.url)).length, 2);
|
||||
});
|
||||
|
||||
|
||||
test('daily task follows upstream sequence: surprise task, one-ad task, then three daily ad callbacks', () => {
|
||||
const store = {
|
||||
qdreader_cookie_json: JSON.stringify({ '12345': cookie }),
|
||||
@@ -1294,6 +1331,54 @@ test('daily task follows upstream sequence: surprise task, one-ad task, then thr
|
||||
});
|
||||
|
||||
|
||||
test('daily task accepts discovered reward list when upstream module name changes', () => {
|
||||
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': { extraAdv: true } }),
|
||||
};
|
||||
const r = runPlugin({
|
||||
content: '启点签到',
|
||||
store,
|
||||
userId: 'user-a',
|
||||
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: {
|
||||
RewardModules: { DailyAd: [
|
||||
{ TaskId: 'new-one-ad', Title: '完成1个广告任务得奖励', IsReceived: 0 },
|
||||
{ TaskId: 'new-three-ad', Title: '完成3个广告任务得奖励', IsReceived: 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: { result: 9, message: '' } },
|
||||
{ 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: { result: 9, message: '' } },
|
||||
{ body: { code: 0, data: { headers: { 'QD-Sign': 'sig' } } } },
|
||||
{ statusCode: 200, body: { code: 0, Data: {
|
||||
RewardModules: { DailyAd: [
|
||||
{ TaskId: 'new-one-ad', Title: '完成1个广告任务得奖励', IsReceived: 1 },
|
||||
{ TaskId: 'new-three-ad', Title: '完成3个广告任务得奖励', IsReceived: 1 },
|
||||
] }
|
||||
} } },
|
||||
],
|
||||
});
|
||||
assert.match(r.replies[0], /每日任务✅\(任务已完成\)/);
|
||||
assert.doesNotMatch(r.replies[0], /任务列表为空/);
|
||||
const bodies = r.calls.filter(c => /video\/adv\/finishWatch$/.test(c.url)).map(c => c.body);
|
||||
assert.equal(bodies.length, 4);
|
||||
assert.match(bodies[0], /new-one-ad/);
|
||||
assert.equal(bodies.filter(b => /new-three-ad/.test(b)).length, 3);
|
||||
});
|
||||
|
||||
|
||||
test('message box runs outside former Beijing 20-22 window and calls message API', () => {
|
||||
const store = {
|
||||
qdreader_cookie_json: JSON.stringify({ '12345': cookie }),
|
||||
|
||||
Reference in New Issue
Block a user