Spaces:
Sleeping
Sleeping
Create main.py
Browse files
main.py
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
from fastapi import FastAPI, Header, HTTPException
|
| 3 |
+
from pydantic import BaseModel
|
| 4 |
+
from typing import Optional
|
| 5 |
+
from playwright.async_api import async_playwright
|
| 6 |
+
from playwright_stealth import stealth_async
|
| 7 |
+
|
| 8 |
+
# ১. অ্যাপ্লিকেশন ইনিশিয়ালাইজেশন
|
| 9 |
+
app = FastAPI(title="Advanced Cloud Browser API", version="2.0")
|
| 10 |
+
|
| 11 |
+
# ২. সিকিউরিটি: আপনার মাস্টার API Key (Hugging Face Secrets থেকে লোড হবে)
|
| 12 |
+
# ডিফল্ট হিসেবে 'CSE_MASTER_KEY_2026' দেওয়া আছে, তবে হাগিং ফেসে এটি ওভাররাইড করা যায়।
|
| 13 |
+
MASTER_API_KEY = os.getenv("API_KEY", "CSE_MASTER_KEY_2026")
|
| 14 |
+
|
| 15 |
+
# ৩. ডেটা মডেল ভ্যালিডেশন (কেউ ভুল ডেটা পাঠালে সার্ভার ক্র্যাশ করবে না)
|
| 16 |
+
class CommandPayload(BaseModel):
|
| 17 |
+
url: str
|
| 18 |
+
js_code: Optional[str] = None # কাস্টম জাভাস্ক্রিপ্ট কোড রান করার জন্য
|
| 19 |
+
extract_html: bool = False # পুরো পেজের এইচটিএমএল দরকার হলে True করবেন
|
| 20 |
+
wait_time_ms: int = 0 # পেজ লোড হওয়ার পর এক্সট্রা ওয়েট করার জন্য (মিলিসেকেন্ডে)
|
| 21 |
+
|
| 22 |
+
# ৪. হেলথ চেক (Hugging Face Space-এর স্ট্যাটাস 'Running' দেখানোর জন্য এটি মাস্ট)
|
| 23 |
+
@app.get("/")
|
| 24 |
+
async def health_check():
|
| 25 |
+
return {"status": "System Online", "message": "Cloud Browser API is running securely."}
|
| 26 |
+
|
| 27 |
+
# ৫. মেইন API এন্ডপয়েন্ট (POST রিকোয়েস্ট)
|
| 28 |
+
@app.post("/api/v1/execute")
|
| 29 |
+
async def execute_browser_task(payload: CommandPayload, x_api_key: str = Header(None)):
|
| 30 |
+
|
| 31 |
+
# ৬. API Key ভেরিফিকেশন (ভুল কি দিলে সরাসরি রিজেক্ট করে দেবে)
|
| 32 |
+
if x_api_key != MASTER_API_KEY:
|
| 33 |
+
raise HTTPException(status_code=403, detail="Access Denied: Invalid Master API Key")
|
| 34 |
+
|
| 35 |
+
# ৭. অ্যাসিনক্রোনাস ব্রাউজার কন্ট্রোল
|
| 36 |
+
async with async_playwright() as p:
|
| 37 |
+
browser = await p.chromium.launch(
|
| 38 |
+
headless=True,
|
| 39 |
+
args=[
|
| 40 |
+
"--no-sandbox",
|
| 41 |
+
"--disable-setuid-sandbox",
|
| 42 |
+
"--disable-dev-shm-usage",
|
| 43 |
+
"--disable-blink-features=AutomationControlled",
|
| 44 |
+
"--window-size=1920,1080",
|
| 45 |
+
"--disable-web-security" # কোরস (CORS) বাইপাস করার জন্য
|
| 46 |
+
]
|
| 47 |
+
)
|
| 48 |
+
|
| 49 |
+
# ৮. হিউম্যান-লাইক কনটেক্সট এবং ফিঙ্গারপ্রিন্ট সেটআপ
|
| 50 |
+
context = await browser.new_context(
|
| 51 |
+
user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36",
|
| 52 |
+
viewport={"width": 1920, "height": 1080},
|
| 53 |
+
java_script_enabled=True
|
| 54 |
+
)
|
| 55 |
+
|
| 56 |
+
page = await context.new_page()
|
| 57 |
+
|
| 58 |
+
# ৯. ক্লাউডফেয়ার বা বট-ডিটেকশন বাইপাস করার জন্য Stealth Mode অ্যাক্টিভেট
|
| 59 |
+
await stealth_async(page)
|
| 60 |
+
|
| 61 |
+
try:
|
| 62 |
+
# ১০. কাঙ্ক্ষিত ইউআরএল-এ যাওয়া এবং নেটওয়ার্ক শান্ত হওয়া পর্যন্ত অপেক্ষা করা
|
| 63 |
+
await page.goto(payload.url, wait_until="networkidle", timeout=60000)
|
| 64 |
+
|
| 65 |
+
# ১১. কাস্টম ওয়েট টাইম (যদি ওয়েবসাইট খুব ভারী হয় বা অ্যানিমেশন থাকে)
|
| 66 |
+
if payload.wait_time_ms > 0:
|
| 67 |
+
await page.wait_for_timeout(payload.wait_time_ms)
|
| 68 |
+
|
| 69 |
+
# ১২. আপনার পাঠানো ডাইনামিক জাভাস্ক্রিপ্ট রান করা
|
| 70 |
+
script_result = None
|
| 71 |
+
if payload.js_code:
|
| 72 |
+
script_result = await page.evaluate(payload.js_code)
|
| 73 |
+
|
| 74 |
+
# ১৩. পেজের এইচটিএমএল এক্সট্রাক্ট করা (যদি রিকোয়েস্ট করা হয়)
|
| 75 |
+
html_content = await page.content() if payload.extract_html else None
|
| 76 |
+
|
| 77 |
+
# ১৪. সাকসেস রেসপন্স রিটার্ন করা
|
| 78 |
+
return {
|
| 79 |
+
"status": "success",
|
| 80 |
+
"current_url": page.url,
|
| 81 |
+
"js_output": script_result,
|
| 82 |
+
"html_extracted": bool(html_content)
|
| 83 |
+
}
|
| 84 |
+
|
| 85 |
+
except Exception as e:
|
| 86 |
+
# কোনো এরর হলে সার্ভার ক্র্যাশ না করে সুন্দরভাবে এরর মেসেজ দেবে
|
| 87 |
+
return {"status": "error", "message": str(e)}
|
| 88 |
+
|
| 89 |
+
finally:
|
| 90 |
+
# কাজ শেষ হলে বা এরর হলেও মেমরি লিক ঠেকাতে ব্রাউজার ক্লোজ করা মাস্ট
|
| 91 |
+
await browser.close()
|