From 976ae51dabe77686e405a2b99127485209c7c9cd Mon Sep 17 00:00:00 2001 From: Arpit Chakladar <54011232+arpitchakladar@users.noreply.github.com> Date: Fri, 13 Jun 2025 17:31:17 +0530 Subject: Adding a flake.nix. Cleaning up the captcha for the OCR. --- src/scripts/login.ts | 111 -------------------------------------------- src/scripts/login/index.ts | 112 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+), 111 deletions(-) delete mode 100644 src/scripts/login.ts create mode 100644 src/scripts/login/index.ts (limited to 'src/scripts') diff --git a/src/scripts/login.ts b/src/scripts/login.ts deleted file mode 100644 index 0fe5239..0000000 --- a/src/scripts/login.ts +++ /dev/null @@ -1,111 +0,0 @@ -import { interceptPost, interceptGet } from "@/shared/intercept-jquery-ajax"; - -interceptPost("viewLoginAreaAction", args => { - const callback = args[1]; - args[1] = (html: any) => { - callback(html); - const captchaInputElement = $("#txtCaptcha"); - const captchaValueElement = $("#txtInput"); - captchaInputElement.val("FFFFFF"); - captchaValueElement.val("FFFFFF"); - (window as any).DrawLoginCaptcha = () => {}; - (window as any).validateLoginCaptcha = () => true; - captchaValueElement.hide(); - captchaInputElement.hide(); - $(".captcharefresh").hide(); - } -}); -interceptPost("viewPasswordRecoveryArea", args => { - const callback = args[1]; - args[1] = (html: any) => { - callback(html); - const captchaInputElement = $("#dText"); - const captchaValueElement = $("#captaText"); - captchaInputElement.val("FFFFFF"); - captchaValueElement.val("FFFFFF"); - (window as any).Captcha = () => {}; - captchaValueElement.hide(); - captchaInputElement.hide(); - $("#captchaRef").hide(); - } -}); -interceptPost("login.action", args => { - const callback = args[2]; - args[2] = (data: any) => { - const loginData = args[1]; - if (!data.exception && data.checkmsg === "success") { - window.localStorage.setItem("loginData", btoa(JSON.stringify(loginData))); - } - - callback(data); - $("#txtInput").val("FFFFFF"); - $("#beforeLoginDiv").hide(); - $("#afterLoginDiv").css("display", "block"); - $("#afterLoginLabel").css("display", "block"); - const username = atob(loginData.username.split("RGxycyMxMjM=")[1]); - $("#afterLoginLabel > label").html(`--> ${username}`); - }; -}); -interceptPost("changePassword.action", args => { - const callback = args[2]; - args[2] = (data: any) => { - callback(data); - $("#txtInput").val("FFFFFF"); - }; -}); -interceptGet("viewRegistrationAreaAction", args => { - const callback = args[1]; - args[1] = (html: any) => { - callback(html); - const captchaInputElement = $("#regInputCaptcha"); - const captchaValueElement = $("#regCaptcha"); - captchaInputElement.val("FFFFFF"); - captchaValueElement.val("FFFFFF"); - $("#registrationForm > div > div:nth-child(5) > div:nth-child(3)").hide(); - $("#registrationForm > div > div:nth-child(5) > div:nth-child(4)").hide(); - $("#registrationForm > div > div:nth-child(5) > div:nth-child(5)").hide(); - (window as any).DrawRegistrationCaptcha = () => {}; - (window as any).validateRegistrationCaptcha = () => true; - } -}); -interceptGet("viewChangePasswordAction", args => { - const callback = args[1]; - args[1] = (html: any) => { - callback(html); - const captchaValueElement = $("#txtCaptcha"); - const captchaInputElement = $("#txtInput"); - captchaValueElement.val("FFFFFF"); - captchaInputElement.val("FFFFFF"); - (window as any).DrawLoginCaptcha = () => {}; - captchaValueElement.hide(); - captchaInputElement.hide(); - $(".captcharefresh").hide(); - } -}); - -document.addEventListener("DOMContentLoaded", () => { - $("#afterLoginDiv > a").click(() => { - window.localStorage.removeItem("loginData"); - }); - - const login = () => { - let loginData = window.localStorage.getItem("loginData"); - loginData = loginData ? JSON.parse(atob(loginData)) : null; - - if (loginData) { - $.post( - "/BanglarBhumi/login.action", - loginData, - data => { - if (data.exception || data.checkmsg !== "success") { - loginData = null; - } - }, - "json" - ); - } - }; - - login(); - setInterval(login, 1000 * 60); -}); diff --git a/src/scripts/login/index.ts b/src/scripts/login/index.ts new file mode 100644 index 0000000..b7503b9 --- /dev/null +++ b/src/scripts/login/index.ts @@ -0,0 +1,112 @@ +import { interceptPost, interceptGet } from "@/shared/intercept-jquery-ajax"; + +function prepareCaptcha(ctx: CanvasRenderingContext2D, width: number, height: number) { + const imgData = ctx.getImageData(0, 0, width, height); + const data = imgData.data; + const radius = 1; + + function isBlack(r: number, g: number, b: number) { + return r < 50 && g < 50 && b < 50; + } + + function isGrayish(r: number, g: number, b: number) { + return Math.abs(r - g) < 15 && Math.abs(g - b) < 15 && r > 100 && r < 200; + } + + function hasNearbyBlack(x: number, y: number) { + for (let dx = -radius; dx <= radius; dx++) { + for (let dy = -radius; dy <= radius; dy++) { + const nx = x + dx; + const ny = y + dy; + if (nx >= 0 && nx < width && ny >= 0 && ny < height) { + const i = (ny * width + nx) * 4; + if (isBlack(data[i], data[i + 1], data[i + 2])) return true; + } + } + } + return false; + } + + for (let y = 0; y < height; y++) { + for (let x = 0; x < width; x++) { + const i = (y * width + x) * 4; + const [r, g, b] = [data[i], data[i + 1], data[i + 2]]; + if (isGrayish(r, g, b) && !hasNearbyBlack(x, y)) { + data[i] = data[i + 1] = data[i + 2] = 255; + } + } + } + for (let y = 0; y < height; y++) { + for (let x = 0; x < width; x++) { + const i = (y * width + x) * 4; + const [r, g, b] = [data[i], data[i + 1], data[i + 2]]; + + if (isGrayish(r, g, b)) { + data[i] = data[i + 1] = data[i + 2] = 0; // make black + } + } + } + ctx.putImageData(imgData, 0, 0); +} + +const observer = new MutationObserver((mutationsList, obs) => { + for (const mutation of mutationsList) { + for (const node of mutation.addedNodes) { + if ((node as any).nodeType === 1 && (node as any).id === "loginform") { + const img = (node as HTMLFormElement).querySelector("#captchaImg") as HTMLImageElement; + const captchaInput = (node as HTMLFormElement).querySelector("txtInput") as HTMLInputElement; + + // Wait for image to load to get correct dimensions + img.addEventListener("load", async () => { + const { width, height } = img; + + // 1. Create canvas + const canvas = document.createElement("canvas"); + canvas.width = width; + canvas.height = height; + canvas.style.display = "block"; + + // 2. Copy styles (optional) + canvas.style.cssText = getComputedStyle(img).cssText; + canvas.style.display = "none"; + + // 3. Insert canvas before image + img.parentNode!.querySelectorAll("canvas").forEach(c => c.remove()); + img.parentNode!.insertBefore(canvas, img); + + // 4. Hide image + img.style.display = "none"; + + // 5. Draw the image onto the canvas + const ctx = canvas.getContext("2d")!; + ctx.drawImage(img, 0, 0); + prepareCaptcha(ctx, canvas.width, canvas.height); + canvas.style.display = ""; + const dataURL = canvas.toDataURL("image/png"); + // TODO: Perform OCR + // window.postMessage({ + // type: "RUN_OCR", + // dataURL: dataURL + // }, "*"); + // + // // Listen for OCR result + // function recieveOCRResult(event: any) { + // if (event.data.type === "OCR_RESULT") { + // console.log("Tesseract result:", event.data.text, "Confidence:", event.data.confidence); + // window.removeEventListener("message", recieveOCRResult); + // if (event.data.confidence < 80 || event.data.text.length !== 6) { + // img.src = "generateCaptcha?" + new Date().getTime(); + // } else { + // captchaInput.value = event.data.text; + // } + // } + // } + // window.addEventListener("message", recieveOCRResult); + }); + } + } + } +}); + +// Start observing the body +observer.observe(document.body, { childList: true, subtree: true }); -- cgit v1.2.3 From bce4cff7f7144bc91d780e2dd2f8e1114109f407 Mon Sep 17 00:00:00 2001 From: Arpit Chakladar <54011232+arpitchakladar@users.noreply.github.com> Date: Fri, 13 Jun 2025 18:30:50 +0530 Subject: Added background scripts. --- config/webpack.config.js | 44 +++++--- .../create-manifest-webpack-plugin/index.js | 2 + package-lock.json | 117 +++++++++++++++++++++ package.json | 3 + src/background/run-ocr.ts | 1 + src/background/second-script.ts | 1 + src/scripts/login/index.ts | 7 ++ 7 files changed, 162 insertions(+), 13 deletions(-) create mode 100644 src/background/run-ocr.ts create mode 100644 src/background/second-script.ts (limited to 'src/scripts') diff --git a/config/webpack.config.js b/config/webpack.config.js index 70b87ca..1d3b4c0 100644 --- a/config/webpack.config.js +++ b/config/webpack.config.js @@ -35,12 +35,21 @@ for (const sharedModule of sharedModules) { injectedSharedModulesImportedCount[sharedModule] = 0; } +const backgroundScriptEntries = {}; const uninjectedScriptEntries = {}; const injectedAfterScriptEntries = {}; const injectedBeforeScriptEntries = {}; const sharedModuleEntries = {}; const sharedModuleExternals = {}; +const backgroundScriptImports = fs.readdirSync(path.resolve(SOURCE_DIR, "background")) + .map(scriptName => `import "${path.resolve(SOURCE_DIR, "background", scriptName)}";`) + .join("\n"); +backgroundScriptEntries["background script"] = { + import: inlineJavascript(backgroundScriptImports), + filename: "background.js" +}; + for (const scriptPath in scripts) { for (const scriptType in scripts[scriptPath]) { const currentScripts = scripts[scriptPath][scriptType]; @@ -84,8 +93,8 @@ const commonOptions = { resolve: { extensions: [".ts", ".js", ".html"], alias: { - "@": global.SOURCE_DIR - } + "@": global.SOURCE_DIR, + }, }, module: { rules: [ @@ -93,27 +102,27 @@ const commonOptions = { test: /\.ts$/, loader: "ts-loader", options: { - configFile: "config/tsconfig.json" + configFile: "config/tsconfig.json", } }, { test: /\.html$/, - loader: path.resolve(CONFIG_DIR, "webpack/loader/to-string-loader.js") - } - ] + loader: path.resolve(CONFIG_DIR, "webpack/loader/to-string-loader.js"), + }, + ], }, optimization: { minimize: process.env.NODE_ENV === "production", - runtimeChunk: false + runtimeChunk: false, }, output: { - iife: true + iife: true, }, plugins: [ new webpack.optimize.LimitChunkCountPlugin({ - maxChunks: 1 - }) - ] + maxChunks: 1, + }), + ], }; const sharedModuleOptions = { @@ -125,14 +134,22 @@ const sharedModuleOptions = { test: /banglar-bhumi-utils\/src\/.*.(^.?|\.[^d]|[^.]d|[^.][^d])\.(t|j)s$/, loader: path.resolve(CONFIG_DIR, "webpack/loader/count-imports-loader.js"), options: { - sharedModulesImportedCount + sharedModulesImportedCount, }, - enforce: "post" + enforce: "post", } ] } }; +const backgroundScriptConfiguration = merge( + commonOptions, + sharedModuleOptions, + { + entry: backgroundScriptEntries, + }, +); + const uninjectedScriptConfiguration = merge( commonOptions, sharedModuleOptions, @@ -206,6 +223,7 @@ const sharedModulesConfiguration = merge( ); module.exports = [ + backgroundScriptConfiguration, uninjectedScriptConfiguration, injectedScriptConfiguration, sharedModulesConfiguration diff --git a/config/webpack/plugins/create-manifest-webpack-plugin/index.js b/config/webpack/plugins/create-manifest-webpack-plugin/index.js index 8dc0ae4..330c22f 100644 --- a/config/webpack/plugins/create-manifest-webpack-plugin/index.js +++ b/config/webpack/plugins/create-manifest-webpack-plugin/index.js @@ -97,6 +97,8 @@ class CreateManifestPlugin { ]; } + manifest.background = { service_worker: "background.js" }; + compilation.emitAsset( "manifest.json", new sources.RawSource( diff --git a/package-lock.json b/package-lock.json index 1c51f5d..26574cd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,9 @@ "name": "banglar-bhumi-utils", "version": "1.1.0", "license": "MIT", + "dependencies": { + "tesseract.js": "^6.0.1" + }, "devDependencies": { "@types/chrome": "^0.0.213", "@types/jquery": "^3.5.16", @@ -517,6 +520,12 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/bmp-js": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/bmp-js/-/bmp-js-0.1.0.tgz", + "integrity": "sha512-vHdS19CnY3hwiNdkaqk93DvjVLfbEcI8mys4UjuWrlX1haDmroo8o4xCzh4wD6DGV6HxRCyauwhHRqMTfERtjw==", + "license": "MIT" + }, "node_modules/braces": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", @@ -949,6 +958,12 @@ "node": ">=8" } }, + "node_modules/idb-keyval": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.2.tgz", + "integrity": "sha512-yjD9nARJ/jb1g+CvD0tlhUHOrJ9Sy0P8T9MF3YaLlHnSRpwPfpTX0XIvpmw3gAJUmEu3FiICLBDPXVwyEvrleg==", + "license": "Apache-2.0" + }, "node_modules/ignore": { "version": "5.2.4", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", @@ -1052,6 +1067,12 @@ "node": ">=0.10.0" } }, + "node_modules/is-url": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", + "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", + "license": "MIT" + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -1217,6 +1238,26 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, "node_modules/node-releases": { "version": "2.0.9", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.9.tgz", @@ -1232,6 +1273,15 @@ "node": ">=0.10.0" } }, + "node_modules/opencollective-postinstall": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", + "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==", + "license": "MIT", + "bin": { + "opencollective-postinstall": "index.js" + } + }, "node_modules/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", @@ -1399,6 +1449,12 @@ "node": ">= 10.13.0" } }, + "node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", + "license": "MIT" + }, "node_modules/require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", @@ -1740,6 +1796,30 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/tesseract.js": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/tesseract.js/-/tesseract.js-6.0.1.tgz", + "integrity": "sha512-/sPvMvrCtgxnNRCjbTYbr7BRu0yfWDsMZQ2a/T5aN/L1t8wUQN6tTWv6p6FwzpoEBA0jrN2UD2SX4QQFRdoDbA==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "bmp-js": "^0.1.0", + "idb-keyval": "^6.2.0", + "is-url": "^1.2.4", + "node-fetch": "^2.6.9", + "opencollective-postinstall": "^2.0.3", + "regenerator-runtime": "^0.13.3", + "tesseract.js-core": "^6.0.0", + "wasm-feature-detect": "^1.2.11", + "zlibjs": "^0.3.1" + } + }, + "node_modules/tesseract.js-core": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/tesseract.js-core/-/tesseract.js-core-6.0.0.tgz", + "integrity": "sha512-1Qncm/9oKM7xgrQXZXNB+NRh19qiXGhxlrR8EwFbK5SaUbPZnS5OMtP/ghtqfd23hsr1ZvZbZjeuAGcMxd/ooA==", + "license": "Apache-2.0" + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -1752,6 +1832,12 @@ "node": ">=8.0" } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, "node_modules/ts-loader": { "version": "9.4.2", "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.4.2.tgz", @@ -1825,6 +1911,12 @@ "punycode": "^2.1.0" } }, + "node_modules/wasm-feature-detect": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/wasm-feature-detect/-/wasm-feature-detect-1.8.0.tgz", + "integrity": "sha512-zksaLKM2fVlnB5jQQDqKXXwYHLQUVH9es+5TOOHwGOVJOCeRBCiPjwSg+3tN2AdTCzjgli4jijCH290kXb/zWQ==", + "license": "Apache-2.0" + }, "node_modules/watchpack": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", @@ -1838,6 +1930,12 @@ "node": ">=10.13.0" } }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, "node_modules/webpack": { "version": "5.75.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.75.0.tgz", @@ -2010,6 +2108,16 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -2036,6 +2144,15 @@ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true + }, + "node_modules/zlibjs": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/zlibjs/-/zlibjs-0.3.1.tgz", + "integrity": "sha512-+J9RrgTKOmlxFSDHo0pI1xM6BLVUv+o0ZT9ANtCxGkjIVCCUdx9alUF8Gm+dGLKbkkkidWIHFDZHDMpfITt4+w==", + "license": "MIT", + "engines": { + "node": "*" + } } } } diff --git a/package.json b/package.json index fab95c5..c45b910 100644 --- a/package.json +++ b/package.json @@ -22,5 +22,8 @@ "webpack": "^5.75.0", "webpack-cli": "^5.0.1", "webpack-merge": "^5.8.0" + }, + "dependencies": { + "tesseract.js": "^6.0.1" } } diff --git a/src/background/run-ocr.ts b/src/background/run-ocr.ts new file mode 100644 index 0000000..d0af073 --- /dev/null +++ b/src/background/run-ocr.ts @@ -0,0 +1 @@ +console.log("THIS IS A BACKGROUND script."); diff --git a/src/background/second-script.ts b/src/background/second-script.ts new file mode 100644 index 0000000..9e3a621 --- /dev/null +++ b/src/background/second-script.ts @@ -0,0 +1 @@ +console.log("THiS IS THE SECOND SCRIPT"); diff --git a/src/scripts/login/index.ts b/src/scripts/login/index.ts index b7503b9..adbcdbc 100644 --- a/src/scripts/login/index.ts +++ b/src/scripts/login/index.ts @@ -1,3 +1,4 @@ +import Tesseract from "tesseract.js"; import { interceptPost, interceptGet } from "@/shared/intercept-jquery-ajax"; function prepareCaptcha(ctx: CanvasRenderingContext2D, width: number, height: number) { @@ -83,6 +84,12 @@ const observer = new MutationObserver((mutationsList, obs) => { prepareCaptcha(ctx, canvas.width, canvas.height); canvas.style.display = ""; const dataURL = canvas.toDataURL("image/png"); + Tesseract.recognize(canvas, 'eng', { + logger: console.log + }).then(({ data: { text, confidence } }) => { + console.log("OCR Result:", text); + console.log("OCR confidence:", confidence); + }); // TODO: Perform OCR // window.postMessage({ // type: "RUN_OCR", -- cgit v1.2.3 From 00e5ea80b1b0ba37ac4b5dc7b10ae6eac26aa1af Mon Sep 17 00:00:00 2001 From: Arpit Chakladar <54011232+arpitchakladar@users.noreply.github.com> Date: Fri, 13 Jun 2025 18:36:30 +0530 Subject: Successfully communicating between background script and content scripts. --- src/background/run-ocr.ts | 8 +++++++- src/background/second-script.ts | 1 - src/scripts.json | 4 +++- src/scripts/login/index.ts | 7 +------ 4 files changed, 11 insertions(+), 9 deletions(-) delete mode 100644 src/background/second-script.ts (limited to 'src/scripts') diff --git a/src/background/run-ocr.ts b/src/background/run-ocr.ts index d0af073..d61e71a 100644 --- a/src/background/run-ocr.ts +++ b/src/background/run-ocr.ts @@ -1 +1,7 @@ -console.log("THIS IS A BACKGROUND script."); +chrome.runtime.onMessage.addListener(async (message, sender, sendResponse) => { + if (message.type === "ping") { + console.log("Received ping from content script"); + console.log(message.data); + sendResponse({ text: "pong" }); + } +}); diff --git a/src/background/second-script.ts b/src/background/second-script.ts deleted file mode 100644 index 9e3a621..0000000 --- a/src/background/second-script.ts +++ /dev/null @@ -1 +0,0 @@ -console.log("THiS IS THE SECOND SCRIPT"); diff --git a/src/scripts.json b/src/scripts.json index 74a465d..715ad4d 100644 --- a/src/scripts.json +++ b/src/scripts.json @@ -1,7 +1,6 @@ { "injected": { "stop-blocking.ts": "*", - "login/index.ts": "*", "otps/grievance-application.ts": "GrievAppViewAction.action", "otps/mutation-application.ts": "MuteApplication.action", "otps/warish-application.ts": "WarishAppViewAction.action", @@ -10,5 +9,8 @@ "captcha/know-your-property.ts": "KnowYourProperty.action", "captcha/application-receipt.ts": "Apprecrep.action", "functionality/sheet-map/index.ts": "SheetMapViewAction.action" + }, + "after": { + "login/index.ts": "*" } } diff --git a/src/scripts/login/index.ts b/src/scripts/login/index.ts index adbcdbc..dacc90a 100644 --- a/src/scripts/login/index.ts +++ b/src/scripts/login/index.ts @@ -84,12 +84,7 @@ const observer = new MutationObserver((mutationsList, obs) => { prepareCaptcha(ctx, canvas.width, canvas.height); canvas.style.display = ""; const dataURL = canvas.toDataURL("image/png"); - Tesseract.recognize(canvas, 'eng', { - logger: console.log - }).then(({ data: { text, confidence } }) => { - console.log("OCR Result:", text); - console.log("OCR confidence:", confidence); - }); + chrome.runtime.sendMessage({ type: "ping", data: "hello background" }).then(console.log); // TODO: Perform OCR // window.postMessage({ // type: "RUN_OCR", -- cgit v1.2.3 From 64e38ab240a1ca3427592eb80f2cef57fddbdafe Mon Sep 17 00:00:00 2001 From: Arpit Chakladar <54011232+arpitchakladar@users.noreply.github.com> Date: Fri, 13 Jun 2025 18:55:27 +0530 Subject: Sending OCR request along with captcha image data to the background script. --- src/background/run-ocr.ts | 18 +++++++++++++----- src/scripts/login/index.ts | 3 +-- 2 files changed, 14 insertions(+), 7 deletions(-) (limited to 'src/scripts') diff --git a/src/background/run-ocr.ts b/src/background/run-ocr.ts index d61e71a..f6d1339 100644 --- a/src/background/run-ocr.ts +++ b/src/background/run-ocr.ts @@ -1,7 +1,15 @@ -chrome.runtime.onMessage.addListener(async (message, sender, sendResponse) => { - if (message.type === "ping") { - console.log("Received ping from content script"); - console.log(message.data); - sendResponse({ text: "pong" }); +import Tesseract from "tesseract.js"; + +chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { + if (message.type === "OCR") { + (async () => { + const { data: { text, confidence } } = await Tesseract.recognize(message.dataURL, "eng+osd", { + logger: m => console.log(m), + }); + sendResponse({ text, confidence }); + })(); + return true; } + + return false; }); diff --git a/src/scripts/login/index.ts b/src/scripts/login/index.ts index dacc90a..b7e0a73 100644 --- a/src/scripts/login/index.ts +++ b/src/scripts/login/index.ts @@ -1,4 +1,3 @@ -import Tesseract from "tesseract.js"; import { interceptPost, interceptGet } from "@/shared/intercept-jquery-ajax"; function prepareCaptcha(ctx: CanvasRenderingContext2D, width: number, height: number) { @@ -84,7 +83,7 @@ const observer = new MutationObserver((mutationsList, obs) => { prepareCaptcha(ctx, canvas.width, canvas.height); canvas.style.display = ""; const dataURL = canvas.toDataURL("image/png"); - chrome.runtime.sendMessage({ type: "ping", data: "hello background" }).then(console.log); + chrome.runtime.sendMessage({ type: "OCR", dataURL }, console.log); // TODO: Perform OCR // window.postMessage({ // type: "RUN_OCR", -- cgit v1.2.3 From 54467df36805eabf9113d1bb84d7434b331cd167 Mon Sep 17 00:00:00 2001 From: Arpit Chakladar <54011232+arpitchakladar@users.noreply.github.com> Date: Sat, 14 Jun 2025 01:40:18 +0530 Subject: Successfully performing OCR on the captcha image and autofilling it for login. --- config/webpack.config.js | 14 +- .../create-manifest-webpack-plugin/index.js | 1 + .../manifest-template.json | 5 +- package.json | 3 - src/background/run-ocr.ts | 65 +++-- src/offscreen.json | 3 - src/offscreen/ocr.ts | 1 - src/offscreen/ocr/index.html | 10 + src/offscreen/ocr/index.js | 43 ++++ src/offscreen/ocr/tesseract-core-lstm.wasm.js | 283 +++++++++++++++++++++ src/offscreen/ocr/tesseract-core-simd-lstm.wasm.js | 283 +++++++++++++++++++++ src/offscreen/ocr/tesseract-core.wasm.js | 282 ++++++++++++++++++++ src/offscreen/ocr/tesseract.esm.min.js | 19 ++ src/offscreen/ocr/worker.min.js | 3 + src/scripts/login/index.ts | 37 ++- static/icon512.png | Bin 16 files changed, 986 insertions(+), 66 deletions(-) delete mode 100644 src/offscreen.json delete mode 100644 src/offscreen/ocr.ts create mode 100644 src/offscreen/ocr/index.html create mode 100644 src/offscreen/ocr/index.js create mode 100644 src/offscreen/ocr/tesseract-core-lstm.wasm.js create mode 100644 src/offscreen/ocr/tesseract-core-simd-lstm.wasm.js create mode 100644 src/offscreen/ocr/tesseract-core.wasm.js create mode 100644 src/offscreen/ocr/tesseract.esm.min.js create mode 100644 src/offscreen/ocr/worker.min.js mode change 100644 => 100755 static/icon512.png (limited to 'src/scripts') diff --git a/config/webpack.config.js b/config/webpack.config.js index 4b21245..8fd3f15 100644 --- a/config/webpack.config.js +++ b/config/webpack.config.js @@ -193,10 +193,16 @@ const sharedModulesConfiguration = merge( entry: sharedModuleEntries, plugins: [ new CopyPlugin({ - patterns: [{ - from: path.resolve(ROOT_DIR, "static"), - to: "./" - }] + patterns: [ + { + from: path.resolve("static"), + to: "./", + }, + { + from: path.resolve("src/offscreen"), + to: "./offscreen", + }, + ], }), new CreateInjectedSharedModulesPlugin({ injectedSharedModulesImportedCount, diff --git a/config/webpack/plugins/create-manifest-webpack-plugin/index.js b/config/webpack/plugins/create-manifest-webpack-plugin/index.js index 2c9ab8e..6f1e2be 100644 --- a/config/webpack/plugins/create-manifest-webpack-plugin/index.js +++ b/config/webpack/plugins/create-manifest-webpack-plugin/index.js @@ -123,3 +123,4 @@ class CreateManifestPlugin { } export default CreateManifestPlugin; + diff --git a/config/webpack/plugins/create-manifest-webpack-plugin/manifest-template.json b/config/webpack/plugins/create-manifest-webpack-plugin/manifest-template.json index d1d29f4..52496b6 100644 --- a/config/webpack/plugins/create-manifest-webpack-plugin/manifest-template.json +++ b/config/webpack/plugins/create-manifest-webpack-plugin/manifest-template.json @@ -1,7 +1,7 @@ { "manifest_version": 3, "name": "Banglar Bhumi Utils", - "permissions": ["scripting", "declarativeNetRequest"], + "permissions": ["offscreen", "scripting", "declarativeNetRequest"], "description": "A chrome extension to improve functionality of the banglarbhumi.gov.in website.", "icons": { "512": "icon512.png" @@ -12,5 +12,8 @@ "enabled": true, "path": "rules.json" }] + }, + "content_security_policy": { + "extension_pages": "script-src 'self' 'wasm-unsafe-eval'; object-src 'self';" } } diff --git a/package.json b/package.json index 60cb50e..fd60090 100644 --- a/package.json +++ b/package.json @@ -24,8 +24,5 @@ "webpack": "^5.75.0", "webpack-cli": "^5.0.1", "webpack-merge": "^5.8.0" - }, - "dependencies": { - "tesseract.js": "^6.0.1" } } diff --git a/src/background/run-ocr.ts b/src/background/run-ocr.ts index 1bf605b..4476f54 100644 --- a/src/background/run-ocr.ts +++ b/src/background/run-ocr.ts @@ -1,42 +1,41 @@ -import Tesseract from "tesseract.js"; -// -// chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { -// if (message.type === "OCR") { -// (async () => { -// const { data: { text, confidence } } = await Tesseract.recognize(message.dataURL, "eng+osd", { -// logger: m => console.log(m), -// }); -// sendResponse({ text, confidence }); -// })(); -// return true; -// } -// -// return false; -// }); +const OFFSCREEN_DOCUMENT_PATH = "offscreen/ocr/index.html"; +// Function to ensure the offscreen document is open +async function setupOffscreenDocument() { + if (await chrome.offscreen.hasDocument()) { + return; // Offscreen document already open + } + await chrome.offscreen.createDocument({ + url: OFFSCREEN_DOCUMENT_PATH, + reasons: [chrome.offscreen.Reason.CLIPBOARD], + justification: "Performing OCR with Tesseract.js in a long-running context." + }); +} + +// Listen for messages from content scripts (and popup if applicable) chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { - if (message.type === "OCR") { + if (message.type === "OCR" && message.dataURL) { (async () => { - console.log(message); - const worker = await Tesseract.createWorker("eng", 1, { - workerBlobURL: false, - logger: console.log, - }); - - await worker.setParameters({ - tessedit_char_whitelist: "ABCDEFGHJKLMNPQRSTUVWXYZ23456789", - }); + try { + // Ensure the offscreen document is open + await setupOffscreenDocument(); - const { - data: { text, confidence } - } = await worker.recognize(message.dataURL); + // Send the OCR request to the offscreen document + const offscreenResponse = await chrome.runtime.sendMessage({ + type: "OFFSCREEN_OCR_REQUEST", + dataURL: message.dataURL + }); - await worker.terminate(); - - sendResponse({ type: "OCR_RESULT", text, confidence }); + if (offscreenResponse && offscreenResponse.success) { + sendResponse({ success: true, text: offscreenResponse.text }); + } else { + sendResponse({ success: false, error: offscreenResponse?.error || "Unknown OCR error" }); + } + } catch (error) { + sendResponse({ success: false, error: (error as Error).message }); + } })(); - - return true; + return true; // Indicate async response } return false; diff --git a/src/offscreen.json b/src/offscreen.json deleted file mode 100644 index 3159170..0000000 --- a/src/offscreen.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - "ocr.ts" -] diff --git a/src/offscreen/ocr.ts b/src/offscreen/ocr.ts deleted file mode 100644 index c645b9f..0000000 --- a/src/offscreen/ocr.ts +++ /dev/null @@ -1 +0,0 @@ -console.log("THIS IS OFFSCREEN DOCUMENT!"); diff --git a/src/offscreen/ocr/index.html b/src/offscreen/ocr/index.html new file mode 100644 index 0000000..ffb3c87 --- /dev/null +++ b/src/offscreen/ocr/index.html @@ -0,0 +1,10 @@ + + +
+ +=e:return[265,e-11,1];case 14>=e:return[266,e-13,1];case 16>=e:return[267,e-15,1];case 18>=e:return[268,e-17,1];case 22>=e:return[269,e-19,2];case 26>=e:return[270,e-23,2];case 30>=e:return[271,e-27,2];case 34>=e:return[272,e-31,2];case 42>=e:return[273,e-35,3];case 50>=e:return[274,e-43,3];case 58>=e:return[275,e-51,3];case 66>=e:return[276,e-59,3];case 82>=e:return[277,e-67,4];case 98>=e:return[278,e-83,4];case 114>=e:return[279,e-99,4];case 130>=e:return[280,e-115,4];case 162>=e:return[281,e-131,5];case 194>=e:return[282,e-163,5];case 226>=e:return[283,e-195,5];case 257>=e:return[284,e-227,5];case 258===e:return[285,e-258,0];default:t("invalid length: "+e)}}var r,n,o=[];for(r=3;258>=r;r++)n=e(r),o[r]=n[2]<<24|n[1]<<16|n[0];return o}(),S=o?new Uint32Array(O):O;function I(e,n){function a(e,r){var n,o,a,s,u=e.N,f=[],c=0;switch(n=S[e.length],f[c++]=65535&n,f[c++]=n>>16&255,f[c++]=n>>24,i){case 1===u:o=[0,u-1,0];break;case 2===u:o=[1,u-2,0];break;case 3===u:o=[2,u-3,0];break;case 4===u:o=[3,u-4,0];break;case 6>=u:o=[4,u-5,1];break;case 8>=u:o=[5,u-7,1];break;case 12>=u:o=[6,u-9,2];break;case 16>=u:o=[7,u-13,2];break;case 24>=u:o=[8,u-17,3];break;case 32>=u:o=[9,u-25,3];break;case 48>=u:o=[10,u-33,4];break;case 64>=u:o=[11,u-49,4];break;case 96>=u:o=[12,u-65,5];break;case 128>=u:o=[13,u-97,5];break;case 192>=u:o=[14,u-129,6];break;case 256>=u:o=[15,u-193,6];break;case 384>=u:o=[16,u-257,7];break;case 512>=u:o=[17,u-385,7];break;case 768>=u:o=[18,u-513,8];break;case 1024>=u:o=[19,u-769,8];break;case 1536>=u:o=[20,u-1025,9];break;case 2048>=u:o=[21,u-1537,9];break;case 3072>=u:o=[22,u-2049,10];break;case 4096>=u:o=[23,u-3073,10];break;case 6144>=u:o=[24,u-4097,11];break;case 8192>=u:o=[25,u-6145,11];break;case 12288>=u:o=[26,u-8193,12];break;case 16384>=u:o=[27,u-12289,12];break;case 24576>=u:o=[28,u-16385,13];break;case 32768>=u:o=[29,u-24577,13];break;default:t("invalid distance")}for(n=o,f[c++]=n[0],f[c++]=n[1],f[c++]=n[2],a=0,s=f.length;a=f;)m[f++]=0;for(f=0;29>=f;)E[f++]=0}for(m[256]=1,s=0,u=n.length;s=u){for(y&&a(y,-1),f=0,c=u-s;f>>=1;return a}function j(t,e){this.input=t,this.b=this.c=0,this.g={},e&&(e.flags&&(this.g=e.flags),"string"==typeof e.filename&&(this.filename=e.filename),"string"==typeof e.comment&&(this.w=e.comment),e.deflateOptions&&(this.l=e.deflateOptions)),this.l||(this.l={})}j.prototype.h=function(){var t,e,n,i,a,s,u,f,c=new(o?Uint8Array:Array)(32768),h=0,l=this.input,y=this.c,d=this.filename,g=this.w;if(c[h++]=31,c[h++]=139,c[h++]=8,t=0,this.g.fname&&(t|=T),this.g.fcomment&&(t|=R),this.g.fhcrc&&(t|=P),c[h++]=t,e=(Date.now?Date.now():+new Date)/1e3|0,c[h++]=255&e,c[h++]=e>>>8&255,c[h++]=e>>>16&255,c[h++]=e>>>24&255,c[h++]=0,c[h++]=B,this.g.fname!==r){for(u=0,f=d.length;u>>0}function st(e,r){var n,i;this.input=e,this.c=0,!r&&(r={})||(r.index&&(this.c=r.index),r.verify&&(this.V=r.verify)),n=e[this.c++],i=e[this.c++],(15&n)===ut?this.method=ut:t(Error("unsupported compression method")),0!=((n<<8)+i)%31&&t(Error("invalid fcheck flag:"+((n<<8)+i)%31)),32&i&&t(Error("fdict flag is not supported")),this.J=new N(e,{index:this.c,bufferSize:r.bufferSize,bufferType:r.bufferType,resize:r.resize})}N.prototype.r=function(t,e){var r=this.a,n=this.b;this.A=t;for(var i,o,a,s,u=r.length-258;256!==(i=it(this,t));)if(256>i)n>=u&&(this.b=n,r=this.f(),n=this.b),r[n++]=i;else for(s=Y[o=i-257],0=u&&(this.b=n,r=this.f(),n=this.b);s--;)r[n]=r[n++-a];for(;8<=this.e;)this.e-=8,this.c--;this.b=n},N.prototype.Q=function(t,e){var r=this.a,n=this.b;this.A=t;for(var i,o,a,s,u=r.length;256!==(i=it(this,t));)if(256>i)n>=u&&(u=(r=this.f()).length),r[n++]=i;else for(s=Y[o=i-257],0
u&&(u=(r=this.f()).length);s--;)r[n]=r[n++-a];for(;8<=this.e;)this.e-=8,this.c--;this.b=n},N.prototype.f=function(){var t,e,r=new(o?Uint8Array:Array)(this.b-32768),n=this.b-32768,i=this.a;if(o)r.set(i.subarray(32768,r.length));else for(t=0,e=r.length;t