001213 / Api.js.bak
Forgets's picture
Rename Api.js to Api.js.bak
e5c984e verified
Raw
History Blame Contribute Delete
6.88 kB
/**
* API.js
*/
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;
global.browserLimit = 100;
global.timeOut = 300000;
// cache
const CACHE_DIR = path.join(__dirname, "cache");
const CACHE_FILE = path.join(CACHE_DIR, "cache.json");
const CACHE_TTL = 5 * 60 * 1000;
const CACHE_AUTOSAVE = process.env.CACHE_AUTOSAVE === "true";
function readCache(type, taskId) {
const file = path.join(CACHE_DIR, type, `${taskId}.json`);
if (!fs.existsSync(file)) return null;
try {
const data = JSON.parse(fs.readFileSync(file, 'utf-8'));
console.log(`cache check: ${type}:${taskId} => ${data ? "HIT" : "MISS"}`);
if (Date.now() - data.timestamp < CACHE_TTL) {
return data;
}
return null;
} catch {
return null;
}
}
function writeCache(type, taskId, value) {
const dir = path.join(CACHE_DIR, type);
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
const file = path.join(dir, `${taskId}.json`);
const data = { timestamp: Date.now(), ...value };
fs.writeFileSync(file, JSON.stringify(data, null, 2), 'utf-8');
console.log(`cache saved: ${type}:${taskId}`);
}
function cleanCache() {
const types = ["turnstile", "recaptcha3", "recaptcha2", "interstitial", "error"];
const now = Date.now();
const TTL = 60 * 60 * 1000;
types.forEach(type => {
const dir = path.join(CACHE_DIR, type);
if (!fs.existsSync(dir)) return;
fs.readdirSync(dir).forEach(file => {
const filePath = path.join(dir, file);
try {
const data = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
if (now - data.timestamp > TTL) {
fs.unlinkSync(filePath);
console.log(`cache expired: ${filePath}`);
}
} catch {
fs.unlinkSync(filePath);
}
});
});
}
setInterval(cleanCache, 600 * 1000);
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
const tasks = {};
// Api_route
app.get("/", (req, res) => {
const baseUrl = `${req.protocol}://${req.get('host')}`;
const uptime = process.uptime();
res.json({
message: "Welcome",
server: {
domain: baseUrl,
version: "7.3.0",
uptime: `${Math.floor(uptime)} seconds`,
limit: global.browserLimit,
timeout: global.timeOut,
status: "recently running"
},
solvers: ["turnstile", "recaptcha2", "recaptcha3", "interstitial"]
});
});
app.post('/solve', async (req, res) => {
const { type, domain, siteKey, taskId, action, proxy, isInvisible } = req.body;
if (taskId) {
const task = tasks[taskId];
if (!task) return res.status(404).json({ status: "error", message: "Task not found" });
if (task.status === "pending") {
return res.json({ status: "processing" });
}
return res.json(task);
}
const newTaskId = Date.now().toString(36);
tasks[newTaskId] = { status: "pending" };
console.log(`New : ${newTaskId}=${type}:${domain}`);
(async () => {
try {
const ctx = await init_browser(proxy?.server);
const page = ctx.page;
let result;
switch (type) {
case "turnstile":
result = await turnstile({ domain, siteKey, action, proxy }, page);
tasks[newTaskId] = { status: "done", ...result };
console.log(`done: ${newTaskId}=${type}:${domain}`);
if (CACHE_AUTOSAVE) writeCache("turnstile", newTaskId, tasks[newTaskId]);
break;
case "interstitial":
result = await interstitial({ domain, proxy }, page);
tasks[newTaskId] = { status: "done", ...result };
console.log(`done: ${newTaskId}=${type}:${domain}`);
if (CACHE_AUTOSAVE) writeCache("interstitial", newTaskId, tasks[newTaskId]);
break;
case "recaptcha2":
result = await recaptchaV2({ domain, siteKey, action, isInvisible, proxy }, page);
tasks[newTaskId] = { status: "done", ...result };
console.log(`done: ${newTaskId}=${type}:${domain}`);
if (CACHE_AUTOSAVE) writeCache("recaptcha2", newTaskId, tasks[newTaskId]);
break;
case "recaptcha3":
result = await recaptchaV3({ domain, siteKey, action, proxy }, page);
tasks[newTaskId] = { status: "done", ...result };
console.log(`done: ${newTaskId}=${type}:${domain}`);
if (CACHE_AUTOSAVE) writeCache("recaptcha3", newTaskId, tasks[newTaskId]);
break;
default:
tasks[newTaskId] = { status: "error", message: "Invalid type" };
}
await ctx.browser.close();
console.log(`Browser closed ${newTaskId}`);
} catch (err) {
tasks[newTaskId] = { status: "error", message: "totally failed" };
console.error(`failed: ${newTaskId}=${type}:${domain}`);
console.error("Detailed error:", err);
}
})();
res.json({ taskId: newTaskId, status: "pending" });
});
// init_browser
async function init_browser(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) => {
const type = req.resourceType();
if (["image", "stylesheet", "font", "media"].includes(type)) req.abort();
else req.continue();
});
console.log(`initialized${proxyServer ? "proxy= " + proxyServer : ""}`);
return { browser, page };
}
const turnstile = require('./Api/turnstile');
const interstitial = require('./Api/interstitial');
const recaptchaV2 = require('./Api/recaptcha2');
const recaptchaV3 = require('./Api/recaptcha3');
app.use((req, res) => {
res.status(404).json({ message: 'Not Found' });
console.warn(`error: ${req.method} ${req.originalUrl}`);
});
app.listen(port, () => {
console.log(`Server running: http://localhost:${port}`);
});