UNPKG

@extra/recaptcha

Version:

A plugin for playwright & puppeteer to solve reCAPTCHAs and hCaptchas automatically.

141 lines 4.94 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.baseUrl = 'https://assets.hcaptcha.com/captcha/v1/'; 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(`iframe[src^='${this.baseUrl}'][data-hcaptcha-widget-id]:not([src*='invisible'])`); return Array.from(nodeList); } /** Find active challenges from invisible hcaptchas */ _findActiveChallenges() { const nodeList = document.querySelectorAll(`div[style*='visible'] iframe[src^='${this.baseUrl}'][src*='hcaptcha-challenge.html'][src*='invisible']`); 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