Spaces:
Runtime error
Runtime error
| const puppeteer = require('puppeteer-extra'); | |
| const StealthPlugin = require('puppeteer-extra-plugin-stealth'); | |
| const RecaptchaPlugin = require('puppeteer-extra-plugin-recaptcha'); | |
| const FormData = require('form-data'); | |
| const fs = require('fs'); | |
| const path = require('path'); | |
| // Use stealth plugin to avoid detection | |
| puppeteer.use(StealthPlugin()); | |
| // Add recaptcha plugin (requires 2captcha API key for actual solving, but helps with detection) | |
| puppeteer.use( | |
| RecaptchaPlugin({ | |
| visualFeedback: true, // Show when solving captcha | |
| throwOnError: false // Don't throw errors, just try to continue | |
| }) | |
| ); | |
| // Helper function to wait | |
| const wait = (ms) => new Promise(resolve => setTimeout(resolve, ms)); | |
| // Random delay to appear more human-like | |
| const randomWait = (min, max) => wait(Math.floor(Math.random() * (max - min + 1)) + min); | |
| // Check if we should wait for manual Cloudflare solving | |
| const MANUAL_CLOUDFLARE = process.env.MANUAL_CLOUDFLARE === 'true'; | |
| const CLOUDFLARE_WAIT = parseInt(process.env.CLOUDFLARE_WAIT || '30000'); | |
| if (MANUAL_CLOUDFLARE) { | |
| console.log('β οΈ MANUAL_CLOUDFLARE mode enabled - will wait up to', CLOUDFLARE_WAIT / 1000, 'seconds for manual solving'); | |
| } | |
| // Function to upload image to uploadnx.zone.id | |
| async function uploadToServer(filePath) { | |
| return new Promise((resolve, reject) => { | |
| const form = new FormData(); | |
| form.append('file', fs.createReadStream(filePath)); | |
| const options = { | |
| method: 'POST', | |
| hostname: 'uploadnx.zone.id', | |
| path: '/api/upload', | |
| headers: form.getHeaders() | |
| }; | |
| const https = require('https'); | |
| const req = https.request(options, (res) => { | |
| let data = ''; | |
| res.on('data', chunk => { | |
| data += chunk; | |
| }); | |
| res.on('end', () => { | |
| if (res.statusCode === 200) { | |
| try { | |
| const response = JSON.parse(data); | |
| resolve(response.short_url); | |
| } catch (e) { | |
| reject(new Error('Invalid JSON response')); | |
| } | |
| } else { | |
| reject(new Error(`Upload failed with status code: ${res.statusCode}`)); | |
| } | |
| }); | |
| }); | |
| req.on('error', reject); | |
| form.pipe(req); | |
| }); | |
| } | |
| // Load cookies from JSON file | |
| function loadCookies(cookieFilePath) { | |
| try { | |
| if (fs.existsSync(cookieFilePath)) { | |
| const cookieData = JSON.parse(fs.readFileSync(cookieFilePath, 'utf8')); | |
| console.log(`β Loaded cookies from: ${cookieFilePath}`); | |
| console.log(` - ${cookieData.cookies.length} cookies found`); | |
| console.log(` - ${Object.keys(cookieData.localStorage || {}).length} localStorage items`); | |
| console.log(` - ${Object.keys(cookieData.sessionStorage || {}).length} sessionStorage items`); | |
| return cookieData; | |
| } else { | |
| console.log(`β οΈ Cookie file not found: ${cookieFilePath}`); | |
| console.log(' Running without cookies...'); | |
| return null; | |
| } | |
| } catch (error) { | |
| console.error(`β Error loading cookies: ${error.message}`); | |
| return null; | |
| } | |
| } | |
| (async () => { | |
| // Look for cookie file in multiple locations | |
| const possibleCookieFiles = [ | |
| path.join(__dirname, 'cookies.json'), | |
| path.join(__dirname, 'betking-cookies.json'), | |
| '/mnt/user-data/uploads/cookies.json' | |
| ]; | |
| let cookieData = null; | |
| for (const cookieFile of possibleCookieFiles) { | |
| cookieData = loadCookies(cookieFile); | |
| if (cookieData) break; | |
| } | |
| const browser = await puppeteer.launch({ | |
| headless: true, | |
| args: [ | |
| '--no-sandbox', | |
| '--disable-setuid-sandbox', | |
| '--disable-blink-features=AutomationControlled', | |
| '--disable-web-security', | |
| '--disable-features=IsolateOrigins,site-per-process', | |
| '--disable-dev-shm-usage', | |
| '--disable-accelerated-2d-canvas', | |
| '--no-first-run', | |
| '--no-zygote', | |
| '--disable-gpu', | |
| '--disable-notifications', | |
| '--disable-popup-blocking', | |
| // EXTREME ANTI-DETECTION | |
| '--disable-features=IsolateOrigins', | |
| '--disable-site-isolation-trials', | |
| '--disable-features=BlockInsecurePrivateNetworkRequests', | |
| '--disable-blink-features=AutomationControlled', | |
| '--excludeSwitches=enable-automation', | |
| '--disable-infobars', | |
| '--window-size=390,844', | |
| '--user-agent=' + (cookieData?.userAgent || 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1'), | |
| // Bypass bot detection | |
| '--disable-blink-features=AutomationControlled', | |
| '--disable-features=VizDisplayCompositor', | |
| '--enable-features=NetworkService,NetworkServiceInProcess', | |
| '--disable-breakpad', | |
| '--disable-component-update', | |
| '--disable-domain-reliability', | |
| '--disable-sync', | |
| '--disable-client-side-phishing-detection', | |
| '--disable-features=site-per-process', | |
| '--enable-features=NetworkServiceInProcess', | |
| // Additional anti-Cloudflare flags | |
| '--disable-features=IsolateOrigins,site-per-process,SitePerProcess', | |
| '--disable-web-security', | |
| '--allow-running-insecure-content', | |
| '--disable-features=VizDisplayCompositor', | |
| '--disable-ipc-flooding-protection', | |
| '--disable-hang-monitor', | |
| '--disable-prompt-on-repost', | |
| '--disable-background-timer-throttling', | |
| '--disable-backgrounding-occluded-windows', | |
| '--disable-renderer-backgrounding', | |
| '--force-color-profile=srgb', | |
| '--disable-features=TranslateUI', | |
| '--disable-features=Translate' | |
| ], | |
| ignoreHTTPSErrors: true, | |
| defaultViewport: null, | |
| ignoreDefaultArgs: ['--enable-automation', '--enable-blink-features=IdleDetection'] | |
| }); | |
| const page = await browser.newPage(); | |
| // EXTREME: Additional page configurations | |
| await page.setBypassCSP(true); | |
| // Set extra permissions to look more like real browser | |
| const context = browser.defaultBrowserContext(); | |
| await context.overridePermissions('https://m.betking.com', [ | |
| 'geolocation', | |
| 'notifications' | |
| ]); | |
| try { | |
| // Enable JavaScript | |
| await page.setJavaScriptEnabled(true); | |
| // Use user agent from cookie file if available | |
| const userAgent = cookieData?.userAgent || 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1'; | |
| await page.setUserAgent(userAgent); | |
| console.log(`β Using User Agent: ${userAgent}`); | |
| // Set realistic mobile viewport to match cookies | |
| await page.setViewport({ | |
| width: 390, | |
| height: 844, | |
| isMobile: true, | |
| hasTouch: true, | |
| deviceScaleFactor: 3 | |
| }); | |
| // Set additional headers | |
| const headers = { | |
| 'Accept-Language': 'en-US,en;q=0.9,en-NG;q=0.8', | |
| 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8', | |
| 'Accept-Encoding': 'gzip, deflate, br', | |
| 'Connection': 'keep-alive', | |
| 'Upgrade-Insecure-Requests': '1', | |
| 'Sec-Fetch-Dest': 'document', | |
| 'Sec-Fetch-Mode': 'navigate', | |
| 'Sec-Fetch-Site': 'none', | |
| 'Sec-Fetch-User': '?1', | |
| 'Cache-Control': 'max-age=0' | |
| }; | |
| await page.setExtraHTTPHeaders(headers); | |
| // EXTREME: Enable request interception to modify headers on the fly | |
| await page.setRequestInterception(true); | |
| page.on('request', (request) => { | |
| const overrides = { | |
| headers: { | |
| ...request.headers(), | |
| 'sec-ch-ua': '"Not_A Brand";v="8", "Chromium";v="120", "Safari";v="16.6"', | |
| 'sec-ch-ua-mobile': '?1', | |
| 'sec-ch-ua-platform': '"iOS"', | |
| 'DNT': '1', | |
| 'Referer': 'https://m.betking.com/', | |
| 'Origin': 'https://m.betking.com' | |
| } | |
| }; | |
| request.continue(overrides); | |
| }); | |
| console.log('β Request interception enabled with custom headers'); | |
| // CRITICAL: Set cookies BEFORE navigating | |
| if (cookieData && cookieData.cookies) { | |
| console.log('\nπͺ Pre-loading cookies...'); | |
| // First, navigate to the domain to establish context | |
| try { | |
| // Try login page directly for cookie context | |
| await page.goto('https://m.betking.com/en-ng/my-accounts/login', { | |
| waitUntil: 'domcontentloaded', | |
| timeout: 15000 | |
| }); | |
| console.log('β Login page loaded for cookie context'); | |
| // Wait a bit for any Cloudflare JS to run | |
| await wait(3000); | |
| } catch (baseError) { | |
| console.log('β οΈ Initial login page load issue, trying base domain...'); | |
| try { | |
| await page.goto('https://m.betking.com/', { | |
| waitUntil: 'domcontentloaded', | |
| timeout: 15000 | |
| }); | |
| console.log('β Base domain loaded'); | |
| await wait(3000); | |
| } catch (fallbackError) { | |
| console.log('β οΈ Base domain also failed, setting domain manually...'); | |
| await page.evaluateOnNewDocument(() => { | |
| document.domain = 'betking.com'; | |
| }); | |
| } | |
| } | |
| // Now set all cookies | |
| console.log('Setting cookies...'); | |
| let cookiesSet = 0; | |
| for (const cookie of cookieData.cookies) { | |
| try { | |
| await page.setCookie(cookie); | |
| cookiesSet++; | |
| } catch (error) { | |
| // Silently skip problematic cookies | |
| } | |
| } | |
| console.log(`β ${cookiesSet}/${cookieData.cookies.length} cookies set successfully`); | |
| } | |
| // Override WebDriver and other bot detection properties | |
| await page.evaluateOnNewDocument(() => { | |
| // Remove webdriver property | |
| Object.defineProperty(navigator, 'webdriver', { | |
| get: () => undefined | |
| }); | |
| // Override permissions | |
| const originalQuery = window.navigator.permissions.query; | |
| window.navigator.permissions.query = (parameters) => ( | |
| parameters.name === 'notifications' ? | |
| Promise.resolve({ state: Notification.permission }) : | |
| originalQuery(parameters) | |
| ); | |
| // Add Chrome object | |
| window.chrome = { | |
| runtime: {}, | |
| loadTimes: function() {}, | |
| csi: function() {}, | |
| app: {} | |
| }; | |
| // Override plugins with realistic values | |
| Object.defineProperty(navigator, 'plugins', { | |
| get: () => [ | |
| { | |
| 0: {type: "application/x-google-chrome-pdf", suffixes: "pdf", description: "Portable Document Format"}, | |
| description: "Portable Document Format", | |
| filename: "internal-pdf-viewer", | |
| length: 1, | |
| name: "Chrome PDF Plugin" | |
| } | |
| ] | |
| }); | |
| // Override languages | |
| Object.defineProperty(navigator, 'languages', { | |
| get: () => ['en-US', 'en'] | |
| }); | |
| // Remove automation indicators | |
| delete navigator.__proto__.webdriver; | |
| // Mock realistic hardware concurrency | |
| Object.defineProperty(navigator, 'hardwareConcurrency', { | |
| get: () => 4 | |
| }); | |
| // Mock realistic device memory | |
| Object.defineProperty(navigator, 'deviceMemory', { | |
| get: () => 8 | |
| }); | |
| // Override platform | |
| Object.defineProperty(navigator, 'platform', { | |
| get: () => 'iPhone' | |
| }); | |
| // Override vendor | |
| Object.defineProperty(navigator, 'vendor', { | |
| get: () => 'Apple Computer, Inc.' | |
| }); | |
| // Mock realistic touch points | |
| Object.defineProperty(navigator, 'maxTouchPoints', { | |
| get: () => 5 | |
| }); | |
| // Override toString to avoid detection | |
| const originalToString = Function.prototype.toString; | |
| Function.prototype.toString = function() { | |
| if (this === navigator.permissions.query) { | |
| return 'function query() { [native code] }'; | |
| } | |
| return originalToString.call(this); | |
| }; | |
| // Remove Headless Chrome detection | |
| Object.defineProperty(navigator, 'webdriver', { | |
| get: () => false | |
| }); | |
| // Mock battery | |
| navigator.getBattery = () => Promise.resolve({ | |
| charging: true, | |
| chargingTime: 0, | |
| dischargingTime: Infinity, | |
| level: 1 | |
| }); | |
| // Override screen properties | |
| Object.defineProperty(screen, 'availHeight', { | |
| get: () => 844 | |
| }); | |
| Object.defineProperty(screen, 'availWidth', { | |
| get: () => 390 | |
| }); | |
| Object.defineProperty(screen, 'height', { | |
| get: () => 844 | |
| }); | |
| Object.defineProperty(screen, 'width', { | |
| get: () => 390 | |
| }); | |
| // Canvas fingerprint spoofing | |
| const originalToDataURL = HTMLCanvasElement.prototype.toDataURL; | |
| HTMLCanvasElement.prototype.toDataURL = function(type) { | |
| const shift = { | |
| 'r': Math.floor(Math.random() * 10) - 5, | |
| 'g': Math.floor(Math.random() * 10) - 5, | |
| 'b': Math.floor(Math.random() * 10) - 5, | |
| 'a': Math.floor(Math.random() * 10) - 5 | |
| }; | |
| const context = this.getContext('2d'); | |
| if (context) { | |
| const imageData = context.getImageData(0, 0, this.width, this.height); | |
| for (let i = 0; i < imageData.data.length; i += 4) { | |
| imageData.data[i + 0] = imageData.data[i + 0] + shift.r; | |
| imageData.data[i + 1] = imageData.data[i + 1] + shift.g; | |
| imageData.data[i + 2] = imageData.data[i + 2] + shift.b; | |
| imageData.data[i + 3] = imageData.data[i + 3] + shift.a; | |
| } | |
| context.putImageData(imageData, 0, 0); | |
| } | |
| return originalToDataURL.apply(this, arguments); | |
| }; | |
| // WebGL fingerprint spoofing | |
| const getParameter = WebGLRenderingContext.prototype.getParameter; | |
| WebGLRenderingContext.prototype.getParameter = function(parameter) { | |
| if (parameter === 37445) { | |
| return 'Apple GPU'; | |
| } | |
| if (parameter === 37446) { | |
| return 'Apple Inc.'; | |
| } | |
| return getParameter.call(this, parameter); | |
| }; | |
| // Audio context fingerprint spoofing | |
| const audioContext = window.AudioContext || window.webkitAudioContext; | |
| if (audioContext) { | |
| const OriginalAudioContext = audioContext; | |
| window.AudioContext = function() { | |
| const context = new OriginalAudioContext(); | |
| const originalCreateOscillator = context.createOscillator; | |
| context.createOscillator = function() { | |
| const oscillator = originalCreateOscillator.call(context); | |
| const originalStart = oscillator.start; | |
| oscillator.start = function(when) { | |
| return originalStart.call(oscillator, when + Math.random() * 0.0001); | |
| }; | |
| return oscillator; | |
| }; | |
| return context; | |
| }; | |
| } | |
| // Remove automation from window | |
| delete window.cdc_adoQpoasnfa76pfcZLmcfl_Array; | |
| delete window.cdc_adoQpoasnfa76pfcZLmcfl_Promise; | |
| delete window.cdc_adoQpoasnfa76pfcZLmcfl_Symbol; | |
| // Override Performance API to prevent timing attacks | |
| const originalGetEntries = Performance.prototype.getEntries; | |
| Performance.prototype.getEntries = function() { | |
| const entries = originalGetEntries.call(this); | |
| return entries.filter(entry => !entry.name.includes('devtools')); | |
| }; | |
| // Override Date to add small random variations | |
| const originalDate = Date; | |
| Date = class extends originalDate { | |
| constructor(...args) { | |
| if (args.length === 0) { | |
| super(); | |
| const offset = Math.floor(Math.random() * 10); | |
| return new originalDate(this.getTime() + offset); | |
| } | |
| return new originalDate(...args); | |
| } | |
| }; | |
| Date.prototype = originalDate.prototype; | |
| Date.now = function() { | |
| return originalDate.now() + Math.floor(Math.random() * 10); | |
| }; | |
| // Spoof notification permission | |
| Object.defineProperty(Notification, 'permission', { | |
| get: () => 'default' | |
| }); | |
| // Mock realistic connection | |
| Object.defineProperty(navigator, 'connection', { | |
| get: () => ({ | |
| effectiveType: '4g', | |
| rtt: 50, | |
| downlink: 10, | |
| saveData: false | |
| }) | |
| }); | |
| // Override outerHeight/Width to match viewport | |
| Object.defineProperty(window, 'outerWidth', { | |
| get: () => 390 | |
| }); | |
| Object.defineProperty(window, 'outerHeight', { | |
| get: () => 844 | |
| }); | |
| }); | |
| console.log('\nπ Navigating to the page...'); | |
| await randomWait(500, 1500); | |
| // Navigate directly to login page | |
| const targetUrl = 'https://m.betking.com/en-ng/my-accounts/login?urlAfterLogin=/en-ng'; | |
| console.log(`Target: ${targetUrl}`); | |
| let response; | |
| try { | |
| response = await page.goto(targetUrl, { | |
| waitUntil: ['domcontentloaded', 'networkidle2'], | |
| timeout: 45000 | |
| }); | |
| } catch (error) { | |
| console.log(`β οΈ Navigation warning: ${error.message}`); | |
| console.log('Attempting to continue anyway...'); | |
| } | |
| if (response) { | |
| const statusCode = response.status(); | |
| console.log(`Response status: ${statusCode}`); | |
| if (statusCode === 403) { | |
| console.log('β οΈ Received 403 Forbidden error.'); | |
| console.log('Checking for Cloudflare challenge...'); | |
| // Check if it's a Cloudflare challenge page | |
| const isCloudflare = await page.evaluate(() => { | |
| const body = document.body.innerText; | |
| const title = document.title; | |
| return ( | |
| body.includes('Cloudflare') || | |
| body.includes('Just a moment') || | |
| body.includes('Checking your browser') || | |
| title.includes('Just a moment') || | |
| document.querySelector('#challenge-form') !== null || | |
| document.querySelector('.cf-browser-verification') !== null | |
| ); | |
| }); | |
| if (isCloudflare) { | |
| console.log('π Cloudflare challenge detected!'); | |
| console.log('β³ Attempting to solve automatically...'); | |
| // Try to click the Cloudflare Turnstile checkbox | |
| try { | |
| // Wait for checkbox to be clickable | |
| await page.waitForSelector('input[type="checkbox"]', { timeout: 5000, visible: true }) | |
| .catch(() => console.log('No visible checkbox found, trying iframe...')); | |
| // Check for iframe (Cloudflare Turnstile uses iframe) | |
| const frames = page.frames(); | |
| console.log(`Found ${frames.length} frames, checking for Cloudflare challenge...`); | |
| let clicked = false; | |
| for (const frame of frames) { | |
| try { | |
| // Try to find and click checkbox in iframe | |
| const checkbox = await frame.$('input[type="checkbox"]'); | |
| if (checkbox) { | |
| console.log('β Found checkbox in iframe, clicking...'); | |
| await checkbox.click(); | |
| clicked = true; | |
| console.log('β Checkbox clicked!'); | |
| break; | |
| } | |
| // Try Turnstile specific selector | |
| const turnstile = await frame.$('.cf-turnstile'); | |
| if (turnstile) { | |
| console.log('β Found Turnstile widget, clicking...'); | |
| await turnstile.click(); | |
| clicked = true; | |
| console.log('β Turnstile clicked!'); | |
| break; | |
| } | |
| // Try clicking the challenge box area | |
| const challengeBox = await frame.$('#challenge-stage'); | |
| if (challengeBox) { | |
| console.log('β Found challenge box, clicking...'); | |
| await challengeBox.click(); | |
| clicked = true; | |
| console.log('β Challenge box clicked!'); | |
| break; | |
| } | |
| } catch (frameError) { | |
| // Continue to next frame | |
| } | |
| } | |
| if (!clicked) { | |
| console.log('β οΈ Could not find clickable element, trying main page...'); | |
| // Try clicking on main page | |
| const mainCheckbox = await page.$('input[type="checkbox"]').catch(() => null); | |
| if (mainCheckbox) { | |
| await mainCheckbox.click(); | |
| console.log('β Main page checkbox clicked!'); | |
| } | |
| } | |
| } catch (clickError) { | |
| console.log('β οΈ Auto-click failed:', clickError.message); | |
| } | |
| // Simulate human-like mouse movements | |
| try { | |
| await wait(500); | |
| await page.mouse.move(100, 100); | |
| await wait(100); | |
| await page.mouse.move(200, 200); | |
| await wait(150); | |
| await page.mouse.move(150, 300); | |
| console.log('β Mouse movements simulated'); | |
| } catch (mouseError) { | |
| console.log('Mouse simulation skipped'); | |
| } | |
| const waitSeconds = CLOUDFLARE_WAIT / 1000; | |
| console.log(`β³ Waiting for Cloudflare to verify (up to ${waitSeconds} seconds)...`); | |
| if (MANUAL_CLOUDFLARE) { | |
| console.log('π‘ You can manually solve the challenge in the browser window!'); | |
| } | |
| // Wait for Cloudflare challenge to complete | |
| try { | |
| await page.waitForFunction( | |
| () => { | |
| // Check if we've passed the challenge | |
| const body = document.body.innerText; | |
| const title = document.title; | |
| return ( | |
| !body.includes('Just a moment') && | |
| !body.includes('Checking your browser') && | |
| !body.includes('Verify you are human') && | |
| !title.includes('Just a moment') && | |
| document.querySelector('#challenge-form') === null && | |
| document.querySelector('.cf-browser-verification') === null | |
| ); | |
| }, | |
| { timeout: CLOUDFLARE_WAIT, polling: 500 } | |
| ); | |
| console.log('β Cloudflare challenge passed!'); | |
| // Take screenshot after passing challenge | |
| await wait(2000); | |
| await page.screenshot({ path: './after-cloudflare.png', fullPage: true }); | |
| console.log('Screenshot after Cloudflare: after-cloudflare.png'); | |
| } catch (cfError) { | |
| console.log('β οΈ Cloudflare challenge timeout - may need manual intervention'); | |
| console.log('Taking screenshot of challenge page...'); | |
| await page.screenshot({ path: './cloudflare-challenge.png', fullPage: true }); | |
| console.log('Screenshot saved to cloudflare-challenge.png'); | |
| // Try to continue anyway | |
| console.log('Attempting to continue despite challenge...'); | |
| } | |
| } else { | |
| console.log('Trying alternative approaches...'); | |
| // Wait and try reloading | |
| await wait(2000); | |
| try { | |
| await page.reload({ waitUntil: ['domcontentloaded', 'networkidle2'], timeout: 30000 }); | |
| console.log('β Page reloaded with cookies'); | |
| } catch (reloadError) { | |
| console.log('Reload had issues, but continuing...'); | |
| } | |
| } | |
| } else if (statusCode >= 400) { | |
| console.log(`β οΈ Received error status: ${statusCode}`); | |
| } else { | |
| console.log('β Page loaded successfully'); | |
| } | |
| } else { | |
| console.log('β οΈ No response received, but page may have loaded'); | |
| } | |
| // Set localStorage and sessionStorage if available | |
| if (cookieData) { | |
| if (cookieData.localStorage && Object.keys(cookieData.localStorage).length > 0) { | |
| console.log('\nπΎ Setting localStorage...'); | |
| try { | |
| await page.evaluate((storage) => { | |
| for (const [key, value] of Object.entries(storage)) { | |
| try { | |
| localStorage.setItem(key, value); | |
| } catch (e) { | |
| // Skip problematic items | |
| } | |
| } | |
| }, cookieData.localStorage); | |
| console.log('β localStorage set successfully'); | |
| } catch (error) { | |
| console.log('β οΈ Could not set localStorage:', error.message); | |
| } | |
| } | |
| if (cookieData.sessionStorage && Object.keys(cookieData.sessionStorage).length > 0) { | |
| console.log('\nπΎ Setting sessionStorage...'); | |
| try { | |
| await page.evaluate((storage) => { | |
| for (const [key, value] of Object.entries(storage)) { | |
| try { | |
| sessionStorage.setItem(key, value); | |
| } catch (e) { | |
| // Skip problematic items | |
| } | |
| } | |
| }, cookieData.sessionStorage); | |
| console.log('β sessionStorage set successfully'); | |
| } catch (error) { | |
| console.log('β οΈ Could not set sessionStorage:', error.message); | |
| } | |
| } | |
| // One more reload to ensure everything is applied | |
| console.log('\nπ Final reload to apply all data...'); | |
| try { | |
| await page.reload({ waitUntil: ['domcontentloaded'], timeout: 30000 }); | |
| console.log('β Page reloaded'); | |
| } catch (reloadError) { | |
| console.log('β οΈ Reload warning:', reloadError.message); | |
| console.log('Continuing anyway...'); | |
| } | |
| } | |
| console.log('\nβ³ Waiting 10 seconds...'); | |
| await wait(10000); | |
| // Take initial screenshot | |
| console.log('\nπΈ Taking initial screenshot...'); | |
| await page.screenshot({ | |
| path: './betking-initial.png', | |
| fullPage: true | |
| }); | |
| console.log('\nπ Checking if we bypassed 403 - looking for login input...'); | |
| // Check for username input field | |
| let loginInputFound = false; | |
| let bypass403Success = false; | |
| try { | |
| const usernameInput = await page.$('#username'); | |
| if (usernameInput) { | |
| loginInputFound = true; | |
| bypass403Success = true; | |
| console.log('β SUCCESS! Found username input - 403 bypass worked!'); | |
| console.log('β We are on the real login page!'); | |
| // Check if input is visible | |
| const isVisible = await usernameInput.isIntersectingViewport(); | |
| console.log(`Username input is visible: ${isVisible}`); | |
| // Get input attributes for confirmation | |
| const inputInfo = await page.evaluate(() => { | |
| const input = document.querySelector('#username'); | |
| if (input) { | |
| return { | |
| id: input.id, | |
| type: input.type, | |
| name: input.name, | |
| placeholder: input.placeholder, | |
| class: input.className | |
| }; | |
| } | |
| return null; | |
| }); | |
| if (inputInfo) { | |
| console.log('π Input field details:'); | |
| console.log(JSON.stringify(inputInfo, null, 2)); | |
| } | |
| // Check for other login elements | |
| const otherElements = await page.evaluate(() => { | |
| return { | |
| passwordField: !!document.querySelector('#password') || !!document.querySelector('input[type="password"]'), | |
| loginButton: !!document.querySelector('button[type="submit"]'), | |
| totalInputs: document.querySelectorAll('input').length, | |
| totalButtons: document.querySelectorAll('button').length, | |
| pageTitle: document.title, | |
| hasLoginForm: !!document.querySelector('form') | |
| }; | |
| }); | |
| console.log('π Page structure analysis:'); | |
| console.log(` - Password field found: ${otherElements.passwordField}`); | |
| console.log(` - Login button found: ${otherElements.loginButton}`); | |
| console.log(` - Total inputs: ${otherElements.totalInputs}`); | |
| console.log(` - Total buttons: ${otherElements.totalButtons}`); | |
| console.log(` - Page title: ${otherElements.pageTitle}`); | |
| console.log(` - Has form: ${otherElements.hasLoginForm}`); | |
| } else { | |
| console.log('β Username input NOT found - still blocked or wrong page'); | |
| } | |
| } catch (error) { | |
| console.log(`β οΈ Error checking for input: ${error.message}`); | |
| } | |
| // Also check if we're still on Cloudflare page | |
| const stillOnCloudflare = await page.evaluate(() => { | |
| const body = document.body.innerText; | |
| const title = document.title; | |
| return ( | |
| body.includes('Just a moment') || | |
| body.includes('Checking your browser') || | |
| body.includes('Verify you are human') || | |
| title.includes('Just a moment') || | |
| body.includes('Cloudflare') | |
| ); | |
| }); | |
| if (stillOnCloudflare) { | |
| console.log('β οΈ Still on Cloudflare challenge page'); | |
| } else if (!loginInputFound) { | |
| console.log('β οΈ Not on Cloudflare, but also not on login page - checking what page we\'re on...'); | |
| const pageInfo = await page.evaluate(() => { | |
| return { | |
| url: window.location.href, | |
| title: document.title, | |
| bodyText: document.body.innerText.substring(0, 500), | |
| h1: document.querySelector('h1')?.innerText, | |
| errorMessage: document.querySelector('.error-message')?.innerText || | |
| document.querySelector('[class*="error"]')?.innerText | |
| }; | |
| }); | |
| console.log('π Current page info:'); | |
| console.log(` - URL: ${pageInfo.url}`); | |
| console.log(` - Title: ${pageInfo.title}`); | |
| console.log(` - H1: ${pageInfo.h1}`); | |
| if (pageInfo.errorMessage) { | |
| console.log(` - Error message: ${pageInfo.errorMessage}`); | |
| } | |
| } | |
| console.log('\nπΈ Taking final screenshot...'); | |
| if (bypass403Success) { | |
| console.log('π STATUS: 403 BYPASS SUCCESSFUL - Login page reached!'); | |
| } else { | |
| console.log('β STATUS: 403 bypass failed or still on challenge page'); | |
| } | |
| await page.screenshot({ | |
| path: './betking-final.png', | |
| fullPage: true | |
| }); | |
| console.log('β Screenshot saved to betking-final.png'); | |
| // Upload screenshot to server | |
| console.log('\nπ€ Uploading screenshot to server...'); | |
| try { | |
| const uploadUrl = await uploadToServer('./betking-final.png'); | |
| console.log('β Upload successful!'); | |
| console.log('\nπ Download link:'); | |
| console.log(uploadUrl); | |
| console.log('\nπ Direct link (copy this):'); | |
| console.log(uploadUrl); | |
| } catch (uploadError) { | |
| console.error('β Failed to upload to server:', uploadError.message); | |
| console.log('Screenshot is still saved locally at: ./betking-final.png'); | |
| } | |
| } catch (error) { | |
| console.error('\nβ Error occurred:', error.message); | |
| console.error('Stack trace:', error.stack); | |
| try { | |
| // Check if page is still open before trying to screenshot | |
| if (!page.isClosed()) { | |
| await page.screenshot({ | |
| path: './betking-error.png', | |
| fullPage: true | |
| }); | |
| console.log('Error screenshot saved to betking-error.png'); | |
| } else { | |
| console.log('Page was closed, cannot take error screenshot'); | |
| } | |
| } catch (screenshotError) { | |
| console.error('Could not take error screenshot:', screenshotError.message); | |
| } | |
| } finally { | |
| try { | |
| if (browser) { | |
| await browser.close(); | |
| console.log('\nβ Browser closed'); | |
| } | |
| } catch (closeError) { | |
| console.log('Browser already closed'); | |
| } | |
| } | |
| })(); |