UNPKG

puppeteer-extra-plugin-recaptcha

Version:
149 lines 5.33 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.HcaptchaContentScript = exports.ContentScriptDefaultData = exports.ContentScriptDefaultOpts = void 0; exports.ContentScriptDefaultOpts = { visualFeedback: true }; exports.ContentScriptDefaultData = { solutions: [] }; /** * Content script for Hcaptcha handling (runs in browser context) * @note External modules are not supported here (due to content script isolation) */ class HcaptchaContentScript { constructor(opts = exports.ContentScriptDefaultOpts, data = exports.ContentScriptDefaultData) { this.baseUrls = [ 'assets.hcaptcha.com/captcha/v1/', 'newassets.hcaptcha.com/captcha/v1/', ]; // Workaround for https://github.com/esbuild-kit/tsx/issues/113 if (typeof globalThis.__name === 'undefined') { globalThis.__defProp = Object.defineProperty; globalThis.__name = (target, value) => globalThis.__defProp(target, 'name', { value, configurable: true }); } this.opts = opts; this.data = data; } async _waitUntilDocumentReady() { return new Promise(function (resolve) { if (!document || !window) return resolve(null); const loadedAlready = /^loaded|^i|^c/.test(document.readyState); if (loadedAlready) return resolve(null); function onReady() { resolve(null); document.removeEventListener('DOMContentLoaded', onReady); window.removeEventListener('load', onReady); } document.addEventListener('DOMContentLoaded', onReady); window.addEventListener('load', onReady); }); } _paintCaptchaBusy($iframe) { try { if (this.opts.visualFeedback) { $iframe.style.filter = `opacity(60%) hue-rotate(400deg)`; // violet } } catch (error) { // noop } return $iframe; } /** Regular checkboxes */ _findRegularCheckboxes() { const nodeList = document.querySelectorAll(this.baseUrls.map(url => `iframe[src*='${url}'][data-hcaptcha-widget-id]:not([src*='invisible'])`).join(',')); return Array.from(nodeList); } /** Find active challenges from invisible hcaptchas */ _findActiveChallenges() { const nodeList = document.querySelectorAll(this.baseUrls.map(url => `div[style*='visible'] iframe[src*='${url}'][src*='hcaptcha.html']`).join(',')); return Array.from(nodeList); } _extractInfoFromIframes(iframes) { return iframes .map(el => el.src.replace('.html#', '.html?')) .map(url => { const { searchParams } = new URL(url); const result = { _vendor: 'hcaptcha', url: document.location.href, id: searchParams.get('id'), sitekey: searchParams.get('sitekey'), display: { size: searchParams.get('size') || 'normal' } }; return result; }); } async findRecaptchas() { const result = { captchas: [], error: null }; try { await this._waitUntilDocumentReady(); const iframes = [ ...this._findRegularCheckboxes(), ...this._findActiveChallenges() ]; if (!iframes.length) { return result; } result.captchas = this._extractInfoFromIframes(iframes); iframes.forEach(el => { this._paintCaptchaBusy(el); }); } catch (error) { result.error = error; return result; } return result; } async enterRecaptchaSolutions() { const result = { solved: [], error: null }; try { await this._waitUntilDocumentReady(); const solutions = this.data.solutions; if (!solutions || !solutions.length) { result.error = 'No solutions provided'; return result; } result.solved = solutions .filter(solution => solution._vendor === 'hcaptcha') .filter(solution => solution.hasSolution === true) .map(solution => { window.postMessage(JSON.stringify({ id: solution.id, label: 'challenge-closed', source: 'hcaptcha', contents: { event: 'challenge-passed', expiration: 120, response: solution.text } }), '*'); return { _vendor: solution._vendor, id: solution.id, isSolved: true, solvedAt: new Date() }; }); } catch (error) { result.error = error; return result; } return result; } } exports.HcaptchaContentScript = HcaptchaContentScript; //# sourceMappingURL=content-hcaptcha.js.map