maylinejix commited on
Commit
2db43f0
·
verified ·
1 Parent(s): 04b9adc

Create server.js

Browse files
Files changed (1) hide show
  1. server.js +356 -0
server.js ADDED
@@ -0,0 +1,356 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const express = require('express');
2
+ const cors = require('cors');
3
+
4
+ const app = express();
5
+ const PORT = process.env.PORT || 7860;
6
+ const API_BASE = 'https://maylinejix-camoufox.hf.space';
7
+
8
+ app.use(cors());
9
+ app.use(express.json());
10
+
11
+ async function submitJob(code) {
12
+ const response = await fetch(`${API_BASE}/api/s-playwright`, {
13
+ method: 'POST',
14
+ headers: { 'Content-Type': 'application/json' },
15
+ body: JSON.stringify({ code, lang: 'python' })
16
+ });
17
+
18
+ if (!response.ok) {
19
+ throw new Error(`API error: ${response.status}`);
20
+ }
21
+
22
+ const result = await response.json();
23
+ if (!result.success) {
24
+ throw new Error(result.error || 'Failed to submit job');
25
+ }
26
+
27
+ return result.job_id;
28
+ }
29
+
30
+ async function pollJob(jobId, maxWaitTime = 120000) {
31
+ const pollInterval = 3000;
32
+ const start = Date.now();
33
+
34
+ while (Date.now() - start < maxWaitTime) {
35
+ const statusResponse = await fetch(`${API_BASE}/job/${jobId}`);
36
+
37
+ if (!statusResponse.ok) {
38
+ throw new Error(`Status check failed: ${statusResponse.status}`);
39
+ }
40
+
41
+ const statusResult = await statusResponse.json();
42
+
43
+ if (!statusResult.success) {
44
+ throw new Error(statusResult.error || 'Status check error');
45
+ }
46
+
47
+ const job = statusResult.job;
48
+
49
+ if (job.status === 'completed') {
50
+ return job.result;
51
+ }
52
+
53
+ if (job.status === 'failed') {
54
+ throw new Error(job.error || 'Job failed');
55
+ }
56
+
57
+ await new Promise(resolve => setTimeout(resolve, pollInterval));
58
+ }
59
+
60
+ throw new Error('Timeout waiting for job completion');
61
+ }
62
+
63
+ app.post('/bycf', async (req, res) => {
64
+ try {
65
+ const { url, sitekey, action = null, cdata = null } = req.body;
66
+
67
+ if (!url || !sitekey) {
68
+ return res.status(400).json({
69
+ author: 'Herza',
70
+ status: 400,
71
+ data: { error: 'URL and SITEKEY are required' }
72
+ });
73
+ }
74
+
75
+ const t = Date.now();
76
+ const esc = (s) => s ? s.replace(/'/g, "\\'") : null;
77
+ const a = esc(action);
78
+ const c = esc(cdata);
79
+
80
+ const code = `import random,time
81
+ ctx=browser.new_context(viewport={'width':1920,'height':1080},ignore_https_errors=True)
82
+ p=ctx.new_page()
83
+ try:
84
+ p.goto('${url}',wait_until='domcontentloaded',timeout=20000)
85
+ time.sleep(0.5)
86
+ p.evaluate("""(function(){const e=document.querySelector('.cf-turnstile');e&&e.remove();const d=document.createElement('div');d.className='cf-turnstile';d.setAttribute('data-sitekey','${sitekey}');${a ? `d.setAttribute('data-action','${a}');` : ''}${c ? `d.setAttribute('data-cdata','${c}');` : ''}d.style.cssText='position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);z-index:999999';document.body.appendChild(d);const s=document.createElement('script');s.src='https://challenges.cloudflare.com/turnstile/v0/api.js';s.async=s.defer=1;document.head.appendChild(s)})()""")
87
+ time.sleep(1.5)
88
+ tk=None
89
+ for i in range(40):
90
+ try:
91
+ inp=p.query_selector('input[name="cf-turnstile-response"]')
92
+ if inp:
93
+ v=inp.get_attribute('value')
94
+ if v and len(v)>50:
95
+ tk=v
96
+ break
97
+ if not v:
98
+ div=p.query_selector('div.cf-turnstile')
99
+ if div:
100
+ b=div.bounding_box()
101
+ if b:
102
+ x=b['x']+b['width']/2
103
+ y=b['y']+b['height']/2
104
+ p.mouse.move(x+random.randint(-15,15),y+random.randint(-15,15))
105
+ time.sleep(0.2)
106
+ p.mouse.click(x,y)
107
+ time.sleep(0.3)
108
+ except:
109
+ pass
110
+ time.sleep(0.3)
111
+ if not tk:raise Exception('No token')
112
+ ck={c['name']:c['value'] for c in p.context.cookies()}
113
+ return_value={'success':True,'token':tk,'sitekey':'${sitekey}','url':'${url}','action':${a ? `'${a}'` : 'None'},'cdata':${c ? `'${c}'` : 'None'},'cookies':ck,'elapsed_ms':int((time.time()*1000)-${t})}
114
+ except Exception as e:
115
+ return_value={'success':False,'error':str(e)}`;
116
+
117
+ const jobId = await submitJob(code);
118
+ const result = await pollJob(jobId);
119
+
120
+ if (!result.success) {
121
+ return res.status(500).json({
122
+ author: 'Herza',
123
+ status: 500,
124
+ data: { error: result.error }
125
+ });
126
+ }
127
+
128
+ res.json({
129
+ author: 'Herza',
130
+ status: 200,
131
+ data: {
132
+ token: result.token,
133
+ sitekey: result.sitekey,
134
+ url: result.url,
135
+ action: result.action,
136
+ cdata: result.cdata,
137
+ cookies: result.cookies,
138
+ elapsed_ms: result.elapsed_ms
139
+ }
140
+ });
141
+
142
+ } catch (error) {
143
+ res.status(500).json({
144
+ author: 'Herza',
145
+ status: 500,
146
+ data: { error: error.message }
147
+ });
148
+ }
149
+ });
150
+
151
+ app.post('/wafsource', async (req, res) => {
152
+ try {
153
+ const { url } = req.body;
154
+
155
+ if (!url) {
156
+ return res.status(400).json({
157
+ author: 'Herza',
158
+ status: 400,
159
+ data: { error: 'URL is required' }
160
+ });
161
+ }
162
+
163
+ const startTime = Date.now();
164
+
165
+ const code = `import random,math,re
166
+ ctx=browser.new_context(viewport={'width':1920,'height':1080},ignore_https_errors=True)
167
+ p=ctx.new_page()
168
+ p.set_viewport_size({'width':1920,'height':1080})
169
+ time.sleep(0.5)
170
+ try:
171
+ p.goto('${url}',wait_until='domcontentloaded',timeout=60000)
172
+ p.evaluate('()=>{Object.defineProperty(window,"innerWidth",{value:1920,writable:false,configurable:false});Object.defineProperty(window,"innerHeight",{value:1080,writable:false,configurable:false})}')
173
+ time.sleep(2)
174
+ time.sleep(5)
175
+ pg=p.content()
176
+ has_cf='cloudflare' in pg.lower() or 'cf-wrapper' in pg.lower()
177
+ if has_cf:
178
+ for _ in range(random.randint(3,5)):
179
+ p.evaluate(f'window.scrollTo(0,{random.randint(50,150)})')
180
+ time.sleep(random.uniform(0.4,0.8))
181
+ p.evaluate('window.scrollTo(0,0)')
182
+ time.sleep(random.uniform(1.0,2.0))
183
+ sx,sy=random.randint(100,300),random.randint(100,300)
184
+ tx,ty=545,290
185
+ d=math.sqrt((tx-sx)**2+(ty-sy)**2)
186
+ st=max(15,min(int(d/random.uniform(3,6)),40))
187
+ for i in range(st):
188
+ t=(i+1)/st
189
+ et=t*t*(3-2*t)
190
+ bx=(sx+tx)/2+random.uniform(-30,30)
191
+ by=(sy+ty)/2+random.uniform(-30,30)
192
+ nx=(1-et)**2*sx+2*(1-et)*et*bx+et**2*tx
193
+ ny=(1-et)**2*sy+2*(1-et)*et*by+et**2*ty
194
+ p.mouse.move(nx,ny)
195
+ time.sleep(random.uniform(0.015,0.040))
196
+ p.mouse.move(tx,ty)
197
+ time.sleep(random.uniform(0.3,0.6))
198
+ p.mouse.down()
199
+ time.sleep(random.uniform(0.12,0.18))
200
+ p.mouse.up()
201
+ time.sleep(11)
202
+ try:p.wait_for_load_state('networkidle',timeout=10000)
203
+ except:pass
204
+ time.sleep(5)
205
+ fu=p.url
206
+ html=p.content()
207
+ title=p.title()
208
+ ck={c['name']:c['value'] for c in p.context.cookies()}
209
+ return_value={'success':True,'url':fu,'html':html,'title':title,'cookies':ck,'had_cloudflare':has_cf,'ms':int((time.time()*1000)-${startTime})}
210
+ except Exception as e:
211
+ return_value={'success':False,'error':str(e)}`;
212
+
213
+ const jobId = await submitJob(code);
214
+ const result = await pollJob(jobId, 300000);
215
+
216
+ if (!result.success) {
217
+ return res.status(500).json({
218
+ author: 'Herza',
219
+ status: 500,
220
+ data: { error: result.error }
221
+ });
222
+ }
223
+
224
+ res.json({
225
+ author: 'Herza',
226
+ status: 200,
227
+ data: {
228
+ url: result.url,
229
+ html: result.html,
230
+ title: result.title,
231
+ cookies: result.cookies,
232
+ had_cloudflare: result.had_cloudflare,
233
+ elapsed_ms: result.ms
234
+ }
235
+ });
236
+
237
+ } catch (error) {
238
+ res.status(500).json({
239
+ author: 'Herza',
240
+ status: 500,
241
+ data: { error: error.message }
242
+ });
243
+ }
244
+ });
245
+
246
+ app.post('/wafsessions', async (req, res) => {
247
+ try {
248
+ const { url } = req.body;
249
+
250
+ if (!url) {
251
+ return res.status(400).json({
252
+ author: 'Herza',
253
+ status: 400,
254
+ data: { error: 'URL is required' }
255
+ });
256
+ }
257
+
258
+ const startTime = Date.now();
259
+
260
+ const code = `import random,math,re
261
+ ctx=browser.new_context(viewport={'width':1920,'height':1080},ignore_https_errors=True)
262
+ p=ctx.new_page()
263
+ p.set_viewport_size({'width':1920,'height':1080})
264
+ time.sleep(0.5)
265
+ try:
266
+ p.goto('${url}',wait_until='domcontentloaded',timeout=60000)
267
+ p.evaluate('()=>{Object.defineProperty(window,"innerWidth",{value:1920,writable:false,configurable:false});Object.defineProperty(window,"innerHeight",{value:1080,writable:false,configurable:false})}')
268
+ time.sleep(2)
269
+ time.sleep(5)
270
+ pg=p.content()
271
+ has_cf='cloudflare' in pg.lower() or 'cf-wrapper' in pg.lower()
272
+ if has_cf:
273
+ for _ in range(random.randint(3,5)):
274
+ p.evaluate(f'window.scrollTo(0,{random.randint(50,150)})')
275
+ time.sleep(random.uniform(0.4,0.8))
276
+ p.evaluate('window.scrollTo(0,0)')
277
+ time.sleep(random.uniform(1.0,2.0))
278
+ sx,sy=random.randint(100,300),random.randint(100,300)
279
+ tx,ty=545,290
280
+ d=math.sqrt((tx-sx)**2+(ty-sy)**2)
281
+ st=max(15,min(int(d/random.uniform(3,6)),40))
282
+ for i in range(st):
283
+ t=(i+1)/st
284
+ et=t*t*(3-2*t)
285
+ bx=(sx+tx)/2+random.uniform(-30,30)
286
+ by=(sy+ty)/2+random.uniform(-30,30)
287
+ nx=(1-et)**2*sx+2*(1-et)*et*bx+et**2*tx
288
+ ny=(1-et)**2*sy+2*(1-et)*et*by+et**2*ty
289
+ p.mouse.move(nx,ny)
290
+ time.sleep(random.uniform(0.015,0.040))
291
+ p.mouse.move(tx,ty)
292
+ time.sleep(random.uniform(0.3,0.6))
293
+ p.mouse.down()
294
+ time.sleep(random.uniform(0.12,0.18))
295
+ p.mouse.up()
296
+ time.sleep(11)
297
+ try:p.wait_for_load_state('networkidle',timeout=10000)
298
+ except:pass
299
+ time.sleep(5)
300
+ fu=p.url
301
+ title=p.title()
302
+ ck={c['name']:c['value'] for c in p.context.cookies()}
303
+ return_value={'success':True,'url':fu,'title':title,'cookies':ck,'had_cloudflare':has_cf,'ms':int((time.time()*1000)-${startTime})}
304
+ except Exception as e:
305
+ return_value={'success':False,'error':str(e)}`;
306
+
307
+ const jobId = await submitJob(code);
308
+ const result = await pollJob(jobId, 300000);
309
+
310
+ if (!result.success) {
311
+ return res.status(500).json({
312
+ author: 'Herza',
313
+ status: 500,
314
+ data: { error: result.error }
315
+ });
316
+ }
317
+
318
+ res.json({
319
+ author: 'Herza',
320
+ status: 200,
321
+ data: {
322
+ url: result.url,
323
+ title: result.title,
324
+ cookies: result.cookies,
325
+ had_cloudflare: result.had_cloudflare,
326
+ elapsed_ms: result.ms
327
+ }
328
+ });
329
+
330
+ } catch (error) {
331
+ res.status(500).json({
332
+ author: 'Herza',
333
+ status: 500,
334
+ data: { error: error.message }
335
+ });
336
+ }
337
+ });
338
+
339
+ app.get('/', (req, res) => {
340
+ res.json({
341
+ author: 'Herza',
342
+ status: 200,
343
+ data: {
344
+ message: 'API is running',
345
+ endpoints: {
346
+ '/bycf': 'POST - Bypass Cloudflare Turnstile (requires: url, sitekey)',
347
+ '/wafsource': 'POST - Get HTML with WAF bypass (requires: url)',
348
+ '/wafsessions': 'POST - Get cookies only (requires: url)'
349
+ }
350
+ }
351
+ });
352
+ });
353
+
354
+ app.listen(PORT, () => {
355
+ console.log(`Server running on port ${PORT}`);
356
+ });