// ==UserScript== // @name 优学院查题 // @namespace http://tampermonkey.net/ // @version 1.1.1 // @description 查题 // @author fffkyxy // @match */umooc/user/study.do* // @grant unsafeWindow // @grant GM_setClipboard // @grant GM_xmlhttpRequest // @run-at document-start // @connect ulearn.ga // ==/UserScript== "use strict"; const set = { get_answer: "https://ulearn.ga/get_answer", upload_data: "https://ulearn.ga/upload_data", heartbeat: "https://ulearn.ga/heartbeat", dragging: false, left: 0, top: 0, uid: -1, timestamp: -1, }; const ITF = { post_form: function (url, data, onload, onerror) { ITF.post(url, data, onload, onerror, { "Content-Type": "application/x-www-form-urlencoded" }); }, post: function (url, data, onload, onerror, headers) { let data_form = new FD(); for (let value in data) { data_form.append(value, data[value]); } GM_xmlhttpRequest({ method: "POST", url: url, headers: headers, data: data_form.text, onload: onload, onerror: onerror, }); }, get: function (url, data, onload, onerror) { let data_form = new FD(); for (let value in data) { data_form.append(value, data[value]); } GM_xmlhttpRequest({ method: "GET", url: url + "?" + data_form.text, onload: onload, onerror: onerror, }); }, upload_api: function (data, send) { if (set.uid == -1) { setTimeout(ITF.upload_api, 1000, data, true); if (send === true) { return; } } ITF.post_form(set.upload_data, { uid: "" + set.uid, data: JSON.stringify(data), }); }, upload_eidpid: function (eid, pid) { ITF.upload_api({ type: 3, eid: eid, pid: pid }); }, upload_paper: function (paper, pid) { ITF.upload_api({ type: 4, pid: pid, paper: paper }); }, upload_answer: function (answer, pid) { ITF.upload_api({ type: 5, pid: pid, answer: answer }); }, upload_title: function (title, qid) { ITF.upload_api({ type: 6, qid: qid, title: title }); }, get_answer: function (qid, td) { ITF.get(set.get_answer, { uid: "" + set.uid, qid: qid }, function (xhr) { if (xhr.status == 200) { try { let data = JSON.parse(xhr.responseText); if (data.code == 1) { td.innerText = data.answer; td.addEventListener("click", function () { GM_setClipboard(data.answer); }); return; } else if (data.code == 0) { td.innerText = "无答案"; return; } } catch (e) { } } td.innerText = "服务器错误"; }, function () { td.innerText = "服务器错误"; }); }, }; Re_Write(); Get_Uid(); Init(); function Re_Write() { const open = unsafeWindow.XMLHttpRequest.prototype.open; unsafeWindow.XMLHttpRequest.prototype.open = function () { let url = arguments[1]; if (url) { if (url.match(/getPaperForStudent/) && url.match(/examId=(\d+)/) && url.match(/paperID=(\d+)/)) { let examID = url.match(/examId=(\d+)/)[1]; let paperID = url.match(/paperID=(\d+)/)[1]; this.addEventListener('load', () => { let data = JSON.parse(this.responseText); ITF.upload_paper(data, paperID); }); ITF.upload_eidpid(examID, paperID); } else if (url.match(/getCorrectAnswer/) && url.match(/examID=(\d+)/) && url.match(/paperID=(\d+)/)) { let examID = url.match(/examID=(\d+)/)[1]; let paperID = url.match(/paperID=(\d+)/)[1]; this.addEventListener('load', () => { let data = JSON.parse(this.responseText); ITF.upload_answer(data, paperID); }); ITF.upload_eidpid(examID, paperID); } } return open.apply(this, arguments); }; } function Init() { if (!document.body) { setTimeout(Init, 100); return; } let style = document.createElement("style"); style.innerHTML = ` #answer_key { min-height: 22px; max-height: 200px; overflow: auto; } .td_center { text-align: center; } .td_left { text-align: left; } .td_right { text-align: right; } .td_width { width: 125px; }`; let div = document.createElement("div"); div.setAttribute("style", "background-color: #4fc8db; position: fixed; top: 54px; right: 10px; width: 270px; opacity: 0.75; border-style: dotted; border-width: 3px;"); div.innerHTML = `

Ulearning 查题

服务器状态: 未知
题目 答案
`; document.body.appendChild(style); document.body.appendChild(div); Bind(); div.addEventListener("mousedown", function (e) { set.dragging = true; let mer = div.getBoundingClientRect(); set.left = e.clientX - mer.left; set.top = e.clientY - mer.top; }); div.addEventListener("mouseup", function () { set.dragging = false; }); div.addEventListener("mousemove", function (e) { if (set.dragging) { let x = e.clientX - set.left; let y = e.clientY - set.top; div.style.left = x + "px"; div.style.top = y + "px"; } }); } function Bind() { let get_answer = document.querySelector("#get_answer"); get_answer && (function () { get_answer.addEventListener("click", Get_Answer, false); })(); let hide_show = document.querySelector("#hide_show"); hide_show && (function () { hide_show.addEventListener("click", function () { let answer_key = document.querySelector("#answer_key"); answer_key && (function () { answer_key.getAttribute("style") === "display: block;" && (function () { answer_key.setAttribute("style", "display: none;"); return true; })() || (function () { answer_key.setAttribute("style", "display: block;"); })(); })(); }, false); })(); } function Get_Uid() { if (unsafeWindow.exam && unsafeWindow.exam.userID) { set.timestamp = new Date().getTime(); set.uid = unsafeWindow.exam.userID; setInterval(Heart, 20000); } else { setTimeout(Get_Uid, 50); } } function Heart() { let server_status = document.querySelector("#server_status"); if (server_status) { ITF.get(set.heartbeat, { uid: "" + set.uid, timestamp: "" + set.timestamp }, function (xhr) { try { let xhr_json = JSON.parse(xhr.responseText); if (xhr_json.code == 1) { server_status.innerText = "正常"; return; } } catch (e) { } server_status.innerText = "异常"; }, function () { server_status.innerText = "异常"; }); } } function Clear_Table() { let answer_table = document.querySelector("#answer_table"); answer_table && (function () { while (answer_table.rows.length > 1) { answer_table.deleteRow(1); } })(); } function Get_Answer() { Clear_Table(); document.querySelectorAll(".cont").forEach(function (item) { item.childNodes.forEach(function (div) { if (div.className.indexOf("part-toggle") != -1) { return; } switch (div.className) { case "multiple-choices": case "judge": case "fill": case "match": case "sort": t1(div); break; case "blankFill": case "cloze": default: t2(div); } }); }); } function t2(div) { let title = div.querySelector(".ques-item-title"); let title_text = title && title.innerText || ""; let answer_table = document.querySelector("#answer_table"); answer_table && (function () { let tr = answer_table.insertRow(); tr.insertCell().innerText = title_text; tr.insertCell(); let items = div.querySelector(".ques-item-content"); items && items.childNodes.forEach(function (item) { let qid = item.getAttribute("data-id") || ""; let tr = answer_table.insertRow(); let t = tr.insertCell(); t.innerText = get_title(item); t.addEventListener("click", function () { GM_setClipboard(this.innerText); }, false); t = tr.insertCell(); ITF.get_answer(qid, t); }); })(); } function t1(div) { let fC = div.firstChild; let qid = check_id(fC); if (!qid) { return; } let title = get_title(fC); let answer_table = document.querySelector("#answer_table"); answer_table && (function () { let tr = answer_table.insertRow(); let t = tr.insertCell(); t.innerText = title; t.addEventListener("click", function () { GM_setClipboard(this.innerText); }, false); t = tr.insertCell(); ITF.get_answer(qid, t); ITF.upload_title(title, qid); })(); } function get_title(fC) { let title = fC.querySelector(".left"); let title_text = title && title.innerText || ""; return title_text; } function check_id(fC) { let qid = fC.getAttribute("data-id") || ""; if (!qid || qid.match(/[^0-9]/)) { return false; } return qid; } class FD { constructor() { this.text = ""; this.data = []; } append(k, v) { this.data.push(encodeURIComponent(k) + "=" + encodeURIComponent(v)); this.text = this.data.join("&").replace(/%20/g, "+"); } }