skillrack-captcha-solver/userscript.js
adithyagenie 3e331096eb
Bump tesseract.js to v5.1.0
Signed-off-by: adithyagenie <adithyagenie@gmail.com>
2024-06-16 08:13:34 +05:30

142 lines
4.7 KiB
JavaScript

//
// Copyright © 2023 adithyagenie
//
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// ==UserScript==
// @name Skillrack Captcha Solver
// @namespace https://github.com/adithyagenie/skillrack-captcha-solver
// @version 0.7
// @description Solves math captcha in SkillRack using Tesseract.js
// @author adithyagenie
// @license AGPL-3.0-or-later
// @include /https:\/\/(www\.)?skillrack\.com\/faces\/candidate\/(codeprogram|tutorprogram|codeprogramgroup)\.xhtml/
// @require https://cdn.jsdelivr.net/npm/tesseract.js@5.1.0/dist/tesseract.min.js
// ==/UserScript==
const USERNAME = "";
const TUTOR = /https:\/\/(www.)?skillrack\.com\/faces\/candidate\/tutorprogram\.xhtml/gi;
const ERROR = "ui-growl-item";
const TUTOR_IMG = "j_id_5o";
const NON_TUTOR_IMG = "j_id_6x";
const BACK_BTN = "j_id_5s";
const CAPTCHA_ID = "capval";
const PROCEED_BTN_ID = "proceedbtn";
(function () {
"use strict";
// 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();
}
// Remove username from captcha
function solveCaptcha(text) {
const cleanedText = text.replace(new RegExp(USERNAME, "gi"), "").trim();
const match = cleanedText.match(/(\d+)\s*\+\s*(\d+)/);
if (match) {
return parseInt(match[1], 10) + parseInt(match[2], 10);
}
else {
handleIncorrrectCaptcha();
return -1;
}
}
function handleCaptcha() {
// Get the captcha
const captchaImageId = window.location.href.includes("tutorprogram") ? TUTOR_IMG : NON_TUTOR_IMG;
const image = document.getElementById(captchaImageId);
const textbox = document.getElementById(CAPTCHA_ID);
const button = document.getElementById(PROCEED_BTN_ID);
if (!image || !textbox || !button) {
console.log("Captcha or input elements not found.");
return;
}
const invertedimg = invertColors(image);
// Image Processing with Tesseract.js
Tesseract.recognize(invertedimg, "eng", {
whitelist: "1234567890+=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@ ",
psm: 6,
})
.then(({ data: { text } }) => {
console.log(`OCR: Result: ${text}`);
// Solve the Math Problem
const result = solveCaptcha(text);
if (result == -1) return;
else if (result === null) {
alert(`Unable to solve math captcha...`)
return;
}
textbox.value = result;
// Click the submit button
button.click();
return;
})
.catch((error) => {
alert("Error processing captcha:", error);
});
}
function handleIncorrrectCaptcha() {
// If in tutorial pages, can't go back.
if (
window.location.href.match(TUTOR)
) {
alert("Unable to solve captcha :(");
let captext = prompt("Captcha:");
if (captext == null) return;
const result = solveCaptcha(captext);
const textbox = document.getElementById(CAPTCHA_ID);
const button = document.getElementById(PROCEED_BTN_ID);
textbox.value = result;
button.click();
return;
}
sessionStorage.setItem("captchaFail", "true");
document.getElementById(BACK_BTN)?.click();
return;
}
document.addEventListener("click", (event) => {
if (
event.target.tagName === "SPAN" && event.target.parentNode.tagName === "BUTTON" && event.target.textContent === "Solve"
) {
// Store button id of problem solve button.
sessionStorage.setItem("Solvebtnid", event.target.parentNode.id);
}
}, 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")) {
// Reset captcha state
sessionStorage.removeItem("captchaFail");
// Get old button id
const old = sessionStorage.getItem("Solvebtnid");
if (old) {
const oldbutt = document.getElementById(old);
oldbutt?.click();
}
return;
}
const errors = document.getElementsByClassName(ERROR);
if (errors.length > 0 && errors[0].textContent.includes("Incorrect Captcha")) {
handleIncorrrectCaptcha();
}
handleCaptcha();
});
})();