您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Fetches answers to *all* Naurok quizes
// ==UserScript== // @name Naurok Bypass v2 // @author griffi-gh // @namespace griffi-gh // @description Fetches answers to *all* Naurok quizes // @version 8.1 // @license MIT // @match *://naurok.com.ua/test/*.html // @grant GM_setValue // @grant GM_getValue // @grant GM_getResourceURL // @run-at document-start // @inject-into content // @sandbox DOM // @connect naurok.com.ua // @icon https://play-lh.googleusercontent.com/scIkpmsUJTfDbV39X0rb-AvxbgxOrpa9zIGJQqDHP1VbuBTmortXomSSWVZnpErwyA=w480-h960 // @homepageURL https://gf.qytechs.cn/uk/scripts/461662-naurok-bypass-v2 // @resource LOADING_IMAGE https://media.tenor.com/MlCeUwzn2nEAAAAM/troll-lol.gif // @resource TEST_IMAGE_URL https://cdn-icons-png.flaticon.com/512/190/190411.png // @resource TEST_UPDATE_IMAGE_URL https://cdn-icons-png.flaticon.com/512/1601/1601884.png // @resource ERROR_IMAGE_URL https://media.tenor.com/hA1b1zIqnHkAAAAd/among-us.gif // ==/UserScript== "use strict"; { console.log("Naurok Bypass v2"); // Check if already loaded if (window._BNAUROK2 != null) { console.error("already loaded"); return; } else { window._BNAUROK2 = true; } //Required to work around the false session issue //Used only if a direct request fails const SESSION_PROXY = "https://eobzz8g6oxzrky0.m.pipedream.net/"; let ERROR_IMAGE_URL, LOADING_IMAGE, TEST_IMAGE_URL, TEST_UPDATE_IMAGE_URL; if (window.GM_getResourceURL) { //Use GM resources if possible console.log("Using GM resources"); LOADING_IMAGE = GM_getResourceURL("LOADING_IMAGE", true); TEST_IMAGE_URL = GM_getResourceURL("TEST_IMAGE_URL", true); TEST_UPDATE_IMAGE_URL = GM_getResourceURL("TEST_UPDATE_IMAGE_URL", true); ERROR_IMAGE_URL = GM_getResourceURL("ERROR_IMAGE_URL", true); } else { console.log("Using URL resources"); LOADING_IMAGE = "https://media.tenor.com/MlCeUwzn2nEAAAAM/troll-lol.gif"; TEST_IMAGE_URL = "https://cdn-icons-png.flaticon.com/512/190/190411.png"; TEST_UPDATE_IMAGE_URL = "https://cdn-icons-png.flaticon.com/512/1601/1601884.png"; ERROR_IMAGE_URL = "https://media.tenor.com/hA1b1zIqnHkAAAAd/among-us.gif"; } const ls_key = `cached-${document.location.pathname.replaceAll("/", "-").slice(1, -5).toLowerCase()}`; async function loadStuff() { //Clean up pre_display() //Get the hostname const hostname = window.location.hostname; console.log("Host:", hostname); //Get test path const base = document.location.href.slice(0, -5); console.log("Base URL:", base); //Load the homework creation page const set_text = await fetch(base + "/set").then(x => x.text()); const set_document = document.createElement("html"); set_document.innerHTML = set_text; console.log("Set document:", set_document); //Get form data and modify it const set_form = set_document.querySelector("#w0"); const set_form_data = new FormData(set_form); set_form_data.set("Homework[deadline_day]", "9999-01-01"); set_form_data.set("Homework[show_answer]", "1"); console.log("Set form data:", set_form_data); //Start homework const homework_res = await fetch(set_form.action, { redirect: 'follow', method: 'POST', credentials: 'include', body: set_form_data, }); //Get homework url and id const homework_url = homework_res.url; const homework_id = homework_url.split("/").at(-1); console.log("Homework url:", homework_url); //Get homework document object const homework_text = await homework_res.text(); const homework_document = document.createElement("html"); homework_document.innerHTML = homework_text; console.log("Homework document:", homework_document); //Get the CSRF token and create FormData from it const homework_csrf_param = homework_document.querySelector('meta[name="csrf-param"]').content; const homework_csrf_token = homework_document.querySelector('meta[name="csrf-token"]').content; const homework_csrf_form_data = new FormData(); homework_csrf_form_data.set(homework_csrf_param, homework_csrf_token); console.log("CSRF param/token:", homework_csrf_param, homework_csrf_token); //Get join code const homework_code = homework_document.querySelector(".homework-code").textContent; console.log("Homework join code:", homework_code); //Load the join page const join_text = await fetch(`https://${hostname}/test/join?gamecode=${homework_code}`).then(res => res.text()); const join_document = document.createElement('html'); join_document.innerHTML = join_text; //Get form data and fill in the username const join_form = join_document.querySelector("#participate-form-code"); const join_form_data = new FormData(join_form); const username = "[object Object]"; join_form_data.set("JoinForm[name]", username); //troll naurok developers while we're at it lol //Start homework session const join_res = await fetch(join_form.action, { redirect: 'follow', method: 'POST', credentials: 'include', body: new URLSearchParams(join_form_data).toString(), headers: { "Content-Type": "application/x-www-form-urlencoded", }, }); console.log("Joined with username", username) //Get test session address const test_session_url = join_res.url; console.log("Test session URL:", test_session_url); //Get the test session document const session_text = await fetch(test_session_url).then(res => res.text()); const session_document = document.createElement("html"); session_document.innerHTML = session_text; //Get session id const testik_elem = session_document.querySelector('[ng-app="testik"]'); const ng_init = testik_elem.getAttribute("ng-init"); const ng_init_numbers = ng_init.match(/[0-9]+/g); const session_id = ng_init_numbers[1] || 0; console.log("Session id", session_id); //Get session info let session_info = await fetch(`https://${hostname}/api2/test/sessions/${session_id}`, { credentials: "include", headers: { 'Accept': 'application/json, text/plain, */*', 'Content-Type': 'application/json' }, redirect: 'follow', }).then(x => x.json()); console.log("Session info: ", session_info); //Work around weird issue if (session_info == false) { console.log("Oops, need to proxy the request"); session_info = await fetch(SESSION_PROXY, { method: "POST", headers: { 'Accept': 'application/json, text/plain, */*', 'Content-Type': 'application/json' }, body: JSON.stringify({ session: session_id }) }).then(x => x.json()); console.log("Session info (proxied):", session_info); } //Find the latest question const {latest_question, questions} = session_info; const question = latest_question ? questions.find(question => question.id == latest_question) : questions[0]; console.log("Question:", question); //Get the answer id const answer_id = question.options[0].id.toString(); console.log("Answer ID:", answer_id); //Answer the question await fetch(`https://${hostname}/api2/test/responses/answer`, { method: "PUT", credentials: "include", headers: { 'Accept': 'application/json, text/plain, */*', 'Content-Type': 'application/json' }, body: JSON.stringify({ "session_id": session_id, "answer": [answer_id], "question_id": question.id, "show_answer": 1, "type": "quiz", "point": question.point.toString(), "homeworkType": question.type, "homework": true }), }); console.log("Responded to the question"); //End the session const end_sess_data = await fetch(`https://${hostname}/api2/test/sessions/end/${session_id}`, { "method": "PUT", "credentials": "include", }).then(res => res.json()); const end_sess_uuid = end_sess_data.session.uuid; console.log("Session UUID:", end_sess_uuid); //Fetch the end page const test_end_text = await fetch(`https://${hostname}/test/complete/${end_sess_uuid}`, { redirect: 'follow' }).then(res => res.text()); //Get the text end document const test_end_document = document.createElement("html"); test_end_document.innerHTML = test_end_text; //Get the answers const answers = test_end_document.querySelector(".homework-stats"); console.log("Answer element:", answers); //Display answers display_answers(answers); console.log("Answers displayed"); //Stop homework await fetch(`https://${hostname}/test/homework/${homework_id}/stop`, { method: 'POST', credentials: 'include', body: homework_csrf_form_data, }); console.log("Homework stopped"); //Delete homework await fetch(`https://${hostname}/test/homework/${homework_id}/delete`, { method: 'POST', credentials: 'include', body: homework_csrf_form_data, }); console.log("Homework deleted"); console.log("DONE"); return answers }; function pre_display() { //Delete previously displayed Array.from(document.querySelectorAll(".question-view-item")).forEach(item => item.remove()); //Clear the regular questions Array.from(document.querySelectorAll(".answer-sheet")).forEach(item => item.remove()); } function display_answers(answers) { pre_display() //Add classes answers.classList.add("row"); answers.classList.add("answer-sheet") //HACK: Remove "- your answer" text answers.innerHTML = answers.innerHTML.replaceAll("<em>— ваша відповідь</em>", ""); //Add answers to the page const afer_element = document.querySelector(".block-head"); afer_element.parentNode.insertBefore(answers, afer_element.nextSibling); }; async function loadStuffWriteCache() { const answers = await loadStuff(); const elem = document.createElement("div"); display_answers(elem); elem.appendChild(answers.cloneNode(true)); (window.GM_setValue ?? localStorage.setItem.bind(localStorage))(ls_key, elem.innerHTML); } //Preload images const images = [] { window._cow_taxes = images; //keep the reference alive images["loading"] = new Image(); images["loading"].src = LOADING_IMAGE; images["test"] = new Image(); images["test"].src = TEST_IMAGE_URL; images["update"] = new Image(); images["update"].src = TEST_UPDATE_IMAGE_URL; images["error"] = new Image(); images["error"].src = ERROR_IMAGE_URL; } function loadErrorHandler(err) { console.error(err); const btn = document.querySelector(".clicky-click"); btn.querySelector("img").replaceWith(images.error); const label = btn.querySelector("span") label.textContent = "Помилка\n"+err.toString()+"\n"; label.innerHTML = label.innerHTML.replaceAll("\n", "<br>"); label.innerHTML += ` FIX 1 - Натисни кнопку ще раз<br> FIX 2 - <a href='https://naurok.com.ua/test/join?gamecode=0' target="_blank">Відкрий і закрий цю сторінку</a><br> FIX 3 - <a href='https://naurok.com.ua/login' target="_blank">Увійди в аккаунт Наурок</a><br> FIX 4 - Спробуй ще раз через 5 хвилин `; } async function loadStuffAndWriteCacheWithErrorHandler() { try { await loadStuffWriteCache(); return true; } catch(err) { loadErrorHandler(err); return false; } } //Load cached answers let is_cached = false; let cached_element = null; if ((window.GM_getValue ?? localStorage.getItem.bind(localStorage))(ls_key, null)) { console.log("Cached found:", ls_key); const elem = document.createElement("div"); try { elem.innerHTML = (GM_getValue ?? localStorage.getItem.bind(localStorage))(ls_key, null); cached_element = elem.firstChild; is_cached = true; (cached_element.querySelector(".chicken-beef")?.classList.add("answer-sheet")) && console.warn("Cache contains chicken beef"); } catch (e) { console.error("Cache invalid:", e); is_cached = false; cached_element = null; } } const MAIN = async () => { //Display cached stuff if (is_cached) { try { display_answers(cached_element); console.log("Cached answer displayed!") } catch(e) { console.error("Cache invalid:", e); is_cached = false; cached_element = null; } } //Add CSS { const style = ` .answer-sheet { padding: 1.33rem; } /* style indicator colors*/ .answer-sheet .homework-stat-option-value.incorect :is(.quiz,.multiquiz) { background: #cccccc !important; color: black !important; } .answer-sheet .homework-stat-option-value.correct :is(.quiz,.multiquiz) { background: #23c552 !important; color: black !important; } /* fix indicator offset */ .answer-sheet .homework-stat-option-value :is(.quiz,.multiquiz) { top: .5rem !important; } /* Green bg on correct*/ .answer-sheet .homework-stat-option-value.correct { background: linear-gradient(to bottom, rgba(0,0,0,0), #e3f7e9 15%, #e3f7e9 85%, rgba(0,0,0,0)) !important; border-radius: .25rem !important; } /* fix uneven p padding*/ .answer-sheet .homework-stat-option-value p { margin: 0.5rem 0.25rem !important; } /* hide q ranking */ .answer-sheet .question-label { display: none !important; } /* hide weird orange overlays */ .answer-sheet .ql-cursor { display: none !important; } /* hide correctness indicators*/ .answer-sheet .content-block.success, .answer-sheet .content-block.skipped, .answer-sheet .content-block.failed, .answer-sheet .content-block.partial { border-left: none !important; } /* style the main button */ .clicky-click { display: flex; width: 100%; border-width: 0; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; line-height: inherit; margin-bottom: 0 !important; } #cb_wrapper { display: blck; text-align: center; } #auto_load_cb { margin-right: .25rem; } #auto_load_cb ~ label { font-weight: unset; } /* Use flex to style our button */ .test-action-button.clicky-click { display: flex !important; flex-direction: column !important; height: unset !important; gap: 10px !important; } .test-action-button.clicky-click * { position: unset !important; } /* This applies to ALL buttons (makes them a bit fancier because why not) */ .test-action-button { transition: all .25s !important; border: 1px solid rgba(0,0,0,.1) !important; border-radius: 10px !important; } .test-action-button:hover { background: #f0f0f0 !important; } .test-action-button:hover > * { filter: drop-shadow(0px 0px 4px #dddddd); } .test-action-button > img { transition: transform .25s !important; } .test-action-button:not(:disabled):hover > img { transform: scale(0.9) rotate(-3deg); } /* todo: style auto load checkbox */ #auto_load_cb {} /* fix scrolling */ body { overflow: auto !important; } /* Remove ads */ /* TODO: fix! hides answers too */ /*.col-sm-8.col-md-9 { display: none !important; }*/ /* Fix em coloring */ .homework-stat-option-value em { color: inherit !important; } `; const style_elem = document.createElement("style"); style_elem.textContent = style; document.head.appendChild(style_elem); } //Create answers button { const button = document.createElement("button"); button.type = "button"; button.classList.add("test-action-button"); button.classList.add("clicky-click"); button.appendChild(images.test); const text_elem = document.createElement("span"); text_elem.textContent = "Завантажити відповіді"; button.appendChild(text_elem); if (is_cached) { button.querySelector('img').replaceWith(images.update); text_elem.textContent = "Оновити відповіді"; } button.addEventListener("click", async () => { button.querySelector('img').replaceWith(images.loading); text_elem.textContent = "Завантаження..."; button.disabled = true; if (await loadStuffAndWriteCacheWithErrorHandler()) { button.querySelector('img').replaceWith(images.update); text_elem.textContent = "Оновити відповіді"; } button.disabled = false; }); const buttons = document.querySelector(".single-test-actions"); buttons.prepend(button); } //Create auto load toggle { //Create checkbox const auto_load_cb = document.createElement("input"); auto_load_cb.id = "auto_load_cb"; auto_load_cb.type = "checkbox"; const save_state = () => { (window.GM_setValue || localStorage.setItem.bind(localStorage))("auto-load", auto_load_cb.checked ? "1" : "0"); } auto_load_cb.checked = ((window.GM_getValue || localStorage.getItem.bind(localStorage))("auto-load") || "0") == "1"; save_state(); auto_load_cb.addEventListener("change", save_state); if (!is_cached && auto_load_cb.checked) { document.querySelector(".clicky-click").click(); } //Add it const cb_wrapper = document.createElement("div"); cb_wrapper.id = "cb_wrapper"; const cb_label = document.createElement("label"); cb_label.textContent = "Автоматично завантажувати відповіді"; cb_label.setAttribute("for", auto_load_cb.id); cb_wrapper.appendChild(auto_load_cb); cb_wrapper.appendChild(cb_label); const afer_element = document.querySelector(".clicky-click"); afer_element.parentNode.insertBefore(cb_wrapper, afer_element.nextSibling); } }; // Run if loaded late if ((document?.readyState == "interactive") || (document?.readyState == "complete")) { MAIN(); } else { document.addEventListener("DOMContentLoaded", MAIN); } }
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址