const express = require('express'); const cors = require('cors'); const app = express(); const PORT = process.env.PORT || 7860; const API_BASE = 'http://172.235.245.114:1875'; const THEYKA_BASE = 'http://172.235.245.114:1808'; app.use(cors()); app.use(express.json()); async function submitJob(code) { const response = await fetch(`${API_BASE}/api/s-playwright`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ code, lang: 'python' }) }); if (!response.ok) throw new Error(`API error: ${response.status}`); const result = await response.json(); if (!result.success) throw new Error(result.error || 'Failed to submit job'); return result.job_id; } async function pollJob(jobId, maxWaitTime = 300000) { const start = Date.now(); while (Date.now() - start < maxWaitTime) { const r = await fetch(`${API_BASE}/job/${jobId}`); if (!r.ok) throw new Error(`Status check failed: ${r.status}`); const data = await r.json(); if (!data.success) throw new Error(data.error || 'Status check error'); const job = data.job; if (job.status === 'completed') return job.result; if (job.status === 'failed') throw new Error(job.error || 'Job failed'); await new Promise(resolve => setTimeout(resolve, 1000)); } throw new Error('Timeout'); } async function solveWithTheyka(url, sitekey, action, cdata) { let endpoint = `${THEYKA_BASE}/turnstile?url=${encodeURIComponent(url)}&sitekey=${encodeURIComponent(sitekey)}`; if (action) endpoint += `&action=${encodeURIComponent(action)}`; if (cdata) endpoint += `&cdata=${encodeURIComponent(cdata)}`; const submitRes = await fetch(endpoint); if (!submitRes.ok) throw new Error(`Theyka submit error: ${submitRes.status}`); const submitData = await submitRes.json(); const task_id = submitData.task_id; if (!task_id) throw new Error('Theyka: no task_id returned'); console.log(`[THEYKA] task_id=${task_id}`); const start = Date.now(); while (Date.now() - start < 60000) { await new Promise(resolve => setTimeout(resolve, 2000)); const resultRes = await fetch(`${THEYKA_BASE}/result?id=${task_id}`); if (!resultRes.ok) continue; const raw = await resultRes.text(); let data; try { data = JSON.parse(raw); } catch { if (raw.trim() === 'CAPTCHA_NOT_READY') continue; throw new Error(`Theyka unexpected: ${raw.slice(0, 100)}`); } if (data?.value === 'CAPTCHA_FAIL') throw new Error('Theyka: CAPTCHA_FAIL'); if (data?.value && data.value !== 'CAPTCHA_NOT_READY') { console.log(`[THEYKA] token ok elapsed=${data.elapsed_time}s`); return { token: data.value, elapsed_ms: Math.round((data.elapsed_time || 0) * 1000) }; } } throw new Error('Theyka: timeout'); } app.post('/bycf', async (req, res) => { try { const { url, sitekey, action = null, cdata = null } = req.body; if (!url || !sitekey) { return res.status(400).json({ author: 'Herza', status: 400, data: { error: 'URL and SITEKEY are required' } }); } const t = Date.now(); const isInvisible = sitekey.includes('_') || sitekey.includes('-'); console.log(`[BYCF] url=${url} sitekey=${sitekey} isInvisible=${isInvisible}`); if (isInvisible) { const { token, elapsed_ms } = await solveWithTheyka(url, sitekey, action, cdata); return res.json({ author: 'Herza', status: 200, data: { token, sitekey, url, action, cdata, cookies: {}, elapsed_ms } }); } const esc = (s) => s ? s.replace(/'/g, "\\'") : null; const a = esc(action); const c = esc(cdata); const urlWithSlash = url.endsWith('/') ? url : url + '/'; const actionAttr = a ? ` data-action="${a}"` : ''; const cdataAttr = c ? ` data-cdata="${c}"` : ''; const htmlB64 = Buffer.from(`T