skillrack-captcha-solver/userscript.js

205 lines
5.9 KiB
JavaScript
Raw Normal View History

2023-08-18 15:47:36 +00:00
//
// Copyright © 2023 adithyagenie
//
// SPDX-License-Identifier: AGPL-3.0-or-later
//
2023-08-18 15:34:25 +00:00
// ==UserScript==
2023-09-02 15:29:41 +00:00
// @name Skillrack Captcha Solver
2023-08-18 15:34:25 +00:00
// @namespace https://github.com/adithyagenie/skillrack-captcha-solver
// @version 0.6
2023-08-18 15:34:25 +00:00
// @description Solves math captcha in SkillRack using Tesseract.js
// @author adithyagenie
2023-10-02 15:33:52 +00:00
// @license AGPL-3.0-or-later
// @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@5.0.2/dist/tesseract.min.js
2023-08-18 15:34:25 +00:00
// ==/UserScript==
const USERNAME = "";
2023-08-18 15:34:25 +00:00
(function () {
2023-09-02 13:44:44 +00:00
"use strict";
// Clear all sessionstorage data if going back out of solve.
2023-09-02 13:44:44 +00:00
if (
window.location.href.match(
/https:\/\/(www.)?skillrack\.com\/faces\/candidate\/codeprogramgroup\.xhtml/gi
)
2023-09-02 13:44:44 +00:00
) {
if (sessionStorage.getItem("Solvebtnid"))
sessionStorage.removeItem("Solvebtnid");
if (sessionStorage.getItem("captchaFail"))
sessionStorage.removeItem("captchaFail");
2023-09-02 13:44:44 +00:00
}
2023-09-02 13:44:44 +00:00
function onClick(event) {
// Get solve button click
2023-09-02 13:44:44 +00:00
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
);
2023-09-02 13:44:44 +00:00
}
}
}
document.addEventListener("click", onClick, false);
2023-08-18 15:34:25 +00:00
// 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")) {
2023-09-02 13:44:44 +00:00
console.log(
"Detected captcha fail. Attempting to open last open page."
2023-09-02 13:44:44 +00:00
);
// Reset captcha state
sessionStorage.removeItem("captchaFail");
// Get old button id
const old = sessionStorage.getItem("Solvebtnid");
2023-09-02 13:44:44 +00:00
if (old) {
const oldbutt = document.getElementById(old);
if (oldbutt) oldbutt.click();
}
return;
}
2023-08-18 15:34:25 +00:00
console.log("Checking for captchas");
// Get the captcha
// Different image ids for tutorial and track websites
2023-09-02 13:44:44 +00:00
let image;
if (
window.location.href.match(
/https:\/\/(www.)?skillrack\.com\/faces\/candidate\/codeprogram\.xhtml/gi
)
2023-09-02 13:44:44 +00:00
)
image = document.getElementById("j_id_6x");
2023-09-02 13:44:44 +00:00
else if (
window.location.href.match(
/https:\/\/(www.)?skillrack\.com\/faces\/candidate\/tutorprogram\.xhtml/gi
)
2023-09-02 13:44:44 +00:00
)
image = document.getElementById("j_id_5o");
2023-09-02 13:44:44 +00:00
2023-08-18 15:34:25 +00:00
const textbox = document.getElementById("capval");
const button = document.getElementById("proceedbtn");
if (image == null) {
2023-09-02 13:44:44 +00:00
console.log("Captcha not found.");
2023-08-18 15:34:25 +00:00
return;
}
2023-09-02 13:44:44 +00:00
// Check if past captcha submission was a failure
2023-09-02 13:44:44 +00:00
const errors = document.getElementsByClassName("ui-growl-item");
if (errors.length > 0) {
if (errors[0].textContent.includes("Incorrect Captcha")) {
if (
window.location.href.match(
/https:\/\/(www.)?skillrack\.com\/faces\/candidate\/tutorprogram\.xhtml/gi
)
2023-09-02 13:44:44 +00:00
) {
alert("Unable to solve captcha :(");
return;
}
sessionStorage.setItem("captchaFail", "true");
2023-09-02 13:44:44 +00:00
console.log("Detected failed attempt at solving captcha");
const back = document.getElementById("j_id_5s");
2023-09-02 13:44:44 +00:00
back.click();
return;
}
}
// Get time for logging
2023-08-20 15:41:53 +00:00
const time = new Date().getTime();
// Clear captcha state
if (sessionStorage.getItem("captchaFail")) {
sessionStorage.removeItem("captchaFail");
2023-09-02 13:44:44 +00:00
}
2023-08-18 15:34:25 +00:00
// Invert colours for better ocr
2023-08-20 15:41:53 +00:00
function invertColors(image) {
2023-08-18 15:34:25 +00:00
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
2023-08-20 15:41:53 +00:00
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();
2023-08-18 15:34:25 +00:00
}
// Remove username from captcha
/**
*
* @param {string} text
* @returns
*/
function removeText(text) {
text = text.replace(USERNAME, "");
let i = text.length - 1;
i = text.lastIndexOf("+")
if (i == -1) {
console.error("Error parsing username.");
return;
}
i--;
for (i; i >= 0; i--) {
if (!("1234567890".includes(text[i]))) {
return text.slice(i + 1);
}
}
console.error("Error parsing username.");
return;
}
2023-08-18 15:34:25 +00:00
// Parse OCR result and solve the problem
2023-08-18 15:34:25 +00:00
function getNums(text) {
2023-08-20 15:41:53 +00:00
const a = text.replace(" ", "").replace("=", "").split("+");
return parseInt(a[0]) + parseInt(a[1]);
2023-08-18 15:34:25 +00:00
}
2023-08-20 15:41:53 +00:00
const invertedimg = invertColors(image);
console.log(`Converting image: ${new Date().getTime() - time} ms.`);
// Image Processing with Tesseract.js
2023-08-20 15:41:53 +00:00
Tesseract.recognize(invertedimg, "eng", {
whitelist: "1234567890+=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@ ",
2023-08-20 15:41:53 +00:00
psm: 7,
})
2023-08-18 15:34:25 +00:00
.then(({ data: { text } }) => {
2023-08-20 15:41:53 +00:00
console.log(`OCR: ${new Date().getTime() - time} ms.`);
// Solve the Math Problem
2023-08-20 15:41:53 +00:00
try {
const mathprob = removeText(text);
const result = getNums(mathprob);
if (isNaN(result)) {
alert(`Unable to solve math captcha... Check the readme file on https://github.com/adithyagenie/skillrack-captcha-solver for instructions on optional username parsing.\n\nSTRING RECOGNISED: ${text}`)
return;
}
2023-08-18 15:34:25 +00:00
console.log(
2023-08-20 15:41:53 +00:00
"Found math captcha. Auto-filling answer: ",
result
2023-08-18 15:34:25 +00:00
);
textbox.value = result;
// Click the submit button
2023-08-18 15:34:25 +00:00
button.click();
2023-08-20 15:41:53 +00:00
console.log(`Took ${new Date().getTime() - time} ms.`);
} catch (e) {
console.error(e);
2023-08-18 15:34:25 +00:00
}
return;
})
.catch((error) => {
console.error("Error processing captcha:", error);
});
});
})();