Spaces:
Sleeping
Sleeping
| import express from 'express'; | |
| import { chromium } from 'playwright'; | |
| import { runLogin } from './login.js'; | |
| import { JSDOM } from 'jsdom'; | |
| import { Readability } from '@mozilla/readability'; | |
| const PORT = process.env.PORT || 7860; | |
| const TIMEOUT = 15000; | |
| const API_KEY = process.env.API_KEY || ''; | |
| const SPACE_ID = process.env.SPACE_ID || ''; // <-- provided by HF | |
| const HOSTNAME = SPACE_ID | |
| ? `https://${SPACE_ID.replace(/\//g, '-').replace(/_/g, '-')}.hf.space` | |
| : '(running outside HF)'; | |
| const app = express(); | |
| app.use(express.json()); | |
| /* ---- screenshot endpoint ---- */ | |
| async function shot(url, res) { | |
| if (!url?.startsWith('http')) return res.status(400).json({ error: 'bad url' }); | |
| const browser = await chromium.launch({ args: ['--no-sandbox'] }); | |
| const page = await browser.newPage({ viewport: { width:1366, height:768 } }); | |
| await page.goto(url, { waitUntil:'networkidle', timeout: TIMEOUT }); | |
| const buf = await page.screenshot({ type:'png', fullPage:true }); | |
| await browser.close(); | |
| res.type('png').send(buf); | |
| } | |
| app.get ('/shot', (req,res)=> shot(req.query.url,res)); | |
| app.post('/shot', (req,res)=> shot(req.body.url,res)); | |
| /* ---- extract endpoint ---- */ | |
| async function extract(url, res){ | |
| if (!url?.startsWith('http')) return res.status(400).json({ error:'bad url'}); | |
| const browser=await chromium.launch({ args:['--no-sandbox'] }); | |
| const page=await browser.newPage(); | |
| await page.goto(url,{ waitUntil:'networkidle', timeout: TIMEOUT}); | |
| const html=await page.content(); | |
| const title=await page.title(); | |
| const dom=new JSDOM(html,{url}); | |
| const reader=new Readability(dom.window.document).parse() || {}; | |
| const links=[...dom.window.document.querySelectorAll('a[href]')].map(a=>a.href); | |
| await browser.close(); | |
| res.json({ url,title, text:reader.textContent||'', html:reader.content||'', links}); | |
| } | |
| app.get ('/extract',(req,res)=>extract(req.query.url,res)); | |
| app.post('/extract',(req,res)=>extract(req.body.url,res)); | |
| /* POST /login β { ok, screenshot_b64 } */ | |
| app.post('/login', async (_req, res) => { | |
| const out = await runLogin(); | |
| if (!out.ok) { | |
| return res.status(500).json(out); | |
| } | |
| const b64 = out.png.toString('base64'); // <-- encode once | |
| res.json({ | |
| ok: true, | |
| screenshot_b64: `data:image/png;base64,${b64}`, // or just b64 | |
| }); | |
| }); | |
| console.log('π°οΈ Public URL will be:', HOSTNAME); | |
| app.listen(PORT, '0.0.0.0', ()=>console.log('π API ready on',PORT)); | |