import asyncio from fastapi import FastAPI, HTTPException from pydantic import BaseModel from playwright.async_api import async_playwright app = FastAPI(title="SaveFrom Extractor API") class DownloadRequest(BaseModel): url: str @app.get("/") def root(): return {"status": "ok"} @app.post("/download") async def extract(req: DownloadRequest): target = f"https://en.savefrom.net/1/{req.url}" try: async with async_playwright() as p: browser = await p.chromium.launch( headless=True, args=[ "--no-sandbox", "--disable-dev-shm-usage", "--disable-blink-features=AutomationControlled", ], ) context = await browser.new_context( user_agent=( "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " "AppleWebKit/537.36 (KHTML, like Gecko) " "Chrome/120.0.0.0 Safari/537.36" ), viewport={"width": 1280, "height": 720}, ) page = await context.new_page() await page.goto(target, wait_until="networkidle", timeout=60_000) # Give SaveFrom time to populate links await page.wait_for_timeout(4000) links = await page.evaluate(""" () => { const results = []; document.querySelectorAll("a").forEach(a => { const href = a.href || ""; if (href.includes(".mp4") || href.includes(".mp3")) { results.push({ url: href, text: a.innerText || null }); } }); return results; } """) await browser.close() if not links: raise HTTPException( status_code=404, detail="No downloadable links found" ) return { "source": "neon dl", "original_url": req.url, "count": len(links), "links": links } except Exception as e: raise HTTPException( status_code=500, detail=f"Extractor error: {str(e)}" ) #if __name__ == "__main__": # uvicorn.run( # "app:app", # host="0.0.0.0", # port=int(os.environ.get("PORT", 7860)), # log_level="info" # )