gadisk820 commited on
Commit
56b6d1b
Β·
verified Β·
1 Parent(s): 3b399e8

Upload 22 files

Browse files
.dockerignore ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ __pycache__/
2
+ *.pyc
3
+ *.pyo
4
+ *.pyd
5
+ .Python
6
+ env/
7
+ venv/
8
+ .venv/
9
+ env.bak/
10
+ venv.bak/
11
+ *.log
12
+ logs/
13
+ data/
14
+ *.db
15
+ .DS_Store
16
+ .git/
17
+ .gitignore
18
+ .vscode/
19
+ .idea/
20
+ *.md
21
+ docker-compose.override.yml
.env ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Email configuration
2
+ EMAIL=gi2h27@gmail.com
3
+
4
+ # Faucet configuration
5
+ MAX_CLAIMS=100000
6
+ COOLDOWN_OVERRIDE=5
7
+
8
+ # Proxy settings (jika perlu)
9
+ HTTP_PROXY=
10
+ HTTPS_PROXY=
11
+ NO_PROXY=localhost,127.0.0.1
12
+
13
+ # Solver settings
14
+ SOLVER_URL=https://gi2h-xxx.hf.space
15
+ SOLVER_KEY=00000000000000000000#0000000000000000000#000000000000000000#
Api.js ADDED
@@ -0,0 +1,260 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * API.js β€” FINAL TOTAL
3
+ * Rate limiting + Cloudflare Interstitial + Cache + Task Queue
4
+ */
5
+
6
+ const express = require('express');
7
+ const { connect } = require("puppeteer-real-browser");
8
+ const fs = require('fs');
9
+ const path = require('path');
10
+
11
+ const app = express();
12
+ const port = process.env.PORT || 7860;
13
+
14
+ // ================= CONFIG =================
15
+ global.browserLimit = 100; // Maksimal browser bersamaan
16
+ global.timeOut = 120000; // 2 menit timeout
17
+
18
+ const CACHE_DIR = path.join(__dirname, "cache");
19
+ const CACHE_TTL = 5 * 60 * 1000; // 5 menit
20
+ const MAX_CONCURRENT = global.browserLimit;
21
+
22
+ // ================= QUEUE =================
23
+ const taskQueue = [];
24
+ let activeTasks = 0;
25
+
26
+ function processQueue() {
27
+ if (activeTasks >= MAX_CONCURRENT || taskQueue.length === 0) return;
28
+ const { task, resolve, reject } = taskQueue.shift();
29
+ activeTasks++;
30
+ task()
31
+ .then(result => {
32
+ activeTasks--;
33
+ resolve(result);
34
+ processQueue();
35
+ })
36
+ .catch(error => {
37
+ activeTasks--;
38
+ reject(error);
39
+ processQueue();
40
+ });
41
+ }
42
+
43
+ function addTask(task) {
44
+ return new Promise((resolve, reject) => {
45
+ taskQueue.push({ task, resolve, reject });
46
+ processQueue();
47
+ });
48
+ }
49
+
50
+ // ================= CACHE =================
51
+ function readCache(type, taskId) {
52
+ const file = path.join(CACHE_DIR, type, `${taskId}.json`);
53
+ if (!fs.existsSync(file)) return null;
54
+ try {
55
+ const data = JSON.parse(fs.readFileSync(file, 'utf-8'));
56
+ if (Date.now() - data.timestamp < CACHE_TTL) return data;
57
+ return null;
58
+ } catch { return null; }
59
+ }
60
+
61
+ function writeCache(type, taskId, value) {
62
+ const dir = path.join(CACHE_DIR, type);
63
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
64
+ const file = path.join(dir, `${taskId}.json`);
65
+ const data = { timestamp: Date.now(), ...value };
66
+ fs.writeFileSync(file, JSON.stringify(data, null, 2), 'utf-8');
67
+ console.log(`cache SAVED: ${type}:${taskId}`);
68
+ }
69
+
70
+ // ================= CLEAN CACHE PERIODIC =================
71
+ setInterval(() => {
72
+ const types = ["recaptcha2", "recaptcha3", "turnstile", "interstitial"];
73
+ const now = Date.now();
74
+ types.forEach(type => {
75
+ const dir = path.join(CACHE_DIR, type);
76
+ if (!fs.existsSync(dir)) return;
77
+ fs.readdirSync(dir).forEach(file => {
78
+ const filePath = path.join(dir, file);
79
+ try {
80
+ const data = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
81
+ if (now - data.timestamp > CACHE_TTL) fs.unlinkSync(filePath);
82
+ } catch {}
83
+ });
84
+ });
85
+ }, 600000); // 10 menit
86
+
87
+ // ================= EXPRESS =================
88
+ app.use(express.json());
89
+ app.use(express.urlencoded({ extended: true }));
90
+
91
+ const tasks = {};
92
+
93
+ // Health endpoint
94
+ app.get("/health", (req, res) => {
95
+ res.json({
96
+ status: "healthy",
97
+ activeTasks,
98
+ queueLength: taskQueue.length,
99
+ maxConcurrent: MAX_CONCURRENT,
100
+ memory: process.memoryUsage()
101
+ });
102
+ });
103
+
104
+ // Root endpoint
105
+ app.get("/", (req, res) => {
106
+ res.json({
107
+ message: "CAPTCHA Solver API",
108
+ version: "8.0.0",
109
+ limits: { concurrent: MAX_CONCURRENT, timeout: global.timeOut },
110
+ endpoints: ["/solve", "/health", "/stats"]
111
+ });
112
+ });
113
+
114
+ // ================= SOLVE ENDPOINT =================
115
+ app.post('/solve', async (req, res) => {
116
+ const { type, domain, siteKey, taskId, action, proxy, isInvisible } = req.body;
117
+
118
+ // Polling jika taskId dikirim
119
+ if (taskId) {
120
+ const task = tasks[taskId];
121
+ if (!task) return res.status(404).json({ status: "error", message: "Task not found" });
122
+ if (task.status === "pending") return res.json({ status: "processing", position: taskQueue.length });
123
+ return res.json({ status: task.status, solution: task.solution });
124
+ }
125
+
126
+ // Buat task baru
127
+ const newTaskId = Date.now().toString(36) + Math.random().toString(36).substr(2);
128
+ tasks[newTaskId] = { status: "pending" };
129
+ console.log(`πŸ†• New task: ${newTaskId}=${type}:${domain}`);
130
+
131
+ // Cek cache
132
+ const cached = readCache(type, newTaskId);
133
+ if (cached) {
134
+ tasks[newTaskId] = cached;
135
+ return res.json({ taskId: newTaskId, status: "done", cached: true });
136
+ }
137
+
138
+ try {
139
+ const result = await addTask(async () => {
140
+ console.log(`πŸš€ Processing: ${newTaskId}`);
141
+ const ctx = await init_browser(proxy?.server);
142
+ const page = ctx.page;
143
+
144
+ let solution = {};
145
+ switch (type) {
146
+ case "recaptcha2":
147
+ solution = await recaptchaV2({ domain, siteKey, action, isInvisible, proxy }, page);
148
+ break;
149
+ case "recaptcha3":
150
+ solution = await recaptchaV3({ domain, siteKey, action, proxy }, page);
151
+ break;
152
+ case "turnstile":
153
+ solution = await turnstile({ domain, siteKey, action, proxy }, page);
154
+ break;
155
+ case "interstitial":
156
+ solution = await interstitial({ domain, proxy }, page);
157
+ break;
158
+ default:
159
+ throw new Error("Invalid type");
160
+ }
161
+
162
+ tasks[newTaskId] = { status: "done", solution };
163
+ writeCache(type, newTaskId, tasks[newTaskId]);
164
+
165
+ await ctx.browser.close();
166
+ console.log(`βœ… Completed: ${newTaskId}`);
167
+ return solution;
168
+ });
169
+
170
+ res.json({
171
+ taskId: newTaskId,
172
+ status: "queued",
173
+ position: taskQueue.length,
174
+ estimatedWait: taskQueue.length * 30000
175
+ });
176
+ } catch (error) {
177
+ tasks[newTaskId] = { status: "error", message: error.message };
178
+ console.error(`❌ Failed: ${newTaskId} - ${error.message}`);
179
+ res.status(500).json({ taskId: newTaskId, status: "error", message: error.message });
180
+ }
181
+ });
182
+
183
+ // GET /solve?taskId=xxx β€” polling
184
+ app.get('/solve', (req, res) => {
185
+ const { taskId } = req.query;
186
+ if (!taskId) return res.status(400).json({ error: "Missing taskId" });
187
+ const task = tasks[taskId];
188
+ if (!task) return res.status(404).json({ error: "Task not found" });
189
+ if (task.status === "pending") return res.json({ status: "processing", position: taskQueue.length });
190
+ return res.json({ status: task.status, solution: task.solution });
191
+ });
192
+
193
+ // ================= BROWSER INIT =================
194
+ async function init_browser(proxyServer = null) {
195
+ const connectOptions = {
196
+ headless: false,
197
+ turnstile: true,
198
+ connectOption: {
199
+ defaultViewport: null,
200
+ args: [
201
+ '--no-sandbox',
202
+ '--disable-setuid-sandbox',
203
+ '--disable-dev-shm-usage',
204
+ '--disable-accelerated-2d-canvas',
205
+ '--disable-gpu',
206
+ '--window-size=1024,768'
207
+ ]
208
+ },
209
+ disableXvfb: false,
210
+ };
211
+
212
+ if (proxyServer) connectOptions.connectOption.args.push(`--proxy-server=${proxyServer}`);
213
+
214
+ const { browser } = await connect(connectOptions);
215
+ const [page] = await browser.pages();
216
+
217
+ // Block resources yang tidak perlu
218
+ await page.setRequestInterception(true);
219
+ page.on('request', req => {
220
+ const type = req.resourceType();
221
+ if (["image", "stylesheet", "font", "media"].includes(type)) req.abort();
222
+ else req.continue();
223
+ });
224
+
225
+ console.log(`🌐 Browser initialized${proxyServer ? " with proxy" : ""}`);
226
+ return { browser, page };
227
+ }
228
+
229
+ // ================= LOAD MODULES =================
230
+ const recaptchaV2 = require('./Api/recaptcha2');
231
+ const recaptchaV3 = require('./Api/recaptcha3');
232
+ const turnstile = require('./Api/turnstile');
233
+ const interstitial = require('./interstitial'); // pastikan file ini ada
234
+
235
+ // ================= STATS =================
236
+ app.get('/stats', (req, res) => {
237
+ res.json({
238
+ activeTasks,
239
+ queueLength: taskQueue.length,
240
+ maxConcurrent: MAX_CONCURRENT,
241
+ memory: process.memoryUsage(),
242
+ uptime: process.uptime()
243
+ });
244
+ });
245
+
246
+ // 404 handler
247
+ app.use((req, res) => res.status(404).json({ message: 'Endpoint not found' }));
248
+
249
+ // ================= START =================
250
+ app.listen(port, () => {
251
+ console.log(`
252
+ ==========================================
253
+ πŸš€ CAPTCHA Solver API v8.0.0
254
+ πŸ“ Port: ${port}
255
+ ⚑ Concurrent Limit: ${MAX_CONCURRENT}
256
+ ⏱️ Timeout: ${global.timeOut}ms
257
+ πŸ• Started: ${new Date().toISOString()}
258
+ ==========================================
259
+ `);
260
+ });
Api.zip CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:5b19cb130eeab9bbf96ad0d26c42f440eee3276eb333f9bc7d6f5096c67b6cbe
3
- size 11432
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:5331966618cd017e0e63f09cbd6cc42ba621855423329ea36d0ae9bed45dc2e1
3
+ size 131
Api/.gitattributes ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
Api/Api.js ADDED
@@ -0,0 +1,260 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * API.js β€” FINAL TOTAL
3
+ * Rate limiting + Cloudflare Interstitial + Cache + Task Queue
4
+ */
5
+
6
+ const express = require('express');
7
+ const { connect } = require("puppeteer-real-browser");
8
+ const fs = require('fs');
9
+ const path = require('path');
10
+
11
+ const app = express();
12
+ const port = process.env.PORT || 7860;
13
+
14
+ // ================= CONFIG =================
15
+ global.browserLimit = 100; // Maksimal browser bersamaan
16
+ global.timeOut = 120000; // 2 menit timeout
17
+
18
+ const CACHE_DIR = path.join(__dirname, "cache");
19
+ const CACHE_TTL = 5 * 60 * 1000; // 5 menit
20
+ const MAX_CONCURRENT = global.browserLimit;
21
+
22
+ // ================= QUEUE =================
23
+ const taskQueue = [];
24
+ let activeTasks = 0;
25
+
26
+ function processQueue() {
27
+ if (activeTasks >= MAX_CONCURRENT || taskQueue.length === 0) return;
28
+ const { task, resolve, reject } = taskQueue.shift();
29
+ activeTasks++;
30
+ task()
31
+ .then(result => {
32
+ activeTasks--;
33
+ resolve(result);
34
+ processQueue();
35
+ })
36
+ .catch(error => {
37
+ activeTasks--;
38
+ reject(error);
39
+ processQueue();
40
+ });
41
+ }
42
+
43
+ function addTask(task) {
44
+ return new Promise((resolve, reject) => {
45
+ taskQueue.push({ task, resolve, reject });
46
+ processQueue();
47
+ });
48
+ }
49
+
50
+ // ================= CACHE =================
51
+ function readCache(type, taskId) {
52
+ const file = path.join(CACHE_DIR, type, `${taskId}.json`);
53
+ if (!fs.existsSync(file)) return null;
54
+ try {
55
+ const data = JSON.parse(fs.readFileSync(file, 'utf-8'));
56
+ if (Date.now() - data.timestamp < CACHE_TTL) return data;
57
+ return null;
58
+ } catch { return null; }
59
+ }
60
+
61
+ function writeCache(type, taskId, value) {
62
+ const dir = path.join(CACHE_DIR, type);
63
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
64
+ const file = path.join(dir, `${taskId}.json`);
65
+ const data = { timestamp: Date.now(), ...value };
66
+ fs.writeFileSync(file, JSON.stringify(data, null, 2), 'utf-8');
67
+ console.log(`cache SAVED: ${type}:${taskId}`);
68
+ }
69
+
70
+ // ================= CLEAN CACHE PERIODIC =================
71
+ setInterval(() => {
72
+ const types = ["recaptcha2", "recaptcha3", "turnstile", "interstitial"];
73
+ const now = Date.now();
74
+ types.forEach(type => {
75
+ const dir = path.join(CACHE_DIR, type);
76
+ if (!fs.existsSync(dir)) return;
77
+ fs.readdirSync(dir).forEach(file => {
78
+ const filePath = path.join(dir, file);
79
+ try {
80
+ const data = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
81
+ if (now - data.timestamp > CACHE_TTL) fs.unlinkSync(filePath);
82
+ } catch {}
83
+ });
84
+ });
85
+ }, 600000); // 10 menit
86
+
87
+ // ================= EXPRESS =================
88
+ app.use(express.json());
89
+ app.use(express.urlencoded({ extended: true }));
90
+
91
+ const tasks = {};
92
+
93
+ // Health endpoint
94
+ app.get("/health", (req, res) => {
95
+ res.json({
96
+ status: "healthy",
97
+ activeTasks,
98
+ queueLength: taskQueue.length,
99
+ maxConcurrent: MAX_CONCURRENT,
100
+ memory: process.memoryUsage()
101
+ });
102
+ });
103
+
104
+ // Root endpoint
105
+ app.get("/", (req, res) => {
106
+ res.json({
107
+ message: "CAPTCHA Solver API",
108
+ version: "8.0.0",
109
+ limits: { concurrent: MAX_CONCURRENT, timeout: global.timeOut },
110
+ endpoints: ["/solve", "/health", "/stats"]
111
+ });
112
+ });
113
+
114
+ // ================= SOLVE ENDPOINT =================
115
+ app.post('/solve', async (req, res) => {
116
+ const { type, domain, siteKey, taskId, action, proxy, isInvisible } = req.body;
117
+
118
+ // Polling jika taskId dikirim
119
+ if (taskId) {
120
+ const task = tasks[taskId];
121
+ if (!task) return res.status(404).json({ status: "error", message: "Task not found" });
122
+ if (task.status === "pending") return res.json({ status: "processing", position: taskQueue.length });
123
+ return res.json({ status: task.status, solution: task.solution });
124
+ }
125
+
126
+ // Buat task baru
127
+ const newTaskId = Date.now().toString(36) + Math.random().toString(36).substr(2);
128
+ tasks[newTaskId] = { status: "pending" };
129
+ console.log(`πŸ†• New task: ${newTaskId}=${type}:${domain}`);
130
+
131
+ // Cek cache
132
+ const cached = readCache(type, newTaskId);
133
+ if (cached) {
134
+ tasks[newTaskId] = cached;
135
+ return res.json({ taskId: newTaskId, status: "done", cached: true });
136
+ }
137
+
138
+ try {
139
+ const result = await addTask(async () => {
140
+ console.log(`πŸš€ Processing: ${newTaskId}`);
141
+ const ctx = await init_browser(proxy?.server);
142
+ const page = ctx.page;
143
+
144
+ let solution = {};
145
+ switch (type) {
146
+ case "recaptcha2":
147
+ solution = await recaptchaV2({ domain, siteKey, action, isInvisible, proxy }, page);
148
+ break;
149
+ case "recaptcha3":
150
+ solution = await recaptchaV3({ domain, siteKey, action, proxy }, page);
151
+ break;
152
+ case "turnstile":
153
+ solution = await turnstile({ domain, siteKey, action, proxy }, page);
154
+ break;
155
+ case "interstitial":
156
+ solution = await interstitial({ domain, proxy }, page);
157
+ break;
158
+ default:
159
+ throw new Error("Invalid type");
160
+ }
161
+
162
+ tasks[newTaskId] = { status: "done", solution };
163
+ writeCache(type, newTaskId, tasks[newTaskId]);
164
+
165
+ await ctx.browser.close();
166
+ console.log(`βœ… Completed: ${newTaskId}`);
167
+ return solution;
168
+ });
169
+
170
+ res.json({
171
+ taskId: newTaskId,
172
+ status: "queued",
173
+ position: taskQueue.length,
174
+ estimatedWait: taskQueue.length * 30000
175
+ });
176
+ } catch (error) {
177
+ tasks[newTaskId] = { status: "error", message: error.message };
178
+ console.error(`❌ Failed: ${newTaskId} - ${error.message}`);
179
+ res.status(500).json({ taskId: newTaskId, status: "error", message: error.message });
180
+ }
181
+ });
182
+
183
+ // GET /solve?taskId=xxx β€” polling
184
+ app.get('/solve', (req, res) => {
185
+ const { taskId } = req.query;
186
+ if (!taskId) return res.status(400).json({ error: "Missing taskId" });
187
+ const task = tasks[taskId];
188
+ if (!task) return res.status(404).json({ error: "Task not found" });
189
+ if (task.status === "pending") return res.json({ status: "processing", position: taskQueue.length });
190
+ return res.json({ status: task.status, solution: task.solution });
191
+ });
192
+
193
+ // ================= BROWSER INIT =================
194
+ async function init_browser(proxyServer = null) {
195
+ const connectOptions = {
196
+ headless: false,
197
+ turnstile: true,
198
+ connectOption: {
199
+ defaultViewport: null,
200
+ args: [
201
+ '--no-sandbox',
202
+ '--disable-setuid-sandbox',
203
+ '--disable-dev-shm-usage',
204
+ '--disable-accelerated-2d-canvas',
205
+ '--disable-gpu',
206
+ '--window-size=1024,768'
207
+ ]
208
+ },
209
+ disableXvfb: false,
210
+ };
211
+
212
+ if (proxyServer) connectOptions.connectOption.args.push(`--proxy-server=${proxyServer}`);
213
+
214
+ const { browser } = await connect(connectOptions);
215
+ const [page] = await browser.pages();
216
+
217
+ // Block resources yang tidak perlu
218
+ await page.setRequestInterception(true);
219
+ page.on('request', req => {
220
+ const type = req.resourceType();
221
+ if (["image", "stylesheet", "font", "media"].includes(type)) req.abort();
222
+ else req.continue();
223
+ });
224
+
225
+ console.log(`🌐 Browser initialized${proxyServer ? " with proxy" : ""}`);
226
+ return { browser, page };
227
+ }
228
+
229
+ // ================= LOAD MODULES =================
230
+ const recaptchaV2 = require('./Api/recaptcha2');
231
+ const recaptchaV3 = require('./Api/recaptcha3');
232
+ const turnstile = require('./Api/turnstile');
233
+ const interstitial = require('./interstitial'); // pastikan file ini ada
234
+
235
+ // ================= STATS =================
236
+ app.get('/stats', (req, res) => {
237
+ res.json({
238
+ activeTasks,
239
+ queueLength: taskQueue.length,
240
+ maxConcurrent: MAX_CONCURRENT,
241
+ memory: process.memoryUsage(),
242
+ uptime: process.uptime()
243
+ });
244
+ });
245
+
246
+ // 404 handler
247
+ app.use((req, res) => res.status(404).json({ message: 'Endpoint not found' }));
248
+
249
+ // ================= START =================
250
+ app.listen(port, () => {
251
+ console.log(`
252
+ ==========================================
253
+ πŸš€ CAPTCHA Solver API v8.0.0
254
+ πŸ“ Port: ${port}
255
+ ⚑ Concurrent Limit: ${MAX_CONCURRENT}
256
+ ⏱️ Timeout: ${global.timeOut}ms
257
+ πŸ• Started: ${new Date().toISOString()}
258
+ ==========================================
259
+ `);
260
+ });
Api/Api/Api.md ADDED
@@ -0,0 +1 @@
 
 
1
+ Api
Api/Api/interstitial.js ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * INTERSTITIAL
3
+ */
4
+ async function interstitial({ domain, proxy }, page) {
5
+ return new Promise(async (resolve, reject) => {
6
+ if (!domain) return reject(new Error("Missing domain parameter"));
7
+
8
+ const startTime = Date.now();
9
+ let isResolved = false;
10
+ let userAgent = null;
11
+
12
+ const cl = setTimeout(() => {
13
+ if (!isResolved) {
14
+ isResolved = true;
15
+ resolve({
16
+ cf_clearance: null,
17
+ cookies: null,
18
+ user_agent: userAgent,
19
+ type: 'interstitial'
20
+ });
21
+ }
22
+ }, 20000);
23
+
24
+ try {
25
+ if (proxy?.username && proxy?.password) {
26
+ await page.authenticate({
27
+ username: proxy.username,
28
+ password: proxy.password,
29
+ });
30
+ }
31
+
32
+ page.removeAllListeners("request");
33
+ page.removeAllListeners("response");
34
+ await page.setRequestInterception(true);
35
+
36
+ page.on("request", async (req) => {
37
+ try {
38
+ await req.continue();
39
+ } catch (_) {}
40
+ });
41
+
42
+ page.on("response", async (res) => {
43
+ try {
44
+ const url = res.url();
45
+ if (url.includes("/cdn-cgi/challenge-platform/")) {
46
+ const headers = res.headers();
47
+ if (headers["set-cookie"]) {
48
+ const cookies = headers["set-cookie"];
49
+ const match = cookies.match(/cf_clearance=([^;]+)/);
50
+ if (match) {
51
+ const cf_clearance = match[1];
52
+ const userAgent = (await res.request().headers())["user-agent"];
53
+
54
+ if (!isResolved) {
55
+ isResolved = true;
56
+ clearTimeout(cl);
57
+ resolve({
58
+ cf_clearance,
59
+ cookies, // seluruh cookie string
60
+ user_agent: userAgent,
61
+ type: 'interstitial'
62
+ });
63
+ }
64
+ }
65
+ }
66
+ }
67
+ } catch (_) {}
68
+ });
69
+
70
+ await page.goto(domain, { waitUntil: "domcontentloaded" });
71
+ userAgent = await page.evaluate(() => navigator.userAgent);
72
+ } catch (err) {
73
+ if (!isResolved) {
74
+ isResolved = true;
75
+ clearTimeout(cl);
76
+ reject(err);
77
+ }
78
+ }
79
+ });
80
+ }
81
+
82
+ module.exports = interstitial;
Api/Api/recaptcha2.js ADDED
@@ -0,0 +1,228 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * API_RECAPTCHA2
3
+ */
4
+ async function recaptchaV2({ domain, siteKey, action = "submit", isInvisible = false, proxy }, page) {
5
+ if (!domain) throw new Error("Missing domain parameter");
6
+ if (!siteKey) throw new Error("Missing siteKey parameter");
7
+
8
+ const timeout = global.timeOut;
9
+
10
+ return new Promise(async (resolve, reject) => {
11
+ let isResolved = false;
12
+
13
+ const cl = setTimeout(() => {
14
+ if (!isResolved) {
15
+ isResolved = true;
16
+ reject(new Error("Timeout Error"));
17
+ }
18
+ }, timeout);
19
+
20
+ try {
21
+ if (proxy?.username && proxy?.password) {
22
+ await page.authenticate({
23
+ username: proxy.username,
24
+ password: proxy.password,
25
+ });
26
+ }
27
+
28
+ const htmlContent = `
29
+ <!DOCTYPE html>
30
+ <html lang="en">
31
+ <head>
32
+ <meta charset="UTF-8">
33
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
34
+ <title>reCAPTCHA v2 Solver</title>
35
+ <style>
36
+ body {
37
+ font-family: Arial, sans-serif;
38
+ margin: 0;
39
+ padding: 20px;
40
+ background: #f5f5f5;
41
+ display: flex;
42
+ justify-content: center;
43
+ align-items: center;
44
+ min-height: 100vh;
45
+ }
46
+ .container {
47
+ background: white;
48
+ padding: 30px;
49
+ border-radius: 10px;
50
+ box-shadow: 0 2px 10px rgba(0,0,0,0.1);
51
+ text-align: center;
52
+ }
53
+ .status {
54
+ margin-top: 20px;
55
+ padding: 10px;
56
+ border-radius: 5px;
57
+ background: #f8f9fa;
58
+ }
59
+ button {
60
+ background: #007bff;
61
+ color: white;
62
+ border: none;
63
+ padding: 10px 20px;
64
+ border-radius: 5px;
65
+ cursor: pointer;
66
+ margin: 10px;
67
+ }
68
+ button:hover { background: #0056b3; }
69
+ </style>
70
+ </head>
71
+ <body>
72
+ <div class="container">
73
+ <h2>reCAPTCHA v2 Solver</h2>
74
+ <p>SiteKey: ${siteKey}</p>
75
+ <div id="recaptcha-container">
76
+ <div class="g-recaptcha"
77
+ data-sitekey="${siteKey}"
78
+ data-callback="recaptchaCallback"
79
+ data-expired-callback="recaptchaExpired"
80
+ data-error-callback="recaptchaError"
81
+ data-size="${isInvisible ? 'invisible' : 'normal'}"
82
+ data-theme="light"></div>
83
+ </div>
84
+ ${isInvisible ? '<button onclick="executeInvisible()">Execute reCAPTCHA</button>' : ''}
85
+ <button onclick="checkToken()">Check Token</button>
86
+ <div class="status" id="status">Waiting for reCAPTCHA...</div>
87
+ </div>
88
+
89
+ <script>
90
+ window.recaptchaToken = null;
91
+ window.recaptchaSolved = false;
92
+
93
+ window.recaptchaCallback = function(token) {
94
+ console.log('reCAPTCHA token received:', token);
95
+ window.recaptchaToken = token;
96
+ window.recaptchaSolved = true;
97
+
98
+ document.getElementById('status').innerHTML =
99
+ 'βœ… reCAPTCHA Solved! Token: ' + token.substring(0, 20) + '...';
100
+ document.getElementById('status').style.background = '#d4edda';
101
+ document.getElementById('status').style.color = '#155724';
102
+
103
+ var input = document.createElement('input');
104
+ input.type = 'hidden';
105
+ input.name = 'g-recaptcha-response';
106
+ input.value = token;
107
+ input.id = 'recaptcha-token-input';
108
+ document.body.appendChild(input);
109
+
110
+ localStorage.setItem('recaptcha_token', token);
111
+ };
112
+
113
+ window.recaptchaExpired = function() {
114
+ console.log('reCAPTCHA expired');
115
+ window.recaptchaToken = null;
116
+ window.recaptchaSolved = false;
117
+ document.getElementById('status').innerHTML = '❌ reCAPTCHA Expired - Refreshing...';
118
+ document.getElementById('status').style.background = '#fff3cd';
119
+ document.getElementById('status').style.color = '#856404';
120
+
121
+ var existing = document.getElementById('recaptcha-token-input');
122
+ if (existing) existing.remove();
123
+
124
+ setTimeout(() => { if (window.grecaptcha) grecaptcha.reset(); }, 1000);
125
+ };
126
+
127
+ window.recaptchaError = function() {
128
+ console.log('reCAPTCHA error');
129
+ document.getElementById('status').innerHTML = '❌ reCAPTCHA Error';
130
+ document.getElementById('status').style.background = '#f8d7da';
131
+ document.getElementById('status').style.color = '#721c24';
132
+ };
133
+
134
+ window.executeInvisible = function() {
135
+ if (window.grecaptcha) grecaptcha.execute();
136
+ };
137
+
138
+ window.checkToken = function() {
139
+ const token = window.recaptchaToken ||
140
+ document.getElementById('recaptcha-token-input')?.value;
141
+ document.getElementById('status').innerHTML = token
142
+ ? 'Token: ' + token
143
+ : 'No token yet';
144
+ };
145
+
146
+ window.onload = function() {
147
+ setTimeout(function() {
148
+ if (${isInvisible} && window.grecaptcha) {
149
+ grecaptcha.execute();
150
+ }
151
+ if (!${isInvisible}) {
152
+ var iframe = document.querySelector('iframe[src*="recaptcha"]');
153
+ if (iframe) {
154
+ console.log('Attempting to interact with reCAPTCHA');
155
+ var rect = iframe.getBoundingClientRect();
156
+ var clickEvent = new MouseEvent('click', {
157
+ view: window, bubbles: true, cancelable: true,
158
+ clientX: rect.left + rect.width / 2,
159
+ clientY: rect.top + rect.height / 2
160
+ });
161
+ iframe.dispatchEvent(clickEvent);
162
+ }
163
+ }
164
+ }, 2000);
165
+ };
166
+ </script>
167
+
168
+ <script src="https://www.google.com/recaptcha/api.js" async defer></script>
169
+ </body>
170
+ </html>
171
+ `;
172
+
173
+ await page.setRequestInterception(true);
174
+ page.removeAllListeners("request");
175
+ page.on("request", async (req) => {
176
+ const url = req.url();
177
+ if ([domain, domain + "/"].includes(url) && req.resourceType() === "document") {
178
+ await req.respond({ status: 200, contentType: "text/html", body: htmlContent });
179
+ } else if (["image", "stylesheet", "font"].includes(req.resourceType())) {
180
+ await req.abort();
181
+ } else {
182
+ await req.continue();
183
+ }
184
+ });
185
+
186
+ await page.goto(domain, { waitUntil: "domcontentloaded", timeout });
187
+ await page.waitForSelector('.g-recaptcha', { timeout: 10000 });
188
+
189
+ const tokenHandle = await page.waitForFunction(() => {
190
+ const input = document.querySelector('#recaptcha-token-input');
191
+ if (input?.value?.length > 10) return input.value;
192
+ const stored = localStorage.getItem('recaptcha_token');
193
+ if (stored?.length > 10) return stored;
194
+ if (window.recaptchaToken?.length > 10) return window.recaptchaToken;
195
+ return null;
196
+ }, { timeout, polling: 100 });
197
+
198
+ const tokenValue = await tokenHandle.jsonValue();
199
+
200
+ isResolved = true;
201
+ clearTimeout(cl);
202
+
203
+ if (!tokenValue || tokenValue.length < 10) {
204
+ reject(new Error("Failed to get valid reCAPTCHA token"));
205
+ } else {
206
+ resolve({ token: tokenValue, type: 'recaptcha_v2' });
207
+ }
208
+ } catch (error) {
209
+ if (!isResolved) {
210
+ isResolved = true;
211
+ clearTimeout(cl);
212
+ try {
213
+ const fallbackToken = await page.evaluate(() => {
214
+ const input = document.querySelector('#recaptcha-token-input');
215
+ return input ? input.value : null;
216
+ });
217
+ if (fallbackToken?.length > 10) {
218
+ resolve({ token: fallbackToken, type: 'recaptcha_v2' });
219
+ return;
220
+ }
221
+ } catch {}
222
+ reject(new Error(`reCAPTCHA solving failed: ${error.message}`));
223
+ }
224
+ }
225
+ });
226
+ }
227
+
228
+ module.exports = recaptchaV2;
Api/Api/recaptcha3.js ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * recaptcha3.js
3
+ */
4
+ async function recaptchaV3({ domain, siteKey, action, proxy }, page) {
5
+ if (!domain) throw new Error("Missing domain parameter");
6
+ if (!siteKey) throw new Error("Missing siteKey parameter");
7
+
8
+ const timeout = 120000;
9
+
10
+ return new Promise(async (resolve, reject) => {
11
+ let isResolved = false;
12
+
13
+ const cl = setTimeout(() => {
14
+ if (!isResolved) {
15
+ isResolved = true;
16
+ reject(new Error("Timeout Error"));
17
+ }
18
+ }, timeout);
19
+
20
+ try {
21
+ if (proxy?.username && proxy?.password) {
22
+ await page.authenticate({
23
+ username: proxy.username,
24
+ password: proxy.password,
25
+ });
26
+ }
27
+
28
+ await page.goto(domain, { waitUntil: "domcontentloaded" });
29
+
30
+ await page.addScriptTag({ url: "https://www.google.com/recaptcha/api.js?render=" + siteKey });
31
+
32
+ const token = await page.evaluate(async (siteKey, action) => {
33
+ return await grecaptcha.execute(siteKey, { action: action || "login" });
34
+ }, siteKey, action);
35
+
36
+ isResolved = true;
37
+ clearTimeout(cl);
38
+
39
+ if (!token || token.length < 10) {
40
+ reject(new Error("Failed to get token"));
41
+ } else {
42
+ resolve({ token: token, type: "recaptcha3" });
43
+ }
44
+ } catch (e) {
45
+ if (!isResolved) {
46
+ isResolved = true;
47
+ clearTimeout(cl);
48
+ reject(e);
49
+ }
50
+ }
51
+ });
52
+ }
53
+
54
+ module.exports = recaptchaV3;
Api/Api/turnstile.js ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * API_TURNSTILE
3
+ */
4
+ async function turnstile({ domain, siteKey, action, proxy }, page) {
5
+ if (!domain) throw new Error("Missing domain parameter");
6
+ if (!siteKey) throw new Error("Missing siteKey parameter");
7
+
8
+ const timeout = global.timeOut;
9
+
10
+ return new Promise(async (resolve, reject) => {
11
+ let isResolved = false;
12
+
13
+ const cl = setTimeout(() => {
14
+ if (!isResolved) {
15
+ isResolved = true;
16
+ reject(new Error("Timeout Error"));
17
+ }
18
+ }, timeout);
19
+
20
+ try {
21
+ if (proxy?.username && proxy?.password) {
22
+ await page.authenticate({
23
+ username: proxy.username,
24
+ password: proxy.password,
25
+ });
26
+ }
27
+
28
+ const htmlContent = `
29
+ <!DOCTYPE html>
30
+ <html lang="en">
31
+ <body>
32
+ <div class="turnstile"></div>
33
+ <script src="https://challenges.cloudflare.com/turnstile/v0/api.js?onload=onloadTurnstileCallback" defer></script>
34
+ <script>
35
+ window.onloadTurnstileCallback = function () {
36
+ turnstile.render('.turnstile', {
37
+ sitekey: '${siteKey}',
38
+ action: '${action || ""}',
39
+ callback: function (token) {
40
+ var c = document.createElement('input');
41
+ c.type = 'hidden';
42
+ c.name = 'cf-response';
43
+ c.value = token;
44
+ document.body.appendChild(c);
45
+ },
46
+ });
47
+ };
48
+ </script>
49
+ </body>
50
+ </html>
51
+ `;
52
+
53
+ await page.setRequestInterception(true);
54
+ page.removeAllListeners("request");
55
+ page.on("request", async (request) => {
56
+ if ([domain, domain + "/"].includes(request.url()) && request.resourceType() === "document") {
57
+ await request.respond({
58
+ status: 200,
59
+ contentType: "text/html",
60
+ body: htmlContent,
61
+ });
62
+ } else {
63
+ await request.continue();
64
+ }
65
+ });
66
+
67
+ await page.goto(domain, { waitUntil: "domcontentloaded" });
68
+ await page.waitForSelector('[name="cf-response"]', { timeout });
69
+
70
+ const token = await page.evaluate(() => {
71
+ return document.querySelector('[name="cf-response"]').value;
72
+ });
73
+
74
+ isResolved = true;
75
+ clearTimeout(cl);
76
+
77
+ if (!token || token.length < 10) {
78
+ reject(new Error("Failed to get token"));
79
+ } else {
80
+ resolve({ token: token, type: 'turnstile' });
81
+ }
82
+ } catch (e) {
83
+ if (!isResolved) {
84
+ isResolved = true;
85
+ clearTimeout(cl);
86
+ reject(e);
87
+ }
88
+ }
89
+ });
90
+ }
91
+
92
+ module.exports = turnstile;
Api/Dockerfile ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM node:20-slim
2
+
3
+ RUN apt update && apt install -y \
4
+ wget gnupg ca-certificates xvfb \
5
+ fonts-liberation libappindicator3-1 libasound2 libatk-bridge2.0-0 \
6
+ libatk1.0-0 libxss1 libnss3 libxcomposite1 libxdamage1 libxrandr2 libgbm1 \
7
+ && wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb \
8
+ && apt install -y ./google-chrome-stable_current_amd64.deb \
9
+ && rm google-chrome-stable_current_amd64.deb
10
+
11
+ WORKDIR /A
12
+
13
+ RUN mkdir -p /A/Api && mkdir -p /A/cache
14
+
15
+ COPY package.json ./
16
+ RUN npm install
17
+
18
+ COPY . .
19
+
20
+ EXPOSE 7860
21
+
22
+ CMD rm -f /tmp/.X99-lock && \
23
+ Xvfb :99 -screen 0 1024x768x24 & \
24
+ export DISPLAY=:99 && \
25
+ npm start
Api/README.md ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Api
3
+ emoji: πŸ¦€
4
+ colorFrom: blue
5
+ colorTo: yellow
6
+ sdk: docker
7
+ pinned: false
8
+ license: mit
9
+ short_description: Api
10
+ ---
11
+
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
Api/interstitial.js ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * INTERSTITIAL
3
+ */
4
+ async function interstitial({ domain, proxy }, page) {
5
+ return new Promise(async (resolve, reject) => {
6
+ if (!domain) return reject(new Error("Missing domain parameter"));
7
+
8
+ const startTime = Date.now();
9
+ let isResolved = false;
10
+ let userAgent = null;
11
+
12
+ const cl = setTimeout(() => {
13
+ if (!isResolved) {
14
+ isResolved = true;
15
+ resolve({
16
+ cf_clearance: null,
17
+ cookies: null,
18
+ user_agent: userAgent,
19
+ type: 'interstitial'
20
+ });
21
+ }
22
+ }, 20000);
23
+
24
+ try {
25
+ if (proxy?.username && proxy?.password) {
26
+ await page.authenticate({
27
+ username: proxy.username,
28
+ password: proxy.password,
29
+ });
30
+ }
31
+
32
+ page.removeAllListeners("request");
33
+ page.removeAllListeners("response");
34
+ await page.setRequestInterception(true);
35
+
36
+ page.on("request", async (req) => {
37
+ try {
38
+ await req.continue();
39
+ } catch (_) {}
40
+ });
41
+
42
+ page.on("response", async (res) => {
43
+ try {
44
+ const url = res.url();
45
+ if (url.includes("/cdn-cgi/challenge-platform/")) {
46
+ const headers = res.headers();
47
+ if (headers["set-cookie"]) {
48
+ const cookies = headers["set-cookie"];
49
+ const match = cookies.match(/cf_clearance=([^;]+)/);
50
+ if (match) {
51
+ const cf_clearance = match[1];
52
+ const userAgent = (await res.request().headers())["user-agent"];
53
+
54
+ if (!isResolved) {
55
+ isResolved = true;
56
+ clearTimeout(cl);
57
+ resolve({
58
+ cf_clearance,
59
+ cookies, // seluruh cookie string
60
+ user_agent: userAgent,
61
+ type: 'interstitial'
62
+ });
63
+ }
64
+ }
65
+ }
66
+ }
67
+ } catch (_) {}
68
+ });
69
+
70
+ await page.goto(domain, { waitUntil: "domcontentloaded" });
71
+ userAgent = await page.evaluate(() => navigator.userAgent);
72
+ } catch (err) {
73
+ if (!isResolved) {
74
+ isResolved = true;
75
+ clearTimeout(cl);
76
+ reject(err);
77
+ }
78
+ }
79
+ });
80
+ }
81
+
82
+ module.exports = interstitial;
Api/package.json ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "api",
3
+ "version": "7.3.0",
4
+ "description": "gmxch_Api",
5
+ "scripts": {
6
+ "start": "node Api.js",
7
+ "dev": "nodemon Api.js"
8
+ },
9
+ "dependencies": {
10
+ "express": "^5.1.0",
11
+ "puppeteer-real-browser": "^1.4.0"
12
+ },
13
+ "devDependencies": {
14
+ "nodemon": "^3.1.10"
15
+ },
16
+ "license": "MIT"
17
+ }
Api/supervisord.conf ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [supervisord]
2
+ nodaemon=true
3
+ logfile=/var/log/supervisor/supervisord.log
4
+ pidfile=/var/run/supervisord.pid
5
+ childlogdir=/var/log/supervisor
6
+
7
+ [program:xvfb]
8
+ command=Xvfb :99 -screen 0 1024x768x24 -ac +extension GLX +render -noreset
9
+ autostart=true
10
+ autorestart=true
11
+ priority=100
12
+ stdout_logfile=/var/log/supervisor/xvfb.log
13
+ stderr_logfile=/var/log/supervisor/xvfb.err
14
+
15
+ [program:api]
16
+ command=npm start
17
+ directory=/app/api
18
+ environment=DISPLAY=":99",NODE_ENV="production"
19
+ autostart=true
20
+ autorestart=true
21
+ priority=200
22
+ stdout_logfile=/var/log/supervisor/api.log
23
+ stderr_logfile=/var/log/supervisor/api.err
24
+ startretries=3
25
+
26
+ [program:bot]
27
+ command=gunicorn --bind 0.0.0.0:7861 --workers 1 --threads 2 --timeout 120 app:app
28
+ directory=/app/bot
29
+ environment=DISPLAY=":99",PYTHONUNBUFFERED="1"
30
+ autostart=true
31
+ autorestart=true
32
+ priority=300
33
+ stdout_logfile=/var/log/supervisor/bot.log
34
+ stderr_logfile=/var/log/supervisor/bot.err
35
+
36
+ [program:nginx]
37
+ command=nginx -g 'daemon off;'
38
+ autostart=true
39
+ autorestart=true
40
+ priority=400
41
+ stdout_logfile=/var/log/supervisor/nginx.log
42
+ stderr_logfile=/var/log/supervisor/nginx.err
Dockerfile CHANGED
@@ -1,33 +1,109 @@
1
- FROM node:20-slim
 
 
 
2
 
3
- # Install dependencies, Chrome, xvfb, unzip
4
- RUN apt update && apt install -y \
5
- wget gnupg ca-certificates xvfb unzip \
6
- fonts-liberation libappindicator3-1 libasound2 libatk-bridge2.0-0 \
7
- libatk1.0-0 libxss1 libnss3 libxcomposite1 libxdamage1 libxrandr2 libgbm1 \
8
- && wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb \
9
- && apt install -y ./google-chrome-stable_current_amd64.deb \
10
- && rm google-chrome-stable_current_amd64.deb \
11
- && ln -s /usr/bin/google-chrome /usr/bin/chrome
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
 
13
- WORKDIR /A
 
 
 
 
 
 
 
 
 
 
14
 
15
- # Folder kerja
16
- RUN mkdir -p /A/Api /A/cache
17
 
18
- # Copy zip dari repo
19
- COPY Api.zip /A/Api.zip
 
 
 
 
20
 
21
- # Extract Api.zip β†’ /A/Api
22
- RUN unzip -q /A/Api.zip -d /A && rm /A/Api.zip
 
 
 
 
 
 
 
23
 
24
- # Install dependency API
25
- WORKDIR /A/Api
 
 
 
26
  RUN npm install --omit=dev
27
 
28
- EXPOSE 7860
29
 
30
- # Jalankan API via xvfb
31
- CMD rm -f /tmp/.X99-lock && \
32
- xvfb-run --auto-servernum --server-args="-screen 0 1024x768x24" \
33
- npm start
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ============================================
2
+ # DOCKERFILE FAUCET BOT - FULL FIX
3
+ # ============================================
4
+ FROM python:3.9-slim
5
 
6
+ # -------------------------------
7
+ # 1. Install system dependencies + Xvfb
8
+ # -------------------------------
9
+ RUN apt-get update && apt-get install -y \
10
+ curl \
11
+ wget \
12
+ gnupg \
13
+ ca-certificates \
14
+ xz-utils \
15
+ xvfb \
16
+ fonts-liberation \
17
+ libnss3 \
18
+ libatk-bridge2.0-0 \
19
+ libx11-xcb1 \
20
+ libxcb-dri3-0 \
21
+ libxcomposite1 \
22
+ libxdamage1 \
23
+ libxrandr2 \
24
+ libgbm1 \
25
+ libasound2 \
26
+ libatk1.0-0 \
27
+ libgtk-3-0 \
28
+ libxshmfence1 \
29
+ && rm -rf /var/lib/apt/lists/*
30
 
31
+ # -------------------------------
32
+ # 2. Install Google Chrome
33
+ # -------------------------------
34
+ RUN mkdir -p /etc/apt/keyrings \
35
+ && wget -q -O - https://dl.google.com/linux/linux_signing_key.pub > /tmp/google.pub \
36
+ && gpg --dearmor < /tmp/google.pub > /etc/apt/keyrings/google-chrome.gpg \
37
+ && echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/google-chrome.gpg] http://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google-chrome.list \
38
+ && apt-get update \
39
+ && apt-get install -y google-chrome-stable \
40
+ && rm -rf /var/lib/apt/lists/* \
41
+ && rm /tmp/google.pub
42
 
43
+ WORKDIR /app
 
44
 
45
+ # -------------------------------
46
+ # 3. Install Python dependencies
47
+ # -------------------------------
48
+ COPY requirements.txt .
49
+ RUN pip install --no-cache-dir --upgrade pip && \
50
+ pip install --no-cache-dir -r requirements.txt
51
 
52
+ # -------------------------------
53
+ # 4. Install Node.js 20
54
+ # -------------------------------
55
+ RUN mkdir -p /etc/apt/keyrings \
56
+ && curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg \
57
+ && echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_20.x nodistro main" > /etc/apt/sources.list.d/nodesource.list \
58
+ && apt-get update \
59
+ && apt-get install -y nodejs \
60
+ && rm -rf /var/lib/apt/lists/*
61
 
62
+ # -------------------------------
63
+ # 5. Copy API
64
+ # -------------------------------
65
+ COPY Api/ /app/Api/
66
+ WORKDIR /app/Api
67
  RUN npm install --omit=dev
68
 
69
+ WORKDIR /app
70
 
71
+ # -------------------------------
72
+ # 6. Copy Python bot
73
+ # -------------------------------
74
+ COPY app.py .
75
+
76
+ # -------------------------------
77
+ # 7. Startup Script
78
+ # -------------------------------
79
+ RUN echo '#!/bin/bash\n\
80
+ echo "πŸ€– STARTING FAUCET BOT"\n\
81
+ echo "======================"\n\
82
+ \n\
83
+ echo "Starting Node.js API..."\n\
84
+ cd /app/Api\n\
85
+ node Api.js &\n\
86
+ \n\
87
+ echo "Waiting for API to start..."\n\
88
+ sleep 5\n\
89
+ \n\
90
+ echo "Starting Python Bot..."\n\
91
+ cd /app\n\
92
+ xvfb-run -a python3 app.py\n\
93
+ ' > /start.sh && chmod +x /start.sh
94
+
95
+ # -------------------------------
96
+ # 8. Healthcheck
97
+ # -------------------------------
98
+ HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \
99
+ CMD curl -f http://localhost:3000/ || exit 1
100
+
101
+ # -------------------------------
102
+ # 9. Expose API port
103
+ # -------------------------------
104
+ EXPOSE 3000
105
+
106
+ # -------------------------------
107
+ # 10. Start container
108
+ # -------------------------------
109
+ CMD ["/start.sh"]
README.md CHANGED
@@ -1,8 +1,8 @@
1
  ---
2
- title: Testapi
3
- emoji: πŸŒ–
4
- colorFrom: purple
5
- colorTo: red
6
  sdk: docker
7
  pinned: false
8
  ---
 
1
  ---
2
+ title: Auto
3
+ emoji: πŸ“‰
4
+ colorFrom: pink
5
+ colorTo: gray
6
  sdk: docker
7
  pinned: false
8
  ---
app.py ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ FAUCET BOT β€” FINAL TOTAL FIX
4
+ 1 worker stabil
5
+ CF solver β†’ root β†’ miner β†’ ccpp loop
6
+ Session hidup 12 jam β†’ otomatis refresh
7
+ Proteksi cookies & JS sesuai web
8
+ """
9
+
10
+ import sys, os, time, re, requests, logging
11
+ from http.cookies import SimpleCookie
12
+
13
+ sys.stdout.reconfigure(line_buffering=True)
14
+
15
+ logging.basicConfig(
16
+ level=logging.INFO,
17
+ format="%(asctime)s - %(levelname)s - %(message)s",
18
+ force=True
19
+ )
20
+ logger = logging.getLogger(__name__)
21
+
22
+ print("πŸš€ Python script starting...", flush=True)
23
+
24
+ # CONFIG
25
+ SOLVER_URL = os.getenv("SOLVER_URL", "http://localhost:7860")
26
+ SOLVER_KEY = os.getenv("SOLVER_KEY", "00000000000000000000#0000000000000000000#000000000000000000#")
27
+ BASE_DOMAIN = "https://www.leaks.work"
28
+ TARGET_PAGE = BASE_DOMAIN + "/miner/ton"
29
+ ACCOUNT_ID = os.getenv("ACCOUNT_ID", "8731-4082-8074")
30
+ TOKEN = os.getenv("TOKEN", "ton")
31
+ CCPP_URL = f"{BASE_DOMAIN}/miner/ccpp.php?id={ACCOUNT_ID}&token={TOKEN}"
32
+ FETCH_INTERVAL = 62
33
+ SESSION_LIFETIME = 60*60*12
34
+ HEADERS_BASE = {"Accept": "*/*", "Referer": TARGET_PAGE}
35
+
36
+ # SOLVER
37
+ def solve_interstitial():
38
+ logger.info("Request CF clearance...")
39
+ payload = {"type":"interstitial","domain":TARGET_PAGE,"apiKey":SOLVER_KEY}
40
+ r = requests.post(SOLVER_URL+"/solve", json=payload, timeout=20)
41
+ data = r.json()
42
+ task_id = data.get("taskId")
43
+ if not task_id: raise Exception("TaskId tidak ada")
44
+ logger.info(f"Task: {task_id}")
45
+
46
+ for _ in range(30):
47
+ time.sleep(2)
48
+ try:
49
+ poll = requests.get(SOLVER_URL+"/solve", params={"taskId":task_id,"apiKey":SOLVER_KEY}, timeout=20)
50
+ if poll.status_code != 200: continue
51
+ result = poll.json()
52
+ status = result.get("status")
53
+ if status == "done":
54
+ solved = result.get("solution", {})
55
+ if not solved.get("cookies"):
56
+ logger.warning("Solver mengembalikan cookies kosong β†’ retry")
57
+ continue
58
+ return {"cookies": solved.get("cookies"), "user_agent": solved.get("user_agent")}
59
+ if status == "error": raise Exception("Solver error")
60
+ except: continue
61
+ raise Exception("Solver gagal dapat cookies")
62
+ def get_current_ip():
63
+ try:
64
+ r = requests.get("https://api.ipify.org", timeout=10)
65
+ if r.status_code == 200:
66
+ return r.text.strip()
67
+ except Exception:
68
+ pass
69
+ return "unknown"
70
+
71
+ # COOKIE
72
+ def parse_cookie_string(cookie_str):
73
+ jar = requests.cookies.RequestsCookieJar()
74
+ if not cookie_str: return jar
75
+ simple = SimpleCookie(); simple.load(cookie_str)
76
+ for k,m in simple.items(): jar.set(k,m.value,domain=".leaks.work",path="/")
77
+ return jar
78
+
79
+ # JS COOKIE
80
+ def extract_js_cookies(text):
81
+ cookies=[]
82
+ for a in re.findall(r'document\.cookie\s*=\s*["\'](.*?)["\']', text or ""):
83
+ first = a.split(";",1)[0]
84
+ if "=" in first: k,v = first.split("=",1); cookies.append((k.strip(),v.strip()))
85
+ return cookies
86
+
87
+ def apply_js_cookies(session,cookie_list):
88
+ for k,v in cookie_list:
89
+ if k.lower().startswith("cf_"): continue
90
+ session.cookies.set(k,v)
91
+
92
+ # SESSION
93
+ def create_session(sol):
94
+ s = requests.Session()
95
+ headers = HEADERS_BASE.copy()
96
+ headers["User-Agent"] = sol.get("user_agent","Mozilla/5.0")
97
+ s.headers.update(headers)
98
+ s.cookies.update(parse_cookie_string(sol.get("cookies")))
99
+ return s
100
+
101
+ # RUN SESSION
102
+ def run_session():
103
+ sol = solve_interstitial()
104
+ session = create_session(sol)
105
+ initial_ip = get_current_ip()
106
+ logger.info(f"🌍 IP: {initial_ip}")
107
+
108
+ logger.info("Warmup root...")
109
+ session.get(BASE_DOMAIN, timeout=20)
110
+ time.sleep(1)
111
+
112
+ logger.info("Warmup miner page...")
113
+ r = session.get(TARGET_PAGE, timeout=20)
114
+ logger.info(f"Warmup status {r.status_code}")
115
+ if r.status_code==403: logger.warning("Warmup blocked β†’ refresh"); return
116
+ apply_js_cookies(session, extract_js_cookies(r.text))
117
+ time.sleep(3)
118
+
119
+ start_time=time.time()
120
+ logger.info("Miner running...")
121
+
122
+ while True:
123
+ if time.time()-start_time>SESSION_LIFETIME: logger.info("12h session ended β†’ refresh"); return
124
+ try:
125
+ r=session.get(CCPP_URL,timeout=20)
126
+ logger.info(f"Fetch status {r.status_code}")
127
+ if r.status_code==403: logger.warning("403 detected β†’ refresh clearance"); return
128
+ apply_js_cookies(session, extract_js_cookies(r.text))
129
+ except: logger.exception("Fetch error β†’ refresh session"); return
130
+ time.sleep(FETCH_INTERVAL)
131
+
132
+ # WORKER
133
+ def worker():
134
+ while True:
135
+ try: run_session()
136
+ except: logger.exception("Session crash")
137
+ logger.info("Restarting session in 5s...")
138
+ time.sleep(5)
139
+
140
+ if __name__=="__main__":
141
+ worker()
docker-compose.yml ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: '3.8'
2
+
3
+ services:
4
+ multi-coin-bot:
5
+ build: .
6
+ container_name: multi-coin-faucet-bot
7
+ restart: unless-stopped
8
+ volumes:
9
+ - ./logs:/app/logs
10
+ - ./data:/app/data
11
+ environment:
12
+ - TZ=Asia/Jakarta
13
+ - EMAIL=gi2h27@gmail.com
14
+ - MAX_CYCLES=100000
15
+ - SOLVER_URL=https://gi2h-xxx.hf.space
16
+ - SOLVER_KEY=00000000000000000000#0000000000000000000#000000000000000000#
17
+ - PYTHONUNBUFFERED=1
18
+ logging:
19
+ driver: "json-file"
20
+ options:
21
+ max-size: "10m"
22
+ max-file: "3"
requirements.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ requests==2.31.0
2
+ colorama==0.4.6
3
+ python-dotenv==1.0.0