From 3e046242b3ae73334e30e2c6d9c9690f68cc02f3 Mon Sep 17 00:00:00 2001 From: overflowerror Date: Fri, 16 Aug 2024 23:51:23 +0200 Subject: [PATCH] add silent mode --- src/default-styles.css | 4 ++++ src/main.ts | 45 ++++++++++++++++++++++++++++-------------- 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/src/default-styles.css b/src/default-styles.css index 6cf1dea..ea7dd94 100644 --- a/src/default-styles.css +++ b/src/default-styles.css @@ -8,6 +8,10 @@ font-family: sans-serif; } +.captcha.silent { + display: none; +} + .captcha span { position: relative; top: -9px; diff --git a/src/main.ts b/src/main.ts index a03adbc..c99c9c3 100644 --- a/src/main.ts +++ b/src/main.ts @@ -6,6 +6,7 @@ import {Challenge, validateChallenge} from "./challenge"; const CLASS_CHECKBOX = "checkbox"; const CLASS_LOADING = "loading"; const CLASS_CHECKED = "checked"; +const CLASS_SILENT = "silent"; const findHashWithPrefix = async (algo: string, hashPrefixBits: number, inputPrefix: string): Promise => { const hashPrefix = new Uint8Array(Array(Math.ceil(hashPrefixBits / 8)).map(_ => 0)); @@ -37,14 +38,25 @@ const toggleChecked = (checkbox: Element) => const toggleLoading = (checkbox: Element) => checkbox.classList.toggle(CLASS_LOADING); -function prepareChallengeExecution(challenge: Challenge, callback: (response: string) => void): () => Promise { - return async function() { - toggleLoading(this); +const executeChallenge = async (challenge: Challenge, challengeCompletedCallback: (response: string) => void): Promise => { + challengeCompletedCallback(await findHashWithPrefix(challenge.algo, challenge.prefixBits, challenge.input)); +} - callback(await findHashWithPrefix(challenge.algo, challenge.prefixBits, challenge.input)); +const prepareSilentCaptcha = (_: Element, challengeCompletedCallback: (response: string) => void): (challenge: Challenge) => Promise => { + return async (challenge: Challenge) => await executeChallenge(challenge, challengeCompletedCallback); +} - toggleLoading(this); - toggleChecked(this); +const prepareInputCaptcha = (captcha: Element, challengeCompletedCallback: (response: string) => void): (challenge: Challenge) => Promise => { + const checkbox = initCaptchaContentAndGetCheckbox(captcha); + + return async (challenge: Challenge) => { + checkbox.addEventListener("click", async function() { + toggleLoading(this); + await executeChallenge(challenge, challengeCompletedCallback); + toggleLoading(this); + toggleChecked(this); + }); + toggleLoading(checkbox); } } @@ -54,10 +66,18 @@ const prepareCaptcha = async (captcha: Element) => { throw "No challenge URL found."; } - let successCallback = captcha.getAttribute("data-success-callback"); - let inputSelector = captcha.getAttribute("data-input-selector"); + const challengeCompletesCallback = (response: string) => { + const successCallback = captcha.getAttribute("data-success-callback"); + const inputSelector = captcha.getAttribute("data-input-selector"); - const checkbox = initCaptchaContentAndGetCheckbox(captcha); + if (successCallback) eval(successCallback)(response); + if (inputSelector) [...document.querySelectorAll(inputSelector)].forEach((input: HTMLInputElement) => input.value = response) + }; + + const initDoneCallback = (captcha.classList.contains(CLASS_SILENT) + ? prepareSilentCaptcha + : prepareInputCaptcha) + (captcha, challengeCompletesCallback); const challengeResponse = await fetch(challengeUrl); const challenge = await challengeResponse.json() as Challenge; @@ -66,12 +86,7 @@ const prepareCaptcha = async (captcha: Element) => { throw "Challenge is invalid."; } - toggleLoading(checkbox); - - checkbox.addEventListener("click", prepareChallengeExecution(challenge, response => { - if (successCallback) eval(successCallback)(response); - if (inputSelector) [...document.querySelectorAll(inputSelector)].forEach((input: HTMLInputElement) => input.value = response) - })); + await initDoneCallback(challenge); } window.addEventListener("load", () =>