189 lines
6.6 KiB
JavaScript
189 lines
6.6 KiB
JavaScript
// ==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]);
|
|
}
|
|
}
|
|
});
|