160 lines
5.5 KiB
JavaScript
160 lines
5.5 KiB
JavaScript
//[open_source: true]
|
|
//[create_at: 2026-05-17 03:00:00]
|
|
//[title: 起点读书CK]
|
|
//[author: Hermes]
|
|
//[service: BOSS]
|
|
//[class: 工具类]
|
|
//[version: 1.1.0]
|
|
//[platform: web,qq,wx,tg,tb]
|
|
//[public: false]
|
|
//[price: 0]
|
|
//[disable: false]
|
|
//[description: 起点读书(QDReader) Autman 机器人交互插件:把 QX 抓到的 Cookie 发给机器人即可保存,按 uid 自动新增/更新;支持查询、删除、导出 QDREADER_COOKIE。]
|
|
//[rule: ^起点(ck|CK|cookie|Cookie)(.*)$]
|
|
//[rule: ^qdreader(.*)$]
|
|
//[param: {"required":false,"key":"otto.qdreader_cookie_json","bool":false,"placeholder":"{\"uid\":\"cookie\"}","name":"QDReader Cookie JSON","desc":"机器人交互维护,JSON Map 格式"}]
|
|
|
|
var STORE_KEY = "qdreader_cookie_json"
|
|
|
|
function reply(msg) {
|
|
if (typeof sender !== "undefined" && sender.reply) sender.reply(msg)
|
|
else if (typeof sendText === "function") sendText(typeof msg === "string" ? msg : JSON.stringify(msg))
|
|
else console.log(typeof msg === "string" ? msg : JSON.stringify(msg))
|
|
}
|
|
function safeJsonParse(s, def) { try { return JSON.parse(s) } catch (e) { return def } }
|
|
function getStore() {
|
|
var raw = get(STORE_KEY) || "{}"
|
|
var obj = safeJsonParse(raw, {})
|
|
if (!obj || typeof obj !== "object" || Array.isArray(obj)) return {}
|
|
return obj
|
|
}
|
|
function setStore(obj) {
|
|
var s = JSON.stringify(obj)
|
|
set(STORE_KEY, s)
|
|
return s
|
|
}
|
|
function parseCookieString(cookie) {
|
|
var jar = {}
|
|
String(cookie || "").split(";").forEach(function (part) {
|
|
var i = part.indexOf("=")
|
|
if (i <= 0) return
|
|
var k = part.slice(0, i).trim()
|
|
var v = part.slice(i + 1).trim()
|
|
if (k) jar[k] = v
|
|
})
|
|
return jar
|
|
}
|
|
function b64decode(s) {
|
|
s = String(s || "")
|
|
try { if (typeof Buffer !== "undefined") return Buffer.from(s, "base64").toString("utf8") } catch (e) {}
|
|
try { return decodeURIComponent(escape(atob(s))) } catch (e) { return "" }
|
|
}
|
|
function uidFromQDHeader(qdheader) {
|
|
var decoded = b64decode(qdheader)
|
|
if (!decoded) return ""
|
|
return String(decoded.split("|")[0] || "").trim()
|
|
}
|
|
function extractUid(cookie) {
|
|
var jar = parseCookieString(cookie)
|
|
var uid = uidFromQDHeader(jar.QDHeader || jar.qdheader || jar.QDHEADER || "")
|
|
if (uid) return uid
|
|
if (jar.uid) return String(jar.uid)
|
|
return ""
|
|
}
|
|
function maskCookie(cookie) {
|
|
cookie = String(cookie || "")
|
|
if (cookie.length <= 24) return cookie
|
|
return cookie.slice(0, 12) + "..." + cookie.slice(-8)
|
|
}
|
|
function contentText() {
|
|
var s = ""
|
|
try { if (typeof getContent === "function") s = getContent() || "" } catch (e) {}
|
|
try { if (!s && typeof sender !== "undefined" && sender.getContent) s = sender.getContent() || "" } catch (e) {}
|
|
try { if (!s && typeof message !== "undefined") s = String(message) } catch (e) {}
|
|
return String(s || "").trim()
|
|
}
|
|
function usage() {
|
|
return [
|
|
"起点读书CK插件",
|
|
"提交:起点ck <QX抓到的cookie>",
|
|
"提交JSON:起点ck json {\"uid\":\"cookie\"}",
|
|
"查询:起点ck 查询",
|
|
"导出:起点ck 导出",
|
|
"删除:起点ck 删除 <uid>",
|
|
"说明:QX只负责抓cookie,把通知/变量里的“起点ck ...”整段发给机器人即可。"
|
|
].join("\n")
|
|
}
|
|
function stripCommand(text) {
|
|
return String(text || "")
|
|
.replace(/^起点(?:ck|CK|cookie|Cookie)\s*/i, "")
|
|
.replace(/^qdreader\s*/i, "")
|
|
.trim()
|
|
}
|
|
|
|
var text = contentText()
|
|
var arg = stripCommand(text)
|
|
if (!arg) { reply(usage()); return }
|
|
|
|
if (/^(帮助|help|h)$/i.test(arg)) { reply(usage()); return }
|
|
|
|
var store = getStore()
|
|
|
|
if (/^(查询|状态|status|list)$/i.test(arg)) {
|
|
var uids = Object.keys(store)
|
|
reply(uids.length ? ("起点读书CK:共 " + uids.length + " 个账号\n" + uids.join("\n")) : "还没有保存起点读书CK")
|
|
return
|
|
}
|
|
|
|
if (/^(导出|export)$/i.test(arg)) {
|
|
reply("QDREADER_COOKIE=" + JSON.stringify(store))
|
|
return
|
|
}
|
|
|
|
var del = arg.match(/^(删除|delete|del|rm)\s+(\S+)/i)
|
|
if (del) {
|
|
var duid = del[2]
|
|
var existed = !!store[duid]
|
|
delete store[duid]
|
|
setStore(store)
|
|
reply(existed ? ("已删除 uid: " + duid) : ("未找到 uid: " + duid))
|
|
return
|
|
}
|
|
|
|
var jsonMatch = arg.match(/^json\s+([\s\S]+)$/i)
|
|
if (jsonMatch) {
|
|
var obj = safeJsonParse(jsonMatch[1], null)
|
|
if (!obj || typeof obj !== "object" || Array.isArray(obj)) { reply("JSON格式错误,示例:起点ck json {\"uid\":\"cookie\"}"); return }
|
|
var count = 0
|
|
for (var uid in obj) {
|
|
if (!obj[uid]) continue
|
|
store[uid] = String(obj[uid])
|
|
count++
|
|
}
|
|
setStore(store)
|
|
reply("起点读书CK JSON已导入/更新 " + count + " 个账号,当前共 " + Object.keys(store).length + " 个账号")
|
|
return
|
|
}
|
|
|
|
// 直接把 cookie 发过来;兼容“uid=xxx; ...”或含 QDHeader 的 Cookie。
|
|
var cookie = arg
|
|
if (cookie.indexOf("=") < 0 || cookie.indexOf(";") < 0) {
|
|
reply("未识别到 Cookie。请发送:起点ck <QX抓到的完整cookie>")
|
|
return
|
|
}
|
|
var uid = extractUid(cookie)
|
|
if (!uid) {
|
|
reply("无法从 Cookie 识别 uid。请确认 QX 抓的是起点读书福利中心 getlogininfo 请求,Cookie 内应包含 QDHeader 或 uid。")
|
|
return
|
|
}
|
|
var isNew = !store[uid]
|
|
var changed = store[uid] !== cookie
|
|
store[uid] = cookie
|
|
setStore(store)
|
|
reply([
|
|
"起点读书CK" + (isNew ? "新增" : (changed ? "更新" : "未变化")) + "成功",
|
|
"uid: " + uid,
|
|
"账号数: " + Object.keys(store).length,
|
|
"cookie: " + maskCookie(cookie),
|
|
"导出环境变量:发送 起点ck 导出"
|
|
].join("\n"))
|