// ==UserScript== // @name CCNA Autofill // @namespace Violentmonkey Scripts // @match *://assessment.netacad.net/* // @match *://www.assessment.netacad.net/* // @grant GM_setValue // @grant GM_getValue // @grant GM_xmlhttpRequest // @grant GM_log // @version 0.0.1 // @author Dominik Säume // ==/UserScript== const URL_STORAGE_KEY = "itexamanswers.net URL"; let awnserData; console.log = console.__proto__.log; window.addEventListener("keydown", event => { switch(event.key){ case "p": const oldAwnsersURL = GM_getValue(URL_STORAGE_KEY); let newAwnsersURL = prompt("Please input the answer url (itexamanswers.net)", oldAwnsersURL); GM_setValue(URL_STORAGE_KEY, newAwnsersURL); fetchData(newAwnsersURL); break; case "n": document.getElementById("next").click(); break; case "a": awnserQuestion(); break; } }) function awnserQuestion(){ const question = document.querySelector(".question:not(.hidden)"); if (!question) { return; } const questionTextDom = question.querySelector(".questionText .mattext"); if (!questionTextDom) return; const questionText = questionTextDom.textContent.trim(); const answersDom = question.querySelector("ul.coreContent"); if (!answersDom) return; const answers = answersDom.children; for (let answer of answers) { const input = answer.querySelector("input"); if (!input) continue; input.checked = false; } const correctAnswers = findAnswers(questionText, answers); if (correctAnswers.length === 0) { GM_log("no awnser") return; } for (const answer of correctAnswers) { const input = answer.querySelector("input"); if (!input) continue; input.checked = true; } } function findAnswers(questionText, answers) { if (awnserData === null) { alert("No chapter data loaded. Maybe the fetch failed?!"); return []; } const correctAnswers = []; for (let entry of awnserData) { if (matchAwnser(questionText.trim(), entry.question.trim())) { for (let availableAnswer of answers) { for (let possibleAnswer of entry.answers) { if (matchAwnser(availableAnswer.textContent.trim(), possibleAnswer)) { correctAnswers.push(availableAnswer); } } } } } return correctAnswers; } function matchAwnser(textA, textB) { const replaceRegex = /[^\w]/gi; textA = textA.replace(replaceRegex, ""); textB = textB.replace(replaceRegex, ""); return (textA === textB); } function fetchData(awnserURL = ""){ GM_xmlhttpRequest({ method: "GET", url: awnserURL, headers: { "Content-Type": "text/html" }, onload: function(response) { awnserImgs = new Map(); const results = []; const parser = new DOMParser(); const virtDom = parser.parseFromString(response.responseText, "text/html"); let answersDom = virtDom.querySelector(".pf-content"); if (!answersDom) { answersDom = virtDom.querySelector(".thecontent"); } let index = -1; for (let childDom of answersDom.children) { index++; if (childDom.tagName === "P" || childDom.tagName === "STRONG" ) { // maybe a question question let innerDom = childDom.querySelector("strong"); if (innerDom === null) { if(!childDom.textContent){ continue; } innerDom = childDom; }; const textContent = innerDom.textContent.trim(); const matches = textContent.match(/^[0-9]+\. (.*)$/); if (matches !== null) { const questionText = matches[1]; // most likely a question let nextChild = answersDom.children[index + 1]; if (nextChild.tagName === "P"){ nextChild = answersDom.children[index + 2]; }; if (nextChild === null) continue; if (nextChild.tagName === "UL") { // most likely the awnser const answers = []; for (let answerDom of nextChild.querySelectorAll("strong")) { let answerText = answerDom.textContent.trim(); if (answerText.endsWith("*")) { answerText = answerText.substring(0, answerText.length - 1); } answers.push(answerText); } results.push({ question: questionText, answers: answers }); } } } } awnserData = results; GM_log(results); GM_log(awnserImgs); } }); }