File size: 5,610 Bytes
d8ea8ce ca7264e d8ea8ce ca7264e d8ea8ce 0554a46 bc15be9 d8ea8ce 0554a46 d8ea8ce ca7264e 0554a46 ca7264e e30a13d 0554a46 ca7264e e30a13d ca7264e e30a13d d8ea8ce ca7264e c092763 f266c6c ca7264e f266c6c ca7264e 08b3eb8 ca7264e d07887a 097870f ca7264e f266c6c d8ea8ce ca7264e 0554a46 ca7264e d8ea8ce ca7264e d8ea8ce f266c6c d8ea8ce ca7264e f266c6c ca7264e d8ea8ce ca7264e d8ea8ce bc15be9 d8ea8ce ca7264e d8ea8ce ca7264e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | const express = require('express');
const cors = require('cors');
const { connect } = require("puppeteer-real-browser");
const app = express();
app.use(cors());
app.use(express.json());
const PORT = process.env.PORT || 7860;
const MAX_CONCURRENT_BROWSERS = 2; // Limit 2 Browser agar RAM aman
let activeBrowsers = 0;
async function createBrowser(proxy = null) {
const options = {
headless: false, // Wajib false
turnstile: true, // Auto-click turnstile bawaan library
args: [
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-dev-shm-usage',
'--disable-accelerated-2d-canvas',
'--no-first-run',
'--no-zygote',
'--disable-gpu',
'--window-size=1920,1080',
'--disable-blink-features=AutomationControlled'
],
executablePath: process.env.CHROME_PATH || "/usr/bin/google-chrome-stable",
customConfig: {},
connectOption: { defaultViewport: null }
};
if (proxy) {
options.args.push(`--proxy-server=${proxy.hostname}:${proxy.port}`);
}
const { browser, page } = await connect(options);
if (proxy && proxy.username && proxy.password) {
await page.authenticate({ username: proxy.username, password: proxy.password });
}
return { browser, page };
}
async function handleTurnstile(page, url, siteKey) {
return new Promise(async (resolve, reject) => {
// PERBAIKAN 1: Timeout diperpanjang jadi 120 detik (2 menit)
const timeout = setTimeout(() => {
reject(new Error("Timeout Turnstile (120s limit reached)"));
}, 120000);
try {
console.log(`[Turnstile] Preparing Injection for ${url}`);
// Template HTML minimalis untuk memancing Turnstile keluar
const htmlContent = `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Turnstile Solver</title>
</head>
<body>
<div class="cf-turnstile" data-sitekey="${siteKey}" data-callback="turnstileCallback"></div>
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
<script>
console.log("Widget rendered...");
function turnstileCallback(token) {
console.log("Token received in browser!");
window.cf_token = token;
}
</script>
</body>
</html>`;
// Intercept request ke URL target dan ganti isinya dengan HTML di atas
await page.setRequestInterception(true);
page.once('request', request => {
request.respond({
status: 200,
contentType: 'text/html',
body: htmlContent
});
});
// Handle request lain (gambar/css) agar tidak error
page.on('request', req => {
if (req.isInterceptResolutionHandled()) return;
req.continue();
});
// Buka URL (ini akan memicu intercept di atas)
console.log(`[Turnstile] Navigating...`);
await page.goto(url, { waitUntil: "domcontentloaded", timeout: 60000 });
// Polling Token
const checkToken = setInterval(async () => {
try {
const token = await page.evaluate(() => window.cf_token);
if (token) {
clearInterval(checkToken);
clearTimeout(timeout);
console.log(`[Turnstile] Token found: ${token.substring(0, 15)}...`);
resolve({ token: token });
}
} catch (e) {}
}, 1000);
} catch (e) {
clearTimeout(timeout);
reject(e);
}
});
}
app.post('/bypass', async (req, res) => {
const { url, mode, siteKey, proxy } = req.body;
if (!url || !mode) return res.status(400).json({ status: "error", message: "Missing url or mode" });
if (activeBrowsers >= MAX_CONCURRENT_BROWSERS) {
return res.status(429).json({ status: "busy", message: "Server busy, try again in a few seconds" });
}
activeBrowsers++;
let browserInstance = null;
try {
console.log(`[REQ] Processing: ${url} | Mode: ${mode}`);
const { browser, page } = await createBrowser(proxy);
browserInstance = browser;
let result;
if (mode === 'turnstile') {
result = await handleTurnstile(page, url, siteKey);
} else {
throw new Error("Invalid mode (only turnstile supported in this version)");
}
console.log(`[SUCCESS] Operation completed.`);
res.json({ status: "success", ...result });
} catch (error) {
console.error(`[ERROR] ${error.message}`);
res.status(500).json({ status: "error", message: error.message });
} finally {
if (browserInstance) {
try { await browserInstance.close(); } catch {}
}
activeBrowsers--;
}
});
app.get('/', (req, res) => res.send("Turnstile Solver Ready (v3 - 120s Timeout)"));
app.listen(PORT, () => console.log(`Server listening on port ${PORT}`));
|