226 lines
6.9 KiB
JavaScript
226 lines
6.9 KiB
JavaScript
// ==UserScript==
|
||
// @name BUCT cource helper
|
||
// @namespace http://tampermonkey.net/
|
||
// @version 2025-03-12
|
||
// @description 北化在线助手
|
||
// @author Bluemangoo
|
||
// @match https://course.buct.edu.cn/meol/jpk/course/layout/newpage/index.jsp?*
|
||
// @icon https://www.google.com/s2/favicons?sz=64&domain=buct.edu.cn
|
||
// @grant GM_registerMenuCommand
|
||
// @grant GM_unregisterMenuCommand
|
||
// ==/UserScript==
|
||
|
||
(function () {
|
||
"use strict";
|
||
|
||
const HOST = "https://local.bluemangoo.net:3443";
|
||
|
||
let stat = {
|
||
question: {
|
||
id: ""
|
||
},
|
||
autoMode: false
|
||
};
|
||
|
||
class Poll {
|
||
polling = true;
|
||
|
||
constructor() {
|
||
this.poll();
|
||
}
|
||
|
||
async poll() {
|
||
if (!this.polling) {
|
||
return;
|
||
}
|
||
let res;
|
||
try {
|
||
res = await fetch(`${HOST}/polling?env=course`, {
|
||
method: "GET",
|
||
headers: {
|
||
"Content-Type": "application/json"
|
||
}
|
||
});
|
||
} catch {
|
||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||
return this.poll();
|
||
}
|
||
this.poll();
|
||
try {
|
||
const data = await res.json();
|
||
if (data.status !== "nothing") {
|
||
const { questionID, answer } = data.data;
|
||
console.log("回答", questionID, "\n", answer);
|
||
answerQuestion(questionID, answer);
|
||
}
|
||
} catch (e) {
|
||
console.error(e);
|
||
}
|
||
}
|
||
}
|
||
|
||
function getAnswerElement() {
|
||
const doc = document
|
||
.getElementById("mainFrame")
|
||
.contentDocument.getElementById("questionshow").contentDocument;
|
||
return doc.getElementsByClassName("extable")[0];
|
||
}
|
||
|
||
function getContent() {
|
||
const doc = document
|
||
.getElementById("mainFrame")
|
||
.contentDocument.getElementById("questionshow").contentDocument;
|
||
const question = doc
|
||
.getElementsByTagName("iframe")[0]
|
||
.contentDocument.getElementById("body").innerText;
|
||
const answer = doc.getElementsByClassName("extable")[0].innerText.replaceAll("\t", "- ");
|
||
return question + answer;
|
||
}
|
||
|
||
function copyToClipboard() {
|
||
navigator.clipboard.writeText(getContent());
|
||
}
|
||
|
||
async function answerQuestion(id, answer) {
|
||
if (id !== stat.question.id) {
|
||
return;
|
||
}
|
||
aiButton.value = "?";
|
||
let answered = false;
|
||
const answers = answer.split("\n");
|
||
const children = getAnswerElement().children[0].children;
|
||
for (const child of children) {
|
||
if (child.classList[0] !== "optionContent") {
|
||
continue;
|
||
}
|
||
if (answers.includes(child.innerText.replaceAll("\t", ""))) {
|
||
child.children[0].children[0].click();
|
||
answered = true;
|
||
}
|
||
}
|
||
if (answered && stat.autoMode) {
|
||
const submitButton = getAnswerElement().nextElementSibling.children[1];
|
||
submitButton.click();
|
||
await new Promise((resolve) => setTimeout(resolve, 500));
|
||
if (!allDone()) {
|
||
aiButton.click();
|
||
}
|
||
}
|
||
}
|
||
|
||
async function ask() {
|
||
const q = getContent();
|
||
const req = await fetch(`${HOST}/question`, {
|
||
method: "POST",
|
||
headers: {
|
||
"Content-Type": "application/json"
|
||
},
|
||
body: JSON.stringify({
|
||
question: q
|
||
})
|
||
});
|
||
const data = await req.json();
|
||
if (data.data.questionId) {
|
||
stat.question.id = data.data.questionId;
|
||
}
|
||
aiButton.value = "Zzz";
|
||
}
|
||
|
||
function getAutoText() {
|
||
return stat.autoMode ? "A*" : "A";
|
||
}
|
||
|
||
function toggleAutoMode() {
|
||
stat.autoMode = !stat.autoMode;
|
||
autoButton.value = getAutoText();
|
||
}
|
||
|
||
function allDone() {
|
||
const element = document
|
||
.getElementById("mainFrame")
|
||
.contentDocument.getElementsByClassName("infotable")[1];
|
||
return !element.innerText.toString().includes("未作答");
|
||
}
|
||
|
||
const flag = {
|
||
copyButton: false,
|
||
aiButton: false
|
||
};
|
||
|
||
let aiButton;
|
||
let autoButton;
|
||
let poll;
|
||
|
||
function newButton(document, value, onclick) {
|
||
const button = document.createElement("input");
|
||
button.value = value;
|
||
button.style = "margin-left: 10px;";
|
||
button.type = "button";
|
||
if (onclick) {
|
||
button.onclick = onclick;
|
||
}
|
||
return button;
|
||
}
|
||
|
||
function createButton(addAiButton = false) {
|
||
const base = document.getElementById("mainFrame");
|
||
const win = base.contentWindow;
|
||
const doc = base.contentDocument;
|
||
win.getContent = getContent;
|
||
win.getAnswerElement = getAnswerElement;
|
||
win.answerQuestion = answerQuestion;
|
||
win.copyToClipboard = copyToClipboard;
|
||
if (!flag.copyButton) {
|
||
const button = newButton(doc, "复制", copyToClipboard);
|
||
doc.getElementsByClassName("navigation")[0].childNodes[1].appendChild(button);
|
||
flag.copyButton = true;
|
||
}
|
||
if (addAiButton && !flag.aiButton) {
|
||
aiButton = newButton(doc, "?", ask);
|
||
doc.getElementsByClassName("navigation")[0].childNodes[1].appendChild(aiButton);
|
||
autoButton = newButton(doc, getAutoText(), toggleAutoMode);
|
||
doc.getElementsByClassName("navigation")[0].childNodes[1].appendChild(autoButton);
|
||
flag.aiButton = true;
|
||
}
|
||
}
|
||
|
||
function initAiBridge() {
|
||
createButton(true);
|
||
if (poll) {
|
||
poll.polling = false;
|
||
}
|
||
poll = new Poll();
|
||
}
|
||
|
||
function stopPolling() {
|
||
if (poll) {
|
||
poll.polling = false;
|
||
flag.copyButton = false;
|
||
flag.aiButton = false;
|
||
}
|
||
}
|
||
|
||
GM_registerMenuCommand("添加复制按钮", createButton);
|
||
GM_registerMenuCommand("初始化ai桥", initAiBridge);
|
||
GM_registerMenuCommand("停止轮询", stopPolling);
|
||
|
||
// window.stat = stat;
|
||
// window.getContent = getContent;
|
||
// window.getAnswerElement = getAnswerElement;
|
||
// window.answerQuestion = answerQuestion;
|
||
// window.copyToClipboard = copyToClipboard;
|
||
// window.ask = ask;
|
||
// window.toggleAutoMode = toggleAutoMode;
|
||
// window.allDone = allDone;
|
||
// window.flag = flag;
|
||
// window.initAiBridge = initAiBridge;
|
||
// window.stopPolling = stopPolling;
|
||
// window.aiButton = aiButton;
|
||
// window.autoButton = autoButton;
|
||
// window.newButton = newButton;
|
||
// window.getAutoText = getAutoText;
|
||
// window.createButton = createButton;
|
||
// window.initAiBridge = initAiBridge;
|
||
// window.stopPolling = stopPolling;
|
||
})();
|