SkillRack Math Captcha Solver

Solves Math Captcha on the SkillRack website using Tesseract.js.

  1. // ==UserScript==
  2. // @name SkillRack Math Captcha Solver
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.6
  5. // @description Solves Math Captcha on the SkillRack website using Tesseract.js.
  6. // @author Bit-Blazer
  7. // @license GNU GPLv3
  8. // @match https://www.skillrack.com/faces/candidate/codeprogram.xhtml
  9. // @match https://www.skillrack.com/faces/candidate/tutorprogram.xhtml
  10. // @icon https://envs.sh/GiG.png
  11. // @require https://cdn.jsdelivr.net/npm/tesseract.js@5/dist/tesseract.min.js
  12. // @grant none
  13. // ==/UserScript==
  14.  
  15. (function () {
  16. "use strict";
  17.  
  18. // Define the IDs of the captcha input field, and proceed button
  19. const CAPTCHA_INPUT = "capval";
  20. const PROCEED_BTN = "proceedbtn";
  21.  
  22. console.log("[Captcha Solver] Script initialized.");
  23.  
  24. /**
  25. * Inverts the colors of the Captcha Image for better OCR results.
  26. * This is useful for enhancing the text recognition capability of Tesseract.js.
  27. * @param {HTMLImageElement} image - The image to be inverted.
  28. * @returns {string} - Base64 encoded data URL of the inverted image.
  29. */
  30. function invertColors(image) {
  31. try {
  32. const canvas = document.createElement("canvas");
  33. const ctx = canvas.getContext("2d");
  34. canvas.width = image.width;
  35. canvas.height = image.height;
  36. ctx.drawImage(image, 0, 0);
  37. ctx.globalCompositeOperation = "difference"; // Invert colors
  38. ctx.fillStyle = "white"; // Set background to white
  39. ctx.fillRect(0, 0, canvas.width, canvas.height); // Fill the canvas
  40. console.log("[Captcha Solver] Image colors inverted successfully.");
  41. return canvas.toDataURL(); // Return the inverted image as a data URL
  42. } catch (error) {
  43. console.error("[Captcha Solver] Error inverting colors:", error);
  44. throw new Error("Image processing failed.");
  45. }
  46. }
  47.  
  48. /**
  49. * Extracts the username from the span element.
  50. * This function looks for the username pattern in the badge label.
  51. * @returns {string} - The extracted username or an empty string if not found.
  52. */
  53. function getUsername() {
  54. const usernameElement = document.querySelector(".ui-chip-text"); // Select the username element
  55. const match = usernameElement.textContent.match(/(\d{12}@\w{3})/); // Match the username pattern
  56. const username = match ? match[0] : ""; // Return the matched username or empty string
  57. console.log("[Captcha Solver] Extracted username:", username);
  58. return username;
  59. }
  60.  
  61. /**
  62. * Solves the captcha by extracting numbers and performing the calculation.
  63. * @param {string} text - The OCR result from the captcha image.
  64. * @param {string} username - The username to be removed from the OCR text.
  65. * @returns {number|null} - The result of the addition or null if not found.
  66. */
  67. function solveCaptcha(text, username) {
  68. try {
  69. // Remove the username from the OCR text and trim whitespace
  70. const cleanedText = text.replace(new RegExp(username, "gi"), "").trim();
  71. // Match the addition pattern in the cleaned text
  72. const match = cleanedText.match(/(\d+)\s*\+\s*(\d+)/);
  73. // Return the sum of the two numbers if a match is found
  74.  
  75. if (!match) {
  76. console.warn(
  77. "[Captcha Solver] No valid captcha pattern found in OCR text:",
  78. text
  79. );
  80. return null;
  81. }
  82. const result = parseInt(match[1], 10) + parseInt(match[2], 10);
  83. console.log(
  84. "[Captcha Solver] Captcha solved:",
  85. `${match[1]} + ${match[2]} = ${result}`
  86. );
  87. return result;
  88. } catch (error) {
  89. console.error("[Captcha Solver] Error solving captcha:", error);
  90. return null;
  91. }
  92. }
  93.  
  94. /**
  95. * Handles the captcha-solving process.
  96. * This function orchestrates the overall captcha solving by coordinating image processing and user interactions.
  97. */
  98. async function handleCaptcha() {
  99. // Get the captcha elements from the DOM
  100. console.log("[Captcha Solver] Handling captcha...");
  101.  
  102. try {
  103. const captchaImage = document.querySelector("img[src*='data:image']");
  104. const captchaInput = document.getElementById(CAPTCHA_INPUT);
  105. const proceedBtn = document.getElementById(PROCEED_BTN);
  106.  
  107. // Log an error and exit if any elements are not found
  108. if (!captchaImage) throw new Error("Captcha image not found.");
  109. if (!captchaInput) throw new Error("Captcha input field not found.");
  110. if (!proceedBtn) throw new Error("Proceed button not found.");
  111.  
  112. // Get the username from the UI
  113. const username = getUsername();
  114. // Invert the colors of the captcha image for better OCR processing
  115. const invertedImg = invertColors(captchaImage);
  116.  
  117. // Process the inverted image using Tesseract.js for OCR
  118. const {
  119. data: { text },
  120. } = await Tesseract.recognize(invertedImg, "eng", {
  121. whitelist:
  122. "1234567890+=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@ ", // Allowed characters
  123. psm: 6, // Page segmentation mode
  124. });
  125.  
  126. console.log("[Captcha Solver] OCR text extracted:", text);
  127.  
  128. // Solve the Captcha using the OCR text and username
  129. const result = solveCaptcha(text, username);
  130. // Notify if the captcha could not be solved
  131. if (result === null) {
  132. console.warn("[Captcha Solver] Unable to solve captcha.");
  133. return;
  134. }
  135.  
  136. // Fill the captcha input with the calculated result
  137. captchaInput.value = result;
  138. // Click the submit button to proceed
  139.  
  140. console.log("[Captcha Solver] Filled captcha input with result:", result);
  141.  
  142. proceedBtn.click();
  143. console.log("[Captcha Solver] Proceed button clicked.");
  144. } catch (error) {
  145. // Log any errors encountered during the OCR process
  146.  
  147. console.error("[Captcha Solver] Error handling captcha:", error);
  148. }
  149. }
  150.  
  151. /**
  152. * Checks if the required elements are available and triggers captcha solving.
  153. */
  154. function monitorElements() {
  155. console.log("Finding Elements....");
  156. const interval = setInterval(() => {
  157. const captchaImage = document.querySelector("img[src*='data:image']");
  158. const captchaInput = document.getElementById(CAPTCHA_INPUT);
  159. const proceedBtn = document.getElementById(PROCEED_BTN);
  160.  
  161. if (captchaImage && captchaInput && proceedBtn) {
  162. console.log(
  163. "[Captcha Solver] Required elements found. Starting captcha solver."
  164. );
  165. clearInterval(interval);
  166. handleCaptcha();
  167. }
  168. }, 500); // Check every 500ms
  169. }
  170.  
  171. monitorElements(); // Start looking for elements here
  172. })();