async function recaptchaV2({ domain, proxy, siteKey, action = "submit", isInvisible = false }, page) { if (!domain) throw new Error("Missing domain parameter"); if (!siteKey) throw new Error("Missing siteKey parameter"); const timeout = global.timeOut || 60000; let isResolved = false; const cl = setTimeout(async () => { if (!isResolved) { throw new Error("Timeout Error"); } }, timeout); try { if (proxy?.username && proxy?.password) { await page.authenticate({ username: proxy.username, password: proxy.password, }); } const htmlContent = ` reCAPTCHA v2 Solver

reCAPTCHA v2 Solver

SiteKey: ${siteKey}

${isInvisible ? '' : ''}
Waiting for reCAPTCHA...
`; // Setup request interception await page.setRequestInterception(true); page.removeAllListeners("request"); page.on("request", async (request) => { const url = request.url(); // Handle main document request if ([domain, domain + "/"].includes(url) && request.resourceType() === "document") { await request.respond({ status: 200, contentType: "text/html", body: htmlContent, }); } // Block unnecessary resources untuk mempercepat else if (request.resourceType() === 'image' || request.resourceType() === 'stylesheet' || request.resourceType() === 'font') { await request.abort(); } else { await request.continue(); } }); // Navigate ke page await page.goto(domain, { waitUntil: "domcontentloaded", timeout: timeout }); // Tunggu reCAPTCHA container load await page.waitForSelector('.g-recaptcha', { timeout: 10000 }); // Tunggu token tersedia dengan multiple strategies const token = await page.waitForFunction(() => { // Cek dari hidden input const input = document.querySelector('#recaptcha-token-input'); if (input && input.value && input.value.length > 10) { return input.value; } // Cek dari localStorage const stored = localStorage.getItem('recaptcha_token'); if (stored && stored.length > 10) { return stored; } // Cek dari global variable if (window.recaptchaToken && window.recaptchaToken.length > 10) { return window.recaptchaToken; } return null; }, { timeout, polling: 100 }); const tokenValue = await token.jsonValue(); isResolved = true; clearTimeout(cl); if (!tokenValue || tokenValue.length < 10) { throw new Error("Failed to get valid reCAPTCHA token"); } console.log('Successfully obtained reCAPTCHA token'); return { token: tokenValue, type: 'recaptcha_v2' }; } catch (error) { clearTimeout(cl); // Fallback: coba ambil token dengan method lain try { const fallbackToken = await page.evaluate(() => { const input = document.querySelector('#recaptcha-token-input'); return input ? input.value : null; }); if (fallbackToken && fallbackToken.length > 10) { return { token: fallbackToken, type: 'recaptcha_v2' }; } } catch (e) { // Ignore fallback error } throw new Error(`reCAPTCHA solving failed: ${error.message}`); } } module.exports = recaptchaV2;