File size: 2,989 Bytes
46fb463 60cf846 46fb463 1445d9d 46fb463 1445d9d 46fb463 | 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 | '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);
});
|