Spaces:
Running
Running
| const express = require('express'); | |
| const cors = require('cors'); | |
| const app = express(); | |
| const PORT = process.env.PORT || 7860; | |
| const API_BASE = 'https://maylinejix-herxagg.hf.space'; | |
| app.use(cors()); | |
| app.use(express.json()); | |
| async function submitJob(code) { | |
| const response = await fetch(`${API_BASE}/api/s-playwright`, { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify({ code, lang: 'python' }) | |
| }); | |
| if (!response.ok) { | |
| throw new Error(`API error: ${response.status}`); | |
| } | |
| const result = await response.json(); | |
| if (!result.success) { | |
| throw new Error(result.error || 'Failed to submit job'); | |
| } | |
| return result.job_id; | |
| } | |
| async function pollJob(jobId, maxWaitTime = 120000) { | |
| const pollInterval = 3000; | |
| const start = Date.now(); | |
| while (Date.now() - start < maxWaitTime) { | |
| const statusResponse = await fetch(`${API_BASE}/job/${jobId}`); | |
| if (!statusResponse.ok) { | |
| throw new Error(`Status check failed: ${statusResponse.status}`); | |
| } | |
| const statusResult = await statusResponse.json(); | |
| if (!statusResult.success) { | |
| throw new Error(statusResult.error || 'Status check error'); | |
| } | |
| const job = statusResult.job; | |
| if (job.status === 'completed') { | |
| return job.result; | |
| } | |
| if (job.status === 'failed') { | |
| throw new Error(job.error || 'Job failed'); | |
| } | |
| await new Promise(resolve => setTimeout(resolve, pollInterval)); | |
| } | |
| throw new Error('Timeout waiting for job completion'); | |
| } | |
| app.post('/bycf', async (req, res) => { | |
| try { | |
| const { url, sitekey, action = null, cdata = null } = req.body; | |
| if (!url || !sitekey) { | |
| return res.status(400).json({ | |
| author: 'Herza', | |
| status: 400, | |
| data: { error: 'URL and SITEKEY are required' } | |
| }); | |
| } | |
| const t = Date.now(); | |
| const esc = (s) => s ? s.replace(/'/g, "\\'") : null; | |
| const a = esc(action); | |
| const c = esc(cdata); | |
| const code = `import random,time | |
| ctx=browser.new_context(viewport={'width':1920,'height':1080},ignore_https_errors=True) | |
| p=ctx.new_page() | |
| try: | |
| p.goto('${url}',wait_until='domcontentloaded',timeout=20000) | |
| time.sleep(0.5) | |
| 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)})()""") | |
| time.sleep(1.5) | |
| tk=None | |
| for i in range(40): | |
| try: | |
| inp=p.query_selector('input[name="cf-turnstile-response"]') | |
| if inp: | |
| v=inp.get_attribute('value') | |
| if v and len(v)>50: | |
| tk=v | |
| break | |
| if not v: | |
| div=p.query_selector('div.cf-turnstile') | |
| if div: | |
| b=div.bounding_box() | |
| if b: | |
| x=b['x']+b['width']/2 | |
| y=b['y']+b['height']/2 | |
| p.mouse.move(x+random.randint(-15,15),y+random.randint(-15,15)) | |
| time.sleep(0.2) | |
| p.mouse.click(x,y) | |
| time.sleep(0.3) | |
| except: | |
| pass | |
| time.sleep(0.3) | |
| if not tk:raise Exception('No token') | |
| ck={c['name']:c['value'] for c in p.context.cookies()} | |
| 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})} | |
| except Exception as e: | |
| return_value={'success':False,'error':str(e)}`; | |
| const jobId = await submitJob(code); | |
| const result = await pollJob(jobId); | |
| if (!result.success) { | |
| return res.status(500).json({ | |
| author: 'Herza', | |
| status: 500, | |
| data: { error: result.error } | |
| }); | |
| } | |
| res.json({ | |
| author: 'Herza', | |
| status: 200, | |
| data: { | |
| token: result.token, | |
| sitekey: result.sitekey, | |
| url: result.url, | |
| action: result.action, | |
| cdata: result.cdata, | |
| cookies: result.cookies, | |
| elapsed_ms: result.elapsed_ms | |
| } | |
| }); | |
| } catch (error) { | |
| res.status(500).json({ | |
| author: 'Herza', | |
| status: 500, | |
| data: { error: error.message } | |
| }); | |
| } | |
| }); | |
| app.post('/wafsource', async (req, res) => { | |
| try { | |
| const { url } = req.body; | |
| if (!url) { | |
| return res.status(400).json({ | |
| author: 'Herza', | |
| status: 400, | |
| data: { error: 'URL is required' } | |
| }); | |
| } | |
| const startTime = Date.now(); | |
| const code = `import random,math,re | |
| ctx=browser.new_context(viewport={'width':1920,'height':1080},ignore_https_errors=True) | |
| p=ctx.new_page() | |
| p.set_viewport_size({'width':1920,'height':1080}) | |
| time.sleep(0.5) | |
| try: | |
| p.goto('${url}',wait_until='domcontentloaded',timeout=60000) | |
| p.evaluate('()=>{Object.defineProperty(window,"innerWidth",{value:1920,writable:false,configurable:false});Object.defineProperty(window,"innerHeight",{value:1080,writable:false,configurable:false})}') | |
| time.sleep(2) | |
| time.sleep(5) | |
| pg=p.content() | |
| has_cf='cloudflare' in pg.lower() or 'cf-wrapper' in pg.lower() | |
| if has_cf: | |
| for _ in range(random.randint(3,5)): | |
| p.evaluate(f'window.scrollTo(0,{random.randint(50,150)})') | |
| time.sleep(random.uniform(0.4,0.8)) | |
| p.evaluate('window.scrollTo(0,0)') | |
| time.sleep(random.uniform(1.0,2.0)) | |
| sx,sy=random.randint(100,300),random.randint(100,300) | |
| tx,ty=545,290 | |
| d=math.sqrt((tx-sx)**2+(ty-sy)**2) | |
| st=max(15,min(int(d/random.uniform(3,6)),40)) | |
| for i in range(st): | |
| t=(i+1)/st | |
| et=t*t*(3-2*t) | |
| bx=(sx+tx)/2+random.uniform(-30,30) | |
| by=(sy+ty)/2+random.uniform(-30,30) | |
| nx=(1-et)**2*sx+2*(1-et)*et*bx+et**2*tx | |
| ny=(1-et)**2*sy+2*(1-et)*et*by+et**2*ty | |
| p.mouse.move(nx,ny) | |
| time.sleep(random.uniform(0.015,0.040)) | |
| p.mouse.move(tx,ty) | |
| time.sleep(random.uniform(0.3,0.6)) | |
| p.mouse.down() | |
| time.sleep(random.uniform(0.12,0.18)) | |
| p.mouse.up() | |
| time.sleep(11) | |
| try:p.wait_for_load_state('networkidle',timeout=10000) | |
| except:pass | |
| time.sleep(5) | |
| fu=p.url | |
| html=p.content() | |
| title=p.title() | |
| ck={c['name']:c['value'] for c in p.context.cookies()} | |
| return_value={'success':True,'url':fu,'html':html,'title':title,'cookies':ck,'had_cloudflare':has_cf,'ms':int((time.time()*1000)-${startTime})} | |
| except Exception as e: | |
| return_value={'success':False,'error':str(e)}`; | |
| const jobId = await submitJob(code); | |
| const result = await pollJob(jobId, 300000); | |
| if (!result.success) { | |
| return res.status(500).json({ | |
| author: 'Herza', | |
| status: 500, | |
| data: { error: result.error } | |
| }); | |
| } | |
| res.json({ | |
| author: 'Herza', | |
| status: 200, | |
| data: { | |
| url: result.url, | |
| html: result.html, | |
| title: result.title, | |
| cookies: result.cookies, | |
| had_cloudflare: result.had_cloudflare, | |
| elapsed_ms: result.ms | |
| } | |
| }); | |
| } catch (error) { | |
| res.status(500).json({ | |
| author: 'Herza', | |
| status: 500, | |
| data: { error: error.message } | |
| }); | |
| } | |
| }); | |
| app.post('/wafsessions', async (req, res) => { | |
| try { | |
| const { url } = req.body; | |
| if (!url) { | |
| return res.status(400).json({ | |
| author: 'Herza', | |
| status: 400, | |
| data: { error: 'URL is required' } | |
| }); | |
| } | |
| const startTime = Date.now(); | |
| const code = `import random,math,re | |
| ctx=browser.new_context(viewport={'width':1920,'height':1080},ignore_https_errors=True) | |
| p=ctx.new_page() | |
| p.set_viewport_size({'width':1920,'height':1080}) | |
| time.sleep(0.5) | |
| try: | |
| p.goto('${url}',wait_until='domcontentloaded',timeout=60000) | |
| p.evaluate('()=>{Object.defineProperty(window,"innerWidth",{value:1920,writable:false,configurable:false});Object.defineProperty(window,"innerHeight",{value:1080,writable:false,configurable:false})}') | |
| time.sleep(2) | |
| time.sleep(5) | |
| pg=p.content() | |
| has_cf='cloudflare' in pg.lower() or 'cf-wrapper' in pg.lower() | |
| if has_cf: | |
| for _ in range(random.randint(3,5)): | |
| p.evaluate(f'window.scrollTo(0,{random.randint(50,150)})') | |
| time.sleep(random.uniform(0.4,0.8)) | |
| p.evaluate('window.scrollTo(0,0)') | |
| time.sleep(random.uniform(1.0,2.0)) | |
| sx,sy=random.randint(100,300),random.randint(100,300) | |
| tx,ty=545,290 | |
| d=math.sqrt((tx-sx)**2+(ty-sy)**2) | |
| st=max(15,min(int(d/random.uniform(3,6)),40)) | |
| for i in range(st): | |
| t=(i+1)/st | |
| et=t*t*(3-2*t) | |
| bx=(sx+tx)/2+random.uniform(-30,30) | |
| by=(sy+ty)/2+random.uniform(-30,30) | |
| nx=(1-et)**2*sx+2*(1-et)*et*bx+et**2*tx | |
| ny=(1-et)**2*sy+2*(1-et)*et*by+et**2*ty | |
| p.mouse.move(nx,ny) | |
| time.sleep(random.uniform(0.015,0.040)) | |
| p.mouse.move(tx,ty) | |
| time.sleep(random.uniform(0.3,0.6)) | |
| p.mouse.down() | |
| time.sleep(random.uniform(0.12,0.18)) | |
| p.mouse.up() | |
| time.sleep(11) | |
| try:p.wait_for_load_state('networkidle',timeout=10000) | |
| except:pass | |
| time.sleep(5) | |
| fu=p.url | |
| title=p.title() | |
| ck={c['name']:c['value'] for c in p.context.cookies()} | |
| return_value={'success':True,'url':fu,'title':title,'cookies':ck,'had_cloudflare':has_cf,'ms':int((time.time()*1000)-${startTime})} | |
| except Exception as e: | |
| return_value={'success':False,'error':str(e)}`; | |
| const jobId = await submitJob(code); | |
| const result = await pollJob(jobId, 300000); | |
| if (!result.success) { | |
| return res.json({ | |
| author: 'Herza', | |
| status: 500, | |
| data: { | |
| error: result.error | |
| } | |
| }); | |
| } | |
| res.json({ | |
| author: 'Herza', | |
| status: 200, | |
| data: { | |
| url: result.url, | |
| title: result.title, | |
| cookies: result.cookies, | |
| had_cloudflare: result.had_cloudflare, | |
| elapsed_ms: result.ms | |
| } | |
| }); | |
| } catch (error) { | |
| res.json({ | |
| author: 'Herza', | |
| status: 500, | |
| data: { error: error.message } | |
| }); | |
| } | |
| }); | |
| app.get('/', (req, res) => { | |
| res.json({ | |
| author: 'Herza', | |
| status: 200, | |
| data: { | |
| message: 'API is running', | |
| endpoints: { | |
| '/bycf': 'POST - Bypass Cloudflare Turnstile (requires: url, sitekey)', | |
| '/wafsource': 'POST - Get HTML with WAF bypass (requires: url)', | |
| '/wafsessions': 'POST - Get cookies only (requires: url)' | |
| } | |
| } | |
| }); | |
| }); | |
| app.listen(PORT, () => { | |
| console.log(`Server running on port ${PORT}`); | |
| }); |