cf / app.js
kavion's picture
debug: add screenshot on failure + poll logging + disableXvfb: true
1445d9d unverified
Raw
History Blame Contribute Delete
2.99 kB
'use strict';
const express = require('express');
const TurnstileSolver = require('./turnstile-solver');
const app = express();
const PORT = process.env.PORT || 7860;
app.use(express.json());
// Singleton solver — browser tetap hidup selama server berjalan
const solver = new TurnstileSolver({
timeout: 25000,
record: false,
width: 1280,
height: 720,
});
// Inisialisasi browser saat startup
let ready = false;
(async () => {
try {
await solver.initialize();
ready = true;
console.log('[API] Solver ready.');
} catch (e) {
console.error('[API] Solver init failed:', e.message);
}
})();
/**
* GET /bypass/turnstile-min
* Query params:
* - url : URL target (wajib)
* - siteKey : Sitekey Turnstile (opsional, kalau tidak ada pakai mode page)
* - apikey : API key sederhana untuk proteksi (opsional, cek env API_KEY)
*
* Response (sukses):
* { status: true, token: "...", time: 3.2 }
*
* Response (gagal):
* { status: false, message: "..." }
*/
app.get('/bypass/turnstile-min', async (req, res) => {
// Cek API key kalau dikonfigurasi
const apiKey = process.env.API_KEY;
if (apiKey && req.query.apikey !== apiKey) {
return res.status(401).json({ status: false, message: 'Invalid API key.' });
}
const { url, siteKey } = req.query;
if (!url) {
return res.status(400).json({ status: false, message: 'Parameter "url" wajib diisi.' });
}
if (!ready) {
return res.status(503).json({ status: false, message: 'Solver belum siap, coba lagi sebentar.' });
}
try {
const result = await solver.solve(url, siteKey || null);
if (!result.success) {
return res.status(500).json({
status: false,
message: result.error || 'Gagal mendapatkan token Turnstile.',
time: result.time,
});
}
return res.json({
status: true,
creator: 'XAi Community',
token: result.token,
time: result.time,
});
} catch (e) {
return res.status(500).json({ status: false, message: e.message });
}
});
// Health check
app.get('/', (req, res) => {
res.json({
status: 'ok',
ready,
endpoints: [
'GET /bypass/turnstile-min?url=<URL>&siteKey=<SITEKEY>&apikey=<KEY>',
'GET /debug/screenshot — lihat screenshot terakhir saat solving gagal',
],
});
});
// Debug: lihat screenshot terakhir
const fs = require('fs');
app.get('/debug/screenshot', (req, res) => {
const p = '/tmp/debug_turnstile.png';
if (!fs.existsSync(p)) return res.status(404).json({ error: 'Belum ada screenshot.' });
res.sendFile(p);
});
app.listen(PORT, '0.0.0.0', () => {
console.log(`[API] Server jalan di port ${PORT}`);
});
// Cleanup saat proses mati
process.on('SIGTERM', async () => {
await solver.cleanup();
process.exit(0);
});