| | const express = require('express'); |
| | const { connect } = require("puppeteer-real-browser"); |
| | const fs = require('fs'); |
| | const path = require('path'); |
| |
|
| | const app = express(); |
| | const port = process.env.PORT || 7860; |
| | const authToken = process.env.authToken || null; |
| | const domain = process.env.DOMAIN || `Limit2`; |
| |
|
| | |
| | global.browserLimit = Number(process.env.browserLimit) || 30; |
| | global.timeOut = Number(process.env.timeOut) || 120000; |
| |
|
| | |
| | const CACHE_DIR = path.join(__dirname, "cache"); |
| | const CACHE_FILE = path.join(CACHE_DIR, "cache.json"); |
| | const CACHE_TTL = 5 * 60 * 1000; |
| |
|
| | function loadCache() { |
| | if (!fs.existsSync(CACHE_FILE)) return {}; |
| | try { return JSON.parse(fs.readFileSync(CACHE_FILE, 'utf-8')); } catch { return {}; } |
| | } |
| |
|
| | function saveCache(cache) { |
| | if (!fs.existsSync(CACHE_DIR)) fs.mkdirSync(CACHE_DIR, { recursive: true }); |
| | fs.writeFileSync(CACHE_FILE, JSON.stringify(cache, null, 2), 'utf-8'); |
| | } |
| |
|
| | |
| | app.use(express.json({ limit: "50mb" })); |
| | app.use(express.urlencoded({ extended: true, limit: "50mb" })); |
| |
|
| | |
| | |
| | const solveTurnstile = require('./endpoints/turnstile'); |
| | const solveCloudflare = require('./endpoints/cloudflare'); |
| | const solveAntibot = require('./endpoints/antibot'); |
| |
|
| | |
| | app.get("/", (req, res) => { |
| | res.json({ |
| | message: "Server is running!", |
| | endpoints: { |
| | cloudflare: `${domain}/cloudflare`, |
| | antibot: `${domain}/antibot` |
| | }, |
| | status: { |
| | browserLimit: global.browserLimit, |
| | authRequired: authToken !== null |
| | } |
| | }); |
| | }); |
| |
|
| | |
| | async function createBrowser(proxyServer = null) { |
| | const connectOptions = { |
| | headless: false, |
| | turnstile: true, |
| | connectOption: { defaultViewport: null }, |
| | disableXvfb: false, |
| | }; |
| | if (proxyServer) connectOptions.args = [`--proxy-server=${proxyServer}`]; |
| |
|
| | const { browser } = await connect(connectOptions); |
| | const [page] = await browser.pages(); |
| |
|
| | await page.goto('about:blank'); |
| | await page.setRequestInterception(true); |
| | page.on('request', (req) => { |
| | if (["image", "stylesheet", "font", "media"].includes(req.resourceType())) req.abort(); |
| | else req.continue(); |
| | }); |
| |
|
| | return { browser, page }; |
| | } |
| |
|
| | |
| | app.post("/antibot", async (req, res) => { |
| | const data = req.body; |
| |
|
| | |
| | if (!data || !data.main || !Array.isArray(data.bots)) { |
| | return res.status(400).json({ message: "Body format salah (kudu aya main & bots array)" }); |
| | } |
| |
|
| | try { |
| | console.log("Menerima tantangan Antibot..."); |
| | |
| | const result = await solveAntibot(data); |
| | |
| | |
| | res.json(result); |
| | } catch (err) { |
| | console.error("Error Antibot:", err.message); |
| | res.status(500).json({ message: err.message }); |
| | } |
| | }); |
| |
|
| | |
| | app.post('/cloudflare', async (req, res) => { |
| | const data = req.body; |
| | if (!data || !data.mode) return res.status(400).json({ message: 'Missing mode' }); |
| |
|
| | if (global.browserLimit <= 0) return res.status(429).json({ message: 'Server Busy' }); |
| |
|
| | global.browserLimit--; |
| | let result, browser; |
| |
|
| | try { |
| | const proxyServer = data.proxy ? `${data.proxy.hostname}:${data.proxy.port}` : null; |
| | const ctx = await createBrowser(proxyServer); |
| | browser = ctx.browser; |
| | const page = ctx.page; |
| |
|
| | switch (data.mode) { |
| | case "turnstile": |
| | const token = await solveTurnstile(data, page); |
| | result = { token }; |
| | break; |
| | case "iuam": |
| | result = await solveCloudflare(data, page); |
| | break; |
| | default: |
| | result = { code: 400, message: 'Invalid mode' }; |
| | } |
| | } catch (err) { |
| | result = { code: 500, message: err.message }; |
| | } finally { |
| | if (browser) await browser.close(); |
| | global.browserLimit++; |
| | } |
| |
|
| | res.status(result.code ?? 200).json(result); |
| | }); |
| |
|
| | |
| | const server = app.listen(port, () => { |
| | console.log(`API Server jalan dina port ${port}`); |
| | }); |
| | server.timeout = global.timeOut; |
| |
|