fix: push qdreader cron results to account owners
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
//[author: Hermes]
|
//[author: Hermes]
|
||||||
//[service: BOSS]
|
//[service: BOSS]
|
||||||
//[class: 工具类]
|
//[class: 工具类]
|
||||||
// [version: 2.15.2]
|
// [version: 2.15.3]
|
||||||
// [platform: web,qq,wx,tg,tb,fs,we]
|
// [platform: web,qq,wx,tg,tb,fs,we]
|
||||||
// [public: false]
|
// [public: false]
|
||||||
// [price: 0]
|
// [price: 0]
|
||||||
@@ -91,6 +91,22 @@ function reply(msg) {
|
|||||||
try { if (typeof push === "function") { push({ content: out }); return } } catch (e) {}
|
try { if (typeof push === "function") { push({ content: out }); return } } catch (e) {}
|
||||||
try { console.log(out) } 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 debug(msg) { try { if (typeof Debug === "function") Debug(String(msg)); else console.log(String(msg)) } catch (e) {} }
|
||||||
|
|
||||||
function cleanStringMap(obj) {
|
function cleanStringMap(obj) {
|
||||||
@@ -286,7 +302,7 @@ function contentText() {
|
|||||||
}
|
}
|
||||||
function usage() {
|
function usage() {
|
||||||
return [
|
return [
|
||||||
"启点读书签到插件 v2.15.2",
|
"启点读书签到插件 v2.15.3",
|
||||||
"【一级菜单】",
|
"【一级菜单】",
|
||||||
"账号管理:启点账号",
|
"账号管理:启点账号",
|
||||||
"执行查询:启点查询",
|
"执行查询:启点查询",
|
||||||
@@ -874,6 +890,7 @@ function signAll(targetUid, allUsers, source, archiveAfterRun) {
|
|||||||
var failCount = 0
|
var failCount = 0
|
||||||
var items = []
|
var items = []
|
||||||
var accountReplies = []
|
var accountReplies = []
|
||||||
|
var accountNotices = []
|
||||||
for (var i = 0; i < uids.length; i++) {
|
for (var i = 0; i < uids.length; i++) {
|
||||||
var uid = uids[i]
|
var uid = uids[i]
|
||||||
var prefix = "启点读书签到结果:\n"
|
var prefix = "启点读书签到结果:\n"
|
||||||
@@ -883,14 +900,18 @@ function signAll(targetUid, allUsers, source, archiveAfterRun) {
|
|||||||
var r = doCheckin(uid, store[uid], source, runId)
|
var r = doCheckin(uid, store[uid], source, runId)
|
||||||
if (r.ok) okCount++; else failCount++
|
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] || "" })
|
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) {
|
} catch (e) {
|
||||||
failCount++
|
failCount++
|
||||||
var emsg = 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] || "" }
|
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)
|
setLastResult(uid, er)
|
||||||
items.push(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()
|
var finishedAt = nowIso()
|
||||||
@@ -898,9 +919,18 @@ function signAll(targetUid, allUsers, source, archiveAfterRun) {
|
|||||||
var tail = []
|
var tail = []
|
||||||
tail.push("汇总:成功 " + okCount + " / 失败 " + failCount + " / 总计 " + uids.length)
|
tail.push("汇总:成功 " + okCount + " / 失败 " + failCount + " / 总计 " + uids.length)
|
||||||
tail.push("记录时间:" + finishedAt + "(" + sourceName(source) + ")")
|
tail.push("记录时间:" + finishedAt + "(" + sourceName(source) + ")")
|
||||||
|
var archiveLine = ""
|
||||||
if (archiveAfterRun) {
|
if (archiveAfterRun) {
|
||||||
var ar = archiveRunLog(source + "-after-sign")
|
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) {
|
if (accountReplies.length > 1) {
|
||||||
for (var ai = 0; ai < accountReplies.length; ai++) reply(accountReplies[ai])
|
for (var ai = 0; ai < accountReplies.length; ai++) reply(accountReplies[ai])
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
//[author: Hermes]
|
//[author: Hermes]
|
||||||
//[service: BOSS]
|
//[service: BOSS]
|
||||||
//[class: 工具类]
|
//[class: 工具类]
|
||||||
// [version: 2.15.2]
|
// [version: 2.15.3]
|
||||||
// [platform: web,qq,wx,tg,tb,fs,we]
|
// [platform: web,qq,wx,tg,tb,fs,we]
|
||||||
// [public: false]
|
// [public: false]
|
||||||
// [price: 0]
|
// [price: 0]
|
||||||
@@ -91,6 +91,22 @@ function reply(msg) {
|
|||||||
try { if (typeof push === "function") { push({ content: out }); return } } catch (e) {}
|
try { if (typeof push === "function") { push({ content: out }); return } } catch (e) {}
|
||||||
try { console.log(out) } 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 debug(msg) { try { if (typeof Debug === "function") Debug(String(msg)); else console.log(String(msg)) } catch (e) {} }
|
||||||
|
|
||||||
function cleanStringMap(obj) {
|
function cleanStringMap(obj) {
|
||||||
@@ -286,7 +302,7 @@ function contentText() {
|
|||||||
}
|
}
|
||||||
function usage() {
|
function usage() {
|
||||||
return [
|
return [
|
||||||
"启点读书签到插件 v2.15.2",
|
"启点读书签到插件 v2.15.3",
|
||||||
"【一级菜单】",
|
"【一级菜单】",
|
||||||
"账号管理:启点账号",
|
"账号管理:启点账号",
|
||||||
"执行查询:启点查询",
|
"执行查询:启点查询",
|
||||||
@@ -874,6 +890,7 @@ function signAll(targetUid, allUsers, source, archiveAfterRun) {
|
|||||||
var failCount = 0
|
var failCount = 0
|
||||||
var items = []
|
var items = []
|
||||||
var accountReplies = []
|
var accountReplies = []
|
||||||
|
var accountNotices = []
|
||||||
for (var i = 0; i < uids.length; i++) {
|
for (var i = 0; i < uids.length; i++) {
|
||||||
var uid = uids[i]
|
var uid = uids[i]
|
||||||
var prefix = "启点读书签到结果:\n"
|
var prefix = "启点读书签到结果:\n"
|
||||||
@@ -883,14 +900,18 @@ function signAll(targetUid, allUsers, source, archiveAfterRun) {
|
|||||||
var r = doCheckin(uid, store[uid], source, runId)
|
var r = doCheckin(uid, store[uid], source, runId)
|
||||||
if (r.ok) okCount++; else failCount++
|
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] || "" })
|
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) {
|
} catch (e) {
|
||||||
failCount++
|
failCount++
|
||||||
var emsg = 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] || "" }
|
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)
|
setLastResult(uid, er)
|
||||||
items.push(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()
|
var finishedAt = nowIso()
|
||||||
@@ -898,9 +919,18 @@ function signAll(targetUid, allUsers, source, archiveAfterRun) {
|
|||||||
var tail = []
|
var tail = []
|
||||||
tail.push("汇总:成功 " + okCount + " / 失败 " + failCount + " / 总计 " + uids.length)
|
tail.push("汇总:成功 " + okCount + " / 失败 " + failCount + " / 总计 " + uids.length)
|
||||||
tail.push("记录时间:" + finishedAt + "(" + sourceName(source) + ")")
|
tail.push("记录时间:" + finishedAt + "(" + sourceName(source) + ")")
|
||||||
|
var archiveLine = ""
|
||||||
if (archiveAfterRun) {
|
if (archiveAfterRun) {
|
||||||
var ar = archiveRunLog(source + "-after-sign")
|
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) {
|
if (accountReplies.length > 1) {
|
||||||
for (var ai = 0; ai < accountReplies.length; ai++) reply(accountReplies[ai])
|
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 } = {}) {
|
function runPlugin({ pluginCode = code, filename = pluginPath, content = '', store = {}, bucketStore = {}, requests = [], userId = 'user-a', listens = [], senderOverrides = {}, globals = {}, admin = true } = {}) {
|
||||||
const replies = [];
|
const replies = [];
|
||||||
|
const pushes = [];
|
||||||
const calls = [];
|
const calls = [];
|
||||||
let requestIndex = 0;
|
let requestIndex = 0;
|
||||||
let listenIndex = 0;
|
let listenIndex = 0;
|
||||||
const baseSender = {
|
const baseSender = {
|
||||||
reply: (msg) => replies.push(String(msg)),
|
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)),
|
sendText: (msg) => replies.push(String(msg)),
|
||||||
getMessage: () => content,
|
getMessage: () => content,
|
||||||
getContent: () => content,
|
getContent: () => content,
|
||||||
@@ -38,7 +42,10 @@ function runPlugin({ pluginCode = code, filename = pluginPath, content = '', sto
|
|||||||
Buffer,
|
Buffer,
|
||||||
sender: { ...baseSender, ...senderOverrides },
|
sender: { ...baseSender, ...senderOverrides },
|
||||||
sendText: (msg) => replies.push(String(msg)),
|
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,
|
GetUserID: () => userId,
|
||||||
GetContent: () => content,
|
GetContent: () => content,
|
||||||
getContent: () => content,
|
getContent: () => content,
|
||||||
@@ -60,7 +67,7 @@ function runPlugin({ pluginCode = code, filename = pluginPath, content = '', sto
|
|||||||
};
|
};
|
||||||
vm.createContext(ctx);
|
vm.createContext(ctx);
|
||||||
vm.runInContext(pluginCode, ctx, { filename });
|
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';
|
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.calls.length, 4, imType);
|
||||||
assert.equal(r.replies.length, 1, imType);
|
assert.equal(r.replies.length, 2, imType);
|
||||||
assert.match(r.replies[0], /汇总:成功 1 \/ 失败 0 \/ 总计 1/, imType);
|
assert.equal(r.pushes.length, 1, imType);
|
||||||
assert.match(r.replies[0], /定时任务\/零点任务/, 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') } });
|
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.calls.length, 8);
|
||||||
assert.equal(cron.replies.length, 3);
|
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', () => {
|
test('unbound global cookies are not visible or usable by normal users', () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user