// // Copyright © 2023 adithyagenie // // SPDX-License-Identifier: AGPL-3.0-or-later // // ==UserScript== // @name Math Problem Solver // @namespace https://github.com/adithyagenie/skillrack-captcha-solver // @version 0.4 // @description Solves math captcha in SkillRack using Tesseract.js // @author adithyagenie // @include https://www.skillrack.com/faces/candidate/codeprogram.xhtml // @include https://www.skillrack.com/faces/candidate/tutorprogram.xhtml // @include https://www.skillrack.com/faces/candidate/codeprogramgroup.xhtml // @require https://cdn.jsdelivr.net/npm/tesseract.js@4.1.1/dist/tesseract.min.js // ==/UserScript== (function () { "use strict"; // Clear all sessionstorage data if going back out of solve. if ( window.location.href == "https://www.skillrack.com/faces/candidate/codeprogramgroup.xhtml" ) { if (sessionStorage.getItem("Solvebtnid")) sessionStorage.removeItem("Solvebtnid"); if (sessionStorage.getItem("captchaFail")) sessionStorage.removeItem("captchaFail"); } function onClick(event) { // Get solve button click if ( event.target.tagName === "SPAN" && event.target.parentNode.tagName === "BUTTON" ) { if (event.target.textContent === "Solve") { // Store button id of problem solve button. sessionStorage.setItem( "Solvebtnid", event.target.parentNode.id ); } } } document.addEventListener("click", onClick, false); // Wait for window to load window.addEventListener("load", function () { // Detect if last captcha attempt was a fail to re-nav back if (sessionStorage.getItem("captchaFail")) { console.log( "Detected captcha fail. Attempting to open last open page." ); // Reset captcha state sessionStorage.removeItem("captchaFail"); // Get old button id const old = sessionStorage.getItem("Solvebtnid"); if (old) { const oldbutt = document.getElementById(old); if (oldbutt) oldbutt.click(); } return; } console.log("Checking for captchas"); // Get the captcha // Different image ids for tutorial and track websites let image; if ( window.location.href == "https://www.skillrack.com/faces/candidate/codeprogram.xhtml" ) image = document.getElementById("j_id_6s"); else if ( window.location.href == "https://www.skillrack.com/faces/candidate/tutorprogram.xhtml" ) image = document.getElementById("j_id_5j"); const textbox = document.getElementById("capval"); const button = document.getElementById("proceedbtn"); if (image == null) { console.log("Captcha not found."); return; } // Check if past captcha submission was a failure const errors = document.getElementsByClassName("ui-growl-item"); if (errors.length > 0) { if (errors[0].textContent.includes("Incorrect Captcha")) { if ( window.location.href == "https://www.skillrack.com/faces/candidate/tutorprogram.xhtml" ) { alert("Unable to solve captcha :("); return; } sessionStorage.setItem("captchaFail", "true"); console.log("Detected failed attempt at solving captcha"); const back = document.getElementById("j_id_5r"); back.click(); return; } } // Get time for logging const time = new Date().getTime(); // Clear captcha state if (sessionStorage.getItem("captchaFail")) { sessionStorage.removeItem("captchaFail"); } // Invert colours for better ocr function invertColors(image) { const canvas = document.createElement("canvas"); const ctx = canvas.getContext("2d"); canvas.width = image.width; canvas.height = image.height; ctx.drawImage(image, 0, 0); ctx.globalCompositeOperation = "difference"; ctx.fillStyle = "white"; ctx.fillRect(0, 0, canvas.width, canvas.height); return canvas.toDataURL(); } // Parse OCR result and solve the problem function getNums(text) { const a = text.replace(" ", "").replace("=", "").split("+"); return parseInt(a[0]) + parseInt(a[1]); } const invertedimg = invertColors(image); console.log(`Converting image: ${new Date().getTime() - time} ms.`); // Image Processing with Tesseract.js Tesseract.recognize(invertedimg, "eng", { whitelist: "1234567890+=", psm: 7, }) .then(({ data: { text } }) => { console.log(`OCR: ${new Date().getTime() - time} ms.`); // Solve the Math Problem try { const result = getNums(text); console.log( "Found math captcha. Auto-filling answer: ", result ); textbox.value = result; // Click the submit button button.click(); console.log(`Took ${new Date().getTime() - time} ms.`); } catch (e) { console.error(e); } return; }) .catch((error) => { console.error("Error processing captcha:", error); }); }); })();