Spaces:
Paused
Paused
| import express from 'express'; | |
| import { chromium } from 'playwright-extra'; | |
| import StealthPlugin from 'puppeteer-extra-plugin-stealth'; | |
| import cors from 'cors'; | |
| import { promises as fs } from 'fs'; | |
| import path from 'path'; | |
| import { fileURLToPath } from 'url'; | |
| const __filename = fileURLToPath(import.meta.url); | |
| const __dirname = path.dirname(__filename); | |
| chromium.use(StealthPlugin()); | |
| const app = express(); | |
| const PORT = process.env.PORT || 7860; | |
| app.use(cors()); | |
| app.use(express.json({ limit: '50mb' })); | |
| app.use('/files', express.static('public')); | |
| const publicDir = path.join(__dirname, 'public'); | |
| await fs.mkdir(publicDir, { recursive: true }).catch(console.error); | |
| function convertPlaywrightCode(code) { | |
| let converted = code; | |
| const replacements = [ | |
| [/const\s+{\s*chromium\s*}\s*=\s*require\(['"](.*?playwright.*?)['"]\)/gi, 'const chromium = globalThis.chromium'], | |
| [/from\s+['"]playwright['"]/gi, ''], | |
| [/import\s+{\s*chromium\s*}\s+from\s+['"]playwright['"]/gi, 'const chromium = globalThis.chromium'], | |
| ]; | |
| replacements.forEach(([pattern, replacement]) => { | |
| converted = converted.replace(pattern, replacement); | |
| }); | |
| return converted; | |
| } | |
| app.post('/api/s-playwright', async (req, res) => { | |
| const { code, lang } = req.body; | |
| if (!code || !lang) { | |
| return res.status(400).json({ | |
| success: false, | |
| error: 'Missing required fields: code and lang' | |
| }); | |
| } | |
| const supportedLangs = ['javascript']; | |
| const normalizedLang = lang.toLowerCase(); | |
| if (!supportedLangs.includes(normalizedLang)) { | |
| return res.status(400).json({ | |
| success: false, | |
| error: `Unsupported language: "${lang}". Supported: ${supportedLangs.join(', ')}` | |
| }); | |
| } | |
| let browser = null; | |
| try { | |
| const convertedCode = convertPlaywrightCode(code); | |
| globalThis.chromium = { | |
| launch: async (options = {}) => { | |
| return await chromium.launch({ | |
| headless: options.headless !== false, | |
| args: [ | |
| '--disable-blink-features=AutomationControlled', | |
| '--no-sandbox', | |
| '--disable-setuid-sandbox', | |
| '--disable-web-security', | |
| '--disable-features=IsolateOrigins,site-per-process', | |
| '--disable-dev-shm-usage', | |
| '--disable-accelerated-2d-canvas', | |
| '--disable-gpu', | |
| '--window-size=1920,1080', | |
| '--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36', | |
| ...(options.args || []) | |
| ] | |
| }); | |
| } | |
| }; | |
| const AsyncFunction = Object.getPrototypeOf(async function(){}).constructor; | |
| const executableCode = new AsyncFunction('chromium', 'publicDir', 'path', 'fs', convertedCode); | |
| const result = await executableCode(globalThis.chromium, publicDir, path, fs); | |
| const timestamp = Date.now(); | |
| const baseUrl = `${req.protocol}://${req.get('host')}`; | |
| const screenshotFiles = await fs.readdir(publicDir); | |
| const recentFiles = screenshotFiles | |
| .filter(f => f.startsWith('screenshot-') && f.endsWith('.png')) | |
| .map(f => ({ | |
| name: f, | |
| publicURL: `${baseUrl}/files/${f}` | |
| })); | |
| res.json({ | |
| success: true, | |
| data: { | |
| result: result, | |
| files: recentFiles, | |
| timestamp: timestamp | |
| } | |
| }); | |
| } catch (error) { | |
| res.status(500).json({ | |
| success: false, | |
| error: error.message, | |
| stack: error.stack | |
| }); | |
| } finally { | |
| if (browser) { | |
| try { | |
| await browser.close(); | |
| } catch (e) { | |
| console.error('Error closing browser:', e.message); | |
| } | |
| } | |
| } | |
| }); | |
| app.get('/', (req, res) => { | |
| res.json({ | |
| message: 'Playwright Stealth API is running', | |
| endpoints: { | |
| 'POST /api/s-playwright': 'Execute playwright code with stealth mode' | |
| }, | |
| features: [ | |
| 'Advanced Anti-Fingerprinting', | |
| 'Stealth Plugin Enabled', | |
| 'Human-like Behavior', | |
| 'Cloudflare WAF Bypass', | |
| 'Auto Playwright code execution' | |
| ] | |
| }); | |
| }); | |
| app.listen(PORT, '0.0.0.0', () => { | |
| console.log(`🚀 Playwright Stealth API running on port ${PORT}`); | |
| console.log(`📝 Endpoint: POST /api/s-playwright`); | |
| console.log(`🎭 Features: Anti-fingerprinting, WAF bypass, stealth mode`); | |
| }); | |
| process.on('SIGTERM', async () => { | |
| console.log('SIGTERM received, shutting down gracefully...'); | |
| process.exit(0); | |
| }); | |
| process.on('SIGINT', async () => { | |
| console.log('SIGINT received, shutting down gracefully...'); | |
| process.exit(0); | |
| }); |