| const delay = ms => new Promise(res => setTimeout(res, ms)); |
|
|
| module.exports = async function(page, url, siteKey, action = 'submit') { |
| return new Promise(async (resolve, reject) => { |
| const timeoutTimer = setTimeout(() => |
| reject(new Error("Timeout Global (40s)")), 40000); |
|
|
| try { |
| console.log(`[RV3] Target: ${url} | Key: ${siteKey}`); |
|
|
| await page.setExtraHTTPHeaders({ |
| 'Accept-Language': 'id-ID,id;q=0.9,en-US;q=0.8,en;q=0.7', |
| 'Sec-Fetch-Site': 'cross-site', |
| 'Sec-Fetch-Mode': 'navigate', |
| 'Sec-Fetch-Dest': 'document', |
| 'Upgrade-Insecure-Requests': '1' |
| }); |
|
|
| try { |
| await page.goto(url, { |
| waitUntil: 'domcontentloaded', |
| timeout: 25000 |
| }); |
| } catch (e) { |
| console.log('[RV3] Navigation warning (ignorable):', e.message); |
| } |
|
|
| try { |
| await page.mouse.move(100, 100); |
| await page.mouse.move(200, 200); |
| await delay(1000); |
| } catch (e) {} |
|
|
| await delay(5000); |
|
|
| const token = await page.evaluate(() => { |
| const iframes = document.querySelectorAll('iframe'); |
| for (let iframe of iframes) { |
| if (iframe.src && iframe.src.includes('recaptcha')) { |
| try { |
| if (iframe.contentDocument) { |
| const tokenEl = iframe.contentDocument.getElementById('recaptcha-token'); |
| if (tokenEl && tokenEl.value) return tokenEl.value; |
| } |
| } catch (e) {} |
| } |
| } |
| if (window.recaptchaToken) return window.recaptchaToken; |
| const inputs = document.querySelectorAll('input[id*="recaptcha"], input[name*="recaptcha"]'); |
| for (let input of inputs) { |
| if (input.value && input.value.length > 100) return input.value; |
| } |
| return null; |
| }); |
|
|
| if (token) { |
| console.log(`[RV3] SUCCESS! Token: ${token.substring(0, 50)}...`); |
| clearTimeout(timeoutTimer); |
| resolve(token); |
| return; |
| } |
|
|
| console.log('[RV3] Trying grecaptcha.execute fallback...'); |
| |
| const executeToken = await page.evaluate(async (siteKey, action) => { |
| return new Promise((resolve, reject) => { |
| const timeout = setTimeout(() => reject('Timeout inside evaluate'), 15000); |
|
|
| const waitForGrecaptcha = (interval = 500, maxAttempts = 20) => { |
| return new Promise(res => { |
| let attempts = 0; |
| const check = setInterval(() => { |
| attempts++; |
| if (window.grecaptcha && window.grecaptcha.execute) { |
| clearInterval(check); |
| res(true); |
| } else if (attempts >= maxAttempts) { |
| clearInterval(check); |
| res(false); |
| } |
| }, interval); |
| }); |
| }; |
|
|
| if (!window.grecaptcha || !window.grecaptcha.execute) { |
| const script = document.createElement('script'); |
| script.src = `https://www.google.com/recaptcha/api.js?render=${siteKey}`; |
| document.head.appendChild(script); |
| } |
|
|
| waitForGrecaptcha().then(ready => { |
| if (ready) { |
| window.grecaptcha.ready(() => { |
| window.grecaptcha.execute(siteKey, { action: action }) |
| .then(token => { |
| clearTimeout(timeout); |
| resolve(token); |
| }) |
| .catch(err => { |
| clearTimeout(timeout); |
| reject('Execute failed: ' + err); |
| }); |
| }); |
| } else { |
| clearTimeout(timeout); |
| reject('grecaptcha load failed'); |
| } |
| }); |
| }); |
| }, siteKey, action).catch(err => { |
| console.log('[RV3] Execute error:', err.message || err); |
| return null; |
| }); |
|
|
| if (executeToken) { |
| console.log(`[RV3] SUCCESS via execute! Token: ${executeToken.substring(0, 50)}...`); |
| clearTimeout(timeoutTimer); |
| resolve(executeToken); |
| return; |
| } |
|
|
| reject(new Error('No token found after all methods')); |
|
|
| } catch (error) { |
| clearTimeout(timeoutTimer); |
| reject(new Error(`${error.message}`)); |
| } |
| }); |
| }; |