fix: persist qdreader last run logs
This commit is contained in:
@@ -45,12 +45,12 @@ q. 退出
|
||||
请回复序号
|
||||
```
|
||||
|
||||
`启点查询` 只负责执行情况和执行动作:
|
||||
`启点查询` 只负责最后执行日志和执行动作,不做实时接口查询:
|
||||
|
||||
```text
|
||||
启点查询
|
||||
1. 查看最近执行情况
|
||||
2. 查询单个账号
|
||||
启点查询(最近签到记录)
|
||||
1. 查看最近签到记录
|
||||
2. 查询单个账号最近记录
|
||||
3. 立即执行签到
|
||||
q. 退出
|
||||
请回复序号
|
||||
@@ -91,7 +91,8 @@ hermes_qidian
|
||||
qdreader_cookie_json # uid -> full cookie
|
||||
qdreader_user_bind_json # uid -> sender.getUserID()
|
||||
qdreader_remark_json # uid -> 备注名
|
||||
qdreader_last_result_json # uid -> 最近执行结果 JSON 字符串
|
||||
qdreader_last_result_json # uid -> 单账号最后执行结果 JSON 字符串
|
||||
qdreader_last_run_json # 最近一次执行批次日志、来源和汇总
|
||||
qdreader_sign_api # 签名网关
|
||||
qdreader_retry_count # 请求失败重试次数
|
||||
qdreader_cron_silent # 定时无账号静默
|
||||
@@ -119,8 +120,20 @@ set(key, value)
|
||||
1. 从 Cookie 解析 `QDHeader/qdh/uid/guid/qimei/qimei36`。
|
||||
2. `POST <qdreader_sign_api>/sign` 获取请求签名头。
|
||||
3. `POST https://h5.if.qidian.com/argus/api/v3/checkin/checkin` 完成签到。
|
||||
4. 写入 `qdreader_last_result_json`。
|
||||
5. 汇总每个账号签到结果。
|
||||
4. 写入单账号最后结果 `qdreader_last_result_json`,包括 `ok/msg/time/source/runId`。
|
||||
5. 写入批次日志 `qdreader_last_run_json`,包括触发来源、开始/结束时间、成功/失败/总数和每账号结果;即使账号执行异常也会记录失败日志。
|
||||
6. 汇总每个账号签到结果。
|
||||
|
||||
## 查询数据来源
|
||||
|
||||
`启点查询` 不请求起点实时接口,只读取最后执行日志:
|
||||
|
||||
```text
|
||||
qdreader_last_run_json # 最近一次执行批次
|
||||
qdreader_last_result_json # 每个 uid 最近一次执行结果
|
||||
```
|
||||
|
||||
因此“查询”语义是“最近签到记录/最后执行日志”。刚添加但从未执行过的账号会显示“暂无执行记录”。
|
||||
|
||||
## 本地验证
|
||||
|
||||
|
||||
@@ -28,6 +28,8 @@ var REMARK_KEY = "qdreader_remark_json"
|
||||
var SIGN_API_KEY = "qdreader_sign_api"
|
||||
var RETRY_KEY = "qdreader_retry_count"
|
||||
var CRON_SILENT_KEY = "qdreader_cron_silent"
|
||||
var LAST_RESULT_KEY = "qdreader_last_result_json"
|
||||
var LAST_RUN_KEY = "qdreader_last_run_json"
|
||||
var DEFAULT_SIGN_API = "https://api.120399.xyz"
|
||||
var QIDIAN_BASE = "https://h5.if.qidian.com"
|
||||
var CHECKIN_PATH = "/argus/api/v3/checkin/checkin"
|
||||
@@ -290,46 +292,73 @@ function resultMsg(obj) {
|
||||
if (!obj) return ""
|
||||
return obj.Message || obj.Msg || obj.message || obj.msg || obj.toast || (obj.data && (obj.data.message || obj.data.msg || obj.data.toast)) || ""
|
||||
}
|
||||
function setLastResult(uid, ok, msg) {
|
||||
var key = "qdreader_last_result_json"
|
||||
var obj = cleanStringMap(safeJsonParse(cfgGet(key, "{}"), {}))
|
||||
obj[String(uid)] = JSON.stringify({ ok: !!ok, msg: String(msg || ""), time: new Date().toISOString() })
|
||||
cfgSet(key, JSON.stringify(obj))
|
||||
function nowIso() { try { return new Date().toISOString() } catch (e) { return String(new Date()) } }
|
||||
function setLastResult(uid, result) {
|
||||
var obj = cleanStringMap(safeJsonParse(cfgGet(LAST_RESULT_KEY, "{}"), {}))
|
||||
obj[String(uid)] = JSON.stringify(result || {})
|
||||
cfgSet(LAST_RESULT_KEY, JSON.stringify(obj))
|
||||
}
|
||||
function getLastResults() {
|
||||
var raw = cleanStringMap(safeJsonParse(cfgGet("qdreader_last_result_json", "{}"), {}))
|
||||
var raw = cleanStringMap(safeJsonParse(cfgGet(LAST_RESULT_KEY, "{}"), {}))
|
||||
var out = {}
|
||||
for (var uid in raw) if (raw.hasOwnProperty(uid)) out[uid] = safeJsonParse(raw[uid], { msg: raw[uid] })
|
||||
return out
|
||||
}
|
||||
function doCheckin(uid, cookie) {
|
||||
function setLastRunLog(log) { cfgSet(LAST_RUN_KEY, JSON.stringify(log || {})) }
|
||||
function getLastRunLog() { return safeJsonParse(cfgGet(LAST_RUN_KEY, "{}"), {}) || {} }
|
||||
function sourceName(source) {
|
||||
if (source === "cron") return "定时任务"
|
||||
if (source === "menu") return "菜单立即执行"
|
||||
if (source === "manual") return "手动签到"
|
||||
return source || "未知"
|
||||
}
|
||||
function doCheckin(uid, cookie, source, runId) {
|
||||
var startedAt = nowIso()
|
||||
var res = qidianRequest(CHECKIN_PATH, "POST", {}, cookie)
|
||||
var ok = resultOk(res)
|
||||
var msg = resultMsg(res) || (ok ? "签到请求成功" : ("签到失败" + (resultCode(res) !== undefined ? " code=" + resultCode(res) : "")))
|
||||
setLastResult(uid, ok, msg)
|
||||
return { uid: uid, ok: ok, msg: msg, raw: res }
|
||||
var result = { uid: String(uid), ok: !!ok, msg: String(msg || ""), time: nowIso(), startedAt: startedAt, source: source || "manual", runId: runId || "" }
|
||||
setLastResult(uid, result)
|
||||
return { uid: uid, ok: ok, msg: msg, raw: res, log: result }
|
||||
}
|
||||
function signAll(targetUid, allUsers) {
|
||||
function signAll(targetUid, allUsers, source) {
|
||||
source = source || (allUsers ? "cron" : "manual")
|
||||
var startedAt = nowIso()
|
||||
var runId = startedAt.replace(/[-:.TZ]/g, "").slice(0, 14) + "_" + source
|
||||
var store = getStore()
|
||||
var bind = getBindStore()
|
||||
var remarks = getRemarkStore()
|
||||
var uids = visibleUids(store, bind, !!allUsers)
|
||||
if (targetUid) uids = uids.filter(function (u) { return u === targetUid })
|
||||
if (!uids.length) return targetUid ? ("未找到 uid: " + targetUid) : "还没有保存启点读书CK"
|
||||
if (!uids.length) {
|
||||
var emptyMsg = targetUid ? ("未找到 uid: " + targetUid) : "还没有保存启点读书CK"
|
||||
setLastRunLog({ runId: runId, source: source, startedAt: startedAt, finishedAt: nowIso(), targetUid: targetUid || "", total: 0, okCount: 0, failCount: 0, message: emptyMsg, items: [] })
|
||||
return emptyMsg
|
||||
}
|
||||
var okCount = 0
|
||||
var failCount = 0
|
||||
var items = []
|
||||
var lines = ["启点读书签到结果:"]
|
||||
for (var i = 0; i < uids.length; i++) {
|
||||
var uid = uids[i]
|
||||
try {
|
||||
var r = doCheckin(uid, store[uid])
|
||||
var r = doCheckin(uid, store[uid], source, runId)
|
||||
if (r.ok) okCount++; else failCount++
|
||||
lines.push((r.ok ? "✅ " : "❌ ") + maskUid(uid) + ":" + r.msg)
|
||||
items.push({ uid: String(uid), ok: !!r.ok, msg: String(r.msg || ""), time: r.log.time, remark: remarks[uid] || "" })
|
||||
lines.push((r.ok ? "✅ " : "❌ ") + maskUid(uid) + (remarks[uid] ? "(" + remarks[uid] + ")" : "") + ":" + r.msg)
|
||||
} catch (e) {
|
||||
failCount++
|
||||
lines.push("❌ " + maskUid(uid) + ":" + (e && e.message ? e.message : String(e)))
|
||||
var emsg = e && e.message ? e.message : String(e)
|
||||
var er = { uid: String(uid), ok: false, msg: emsg, time: nowIso(), startedAt: startedAt, source: source, runId: runId, error: true, remark: remarks[uid] || "" }
|
||||
setLastResult(uid, er)
|
||||
items.push(er)
|
||||
lines.push("❌ " + maskUid(uid) + (remarks[uid] ? "(" + remarks[uid] + ")" : "") + ":" + emsg)
|
||||
}
|
||||
}
|
||||
var finishedAt = nowIso()
|
||||
setLastRunLog({ runId: runId, source: source, startedAt: startedAt, finishedAt: finishedAt, targetUid: targetUid || "", allUsers: !!allUsers, total: uids.length, okCount: okCount, failCount: failCount, items: items })
|
||||
lines.push("汇总:成功 " + okCount + " / 失败 " + failCount + " / 总计 " + uids.length)
|
||||
lines.push("记录时间:" + finishedAt + "(" + sourceName(source) + ")")
|
||||
return lines.join("\n")
|
||||
}
|
||||
|
||||
@@ -343,6 +372,7 @@ function queryStatus(targetUid) {
|
||||
var store = getStore()
|
||||
var bind = getBindStore()
|
||||
var last = getLastResults()
|
||||
var run = getLastRunLog()
|
||||
var remarks = getRemarkStore()
|
||||
var uids = visibleUids(store, bind, false)
|
||||
if (targetUid) {
|
||||
@@ -350,7 +380,9 @@ function queryStatus(targetUid) {
|
||||
uids = [targetUid]
|
||||
}
|
||||
if (!uids.length) return "当前用户还没有保存启点读书CK"
|
||||
var lines = [targetUid ? "启点单账号执行情况:" : "启点执行情况:"]
|
||||
var title = targetUid ? "启点单账号最近签到记录:" : "启点最近签到记录:"
|
||||
var lines = [title]
|
||||
if (!targetUid && run && run.finishedAt) lines.push("最近批次:" + sourceName(run.source) + " @ " + run.finishedAt + ";成功 " + (run.okCount || 0) + " / 失败 " + (run.failCount || 0) + " / 总计 " + (run.total || 0))
|
||||
for (var i = 0; i < uids.length; i++) lines.push(formatStatusLine(uids[i], last, remarks))
|
||||
return lines.join("\n")
|
||||
}
|
||||
@@ -373,9 +405,9 @@ function accountMenuText() {
|
||||
}
|
||||
function queryMenuText() {
|
||||
return [
|
||||
"启点查询",
|
||||
"1. 查看最近执行情况",
|
||||
"2. 查询单个账号",
|
||||
"启点查询(最近签到记录)",
|
||||
"1. 查看最近签到记录",
|
||||
"2. 查询单个账号最近记录",
|
||||
"3. 立即执行签到",
|
||||
"q. 退出",
|
||||
"请回复序号"
|
||||
@@ -490,7 +522,7 @@ function queryMenu() {
|
||||
if (!uid) return reply("已退出")
|
||||
return reply(queryStatus(uid))
|
||||
}
|
||||
if (/^(3|执行|签到|立即)$/i.test(op)) return reply(signAll("", false))
|
||||
if (/^(3|执行|签到|立即)$/i.test(op)) return reply(signAll("", false, "menu"))
|
||||
return reply("未识别选项,已退出")
|
||||
}
|
||||
function handleDelete(arg, store, bind) {
|
||||
@@ -535,7 +567,7 @@ function main() {
|
||||
var bind = getBindStore()
|
||||
if (cmd === "sign" || /^(签到|sign|run)(?:\s+|$)/i.test(arg)) {
|
||||
var target = trim(arg.replace(/^(签到|sign|run)\s*/i, ""))
|
||||
var out = signAll(target, isCronRun)
|
||||
var out = signAll(target, isCronRun, isCronRun ? "cron" : "manual")
|
||||
if (!(isCronRun && getBool(CRON_SILENT_KEY, false) && out === "还没有保存启点读书CK")) reply(out)
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user