Cdata / index.js
Arrgcw6's picture
Update index.js
aacb46d verified
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 = 3; // Batasi agar RAM HF tidak jebol
let activeBrowsers = 0;
async function createBrowser(proxy = null) {
const options = {
headless: false, // Wajib false agar Turnstile mengira ini user asli
turnstile: true, // Fitur auto-solve bawaan library (opsional, tapi kita pakai manual logic)
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',
],
// Menggunakan Chrome yang sudah diinstall Dockerfile
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}`);
}
// Connect ke browser
const { browser, page } = await connect(options);
if (proxy && proxy.username && proxy.password) {
await page.authenticate({ username: proxy.username, password: proxy.password });
}
return { browser, page };
}
// FUNGSI UTAMA: Handle Turnstile dengan cData
async function handleTurnstile(page, url, siteKey, cData = null, action = null) {
return new Promise(async (resolve, reject) => {
// Timeout 60 detik
const timeout = setTimeout(() => reject(new Error("Timeout waiting for Turnstile token")), 60000);
try {
console.log(`[Turnstile] Navigating to Real URL: ${url}`);
// 1. Buka URL Asli (PENTING: Jangan pakai konten palsu)
await page.goto(url, { waitUntil: "domcontentloaded", timeout: 30000 });
// 2. Inject Logika Render Widget
// Kita menyuntikkan script ke browser untuk merender widget sesuai request bot
await page.evaluate((key, data, act) => {
// Hapus widget yang mungkin sudah ada agar tidak bentrok
document.querySelectorAll('.cf-turnstile').forEach(e => e.remove());
document.querySelectorAll('iframe[src*="challenges.cloudflare.com"]').forEach(e => e.remove());
// Buat wadah baru
const div = document.createElement('div');
div.id = 'custom-turnstile-container';
div.style.position = 'fixed';
div.style.top = '10px';
div.style.left = '10px';
div.style.zIndex = '99999';
document.body.appendChild(div);
// Pastikan library Turnstile ada
if (typeof window.turnstile === 'undefined') {
const script = document.createElement('script');
script.src = "https://challenges.cloudflare.com/turnstile/v0/api.js";
document.body.appendChild(script);
}
// Fungsi Callback
window.cf_solved_token = null; // Reset token
// Tunggu sebentar lalu render
setTimeout(() => {
if (window.turnstile) {
window.turnstile.render('#custom-turnstile-container', {
sitekey: key,
cData: data, // Masukkan cData di sini
action: act, // Masukkan Action di sini
callback: function(token) {
window.cf_solved_token = token;
}
});
}
}, 1000);
}, siteKey, cData, action);
// 3. Polling: Cek apakah token sudah muncul di variabel window.cf_solved_token
const checkToken = setInterval(async () => {
try {
const token = await page.evaluate(() => window.cf_solved_token);
if (token) {
clearInterval(checkToken);
clearTimeout(timeout);
resolve({ token: token });
}
// Cek error box (opsional)
// const error = await page.evaluate(() => document.querySelector('...error...'));
} catch (e) {}
}, 1000);
} catch (e) {
clearTimeout(timeout);
reject(e);
}
});
}
// Endpoint API
app.post('/bypass', async (req, res) => {
// Tambahkan parameter cdata dan action
const { url, mode, siteKey, cdata, action, proxy } = req.body;
if (!url || !mode) return res.status(400).json({ status: "error", message: "Missing url or mode" });
if (mode === 'turnstile' && !siteKey) return res.status(400).json({ status: "error", message: "siteKey required for turnstile" });
// Cek Slot Browser
if (activeBrowsers >= MAX_CONCURRENT_BROWSERS) {
return res.status(429).json({ status: "busy", message: "Server busy, try again later" });
}
activeBrowsers++;
let browserInstance = null;
try {
console.log(`[REQ] Processing: ${url} | Mode: ${mode} | cData: ${cdata ? "YES" : "NO"}`);
const { browser, page } = await createBrowser(proxy);
browserInstance = browser;
let result;
if (mode === 'turnstile') {
// Panggil fungsi handleTurnstile dengan parameter baru
result = await handleTurnstile(page, url, siteKey, cdata, action);
} else {
throw new Error("Invalid mode. Only 'turnstile' supported in this fix.");
}
console.log(`[SUCCESS] Token: ${result.token.substring(0, 15)}...`);
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 cData Solver Ready"));
app.listen(PORT, () => console.log(`Server listening on port ${PORT}`));