// ==UserScript==
// @name 爱问答助手
// @namespace aiask/askHelper
// @version 2.7.2
// @author aiask
// @description 全平台网课答题助手,一键解析当前页面试题并获取答案,支持作业 / 考试 / 章节测验的自动收录与答题。已适配【超星学习通、知到智慧树、中国大学MOOC、职教云·智慧职教、云班课、国家开放大学、广东开放大学、上海开放大学、江苏开放大学、云南开放大学、四川开放大学、云上河开、安徽继续教育、河南继续教育、武汉理工继续教育、东北财经大学成教、芯位教育、青书学堂、优课在线UOOC、西财在线、华医网、麦能网、良师在线、川农在线、成教云、电大中专、京人平台、北京联大学堂、绎通继教云、继教云、继教在线、学起Plus、日照专业技术人员继续教育、亿学宝、文顶在线、柠檬文才、春风雨、出头系统、云幕学苑、21tb、168网校、learnin、广西自考助学、UMU互动平台】等 40+ 平台,更多平台持续适配中...
// @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAAXNSR0IArs4c6QAAAHVQTFRFR3BMgICBQD8/QUVHQ0ZIRUhKX2FiQD8/Tk1NP0VJPzs7Pz8/QD4+UE9QQD8/PVlnQD8/M6vj////n5+fN5C60NDQSl9qOXWSZL/qTFNXzOr4QWl8yMjItLS02traOIOnNZzN6OfnlJeZ9/f3PYGgpdrzmdXxgSBJqQAAABB0Uk5TAP5E6vys+7/Q0RhsfPFV/OwFarYAAAEESURBVHjapdHrboMgGIBhUHBaD/sAlTE8VOt2/5c4GlBMRZOl7w8j+kQQ0FaVwbG48IDq+piMPcgkO1bD/8DXvhD4/fb9ePDuGiqa2krV7pO1AxSLYIl2ABoeTLSvYMBi4N0sphOAlVaqg1aTPggmZYYaFvNMBYGQz6G6m2vbhEBvF81MxALFTDpbQQd3ZhvBgxqiFfBEO/CJ7ZxkNPcUbWBwn5DJw4KSsJHcHPCTLLDuQxpLkiMLbAIWJs1wBRVkyAFXT7Sa+AYQjTywNfOD74DNA18I9Ifjpg7Es/3Jj5eKyIEcBgNwhk5L8XMPonMQQcfNhBfRpIfbFbiRskCX5enFyz/07TSN9vGxKwAAAABJRU5ErkJggg==
// @match https://m.umu.cn/session/quiz/*
// @match *://*.chaoxing.com/*
// @match *://*.hlju.edu.cn/*
// @match *://*.ecust.edu.cn/*
// @match *://lms.ouchn.cn/*
// @match *://*.ouchn.cn/*
// @match *://xczxzdbf.moodle.qwbx.ouchn.cn/*
// @match *://study.ouchn.cn/*
// @match *://moodle.syxy.ouchn.cn/*
// @match *://moodle.qwbx.ouchn.cn/*
// @match *://*.tongyi.com/*
// @match *://chat.deepseek.com/*
// @match *://*.zhihuishu.com/*
// @match *://course.ougd.cn/*
// @match *://elearning.bjou.edu.cn/*
// @match *://whkpc.hnqtyq.cn:5678/*
// @match *://www.51xinwei.com/*
// @match *://*.w-ling.cn/*
// @match *://*.edu-edu.com/*
// @match *://xuexi.jsou.cn/*
// @match *://*.icve.com.cn/*
// @match *://zice.cnzx.info/*
// @match *://any.cnzx.info:81/*
// @match *://www.icourse163.org/*
// @match *://*.shou.org.cn/*
// @match *://*.ahjxjy.cn/*
// @match *://*.chinaedu.net/*
// @match *://*.qingshuxuetang.com/*
// @match *://cce.org.uooconline.com/*
// @match *://*.courshare.cn/*
// @match *://*.cep.webtrn.cn/*
// @match *://*.webtrn.cn/*
// @match *://*.cj-edu.com/*
// @match *://*.ytccr.com/*
// @match *://*.exam-cloud.cn/*
// @match *://gdrtvu.exam-cloud.cn/*
// @match *://*.open.ha.cn/*
// @match *://lhycjy.cloudwis.tech/*
// @match *://*.sclecb.cn/*
// @match *://*.web2.superchutou.com/*
// @match *://*.ls365.net/*
// @match *://*.jijiaox.com/*
// @match *://*.wencaischool.net/*
// @match *://sdrz.gxk.yxlearning.com/*
// @match *://*.crjxjy.net/*
// @match *://*.cjnep.net/*
// @match *://*.91huayi.com/*
// @match *://teach.ynou.edu.cn/*
// @match *://*.edu-edu.com.cn/*
// @match *://*.21tb.com/*
// @match *://*.168wangxiao.com/*
// @match *://*.mynep.com/*
// @match *://www.mosoteach.cn/*
// @match *://*.aufe.edu.cn/*
// @match *://*.learnin.com.cn/*
// @match *://*.ouchn.edu.cn/*
// @match *://*.swufe-online.com/*
// @match *://ks.cqsdx.cn/*
// @match *://*.qau.edu.cn/*
// @match *://*.gdufemooc.cn/*
// @match *://*.telfri-edu.com/*
// @match *://www.beeline-ai.com/*
// @match *://*.wxic.edu.cn/*
// @match *://*.yxbyun.com/*
// @match *://*.wdjycj.com/*
// @match *://*.hbcjpt.com/*
// @match *://*.csmu.edu.cn/*
// @match *://*.ketangx.net/*
// @match *://*.cnzx.info/*
// @match *://www.asklib.com/*
// @match *://*.xust.edu.cn/*
// @match *://*.whut.edu.cn/*
// @match *://*.lut.edu.cn/*
// @match *://*.wwwwsoft.com/*
// @match *://*.dufe.edu.cn/*
// @match *://*.lygtc.edu.cn/*
// @match *://*.cfyedu.com/*
// @match *://*.iwdjy.com/*
// @match *://*.jijiaool.com/*
// @match *://lms.cjzx.hblll.com/*
// @match *://*.ouc-online.com.cn/*
// @match *://*.lsedu.vip/*
// @match *://*.jxjypt.cn/*
// @match *://*.jsnu.edu.cn/*
// @match *://*.geovisearth.com/*
// @match *://*.bgzk-edu.cn/*
// @match *://*.cqie.cn/*
// @match *://mooc1.ceduacad.ahut.edu.cn/*
// @require https://mirrors.sustech.edu.cn/cdnjs/ajax/libs/vue/3.4.27/vue.global.min.js
// @require https://mirrors.sustech.edu.cn/cdnjs/ajax/libs/vue-demi/0.14.6/index.iife.js
// @require data:application/javascript,%3Bwindow.Vue%3DVue%3B
// @require https://fastly.jsdelivr.net/npm/@iconify/vue@5.0.0/dist/iconify.js
// @require https://mirrors.sustech.edu.cn/cdnjs/ajax/libs/jquery/3.6.0/jquery.min.js
// @require https://mirrors.sustech.edu.cn/cdnjs/ajax/libs/dompurify/3.1.6/purify.min.js
// @require https://mirrors.sustech.edu.cn/cdnjs/ajax/libs/crypto-js/4.2.0/crypto-js.min.js
// @require https://mirrors.sustech.edu.cn/cdnjs/ajax/libs/pinia/2.2.4/pinia.iife.prod.js
// @connect 127.0.0.1
// @connect icodef.com
// @connect wk66.top
// @connect zhihuishu.com
// @connect greasyfork.org
// @connect chaoxing.com
// @connect shou.org.cn
// @connect jsdelivr.net
// @connect jsdmirror.cn
// @connect gitee.com
// @connect vxo.im
// @connect zeroai.chat
// @connect forestpolice.org
// @connect scriptcat.org
// @connect api.github.com
// @connect aiask.site
// @connect api.deepseek.com
// @connect dashscope.aliyuncs.com
// @connect open.bigmodel.cn
// @connect qianfan.baidubce.com
// @connect ark.cn-beijing.volces.com
// @connect api.hunyuan.cloud.tencent.com
// @connect api.longcat.chat
// @connect api.moonshot.ai
// @connect api.siliconflow.cn
// @connect api.openai.com
// @connect api.anthropic.com
// @connect generativelanguage.googleapis.com
// @connect openrouter.ai
// @connect api.groq.com
// @connect api.together.ai
// @connect api.mistral.ai
// @connect m.umu.cn
// @connect hlju.edu.cn
// @connect ecust.edu.cn
// @connect lms.ouchn.cn
// @connect ouchn.cn
// @connect xczxzdbf.moodle.qwbx.ouchn.cn
// @connect study.ouchn.cn
// @connect moodle.syxy.ouchn.cn
// @connect moodle.qwbx.ouchn.cn
// @connect tongyi.com
// @connect chat.deepseek.com
// @connect course.ougd.cn
// @connect elearning.bjou.edu.cn
// @connect whkpc.hnqtyq.cn
// @connect www.51xinwei.com
// @connect w-ling.cn
// @connect edu-edu.com
// @connect xuexi.jsou.cn
// @connect icve.com.cn
// @connect zice.cnzx.info
// @connect any.cnzx.info
// @connect www.icourse163.org
// @connect ahjxjy.cn
// @connect chinaedu.net
// @connect qingshuxuetang.com
// @connect cce.org.uooconline.com
// @connect courshare.cn
// @connect cep.webtrn.cn
// @connect webtrn.cn
// @connect cj-edu.com
// @connect ytccr.com
// @connect exam-cloud.cn
// @connect gdrtvu.exam-cloud.cn
// @connect open.ha.cn
// @connect lhycjy.cloudwis.tech
// @connect sclecb.cn
// @connect web2.superchutou.com
// @connect ls365.net
// @connect jijiaox.com
// @connect wencaischool.net
// @connect sdrz.gxk.yxlearning.com
// @connect crjxjy.net
// @connect cjnep.net
// @connect 91huayi.com
// @connect teach.ynou.edu.cn
// @connect edu-edu.com.cn
// @connect 21tb.com
// @connect 168wangxiao.com
// @connect mynep.com
// @connect www.mosoteach.cn
// @connect aufe.edu.cn
// @connect learnin.com.cn
// @connect ouchn.edu.cn
// @connect swufe-online.com
// @connect ks.cqsdx.cn
// @connect qau.edu.cn
// @connect gdufemooc.cn
// @connect telfri-edu.com
// @connect www.beeline-ai.com
// @connect wxic.edu.cn
// @connect yxbyun.com
// @connect wdjycj.com
// @connect hbcjpt.com
// @connect csmu.edu.cn
// @connect ketangx.net
// @connect cnzx.info
// @connect www.asklib.com
// @connect xust.edu.cn
// @connect whut.edu.cn
// @connect lut.edu.cn
// @connect wwwwsoft.com
// @connect dufe.edu.cn
// @connect lygtc.edu.cn
// @connect cfyedu.com
// @connect iwdjy.com
// @connect jijiaool.com
// @connect lms.cjzx.hblll.com
// @connect ouc-online.com.cn
// @connect lsedu.vip
// @connect jxjypt.cn
// @connect jsnu.edu.cn
// @connect geovisearth.com
// @connect bgzk-edu.cn
// @connect cqie.cn
// @connect mooc1.ceduacad.ahut.edu.cn
// @grant GM.xmlHttpRequest
// @grant GM_deleteValue
// @grant GM_getValue
// @grant GM_info
// @grant GM_listValues
// @grant GM_setValue
// @grant GM_xmlhttpRequest
// @grant unsafeWindow
// @run-at document-start
// ==/UserScript==
// hello
(function (vue, vue$1, pinia, M, j, O) {
'use strict';
var e = Object.defineProperty, __publicField = (t, n, a) => ((t, n, a) => n in t ? e(t, n, {
enumerable: true,
configurable: true,
writable: true,
value: a
}) : t[n] = a)(t, "symbol" != typeof n ? n + "" : n, a);
const z = new Set([ "preparing", "searching", "matched", "published", "rendering", "filling" ]), D = {
todo: "\u672a\u7b54",
run: "\u67e5\u627e\u4e2d",
done: "\u5df2\u7b54",
none: "\u65e0\u7b54\u6848",
wait: "AI \u5f85\u786e\u8ba4"
};
function tallyMarks(e) {
const t = {
done: 0,
none: 0,
wait: 0,
todo: 0
};
for (const n of e) "run" === n ? t.todo++ : t[n]++;
return t;
}
const F = "\u672c\u5730\u7f13\u5b58", isAiForm = (e = "") => /AI/i.test(e), hasAnswer = e => {
if (e.needLogin) return false;
const t = e.answer;
return Array.isArray(t) ? t.length > 0 : t && "object" == typeof t ? Object.keys(t).length > 0 : "string" == typeof t ? t.trim().length > 0 : !!t;
};
const N = [ "width", "height", "aria-label" ], R = {
key: 0,
cx: "7",
cy: "7",
r: "5.5",
fill: "none",
stroke: "currentColor",
"stroke-width": "1.5",
"stroke-dasharray": "2.2 1.8"
}, B = vue.createElementVNode("circle", {
cx: "7",
cy: "7",
r: "5.5",
fill: "none",
stroke: "currentColor",
"stroke-opacity": "0.25",
"stroke-width": "1.5"
}, null, -1), G = vue.createElementVNode("path", {
class: "status-glyph-arc",
d: "M7 1.5a5.5 5.5 0 0 1 5.5 5.5",
fill: "none",
stroke: "currentColor",
"stroke-width": "1.5",
"stroke-linecap": "round"
}, null, -1), K = vue.createElementVNode("circle", {
cx: "7",
cy: "7",
r: "6.25",
fill: "currentColor"
}, null, -1), V = vue.createElementVNode("path", {
d: "M4.4 7.2l1.8 1.8 3.5-3.7",
fill: "none",
stroke: "var(--c-bg-surface)",
"stroke-width": "1.5",
"stroke-linecap": "round",
"stroke-linejoin": "round"
}, null, -1), W = vue.createElementVNode("circle", {
cx: "7",
cy: "7",
r: "5.5",
fill: "none",
stroke: "currentColor",
"stroke-width": "1.5"
}, null, -1), Q = vue.createElementVNode("path", {
d: "M5 5l4 4M9 5l-4 4",
stroke: "currentColor",
"stroke-width": "1.5",
"stroke-linecap": "round"
}, null, -1), J = vue.createElementVNode("circle", {
cx: "7",
cy: "7",
r: "5.5",
fill: "none",
stroke: "currentColor",
"stroke-width": "1.5"
}, null, -1), Z = vue.createElementVNode("path", {
d: "M7 3.25a3.75 3.75 0 0 0 0 7.5z",
fill: "currentColor"
}, null, -1), Y = vue.defineComponent({
__name: "StatusGlyph",
props: {
mark: {},
size: {
default: 14
}
},
setup: e => (e, t) => (vue.openBlock(), vue.createElementBlock("svg", {
class: vue.normalizeClass([ "status-glyph", `is-${e.mark}` ]),
width: e.size,
height: e.size,
viewBox: "0 0 14 14",
role: "img",
"aria-label": vue.unref(D)[e.mark]
}, [ "todo" === e.mark ? (vue.openBlock(), vue.createElementBlock("circle", R)) : "run" === e.mark ? (vue.openBlock(), vue.createElementBlock(vue.Fragment, {
key: 1
}, [ B, G ], 64)) : "done" === e.mark ? (vue.openBlock(), vue.createElementBlock(vue.Fragment, {
key: 2
}, [ K, V ], 64)) : "none" === e.mark ? (vue.openBlock(), vue.createElementBlock(vue.Fragment, {
key: 3
}, [ W, Q ], 64)) : (vue.openBlock(), vue.createElementBlock(vue.Fragment, {
key: 4
}, [ J, Z ], 64)) ], 10, N))
});
var X = (() => "undefined" != typeof GM_deleteValue ? GM_deleteValue : void 0)(), ee = (() => "undefined" != typeof GM_getValue ? GM_getValue : void 0)(), te = (() => "undefined" != typeof GM_info ? GM_info : void 0)(), ne = (() => "undefined" != typeof GM_listValues ? GM_listValues : void 0)(), ae = (() => "undefined" != typeof GM_setValue ? GM_setValue : void 0)(), re = (() => "undefined" != typeof GM_xmlhttpRequest ? GM_xmlhttpRequest : void 0)(), ie = (() => "undefined" != typeof unsafeWindow ? unsafeWindow : void 0)();
const se = "AiAsk_";
class Cache {
static set(e, t, n = 0) {
e = se + e;
const a = {
value: t,
expire: n > 0 ? Date.now() + 1e3 * n : 0
};
return ae(e, a), ee(e);
}
static get(e, t = null) {
const n = ee(e = se + e);
return n && n.expire && n.expire < Date.now() ? (X(e), t) : n ? n.value : t;
}
static match(e) {
return e = se + e, ne().filter((t => t.startsWith(e)));
}
static matchGet(e) {
const t = se + e;
let n = ne().filter((e => e.startsWith(t))).map((e => function(e, t, n) {
if (t && t.expire && t.expire < Date.now()) return n(e), null;
const a = t ? t.value : null;
return a && (a.key = e.replace("AiAsk_", "")), a;
}(e, ee(e, {
value: null,
expire: 0
}), X))).filter((e => null !== e));
return n.sort(((e, t) => (t.createTime || 0) - (e.createTime || 0))), n;
}
static remove(e) {
X(se + e);
}
static clear() {
ne().filter((e => e.startsWith(se))).forEach(X);
}
static matchRemove(e) {
e = se + e, ne().filter((t => t.startsWith(e))).forEach(X);
}
}
let oe = null;
function log$1(...e) {}
const addLog = (e, t = "info") => {
try {
const n = null == oe ? void 0 : oe(), a = (new Date).toLocaleString();
null == n || n.addLog({
time: a,
type: t,
content: e
}), n || console.log(e);
} catch (n) {
console.log(e);
}
}, le = {
success: '',
error: '',
warning: '',
info: ''
}, ce = {
success: "\u6210\u529f",
error: "\u9519\u8bef",
warning: "\u63d0\u9192",
info: "\u63d0\u793a"
};
let ue = null;
const systemTheme = () => {
var e;
return "undefined" != typeof window && (null == (e = window.matchMedia) ? void 0 : e.call(window, "(prefers-color-scheme: dark)").matches) ? "dark" : "light";
};
let pe = null;
function getStack(e = true) {
if (pe && pe.isConnected) return pe;
if (!e) return null;
const t = document.createElement("div");
t.id = "aah-toast-host";
const n = t.attachShadow({
mode: "closed"
}), a = document.createElement("style");
a.textContent = "\n:host { all: initial; }\n.stack {\n --bg: #ffffff; --border: #e1e3e8; --text: #1d2129; --muted: #4b5260;\n --success: #1d8549; --danger: #c93030; --warning: #a86200; --info: #1672b8;\n --shadow: 0 8px 24px -6px rgba(20, 24, 33, 0.16), 0 2px 6px rgba(20, 24, 33, 0.06);\n position: fixed;\n top: 16px;\n right: 16px;\n z-index: 2147483647;\n display: flex;\n flex-direction: column;\n align-items: flex-end;\n gap: 8px;\n width: min(360px, calc(100vw - 32px));\n pointer-events: none;\n font: 13px/1.55 -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'Segoe UI', sans-serif;\n -webkit-font-smoothing: antialiased;\n}\n.stack[data-theme='dark'] {\n --bg: #1f2024; --border: #2d3035; --text: #e6e7ea; --muted: #b4b8c0;\n --success: #4cc27e; --danger: #f0716b; --warning: #e8a73c; --info: #4da3e6;\n --shadow: 0 8px 24px -6px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.04);\n}\n.toast {\n display: grid;\n grid-template-columns: 16px minmax(0, 1fr);\n gap: 8px;\n align-items: start;\n box-sizing: border-box;\n max-width: 100%;\n padding: 10px 12px;\n border: 1px solid var(--border);\n border-radius: 8px;\n background: var(--bg);\n box-shadow: var(--shadow);\n color: var(--text);\n pointer-events: auto;\n cursor: default;\n animation: toast-in 220ms cubic-bezier(0.16, 1, 0.3, 1);\n transition: opacity 180ms ease-out, transform 180ms ease-out;\n}\n.toast svg { width: 16px; height: 16px; margin-top: 2px; }\n.toast[data-type='success'] svg { color: var(--success); }\n.toast[data-type='error'] svg { color: var(--danger); }\n.toast[data-type='warning'] svg { color: var(--warning); }\n.toast[data-type='info'] svg { color: var(--info); }\n.content { min-width: 0; overflow-wrap: anywhere; white-space: pre-line; }\n.content p { margin: 0 0 4px; }\n.content p:last-child { margin-bottom: 0; }\n.content a { color: var(--info); font-weight: 500; text-underline-offset: 2px; }\n.content strong { font-weight: 600; }\n.toast.leaving { opacity: 0; transform: translateY(-4px); }\n@keyframes toast-in {\n from { opacity: 0; transform: translateY(-6px); }\n to { opacity: 1; transform: none; }\n}\n@media (prefers-reduced-motion: reduce) {\n .toast { animation: none; transition: none; }\n}";
const r = document.createElement("div");
return r.className = "stack", r.setAttribute("role", "status"), r.setAttribute("aria-live", "polite"),
r.dataset.theme = ue ?? systemTheme(), n.append(a, r), document.body.appendChild(t),
pe = r, r;
}
function msg(e, t = "info") {
try {
const n = le[t] ? t : "info", a = getStack(), r = document.createElement("div");
r.className = "toast", r.dataset.type = n, r.setAttribute("aria-label", ce[n]),
r.innerHTML = ``;
const i = document.createElement("div");
i.className = "content", i.innerHTML = M.sanitize(e), r.appendChild(i), a.appendChild(r);
const dismiss = () => {
r.classList.add("leaving"), setTimeout((() => r.remove()), 200);
};
let s = setTimeout(dismiss, 2800);
r.addEventListener("mouseenter", (() => clearTimeout(s))), r.addEventListener("mouseleave", (() => {
s = setTimeout(dismiss, 1500);
})), addLog(e, t);
} catch (n) {
addLog(`\u6d88\u606f\u901a\u77e5\u5931\u8d25\u3010${e}\u3011`, "error");
}
}
async function encrypt(e = "", t = "asdgdfghfghfghfg", n = "1234567890123456") {
try {
if (!e) return "";
if (t = t.substring(0, 16), n = n.substring(0, 16), !window.crypto || !window.crypto.subtle) {
const a = j.enc.Utf8.parse(t), r = j.enc.Utf8.parse(n);
return j.AES.encrypt(e, a, {
iv: r,
mode: j.mode.CBC,
padding: j.pad.Pkcs7
}).toString();
}
const r = new TextEncoder, i = r.encode(e), s = r.encode(t), o = r.encode(n), l = await crypto.subtle.importKey("raw", s, {
name: "AES-CBC"
}, !1, [ "encrypt" ]), c = await crypto.subtle.encrypt({
name: "AES-CBC",
iv: o
}, l, i), u = new Uint8Array(c), p = 1024;
let d, m = "";
for (let e = 0; e < u.length; e += p) {
const t = u.slice(e, Math.min(e + p, u.length));
m += String.fromCharCode.apply(null, Array.from(t));
}
try {
d = btoa(m);
} catch (a) {
d = m.split("").map((e => ("0" + e.charCodeAt(0).toString(16)).slice(-2))).join("");
}
return d;
} catch (r) {
return addLog(`\u52a0\u5bc6\u5f02\u5e38: ${r instanceof Error ? r.message : "\u672a\u77e5\u9519\u8bef"}`, "error"),
"";
}
}
async function decrypt(e = "", t = "asdgdfghfghfghfg", n = "1234567890123456") {
try {
if (!e) return "";
if (t = t.substring(0, 16), n = n.substring(0, 16), !window.crypto || !window.crypto.subtle) {
const a = j.enc.Utf8.parse(t), r = j.enc.Utf8.parse(n);
return j.AES.decrypt(e, a, {
iv: r,
mode: j.mode.CBC,
padding: j.pad.Pkcs7
}).toString(j.enc.Utf8);
}
/^[A-Za-z0-9+/]*={0,2}$/.test(e);
const r = new TextEncoder, i = r.encode(t), s = r.encode(n);
let o;
try {
o = atob(e);
} catch (a) {
throw new Error("Base64 \u89e3\u7801\u5931\u8d25\uff0c\u6570\u636e\u683c\u5f0f\u4e0d\u6b63\u786e");
}
const l = new Uint8Array(o.length);
for (let e = 0; e < o.length; e++) l[e] = o.charCodeAt(e);
if (l.length % 16 != 0) throw new Error("\u52a0\u5bc6\u6570\u636e\u957f\u5ea6\u4e0d\u6b63\u786e\uff0c\u4e0d\u662f16\u7684\u500d\u6570");
const c = await crypto.subtle.importKey("raw", i, {
name: "AES-CBC"
}, !1, [ "decrypt" ]), u = await crypto.subtle.decrypt({
name: "AES-CBC",
iv: s
}, c, l);
return new TextDecoder("utf-8", {
fatal: !0
}).decode(u);
} catch (r) {
return addLog(`\u89e3\u5bc6\u5f02\u5e38: ${r instanceof Error ? r.message : "\u672a\u77e5\u9519\u8bef"}`, "error"),
"";
}
}
function md5(e) {
return j.MD5(e).toString();
}
function somd5(e) {
return md5(e);
}
const isPlainObject$1 = e => "object" == typeof e && null !== e && !Array.isArray(e), flattenForSignature = (e, t = "") => {
const n = [];
return Object.keys(e).sort().forEach((a => {
if (!t && "html" === a) return;
const r = t ? `${t}.${a}` : a, i = e[a];
(e => null == e || !(!Array.isArray(e) || 0 !== e.length) || !(!isPlainObject$1(e) || 0 !== Object.keys(e).length))(i) || (Array.isArray(i) ? n.push(`${r}=${(e => e.every((e => "object" != typeof e)) ? [ ...e ].sort().join(",") : JSON.stringify(e))(i)}`) : isPlainObject$1(i) ? n.push(...flattenForSignature(i, r)) : n.push(`${r}=${String(i)}`));
})), n;
};
function get_t(e = {}) {
return md5(flattenForSignature(e).join("&"));
}
const getImageSrc = e => {
const t = String(e).match(/(?:^|\s)src\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>]+))/i);
return t && (t[1] || t[2] || t[3]) || "";
}, stripImageSrcQuery = e => e.replace(/[?#].*$/, ""), cleanQuestionText = (e, t = false) => String(e ?? "").replace(/
]*)>/gi, ((e, t) => getImageSrc(t))).replace(/
/gi, "\n").replace(/<(\/)?(p|div).*?>/gi, "\n").replace(/<[^>]+>/g, "").replace(t ? /[\r\xa0]/g : /[\t\r\xa0]/g, " ").replace(/[\u2000-\u200a]/g, " ").replace(/ {2,}/g, " ").replace(/\n{2,}/g, "\n").replace(t ? /^[^\S\t]+|[^\S\t]+$/g : /^\s+|\s+$/g, ""), cleanQuestionTextWithImageHtml = (e, t = false) => {
const n = [];
return String(e ?? "").replace(/
]*)>/gi, ((e, t) => {
const a = getImageSrc(t);
if (!a) return "";
const r = `\0AAH_IMAGE_PLACEHOLDER_${n.length}\0`;
return n.push(`
/g, ">"))(a)}">`),
r;
})).replace(/
/gi, "\n").replace(/<(\/)?(p|div).*?>/gi, "\n").replace(/<[^>]+>/g, "").replace(/\u0000AAH_IMAGE_PLACEHOLDER_(\d+)\u0000/g, ((e, t) => n[Number(t)] || "")).replace(t ? /[\r\xa0]/g : /[\t\r\xa0]/g, " ").replace(/[\u2000-\u200a]/g, " ").replace(/ {2,}/g, " ").replace(/\n{2,}/g, "\n").replace(t ? /^[^\S\t]+|[^\S\t]+$/g : /^\s+|\s+$/g, "");
}, cleanQuestionTitle = (e, t = false) => e.replace(/^[.*?]\s*/, "").replace(/^\u3010.*?\u3011\s*/, "").replace(/\s*[\uff08(]\s*\d+(?:\.\d+)?\s*\u5206?\s*[\uff09)]\s*$/, "").replace(/^\d+\./, "").replace(t ? /^[^\S\t]+|[^\S\t]+$/g : /^\s+|\s+$/g, "").replace(/^\d+\uff0e/, "").replace(t ? /^[^\S\t]+|[^\S\t]+$/g : /^\s+|\s+$/g, ""), normalizeComparableText = e => (e => {
if (/^[+-]?\d+(\.\d+)?$/.test(e)) return e;
const t = e.replace(/\s+/g, "");
return t.replace(new RegExp("\\p{P}", "gu"), "") || t;
})((e => String(e ?? "").replace(/
]*)>/gi, ((e, t) => stripImageSrcQuery(getImageSrc(t)))).replace(/<[^>]*>/g, ""))(e)).trim(), removeOptionPrefixes = (e, {removeBareLetter: t = false} = {}) => e.map(((e, n) => {
const a = String.fromCharCode(65 + n), r = t ? `^${a}(?:\\s*[.\u3001\uff0e)\uff09:\uff1a]\\s*|\\s+)?` : `^${a}\\s*[.\u3001\uff0e)\uff09:\uff1a]\\s*`;
return e.replace(new RegExp(r), "").trim();
})), normalizeHashText = e => String(e ?? "").replace(/
]*)>/gi, ((e, t) => {
const n = getImageSrc(t);
return n ? `
` : "";
})), questionHash = (e, t, n, a = true) => {
if (("15" === e || 15 === e) && Array.isArray(n) && n.length > 0 && "object" == typeof n[0]) {
const r = n.map((e => {
if (e.question && e.options) {
const t = Array.from(e.options).map(normalizeHashText);
a && t.sort();
const n = t.join("");
return `${e.type || "0"}${normalizeHashText(e.question)}${n}`;
}
return "";
})).filter(Boolean);
let i = `${e}${normalizeHashText(t)}${r.join("")}`;
return i = i.replace(/\s/g, ""), md5(i);
}
const r = Array.from(n).map(normalizeHashText);
a && r.sort();
const i = r.join("");
let s = `${e}${normalizeHashText(t)}${i}`;
return s = s.replace(/\s/g, ""), md5(s);
}, sanitizeHtml = (e, t, n) => {
const a = M.sanitize;
return "function" == typeof a ? a(e, {
ALLOWED_TAGS: t,
ALLOWED_ATTR: n,
ALLOW_DATA_ATTR: false,
KEEP_CONTENT: true
}) : ((e, t, n) => {
const a = new Set(t), r = new Set(n);
return e.replace(/