File size: 6,879 Bytes
7de2405 dc53707 7de2405 dc53707 7de2405 dc53707 f334297 dc53707 7b59bef dc53707 f334297 dc53707 f334297 dc53707 f334297 dc53707 f334297 dc53707 f334297 dc53707 7de2405 dc53707 7de2405 dc53707 f334297 dc53707 f334297 7de2405 dc53707 f334297 7de2405 f334297 dc53707 7de2405 dc53707 7de2405 dc53707 f334297 7de2405 f334297 dc53707 f334297 dc53707 7de2405 f334297 dc53707 7de2405 dc53707 f334297 dc53707 7de2405 dc53707 7de2405 dc53707 7de2405 dc53707 7de2405 dc53707 7de2405 dc53707 931d770 dc53707 931d770 dc53707 f334297 931d770 dc53707 884596e 931d770 dc53707 931d770 dc53707 931d770 dc53707 931d770 f334297 884596e dc53707 f334297 884596e dc53707 7b59bef dc53707 | 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 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 | /**
* 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}`);
}); |