Spaces:
Paused
Paused
Download server.js from maylinejix/Bycf: direct link, hf CLI and curl.
- Browser
- Download file 11 kB
-
https://huggingface.co/spaces/maylinejix/Bycf/resolve/main/server.js
- Command line
-
hf download hf://spaces/maylinejix/Bycf/server.js
-
curl -L -o server.js https://huggingface.co/spaces/maylinejix/Bycf/resolve/main/server.js
11 kB
| const express = require('express'); | |
| const cors = require('cors'); | |
| const app = express(); | |
| const PORT = process.env.PORT || 7860; | |
| const API_BASE = 'http://172.235.245.114:1875'; | |
| const THEYKA_BASE = 'http://172.235.245.114:1808'; | |
| 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 = 300000) { | |
| const start = Date.now(); | |
| while (Date.now() - start < maxWaitTime) { | |
| const r = await fetch(`${API_BASE}/job/${jobId}`); | |
| if (!r.ok) throw new Error(`Status check failed: ${r.status}`); | |
| const data = await r.json(); | |
| if (!data.success) throw new Error(data.error || 'Status check error'); | |
| const job = data.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, 1000)); | |
| } | |
| throw new Error('Timeout'); | |
| } | |
| async function solveWithTheyka(url, sitekey, action, cdata) { | |
| let endpoint = `${THEYKA_BASE}/turnstile?url=${encodeURIComponent(url)}&sitekey=${encodeURIComponent(sitekey)}`; | |
| if (action) endpoint += `&action=${encodeURIComponent(action)}`; | |
| if (cdata) endpoint += `&cdata=${encodeURIComponent(cdata)}`; | |
| const submitRes = await fetch(endpoint); | |
| if (!submitRes.ok) throw new Error(`Theyka submit error: ${submitRes.status}`); | |
| const submitData = await submitRes.json(); | |
| const task_id = submitData.task_id; | |
| if (!task_id) throw new Error('Theyka: no task_id returned'); | |
| console.log(`[THEYKA] task_id=${task_id}`); | |
| const start = Date.now(); | |
| while (Date.now() - start < 60000) { | |
| await new Promise(resolve => setTimeout(resolve, 2000)); | |
| const resultRes = await fetch(`${THEYKA_BASE}/result?id=${task_id}`); | |
| if (!resultRes.ok) continue; | |
| const raw = await resultRes.text(); | |
| let data; | |
| try { | |
| data = JSON.parse(raw); | |
| } catch { | |
| if (raw.trim() === 'CAPTCHA_NOT_READY') continue; | |
| throw new Error(`Theyka unexpected: ${raw.slice(0, 100)}`); | |
| } | |
| if (data?.value === 'CAPTCHA_FAIL') throw new Error('Theyka: CAPTCHA_FAIL'); | |
| if (data?.value && data.value !== 'CAPTCHA_NOT_READY') { | |
| console.log(`[THEYKA] token ok elapsed=${data.elapsed_time}s`); | |
| return { token: data.value, elapsed_ms: Math.round((data.elapsed_time || 0) * 1000) }; | |
| } | |
| } | |
| throw new Error('Theyka: timeout'); | |
| } | |
| 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 isInvisible = sitekey.includes('_') || sitekey.includes('-'); | |
| console.log(`[BYCF] url=${url} sitekey=${sitekey} isInvisible=${isInvisible}`); | |
| if (isInvisible) { | |
| const { token, elapsed_ms } = await solveWithTheyka(url, sitekey, action, cdata); | |
| return res.json({ author: 'Herza', status: 200, data: { token, sitekey, url, action, cdata, cookies: {}, elapsed_ms } }); | |
| } | |
| const esc = (s) => s ? s.replace(/'/g, "\\'") : null; | |
| const a = esc(action); | |
| const c = esc(cdata); | |
| const urlWithSlash = url.endsWith('/') ? url : url + '/'; | |
| const actionAttr = a ? ` data-action="${a}"` : ''; | |
| const cdataAttr = c ? ` data-cdata="${c}"` : ''; | |
| const htmlB64 = Buffer.from(`<!DOCTYPE html><html><head><meta charset="UTF-8"><title>T</title><script>window.__cfToken=null;function cfCallback(t){window.__cfToken=t;}<\/script><script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer><\/script></head><body><div class="cf-turnstile" data-sitekey="${sitekey}" data-callback="cfCallback"${actionAttr}${cdataAttr}></div></body></html>`).toString('base64'); | |
| const code = `import random,time,base64 | |
| ctx=browser.new_context(viewport={'width':1920,'height':1080},ignore_https_errors=True) | |
| p=ctx.new_page() | |
| try: | |
| html_body=base64.b64decode('${htmlB64}').decode('utf-8') | |
| p.route('${urlWithSlash}',lambda route:route.fulfill(body=html_body,status=200,content_type='text/html')) | |
| p.goto('${urlWithSlash}',wait_until='domcontentloaded',timeout=20000) | |
| time.sleep(2) | |
| tk=None | |
| for i in range(60): | |
| try: | |
| tk=p.evaluate('window.__cfToken') | |
| if tk and len(tk)>50:break | |
| tk=None | |
| 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 tk: | |
| 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(-10,10),y+random.randint(-10,10)) | |
| time.sleep(0.2) | |
| p.mouse.click(x,y) | |
| 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) { | |
| console.error(`[BYCF] Error: ${error.message}`); | |
| 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 | |
| ctx=browser.new_context(viewport={'width':1920,'height':1080},ignore_https_errors=True) | |
| p=ctx.new_page() | |
| time.sleep(0.5) | |
| try: | |
| p.goto('${url}',wait_until='domcontentloaded',timeout=60000) | |
| time.sleep(7) | |
| 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 | |
| ctx=browser.new_context(viewport={'width':1920,'height':1080},ignore_https_errors=True) | |
| p=ctx.new_page() | |
| time.sleep(0.5) | |
| try: | |
| p.goto('${url}',wait_until='domcontentloaded',timeout=60000) | |
| time.sleep(7) | |
| 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', '/wafsource': 'POST', '/wafsessions': 'POST' } } }); | |
| }); | |
| app.listen(PORT, () => console.log(`Server running on port ${PORT}`)); | |