fix: push qdreader cron results to account owners
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
//[author: Hermes]
|
||||
//[service: BOSS]
|
||||
//[class: 工具类]
|
||||
// [version: 2.15.2]
|
||||
// [version: 2.15.3]
|
||||
// [platform: web,qq,wx,tg,tb,fs,we]
|
||||
// [public: false]
|
||||
// [price: 0]
|
||||
@@ -91,6 +91,22 @@ function reply(msg) {
|
||||
try { if (typeof push === "function") { push({ content: out }); return } } catch (e) {}
|
||||
try { console.log(out) } catch (e) {}
|
||||
}
|
||||
function pushToUser(userId, content) {
|
||||
userId = trim(userId || "")
|
||||
content = typeof content === "string" ? content : JSON.stringify(content)
|
||||
if (!userId || !content) return false
|
||||
if (typeof push !== "function") return false
|
||||
var payloads = [
|
||||
{ imType: "wx", userID: userId, content: content },
|
||||
{ imType: "we", userID: userId, content: content },
|
||||
{ imType: "web", userID: userId, content: content },
|
||||
{ userID: userId, content: content }
|
||||
]
|
||||
for (var i = 0; i < payloads.length; i++) {
|
||||
try { push(payloads[i]); return true } catch (e) {}
|
||||
}
|
||||
return false
|
||||
}
|
||||
function debug(msg) { try { if (typeof Debug === "function") Debug(String(msg)); else console.log(String(msg)) } catch (e) {} }
|
||||
|
||||
function cleanStringMap(obj) {
|
||||
@@ -286,7 +302,7 @@ function contentText() {
|
||||
}
|
||||
function usage() {
|
||||
return [
|
||||
"启点读书签到插件 v2.15.2",
|
||||
"启点读书签到插件 v2.15.3",
|
||||
"【一级菜单】",
|
||||
"账号管理:启点账号",
|
||||
"执行查询:启点查询",
|
||||
@@ -874,6 +890,7 @@ function signAll(targetUid, allUsers, source, archiveAfterRun) {
|
||||
var failCount = 0
|
||||
var items = []
|
||||
var accountReplies = []
|
||||
var accountNotices = []
|
||||
for (var i = 0; i < uids.length; i++) {
|
||||
var uid = uids[i]
|
||||
var prefix = "启点读书签到结果:\n"
|
||||
@@ -883,14 +900,18 @@ function signAll(targetUid, allUsers, source, archiveAfterRun) {
|
||||
var r = doCheckin(uid, store[uid], source, runId)
|
||||
if (r.ok) okCount++; else failCount++
|
||||
items.push({ uid: String(uid), ok: !!r.ok, msg: String(r.msg || ""), time: r.log.time, remark: remarks[uid] || "" })
|
||||
accountReplies.push(prefix + (r.ok ? "✅ " : "❌ ") + maskUid(uid) + suffix + ":" + r.msg)
|
||||
var msg = prefix + (r.ok ? "✅ " : "❌ ") + maskUid(uid) + suffix + ":" + r.msg
|
||||
accountReplies.push(msg)
|
||||
accountNotices.push({ uid: String(uid), owner: bind[String(uid)] || "", msg: msg })
|
||||
} catch (e) {
|
||||
failCount++
|
||||
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)
|
||||
accountReplies.push(prefix + "❌ " + maskUid(uid) + suffix + ":" + emsg)
|
||||
var errMsg = prefix + "❌ " + maskUid(uid) + suffix + ":" + emsg
|
||||
accountReplies.push(errMsg)
|
||||
accountNotices.push({ uid: String(uid), owner: bind[String(uid)] || "", msg: errMsg })
|
||||
}
|
||||
}
|
||||
var finishedAt = nowIso()
|
||||
@@ -898,9 +919,18 @@ function signAll(targetUid, allUsers, source, archiveAfterRun) {
|
||||
var tail = []
|
||||
tail.push("汇总:成功 " + okCount + " / 失败 " + failCount + " / 总计 " + uids.length)
|
||||
tail.push("记录时间:" + finishedAt + "(" + sourceName(source) + ")")
|
||||
var archiveLine = ""
|
||||
if (archiveAfterRun) {
|
||||
var ar = archiveRunLog(source + "-after-sign")
|
||||
if (ar && ar.archived) tail.push("日志已归档:" + ar.key)
|
||||
if (ar && ar.archived) { archiveLine = "日志已归档:" + ar.key; tail.push(archiveLine) }
|
||||
}
|
||||
if (allUsers && source === "cron") {
|
||||
for (var pi = 0; pi < accountNotices.length; pi++) {
|
||||
var notice = accountNotices[pi]
|
||||
var body = notice.msg + "\n" + tail.join("\n")
|
||||
if (!pushToUser(notice.owner, body)) debug("QDReader cron push skipped for uid " + notice.uid + ": empty owner or push unavailable")
|
||||
}
|
||||
return tail.join("\n")
|
||||
}
|
||||
if (accountReplies.length > 1) {
|
||||
for (var ai = 0; ai < accountReplies.length; ai++) reply(accountReplies[ai])
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
//[author: Hermes]
|
||||
//[service: BOSS]
|
||||
//[class: 工具类]
|
||||
// [version: 2.15.2]
|
||||
// [version: 2.15.3]
|
||||
// [platform: web,qq,wx,tg,tb,fs,we]
|
||||
// [public: false]
|
||||
// [price: 0]
|
||||
@@ -91,6 +91,22 @@ function reply(msg) {
|
||||
try { if (typeof push === "function") { push({ content: out }); return } } catch (e) {}
|
||||
try { console.log(out) } catch (e) {}
|
||||
}
|
||||
function pushToUser(userId, content) {
|
||||
userId = trim(userId || "")
|
||||
content = typeof content === "string" ? content : JSON.stringify(content)
|
||||
if (!userId || !content) return false
|
||||
if (typeof push !== "function") return false
|
||||
var payloads = [
|
||||
{ imType: "wx", userID: userId, content: content },
|
||||
{ imType: "we", userID: userId, content: content },
|
||||
{ imType: "web", userID: userId, content: content },
|
||||
{ userID: userId, content: content }
|
||||
]
|
||||
for (var i = 0; i < payloads.length; i++) {
|
||||
try { push(payloads[i]); return true } catch (e) {}
|
||||
}
|
||||
return false
|
||||
}
|
||||
function debug(msg) { try { if (typeof Debug === "function") Debug(String(msg)); else console.log(String(msg)) } catch (e) {} }
|
||||
|
||||
function cleanStringMap(obj) {
|
||||
@@ -286,7 +302,7 @@ function contentText() {
|
||||
}
|
||||
function usage() {
|
||||
return [
|
||||
"启点读书签到插件 v2.15.2",
|
||||
"启点读书签到插件 v2.15.3",
|
||||
"【一级菜单】",
|
||||
"账号管理:启点账号",
|
||||
"执行查询:启点查询",
|
||||
@@ -874,6 +890,7 @@ function signAll(targetUid, allUsers, source, archiveAfterRun) {
|
||||
var failCount = 0
|
||||
var items = []
|
||||
var accountReplies = []
|
||||
var accountNotices = []
|
||||
for (var i = 0; i < uids.length; i++) {
|
||||
var uid = uids[i]
|
||||
var prefix = "启点读书签到结果:\n"
|
||||
@@ -883,14 +900,18 @@ function signAll(targetUid, allUsers, source, archiveAfterRun) {
|
||||
var r = doCheckin(uid, store[uid], source, runId)
|
||||
if (r.ok) okCount++; else failCount++
|
||||
items.push({ uid: String(uid), ok: !!r.ok, msg: String(r.msg || ""), time: r.log.time, remark: remarks[uid] || "" })
|
||||
accountReplies.push(prefix + (r.ok ? "✅ " : "❌ ") + maskUid(uid) + suffix + ":" + r.msg)
|
||||
var msg = prefix + (r.ok ? "✅ " : "❌ ") + maskUid(uid) + suffix + ":" + r.msg
|
||||
accountReplies.push(msg)
|
||||
accountNotices.push({ uid: String(uid), owner: bind[String(uid)] || "", msg: msg })
|
||||
} catch (e) {
|
||||
failCount++
|
||||
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)
|
||||
accountReplies.push(prefix + "❌ " + maskUid(uid) + suffix + ":" + emsg)
|
||||
var errMsg = prefix + "❌ " + maskUid(uid) + suffix + ":" + emsg
|
||||
accountReplies.push(errMsg)
|
||||
accountNotices.push({ uid: String(uid), owner: bind[String(uid)] || "", msg: errMsg })
|
||||
}
|
||||
}
|
||||
var finishedAt = nowIso()
|
||||
@@ -898,9 +919,18 @@ function signAll(targetUid, allUsers, source, archiveAfterRun) {
|
||||
var tail = []
|
||||
tail.push("汇总:成功 " + okCount + " / 失败 " + failCount + " / 总计 " + uids.length)
|
||||
tail.push("记录时间:" + finishedAt + "(" + sourceName(source) + ")")
|
||||
var archiveLine = ""
|
||||
if (archiveAfterRun) {
|
||||
var ar = archiveRunLog(source + "-after-sign")
|
||||
if (ar && ar.archived) tail.push("日志已归档:" + ar.key)
|
||||
if (ar && ar.archived) { archiveLine = "日志已归档:" + ar.key; tail.push(archiveLine) }
|
||||
}
|
||||
if (allUsers && source === "cron") {
|
||||
for (var pi = 0; pi < accountNotices.length; pi++) {
|
||||
var notice = accountNotices[pi]
|
||||
var body = notice.msg + "\n" + tail.join("\n")
|
||||
if (!pushToUser(notice.owner, body)) debug("QDReader cron push skipped for uid " + notice.uid + ": empty owner or push unavailable")
|
||||
}
|
||||
return tail.join("\n")
|
||||
}
|
||||
if (accountReplies.length > 1) {
|
||||
for (var ai = 0; ai < accountReplies.length; ai++) reply(accountReplies[ai])
|
||||
|
||||
@@ -20,12 +20,16 @@ function fixedDateClass(iso) {
|
||||
|
||||
function runPlugin({ pluginCode = code, filename = pluginPath, content = '', store = {}, bucketStore = {}, requests = [], userId = 'user-a', listens = [], senderOverrides = {}, globals = {}, admin = true } = {}) {
|
||||
const replies = [];
|
||||
const pushes = [];
|
||||
const calls = [];
|
||||
let requestIndex = 0;
|
||||
let listenIndex = 0;
|
||||
const baseSender = {
|
||||
reply: (msg) => replies.push(String(msg)),
|
||||
push: (msg) => replies.push(typeof msg === 'string' ? msg : String((msg && (msg.content || msg.message || msg.text)) || JSON.stringify(msg))),
|
||||
push: (msg) => {
|
||||
pushes.push(msg);
|
||||
replies.push(typeof msg === 'string' ? msg : String((msg && (msg.content || msg.message || msg.text)) || JSON.stringify(msg)));
|
||||
},
|
||||
sendText: (msg) => replies.push(String(msg)),
|
||||
getMessage: () => content,
|
||||
getContent: () => content,
|
||||
@@ -38,7 +42,10 @@ function runPlugin({ pluginCode = code, filename = pluginPath, content = '', sto
|
||||
Buffer,
|
||||
sender: { ...baseSender, ...senderOverrides },
|
||||
sendText: (msg) => replies.push(String(msg)),
|
||||
push: (msg) => replies.push(typeof msg === 'string' ? msg : String((msg && (msg.content || msg.message || msg.text)) || JSON.stringify(msg))),
|
||||
push: (msg) => {
|
||||
pushes.push(msg);
|
||||
replies.push(typeof msg === 'string' ? msg : String((msg && (msg.content || msg.message || msg.text)) || JSON.stringify(msg)));
|
||||
},
|
||||
GetUserID: () => userId,
|
||||
GetContent: () => content,
|
||||
getContent: () => content,
|
||||
@@ -60,7 +67,7 @@ function runPlugin({ pluginCode = code, filename = pluginPath, content = '', sto
|
||||
};
|
||||
vm.createContext(ctx);
|
||||
vm.runInContext(pluginCode, ctx, { filename });
|
||||
return { replies, calls, store, bucketStore };
|
||||
return { replies, pushes, calls, store, bucketStore };
|
||||
}
|
||||
|
||||
const cookie = 'uid=12345; QDHeader=MTIzNDV8eA==; qdh=qdh; ywguid=guid; qimei=qimei; qimei36=qimei36; sessionyw=s; appId=10';
|
||||
@@ -769,9 +776,13 @@ test('cron detection uses ImType cron/fake and does not consume input as command
|
||||
},
|
||||
});
|
||||
assert.equal(r.calls.length, 4, imType);
|
||||
assert.equal(r.replies.length, 1, imType);
|
||||
assert.match(r.replies[0], /汇总:成功 1 \/ 失败 0 \/ 总计 1/, imType);
|
||||
assert.match(r.replies[0], /定时任务\/零点任务/, imType);
|
||||
assert.equal(r.replies.length, 2, imType);
|
||||
assert.equal(r.pushes.length, 1, imType);
|
||||
assert.equal(r.pushes[0].userID, 'user-a', imType);
|
||||
assert.match(r.pushes[0].content, /汇总:成功 1 \/ 失败 0 \/ 总计 1/, imType);
|
||||
assert.match(r.pushes[0].content, /日志已归档:2026-05-19/, imType);
|
||||
assert.match(r.replies.join('\n'), /汇总:成功 1 \/ 失败 0 \/ 总计 1/, imType);
|
||||
assert.match(r.replies.join('\n'), /定时任务\/零点任务/, imType);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -786,7 +797,9 @@ test('manual sign only runs current user accounts while cron runs all accounts',
|
||||
const cron = runPlugin({ content: '', store: { ...store }, userId: 'cron', globals: { Date: fixedDateClass('2026-05-19T07:01:00.000+08:00') } });
|
||||
assert.equal(cron.calls.length, 8);
|
||||
assert.equal(cron.replies.length, 3);
|
||||
assert.match(cron.replies[2], /总计 2/);
|
||||
assert.equal(cron.pushes.length, 2);
|
||||
assert.deepEqual(cron.pushes.map((p) => p.userID).sort(), ['user-a', 'user-b']);
|
||||
assert.match(cron.replies.join('\n'), /总计 2/);
|
||||
});
|
||||
|
||||
test('unbound global cookies are not visible or usable by normal users', () => {
|
||||
|
||||
Reference in New Issue
Block a user