fix(qdreader): format query logs for readability
This commit is contained in:
@@ -69,7 +69,7 @@ GET /api/sms/stats
|
|||||||
- 定时运行:`cron: 1 7 * * *`,每日 07:01 自动签到;签到结束后立即归档并清空最近运行日志
|
- 定时运行:`cron: 1 7 * * *`,每日 07:01 自动签到;签到结束后立即归档并清空最近运行日志
|
||||||
- 手动运行:`启点签到` / `启点签到 <uid>`
|
- 手动运行:`启点签到` / `启点签到 <uid>`
|
||||||
- Cookie 维护:`启点账号` / `启点ck <cookie>` / `启点查询`
|
- Cookie 维护:`启点账号` / `启点ck <cookie>` / `启点查询`
|
||||||
- v2.5.7:保持单插件;定时只负责 07:01 签到,每次签到结束后立即归档运行日志,不再依赖零点归档定时。
|
- v2.5.8:保持单插件;定时只负责 07:01 签到,每次签到结束后立即归档运行日志;查询结果按批次/来源/汇总/明细排版并截断过长原始消息。
|
||||||
|
|
||||||
Raw 导入:
|
Raw 导入:
|
||||||
|
|
||||||
|
|||||||
+43
-22
@@ -4,7 +4,7 @@
|
|||||||
//[author: Hermes]
|
//[author: Hermes]
|
||||||
//[service: BOSS]
|
//[service: BOSS]
|
||||||
//[class: 工具类]
|
//[class: 工具类]
|
||||||
//[version: 2.5.7]
|
//[version: 2.5.8]
|
||||||
//[platform: web,qq,wx,tg,tb,fs,we]
|
//[platform: web,qq,wx,tg,tb,fs,we]
|
||||||
//[public: false]
|
//[public: false]
|
||||||
//[price: 0]
|
//[price: 0]
|
||||||
@@ -260,7 +260,7 @@ function contentText() {
|
|||||||
}
|
}
|
||||||
function usage() {
|
function usage() {
|
||||||
return [
|
return [
|
||||||
"启点读书签到插件 v2.5.7",
|
"启点读书签到插件 v2.5.8",
|
||||||
"【一级菜单】",
|
"【一级菜单】",
|
||||||
"账号管理:启点账号",
|
"账号管理:启点账号",
|
||||||
"执行查询:启点查询",
|
"执行查询:启点查询",
|
||||||
@@ -527,17 +527,35 @@ function signAll(targetUid, allUsers, source, archiveAfterRun) {
|
|||||||
return lines.join("\n")
|
return lines.join("\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatStatusLine(uid, last, remarks) {
|
function shortTime(iso) {
|
||||||
var name = maskUid(uid) + (remarks && remarks[uid] ? "(" + remarks[uid] + ")" : "")
|
if (!iso) return "未知时间"
|
||||||
var r = last[uid]
|
var s = String(iso)
|
||||||
if (!r) return "- " + name + ":暂无执行记录"
|
var m = s.match(/(\d{4}-\d{2}-\d{2})[T ](\d{2}:\d{2})/)
|
||||||
return "- " + name + ":" + (r.ok ? "✅ " : "❌ ") + (r.msg || "无结果") + (r.time ? " @ " + r.time : "")
|
if (m) return m[1] + " " + m[2]
|
||||||
|
return s.replace(/\.\d{3}Z$/, "Z")
|
||||||
}
|
}
|
||||||
function formatArchiveStatusLine(uid, archiveInfo, remarks) {
|
function displayMsg(msg) {
|
||||||
var name = maskUid(uid) + (remarks && remarks[uid] ? "(" + remarks[uid] + ")" : "")
|
msg = trim(msg || "无结果")
|
||||||
var r = archiveInfo && archiveInfo.itemMap ? archiveInfo.itemMap[String(uid)] : null
|
if (!msg) return "无结果"
|
||||||
if (!r) return "- " + name + ":归档中暂无该账号记录"
|
msg = msg.replace(/\s+/g, " ")
|
||||||
return "- " + name + ":" + (r.ok ? "✅ " : "❌ ") + (r.msg || "无结果") + (r.time ? " @ " + r.time : "")
|
if (msg.length > 60) msg = msg.slice(0, 57) + "..."
|
||||||
|
return msg
|
||||||
|
}
|
||||||
|
function accountName(uid, remarks) {
|
||||||
|
return maskUid(uid) + (remarks && remarks[uid] ? "(" + remarks[uid] + ")" : "")
|
||||||
|
}
|
||||||
|
function formatResultLine(uid, r, remarks, emptyText) {
|
||||||
|
var name = accountName(uid, remarks)
|
||||||
|
if (!r) return "• " + name + ":⚪ " + (emptyText || "暂无执行记录")
|
||||||
|
return "• " + name + ":" + (r.ok ? "✅ " : "❌ ") + displayMsg(r.msg) + (r.time ? "\n 时间:" + shortTime(r.time) : "")
|
||||||
|
}
|
||||||
|
function formatRunSummary(log, label, key) {
|
||||||
|
log = log || {}
|
||||||
|
var lines = []
|
||||||
|
lines.push((label || "最近批次") + (key ? ":" + key : ""))
|
||||||
|
lines.push("来源:" + sourceName(log.source) + " | 时间:" + shortTime(log.finishedAt))
|
||||||
|
lines.push("汇总:✅ " + (log.okCount || 0) + " | ❌ " + (log.failCount || 0) + " | 总计 " + (log.total || 0))
|
||||||
|
return lines
|
||||||
}
|
}
|
||||||
function queryStatus(targetUid) {
|
function queryStatus(targetUid) {
|
||||||
var store = getStore()
|
var store = getStore()
|
||||||
@@ -551,20 +569,23 @@ function queryStatus(targetUid) {
|
|||||||
uids = [targetUid]
|
uids = [targetUid]
|
||||||
}
|
}
|
||||||
if (!uids.length) return "当前用户还没有保存启点读书CK"
|
if (!uids.length) return "当前用户还没有保存启点读书CK"
|
||||||
var title = targetUid ? "启点单账号最近签到记录:" : "启点最近签到记录:"
|
|
||||||
var archiveInfo = latestArchiveForVisible(uids)
|
var archiveInfo = latestArchiveForVisible(uids)
|
||||||
var useArchive = archiveInfo && (!run || !run.finishedAt)
|
var useArchive = archiveInfo && (!run || !run.finishedAt)
|
||||||
if (useArchive) title = targetUid ? "启点单账号最近归档签到记录:" : "启点最近归档签到记录:"
|
var lines = []
|
||||||
var lines = [title]
|
|
||||||
if (useArchive) {
|
if (useArchive) {
|
||||||
var arun = archiveInfo.log || {}
|
var arun = archiveInfo.log || {}
|
||||||
lines.push("最近归档:" + archiveInfo.key + ";" + sourceName(arun.source) + " @ " + (arun.finishedAt || "未知时间") + ";成功 " + (arun.okCount || 0) + " / 失败 " + (arun.failCount || 0) + " / 总计 " + (arun.total || 0))
|
lines.push(targetUid ? "启点单账号最近签到记录" : "启点最近签到记录")
|
||||||
for (var ai = 0; ai < uids.length; ai++) lines.push(formatArchiveStatusLine(uids[ai], archiveInfo, remarks))
|
lines = lines.concat(formatRunSummary(arun, "归档批次", archiveInfo.key))
|
||||||
} else {
|
lines.push("结果明细:")
|
||||||
if (!targetUid && run && run.finishedAt) lines.push("最近批次:" + sourceName(run.source) + " @ " + run.finishedAt + ";成功 " + (run.okCount || 0) + " / 失败 " + (run.failCount || 0) + " / 总计 " + (run.total || 0))
|
for (var ai = 0; ai < uids.length; ai++) lines.push(formatResultLine(uids[ai], archiveInfo.itemMap[String(uids[ai])], remarks, "归档中暂无该账号记录"))
|
||||||
for (var i = 0; i < uids.length; i++) lines.push(formatStatusLine(uids[i], last, remarks))
|
return lines.join("\n")
|
||||||
if (archiveInfo) lines.push("最近归档:" + archiveInfo.key + "(发送启点查询可按归档判断昨日签到)")
|
|
||||||
}
|
}
|
||||||
|
lines.push(targetUid ? "启点单账号最近签到记录" : "启点最近签到记录")
|
||||||
|
if (!targetUid && run && run.finishedAt) lines = lines.concat(formatRunSummary(run, "最近批次", ""))
|
||||||
|
else if (run && run.finishedAt) lines.push("时间:" + shortTime(run.finishedAt) + " | 来源:" + sourceName(run.source))
|
||||||
|
lines.push("结果明细:")
|
||||||
|
for (var i = 0; i < uids.length; i++) lines.push(formatResultLine(uids[i], last[uids[i]], remarks, "暂无执行记录"))
|
||||||
|
if (archiveInfo) lines.push("历史归档:" + archiveInfo.key + "(可用于判断最近一次签到)")
|
||||||
return lines.join("\n")
|
return lines.join("\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -651,7 +672,7 @@ function accountDetailText(uid, store, bind) {
|
|||||||
"uid: " + maskUid(uid),
|
"uid: " + maskUid(uid),
|
||||||
"备注: " + (remarks[uid] || "未设置"),
|
"备注: " + (remarks[uid] || "未设置"),
|
||||||
"cookie: " + maskCookie(store[uid]),
|
"cookie: " + maskCookie(store[uid]),
|
||||||
formatStatusLine(uid, last, remarks),
|
formatResultLine(uid, last[uid], remarks, "暂无执行记录"),
|
||||||
"修改备注请回复新备注名,发送 清空 可删除备注,发送 q 退出"
|
"修改备注请回复新备注名,发送 清空 可删除备注,发送 q 退出"
|
||||||
].join("\n")
|
].join("\n")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ qdreader_last_result_json # 每个 uid 当日/当前批次结果
|
|||||||
qdreader_archive_json # 每次签到后立即归档的历史批次
|
qdreader_archive_json # 每次签到后立即归档的历史批次
|
||||||
```
|
```
|
||||||
|
|
||||||
因此“查询”语义是“最近签到记录/最后执行日志”。刚添加但从未执行过的账号会显示“暂无执行记录”。因为签到完成后最近日志会立即归档并清空,`启点查询` 会回退到最近归档,根据归档中的账号结果判断最近签到情况并反馈给用户。
|
因此“查询”语义是“最近签到记录/最后执行日志”。刚添加但从未执行过的账号会显示“暂无执行记录”。因为签到完成后最近日志会立即归档并清空,`启点查询` 会回退到最近归档,根据归档中的账号结果判断最近签到情况并反馈给用户。查询输出会加工成“批次/来源/汇总/结果明细”结构,时间压缩到分钟,过长的接口错误/原始响应会截断,避免刷屏。
|
||||||
|
|
||||||
## 本地验证
|
## 本地验证
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
//[author: Hermes]
|
//[author: Hermes]
|
||||||
//[service: BOSS]
|
//[service: BOSS]
|
||||||
//[class: 工具类]
|
//[class: 工具类]
|
||||||
//[version: 2.5.7]
|
//[version: 2.5.8]
|
||||||
//[platform: web,qq,wx,tg,tb,fs,we]
|
//[platform: web,qq,wx,tg,tb,fs,we]
|
||||||
//[public: false]
|
//[public: false]
|
||||||
//[price: 0]
|
//[price: 0]
|
||||||
@@ -260,7 +260,7 @@ function contentText() {
|
|||||||
}
|
}
|
||||||
function usage() {
|
function usage() {
|
||||||
return [
|
return [
|
||||||
"启点读书签到插件 v2.5.7",
|
"启点读书签到插件 v2.5.8",
|
||||||
"【一级菜单】",
|
"【一级菜单】",
|
||||||
"账号管理:启点账号",
|
"账号管理:启点账号",
|
||||||
"执行查询:启点查询",
|
"执行查询:启点查询",
|
||||||
@@ -527,17 +527,35 @@ function signAll(targetUid, allUsers, source, archiveAfterRun) {
|
|||||||
return lines.join("\n")
|
return lines.join("\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatStatusLine(uid, last, remarks) {
|
function shortTime(iso) {
|
||||||
var name = maskUid(uid) + (remarks && remarks[uid] ? "(" + remarks[uid] + ")" : "")
|
if (!iso) return "未知时间"
|
||||||
var r = last[uid]
|
var s = String(iso)
|
||||||
if (!r) return "- " + name + ":暂无执行记录"
|
var m = s.match(/(\d{4}-\d{2}-\d{2})[T ](\d{2}:\d{2})/)
|
||||||
return "- " + name + ":" + (r.ok ? "✅ " : "❌ ") + (r.msg || "无结果") + (r.time ? " @ " + r.time : "")
|
if (m) return m[1] + " " + m[2]
|
||||||
|
return s.replace(/\.\d{3}Z$/, "Z")
|
||||||
}
|
}
|
||||||
function formatArchiveStatusLine(uid, archiveInfo, remarks) {
|
function displayMsg(msg) {
|
||||||
var name = maskUid(uid) + (remarks && remarks[uid] ? "(" + remarks[uid] + ")" : "")
|
msg = trim(msg || "无结果")
|
||||||
var r = archiveInfo && archiveInfo.itemMap ? archiveInfo.itemMap[String(uid)] : null
|
if (!msg) return "无结果"
|
||||||
if (!r) return "- " + name + ":归档中暂无该账号记录"
|
msg = msg.replace(/\s+/g, " ")
|
||||||
return "- " + name + ":" + (r.ok ? "✅ " : "❌ ") + (r.msg || "无结果") + (r.time ? " @ " + r.time : "")
|
if (msg.length > 60) msg = msg.slice(0, 57) + "..."
|
||||||
|
return msg
|
||||||
|
}
|
||||||
|
function accountName(uid, remarks) {
|
||||||
|
return maskUid(uid) + (remarks && remarks[uid] ? "(" + remarks[uid] + ")" : "")
|
||||||
|
}
|
||||||
|
function formatResultLine(uid, r, remarks, emptyText) {
|
||||||
|
var name = accountName(uid, remarks)
|
||||||
|
if (!r) return "• " + name + ":⚪ " + (emptyText || "暂无执行记录")
|
||||||
|
return "• " + name + ":" + (r.ok ? "✅ " : "❌ ") + displayMsg(r.msg) + (r.time ? "\n 时间:" + shortTime(r.time) : "")
|
||||||
|
}
|
||||||
|
function formatRunSummary(log, label, key) {
|
||||||
|
log = log || {}
|
||||||
|
var lines = []
|
||||||
|
lines.push((label || "最近批次") + (key ? ":" + key : ""))
|
||||||
|
lines.push("来源:" + sourceName(log.source) + " | 时间:" + shortTime(log.finishedAt))
|
||||||
|
lines.push("汇总:✅ " + (log.okCount || 0) + " | ❌ " + (log.failCount || 0) + " | 总计 " + (log.total || 0))
|
||||||
|
return lines
|
||||||
}
|
}
|
||||||
function queryStatus(targetUid) {
|
function queryStatus(targetUid) {
|
||||||
var store = getStore()
|
var store = getStore()
|
||||||
@@ -551,20 +569,23 @@ function queryStatus(targetUid) {
|
|||||||
uids = [targetUid]
|
uids = [targetUid]
|
||||||
}
|
}
|
||||||
if (!uids.length) return "当前用户还没有保存启点读书CK"
|
if (!uids.length) return "当前用户还没有保存启点读书CK"
|
||||||
var title = targetUid ? "启点单账号最近签到记录:" : "启点最近签到记录:"
|
|
||||||
var archiveInfo = latestArchiveForVisible(uids)
|
var archiveInfo = latestArchiveForVisible(uids)
|
||||||
var useArchive = archiveInfo && (!run || !run.finishedAt)
|
var useArchive = archiveInfo && (!run || !run.finishedAt)
|
||||||
if (useArchive) title = targetUid ? "启点单账号最近归档签到记录:" : "启点最近归档签到记录:"
|
var lines = []
|
||||||
var lines = [title]
|
|
||||||
if (useArchive) {
|
if (useArchive) {
|
||||||
var arun = archiveInfo.log || {}
|
var arun = archiveInfo.log || {}
|
||||||
lines.push("最近归档:" + archiveInfo.key + ";" + sourceName(arun.source) + " @ " + (arun.finishedAt || "未知时间") + ";成功 " + (arun.okCount || 0) + " / 失败 " + (arun.failCount || 0) + " / 总计 " + (arun.total || 0))
|
lines.push(targetUid ? "启点单账号最近签到记录" : "启点最近签到记录")
|
||||||
for (var ai = 0; ai < uids.length; ai++) lines.push(formatArchiveStatusLine(uids[ai], archiveInfo, remarks))
|
lines = lines.concat(formatRunSummary(arun, "归档批次", archiveInfo.key))
|
||||||
} else {
|
lines.push("结果明细:")
|
||||||
if (!targetUid && run && run.finishedAt) lines.push("最近批次:" + sourceName(run.source) + " @ " + run.finishedAt + ";成功 " + (run.okCount || 0) + " / 失败 " + (run.failCount || 0) + " / 总计 " + (run.total || 0))
|
for (var ai = 0; ai < uids.length; ai++) lines.push(formatResultLine(uids[ai], archiveInfo.itemMap[String(uids[ai])], remarks, "归档中暂无该账号记录"))
|
||||||
for (var i = 0; i < uids.length; i++) lines.push(formatStatusLine(uids[i], last, remarks))
|
return lines.join("\n")
|
||||||
if (archiveInfo) lines.push("最近归档:" + archiveInfo.key + "(发送启点查询可按归档判断昨日签到)")
|
|
||||||
}
|
}
|
||||||
|
lines.push(targetUid ? "启点单账号最近签到记录" : "启点最近签到记录")
|
||||||
|
if (!targetUid && run && run.finishedAt) lines = lines.concat(formatRunSummary(run, "最近批次", ""))
|
||||||
|
else if (run && run.finishedAt) lines.push("时间:" + shortTime(run.finishedAt) + " | 来源:" + sourceName(run.source))
|
||||||
|
lines.push("结果明细:")
|
||||||
|
for (var i = 0; i < uids.length; i++) lines.push(formatResultLine(uids[i], last[uids[i]], remarks, "暂无执行记录"))
|
||||||
|
if (archiveInfo) lines.push("历史归档:" + archiveInfo.key + "(可用于判断最近一次签到)")
|
||||||
return lines.join("\n")
|
return lines.join("\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -651,7 +672,7 @@ function accountDetailText(uid, store, bind) {
|
|||||||
"uid: " + maskUid(uid),
|
"uid: " + maskUid(uid),
|
||||||
"备注: " + (remarks[uid] || "未设置"),
|
"备注: " + (remarks[uid] || "未设置"),
|
||||||
"cookie: " + maskCookie(store[uid]),
|
"cookie: " + maskCookie(store[uid]),
|
||||||
formatStatusLine(uid, last, remarks),
|
formatResultLine(uid, last[uid], remarks, "暂无执行记录"),
|
||||||
"修改备注请回复新备注名,发送 清空 可删除备注,发送 q 退出"
|
"修改备注请回复新备注名,发送 清空 可删除备注,发送 q 退出"
|
||||||
].join("\n")
|
].join("\n")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -289,10 +289,33 @@ test('query falls back to archived sign results after daily log was cleared', ()
|
|||||||
qdreader_archive_json: JSON.stringify({ '2026-05-18': archiveRun }),
|
qdreader_archive_json: JSON.stringify({ '2026-05-18': archiveRun }),
|
||||||
};
|
};
|
||||||
const r = runPlugin({ content: '启点查询', store, userId: 'user-a', listens: ['1'] });
|
const r = runPlugin({ content: '启点查询', store, userId: 'user-a', listens: ['1'] });
|
||||||
assert.match(r.replies[1], /启点最近归档签到记录/);
|
assert.match(r.replies[1], /启点最近签到记录/);
|
||||||
assert.match(r.replies[1], /最近归档:2026-05-18/);
|
assert.match(r.replies[1], /归档批次:2026-05-18/);
|
||||||
assert.match(r.replies[1], /12\*\*\*45(主号):✅ 签到成功/);
|
assert.match(r.replies[1], /汇总:✅ 1 | ❌ 1 | 总计 2/);
|
||||||
assert.match(r.replies[1], /67\*\*\*90(副号):❌ Cookie失效/);
|
assert.match(r.replies[1], /• 12\*\*\*45(主号):✅ 签到成功/);
|
||||||
|
assert.match(r.replies[1], /• 67\*\*\*90(副号):❌ Cookie失效/);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('query output shortens timestamps and long raw messages for readability', () => {
|
||||||
|
const archiveRun = {
|
||||||
|
source: 'cron',
|
||||||
|
finishedAt: '2026-05-18T07:15:02.123Z',
|
||||||
|
total: 1,
|
||||||
|
okCount: 0,
|
||||||
|
failCount: 1,
|
||||||
|
items: [
|
||||||
|
{ uid: '12345', ok: false, msg: 'Error: very long upstream response payload with stack trace and raw json body that should not flood chat output', time: '2026-05-18T07:15:01.456Z' },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
const store = {
|
||||||
|
qdreader_cookie_json: JSON.stringify({ '12345': cookie }),
|
||||||
|
qdreader_user_bind_json: JSON.stringify({ '12345': 'user-a' }),
|
||||||
|
qdreader_archive_json: JSON.stringify({ '2026-05-18': archiveRun }),
|
||||||
|
};
|
||||||
|
const r = runPlugin({ content: '启点查询', store, userId: 'user-a', listens: ['1'] });
|
||||||
|
assert.match(r.replies[1], /时间:2026-05-18 07:15/);
|
||||||
|
assert.match(r.replies[1], /Error: very long upstream response payload with stack tra\.\.\./);
|
||||||
|
assert.doesNotMatch(r.replies[1], /raw json body that should not flood/);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('manual sign and cron sign both call sign gateway then qidian checkin', () => {
|
test('manual sign and cron sign both call sign gateway then qidian checkin', () => {
|
||||||
@@ -393,7 +416,9 @@ test('query command shows last sign log not account management', () => {
|
|||||||
const r = runPlugin({ content: '启点查询', store, userId: 'user-a', listens: ['1'] });
|
const r = runPlugin({ content: '启点查询', store, userId: 'user-a', listens: ['1'] });
|
||||||
assert.match(r.replies[0], /启点查询/);
|
assert.match(r.replies[0], /启点查询/);
|
||||||
assert.match(r.replies[1], /启点最近签到记录/);
|
assert.match(r.replies[1], /启点最近签到记录/);
|
||||||
assert.match(r.replies[1], /最近批次:定时任务/);
|
assert.match(r.replies[1], /最近批次/);
|
||||||
|
assert.match(r.replies[1], /来源:定时任务/);
|
||||||
|
assert.match(r.replies[1], /汇总:✅ 1 | ❌ 1 | 总计 2/);
|
||||||
assert.match(r.replies[1], /12\*\*\*45/);
|
assert.match(r.replies[1], /12\*\*\*45/);
|
||||||
assert.match(r.replies[1], /主号/);
|
assert.match(r.replies[1], /主号/);
|
||||||
assert.match(r.replies[1], /签到成功/);
|
assert.match(r.replies[1], /签到成功/);
|
||||||
|
|||||||
Reference in New Issue
Block a user