Forgets commited on
Commit
7b59bef
·
verified ·
1 Parent(s): 59ae0dd

Update Api.js

Browse files
Files changed (1) hide show
  1. Api.js +64 -112
Api.js CHANGED
@@ -1,5 +1,6 @@
1
  /**
2
- * API.js
 
3
  */
4
  const express = require('express');
5
  const { connect } = require("puppeteer-real-browser");
@@ -8,198 +9,149 @@ const path = require('path');
8
 
9
  const app = express();
10
  const port = process.env.PORT || 7860;
11
- const authToken = process.env.authToken || null;
12
 
13
  global.browserLimit = 100;
14
  global.timeOut = 300000;
15
 
16
- // cache
 
 
 
17
  const CACHE_DIR = path.join(__dirname, "cache");
18
- const CACHE_FILE = path.join(CACHE_DIR, "cache.json");
19
- const CACHE_TTL = 5 * 60 * 1000;
20
  const CACHE_AUTOSAVE = process.env.CACHE_AUTOSAVE === "true";
 
21
 
22
- function readCache(type, taskId) {
23
- const file = path.join(CACHE_DIR, type, `${taskId}.json`);
24
- if (!fs.existsSync(file)) return null;
25
-
26
- try {
27
- const data = JSON.parse(fs.readFileSync(file, 'utf-8'));
28
- console.log(`cache check: ${type}:${taskId} => ${data ? "HIT" : "MISS"}`);
29
- if (Date.now() - data.timestamp < CACHE_TTL) {
30
- return data;
31
- }
32
- return null;
33
- } catch {
34
- return null;
35
- }
36
- }
37
 
38
  function writeCache(type, taskId, value) {
39
  const dir = path.join(CACHE_DIR, type);
40
  if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
41
-
42
  const file = path.join(dir, `${taskId}.json`);
43
  const data = { timestamp: Date.now(), ...value };
44
-
45
  fs.writeFileSync(file, JSON.stringify(data, null, 2), 'utf-8');
46
- console.log(`cache saved: ${type}:${taskId}`);
47
- }
48
-
49
- function cleanCache() {
50
- const types = ["turnstile", "recaptcha3", "recaptcha2", "interstitial", "error"];
51
- const now = Date.now();
52
- const TTL = 60 * 60 * 1000;
53
-
54
- types.forEach(type => {
55
- const dir = path.join(CACHE_DIR, type);
56
- if (!fs.existsSync(dir)) return;
57
-
58
- fs.readdirSync(dir).forEach(file => {
59
- const filePath = path.join(dir, file);
60
- try {
61
- const data = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
62
- if (now - data.timestamp > TTL) {
63
- fs.unlinkSync(filePath);
64
- console.log(`cache expired: ${filePath}`);
65
- }
66
- } catch {
67
- fs.unlinkSync(filePath);
68
- }
69
- });
70
- });
71
  }
72
 
73
- setInterval(cleanCache, 600 * 1000);
74
-
75
  app.use(express.json());
76
  app.use(express.urlencoded({ extended: true }));
77
  const tasks = {};
78
 
79
- // Api_route
80
  app.get("/", (req, res) => {
81
- const baseUrl = `${req.protocol}://${req.get('host')}`;
82
- const uptime = process.uptime();
83
  res.json({
84
- message: "Welcome",
85
- server: {
86
- domain: baseUrl,
87
- version: "7.3.0",
88
- uptime: `${Math.floor(uptime)} seconds`,
89
- limit: global.browserLimit,
90
- timeout: global.timeOut,
91
- status: "recently running"
92
- },
93
- solvers: ["turnstile", "recaptcha2", "recaptcha3", "interstitial"]
94
  });
95
  });
96
 
97
-
98
  app.post('/solve', async (req, res) => {
99
  const { type, domain, siteKey, taskId, action, proxy, isInvisible } = req.body;
100
 
101
  if (taskId) {
102
  const task = tasks[taskId];
103
  if (!task) return res.status(404).json({ status: "error", message: "Task not found" });
104
-
105
- if (task.status === "pending") {
106
- return res.json({ status: "processing" });
107
- }
108
-
109
- return res.json(task);
110
  }
111
 
112
  const newTaskId = Date.now().toString(36);
113
  tasks[newTaskId] = { status: "pending" };
114
- console.log(`New : ${newTaskId}=${type}:${domain}`);
115
 
116
  (async () => {
 
117
  try {
118
- const ctx = await init_browser(proxy?.server);
 
 
119
  const page = ctx.page;
120
  let result;
121
 
122
  switch (type) {
123
  case "turnstile":
124
  result = await turnstile({ domain, siteKey, action, proxy }, page);
125
- tasks[newTaskId] = { status: "done", ...result };
126
- console.log(`done: ${newTaskId}=${type}:${domain}`);
127
- if (CACHE_AUTOSAVE) writeCache("turnstile", newTaskId, tasks[newTaskId]);
128
- break;
129
-
130
- case "interstitial":
131
- result = await interstitial({ domain, proxy }, page);
132
- tasks[newTaskId] = { status: "done", ...result };
133
- console.log(`done: ${newTaskId}=${type}:${domain}`);
134
- if (CACHE_AUTOSAVE) writeCache("interstitial", newTaskId, tasks[newTaskId]);
135
  break;
136
-
137
  case "recaptcha2":
138
  result = await recaptchaV2({ domain, siteKey, action, isInvisible, proxy }, page);
139
- tasks[newTaskId] = { status: "done", ...result };
140
- console.log(`done: ${newTaskId}=${type}:${domain}`);
141
- if (CACHE_AUTOSAVE) writeCache("recaptcha2", newTaskId, tasks[newTaskId]);
142
  break;
143
-
144
  case "recaptcha3":
145
  result = await recaptchaV3({ domain, siteKey, action, proxy }, page);
146
- tasks[newTaskId] = { status: "done", ...result };
147
- console.log(`done: ${newTaskId}=${type}:${domain}`);
148
- if (CACHE_AUTOSAVE) writeCache("recaptcha3", newTaskId, tasks[newTaskId]);
149
  break;
150
-
 
 
151
  default:
152
- tasks[newTaskId] = { status: "error", message: "Invalid type" };
153
  }
154
 
155
- await ctx.browser.close();
156
- console.log(`Browser closed ${newTaskId}`);
 
 
157
  } catch (err) {
158
- tasks[newTaskId] = { status: "error", message: "totally failed" };
159
- console.error(`failed: ${newTaskId}=${type}:${domain}`);
160
- console.error("Detailed error:", err);
 
161
  }
162
  })();
163
 
164
  res.json({ taskId: newTaskId, status: "pending" });
165
  });
166
 
167
- // init_browser
168
- async function init_browser(proxyServer = null) {
 
 
169
  const connectOptions = {
170
  headless: false,
171
  turnstile: true,
172
- connectOption: { defaultViewport: null },
 
 
 
 
 
 
 
 
 
 
173
  disableXvfb: false,
174
  };
175
- if (proxyServer) connectOptions.args = [`--proxy-server=${proxyServer}`];
 
 
 
 
176
 
177
  const { browser } = await connect(connectOptions);
178
  const [page] = await browser.pages();
179
 
180
- await page.goto('about:blank');
 
 
 
 
 
 
181
  await page.setRequestInterception(true);
182
  page.on('request', (req) => {
183
- const type = req.resourceType();
184
- if (["image", "stylesheet", "font", "media"].includes(type)) req.abort();
185
  else req.continue();
186
  });
187
- console.log(`initialized${proxyServer ? "proxy= " + proxyServer : ""}`);
188
 
 
189
  return { browser, page };
190
  }
191
 
192
-
193
  const turnstile = require('./Api/turnstile');
194
  const interstitial = require('./Api/interstitial');
195
  const recaptchaV2 = require('./Api/recaptcha2');
196
  const recaptchaV3 = require('./Api/recaptcha3');
197
 
198
- app.use((req, res) => {
199
- res.status(404).json({ message: 'Not Found' });
200
- console.warn(`error: ${req.method} ${req.originalUrl}`);
201
- });
202
-
203
  app.listen(port, () => {
204
- console.log(`Server running: http://localhost:${port}`);
205
- });
 
1
  /**
2
+ * API.js - Integrated with Extension & Docker Path
3
+ * Powered by Gemini - Mode: DAN
4
  */
5
  const express = require('express');
6
  const { connect } = require("puppeteer-real-browser");
 
9
 
10
  const app = express();
11
  const port = process.env.PORT || 7860;
 
12
 
13
  global.browserLimit = 100;
14
  global.timeOut = 300000;
15
 
16
+ // Path Ekstensi dari Docker (Absolute Path)
17
+ const EXTENSION_PATH = '/A/extensions/rek';
18
+
19
+ // Cache Configuration
20
  const CACHE_DIR = path.join(__dirname, "cache");
 
 
21
  const CACHE_AUTOSAVE = process.env.CACHE_AUTOSAVE === "true";
22
+ const CACHE_TTL = 5 * 60 * 1000;
23
 
24
+ if (!fs.existsSync(CACHE_DIR)) fs.mkdirSync(CACHE_DIR, { recursive: true });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
 
26
  function writeCache(type, taskId, value) {
27
  const dir = path.join(CACHE_DIR, type);
28
  if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
 
29
  const file = path.join(dir, `${taskId}.json`);
30
  const data = { timestamp: Date.now(), ...value };
 
31
  fs.writeFileSync(file, JSON.stringify(data, null, 2), 'utf-8');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  }
33
 
 
 
34
  app.use(express.json());
35
  app.use(express.urlencoded({ extended: true }));
36
  const tasks = {};
37
 
38
+ // Root Route
39
  app.get("/", (req, res) => {
 
 
40
  res.json({
41
+ message: "Solver API Running",
42
+ version: "7.4.0-Ext",
43
+ extension: fs.existsSync(EXTENSION_PATH) ? "Loaded" : "Not Found",
44
+ uptime: `${Math.floor(process.uptime())}s`
 
 
 
 
 
 
45
  });
46
  });
47
 
 
48
  app.post('/solve', async (req, res) => {
49
  const { type, domain, siteKey, taskId, action, proxy, isInvisible } = req.body;
50
 
51
  if (taskId) {
52
  const task = tasks[taskId];
53
  if (!task) return res.status(404).json({ status: "error", message: "Task not found" });
54
+ return res.json(task.status === "pending" ? { status: "processing" } : task);
 
 
 
 
 
55
  }
56
 
57
  const newTaskId = Date.now().toString(36);
58
  tasks[newTaskId] = { status: "pending" };
59
+ console.log(`[NEW] ${newTaskId} | Type: ${type} | Domain: ${domain}`);
60
 
61
  (async () => {
62
+ let browserInstance;
63
  try {
64
+ // Inisialisasi browser dengan Proxy & Extension data
65
+ const ctx = await init_browser(proxy);
66
+ browserInstance = ctx.browser;
67
  const page = ctx.page;
68
  let result;
69
 
70
  switch (type) {
71
  case "turnstile":
72
  result = await turnstile({ domain, siteKey, action, proxy }, page);
 
 
 
 
 
 
 
 
 
 
73
  break;
 
74
  case "recaptcha2":
75
  result = await recaptchaV2({ domain, siteKey, action, isInvisible, proxy }, page);
 
 
 
76
  break;
 
77
  case "recaptcha3":
78
  result = await recaptchaV3({ domain, siteKey, action, proxy }, page);
 
 
 
79
  break;
80
+ case "interstitial":
81
+ result = await interstitial({ domain, proxy }, page);
82
+ break;
83
  default:
84
+ throw new Error("Invalid type");
85
  }
86
 
87
+ tasks[newTaskId] = { status: "done", ...result };
88
+ if (CACHE_AUTOSAVE) writeCache(type, newTaskId, tasks[newTaskId]);
89
+ console.log(`[DONE] ${newTaskId}`);
90
+
91
  } catch (err) {
92
+ tasks[newTaskId] = { status: "error", message: err.message };
93
+ console.error(`[FAILED] ${newTaskId}:`, err.message);
94
+ } finally {
95
+ if (browserInstance) await browserInstance.close();
96
  }
97
  })();
98
 
99
  res.json({ taskId: newTaskId, status: "pending" });
100
  });
101
 
102
+ /**
103
+ * Optimized init_browser with Extension Support
104
+ */
105
+ async function init_browser(proxyData = null) {
106
  const connectOptions = {
107
  headless: false,
108
  turnstile: true,
109
+ connectOption: {
110
+ defaultViewport: null,
111
+ protocolTimeout: 600000, // Anti-timeout
112
+ args: [
113
+ '--no-sandbox',
114
+ '--disable-setuid-sandbox',
115
+ '--disable-dev-shm-usage',
116
+ `--disable-extensions-except=${EXTENSION_PATH}`,
117
+ `--load-extension=${EXTENSION_PATH}`
118
+ ]
119
+ },
120
  disableXvfb: false,
121
  };
122
+
123
+ // Handle Proxy Server
124
+ if (proxyData && proxyData.server) {
125
+ connectOptions.connectOption.args.push(`--proxy-server=${proxyData.server}`);
126
+ }
127
 
128
  const { browser } = await connect(connectOptions);
129
  const [page] = await browser.pages();
130
 
131
+ // Handle Proxy Authentication (SOCKS5/HTTP)
132
+ if (proxyData && proxyData.auth) {
133
+ const [username, password] = proxyData.auth.split(':');
134
+ await page.authenticate({ username, password });
135
+ }
136
+
137
+ // Intercept: JANGAN blokir stylesheet agar reCAPTCHA tampil sempurna
138
  await page.setRequestInterception(true);
139
  page.on('request', (req) => {
140
+ const resource = req.resourceType();
141
+ if (["image", "font", "media"].includes(resource)) req.abort();
142
  else req.continue();
143
  });
 
144
 
145
+ console.log(`[SYSTEM] Browser ready. Extension: ${fs.existsSync(EXTENSION_PATH)}`);
146
  return { browser, page };
147
  }
148
 
149
+ // Load Modules
150
  const turnstile = require('./Api/turnstile');
151
  const interstitial = require('./Api/interstitial');
152
  const recaptchaV2 = require('./Api/recaptcha2');
153
  const recaptchaV3 = require('./Api/recaptcha3');
154
 
 
 
 
 
 
155
  app.listen(port, () => {
156
+ console.log(`Server running on port ${port}`);
157
+ });