// ==UserScript== // @name TSA+ // @namespace Violentmonkey Scripts // @match https://tsa.hust.edu.vn/dang-ky-thi* // @namespace tretrauit-dev // @grant none // @version 1.0 // @author tretrauit // @description 18:56:28 16/5/2024 // @require https://raw.githubusercontent.com/naugtur/insertionQuery/master/insQ.min.js // ==/UserScript== const sleep = ms => new Promise(r => setTimeout(r, ms)); function getElementByInnerText(element, text) { return Array.from(element.querySelectorAll("*")).find((e) => e.innerText === text); } // Replace console functions with our own. // biome-ignore lint/complexity/noStaticOnlyClass: console replacement (in SessionStorage) since TSA disabled it fuck. class console { static log(...args) { const log = sessionStorage.getItem("tsaplus.console.log"); if (log) { sessionStorage.setItem("tsaplus.console.log", `${log}\n${args.toString()}`); } else { sessionStorage.setItem("tsaplus.console.log", args.toString()); } } static info(...args) { const log = sessionStorage.getItem("tsaplus.console.info"); if (log) { sessionStorage.setItem("tsaplus.console.info", `${log}\n${args.toString()}`); } else { sessionStorage.setItem("tsaplus.console.info", args.toString()); } } static warn(...args) { const log = sessionStorage.getItem("tsaplus.console.warn"); if (log) { sessionStorage.setItem("tsaplus.console.warn", `${log}\n${args.toString()}`); } else { sessionStorage.setItem("tsaplus.console.warn", args.toString()); } } static error(...args) { const log = sessionStorage.getItem("tsaplus.console.error"); if (log) { sessionStorage.setItem("tsaplus.console.error", `${log}\n${args.toString()}`); } else { sessionStorage.setItem("tsaplus.console.error", args.toString()); } } } unsafeWindow.console = console; // Hijack XHR with ours. let lastExamDetail = null; const OrigXHR = unsafeWindow.XMLHttpRequest; function xhrResponseCallback(xhr) { if (xhr.responseURL.includes("https://api-hust.khaothi.online/my/apiv1/exams/get-exam-plan-detail")) { console.log(`Set lastExamDetail to ${xhr.responseURL}`); lastExamDetail = xhr.response; } } class XMLHttpRequest extends OrigXHR { constructor(...args) { super(...args); // alert("XHR created"); this.onload = () => { xhrResponseCallback(this); // alert("XHR loaded"); }; } send(...args) { super.send(...args); } } unsafeWindow.XMLHttpRequest = XMLHttpRequest; insertionQ(".ant-modal-root").every(async (_) => { let retry = 0; while (retry < 50 && lastExamDetail === null) { retry += 1; await sleep(100); if (retry >= 50) { return; } } console.log("Found lastExamDetail"); const examDetail = JSON.parse(lastExamDetail); lastExamDetail = null; const examId = examDetail.data.exam.id; const rsp = await fetch(`https://api-hust.khaothi.online/my/apiv1/exam-plan/get-test-sites?exam_id=${examId}`, { headers: { Authorization: `Bearer ${localStorage.getItem("authen_access_token")}` } }) const data = await rsp.json(); const [element, elementType] = await Promise.any([(async () => { let element; do { await sleep(10); element = getElementByInnerText(document, "Thông tin đăng ký"); retry += 1; if (retry >= 100) { return [null, null]; } } while (element === undefined || element.parentElement === undefined); return [element, "register"]; })(), (async () => { let element; do { await sleep(10); element = getElementByInnerText(document, "Điểm TSA"); retry += 1; if (retry >= 100) { return [null, null]; } } while (element === undefined || element.parentElement === undefined); return [element, "score"]; })()]) const waveInfo = {}; const genericInfo = { totalContestants: 0, totalCapacity: 0 }; switch (elementType) { case "register": firstCol = element.parentElement.parentElement.children[0]; break; case "score": firstCol = element.parentElement.parentElement.parentElement.parentElement; break; case null: return; } for (const testSite of data.data.test_sites) { if (testSite.name.startsWith("Đợt")) { const wave = testSite.name.split(" ")[1]; if (!waveInfo[wave]) { waveInfo[wave] = { totalContestants: 0, totalCapacity: 0 } } waveInfo[wave].totalContestants += testSite.count_test_taker; if (testSite.max_test_taker === 0) { waveInfo[wave].totalCapacity += testSite.count_test_taker; } else { waveInfo[wave].totalCapacity += testSite.max_test_taker; } } else { genericInfo.totalContestants += testSite.count_test_taker; if (testSite.max_test_taker === 0) { genericInfo.totalCapacity += testSite.count_test_taker; } else { genericInfo.totalCapacity += testSite.max_test_taker; } } } console.log(`Wave info: ${JSON.stringify(waveInfo)}`); console.log(`Generic info: ${JSON.stringify(genericInfo)}`); if (Object.keys(waveInfo).length > 0) { for (const [waveName, wave] of Object.entries(waveInfo)) { console.log("Adding wave info"); const pElement = document.createElement("p"); pElement.innerHTML = `Số thí sinh đăng ký đợt ${waveName}: ${wave.totalContestants}/${wave.totalCapacity}`; if (elementType === "register") { firstCol.insertBefore(pElement, firstCol.children[1]); } else { firstCol.insertBefore(pElement, firstCol.children[0]); } } } else { console.log("Adding generic info"); const pElement = document.createElement("p"); pElement.innerHTML = `Số thí sinh đăng ký: ${genericInfo.totalContestants}/${genericInfo.totalCapacity}`; if (elementType === "register") { firstCol.insertBefore(pElement, firstCol.children[1]); } else { firstCol.insertBefore(pElement, firstCol.children[0]); } } });