Spaces:
Runtime error
Runtime error
Update main.py
Browse files
main.py
CHANGED
|
@@ -10,7 +10,8 @@ import json
|
|
| 10 |
import requests
|
| 11 |
import time
|
| 12 |
import hashlib
|
| 13 |
-
import re
|
|
|
|
| 14 |
|
| 15 |
app = FastAPI()
|
| 16 |
|
|
@@ -27,67 +28,86 @@ if not os.path.exists(TEMP_DIR):
|
|
| 27 |
os.makedirs(TEMP_DIR)
|
| 28 |
|
| 29 |
# --- CONFIGURATION ---
|
| 30 |
-
RAPID_API_KEY = "76af57b863msh20fecf9aaa3b6c6p1bbc52jsn3b00ca30e34f" # <--- ဘရိုရဲ့ Key ကို ဒီမှာ ထည့်ပါ
|
| 31 |
RAPID_API_HOST = "facebook-media-downloader1.p.rapidapi.com"
|
| 32 |
|
| 33 |
def cleanup(file_path: str):
|
| 34 |
if os.path.exists(file_path):
|
| 35 |
os.remove(file_path)
|
| 36 |
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 40 |
|
| 41 |
-
# --- PRIVATE
|
| 42 |
@app.post("/download-private")
|
| 43 |
async def download_private_fb(payload: dict = Body(...)):
|
| 44 |
html_source = payload.get("html", "")
|
| 45 |
-
logs = ["
|
| 46 |
|
| 47 |
if not html_source:
|
| 48 |
-
|
| 49 |
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
video_url = sd_match.group(1).replace('\\/', '/')
|
| 62 |
-
logs.append("SD Quality link found in source.")
|
| 63 |
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
"success": True,
|
| 67 |
-
"method": "Private Source Parser",
|
| 68 |
-
"video_url": video_url,
|
| 69 |
-
"logs": logs
|
| 70 |
-
}
|
| 71 |
-
else:
|
| 72 |
-
return {"success": False, "error": "Could not find video links in HTML. Make sure you copied everything.", "logs": logs}
|
| 73 |
-
|
| 74 |
-
except Exception as e:
|
| 75 |
-
return {"success": False, "error": str(e), "logs": logs}
|
| 76 |
|
| 77 |
-
#
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 85 |
|
| 86 |
-
|
| 87 |
-
if os.path.exists(video_path):
|
| 88 |
-
return {"success": True, "method": "Cache", "video_url": f"https://{space_id}.hf.space/get_file?id={file_id}.mp4"}
|
| 89 |
|
| 90 |
-
|
|
|
|
|
|
|
|
|
|
| 91 |
try:
|
| 92 |
api_url = f"https://{RAPID_API_HOST}/get_media"
|
| 93 |
res = requests.post(api_url, json={"url": url}, headers={"x-rapidapi-key": RAPID_API_KEY, "x-rapidapi-host": RAPID_API_HOST}, timeout=15)
|
|
@@ -95,17 +115,14 @@ async def download_fb_video(background_tasks: BackgroundTasks, url: str = Query(
|
|
| 95 |
data = res.json()
|
| 96 |
v_url = data.get("hd") or data.get("sd") or data.get("url")
|
| 97 |
if isinstance(v_url, list): v_url = v_url[0]
|
| 98 |
-
if v_url:
|
| 99 |
-
return {"success": True, "method": "RapidAPI", "video_url": v_url, "music_url": data.get("audio")}
|
| 100 |
except:
|
| 101 |
pass
|
| 102 |
-
|
| 103 |
-
# Fallback to yt-dlp
|
| 104 |
-
return {"success": False, "error": "Public download failed. Try Private Mode if this is a restricted video."}
|
| 105 |
|
| 106 |
@app.get("/get_file")
|
| 107 |
async def get_file(id: str):
|
| 108 |
file_path = os.path.join(TEMP_DIR, id)
|
| 109 |
if os.path.exists(file_path):
|
| 110 |
return FileResponse(file_path, media_type="video/mp4", filename=f"fb_hq_{id}")
|
| 111 |
-
raise HTTPException(status_code=404, detail="
|
|
|
|
| 10 |
import requests
|
| 11 |
import time
|
| 12 |
import hashlib
|
| 13 |
+
import re
|
| 14 |
+
import urllib.parse
|
| 15 |
|
| 16 |
app = FastAPI()
|
| 17 |
|
|
|
|
| 28 |
os.makedirs(TEMP_DIR)
|
| 29 |
|
| 30 |
# --- CONFIGURATION ---
|
| 31 |
+
RAPID_API_KEY = "76af57b863msh20fecf9aaa3b6c6p1bbc52jsn3b00ca30e34f" # <--- ဘရိုရဲ့ Key ကို ဒီမှာ ထည့်ပေးပါ
|
| 32 |
RAPID_API_HOST = "facebook-media-downloader1.p.rapidapi.com"
|
| 33 |
|
| 34 |
def cleanup(file_path: str):
|
| 35 |
if os.path.exists(file_path):
|
| 36 |
os.remove(file_path)
|
| 37 |
|
| 38 |
+
def clean_fb_url(url: str):
|
| 39 |
+
"""Facebook Source ထဲက ဝှက်ထားတဲ့ link တွေကို သန့်စင်ပေးခြင်း"""
|
| 40 |
+
if not url: return None
|
| 41 |
+
# Unescape backslashes (\/) and unicode
|
| 42 |
+
url = url.replace('\\/', '/')
|
| 43 |
+
try:
|
| 44 |
+
url = json.loads(f'"{url}"')
|
| 45 |
+
except:
|
| 46 |
+
pass
|
| 47 |
+
# HTML entities (&) ကို ရှင်းလင်းခြင်း
|
| 48 |
+
return urllib.parse.unquote(url).replace('&', '&')
|
| 49 |
|
| 50 |
+
# --- AGGRESSIVE PRIVATE SCRAPER ---
|
| 51 |
@app.post("/download-private")
|
| 52 |
async def download_private_fb(payload: dict = Body(...)):
|
| 53 |
html_source = payload.get("html", "")
|
| 54 |
+
logs = ["Aggressive Search started..."]
|
| 55 |
|
| 56 |
if not html_source:
|
| 57 |
+
return {"success": False, "error": "HTML Source is empty."}
|
| 58 |
|
| 59 |
+
# ရှာဖွေမည့် Key ပုံစံများ (Facebook က ဝှက်ထားတတ်သမျှ အကုန်ထည့်ထားပါသည်)
|
| 60 |
+
patterns = [
|
| 61 |
+
r'"browser_native_hd_url":"([^"]+)"',
|
| 62 |
+
r'"browser_native_sd_url":"([^"]+)"',
|
| 63 |
+
r'"playable_url_quality_hd":"([^"]+)"',
|
| 64 |
+
r'"playable_url":"([^"]+)"',
|
| 65 |
+
r'"base_url":"([^"]+)"',
|
| 66 |
+
r'hd_src:"([^"]+)"',
|
| 67 |
+
r'sd_src:"([^"]+)"',
|
| 68 |
+
r'video:\[\{url:"([^"]+)"'
|
| 69 |
+
]
|
|
|
|
|
|
|
| 70 |
|
| 71 |
+
hd_url = None
|
| 72 |
+
sd_url = None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 73 |
|
| 74 |
+
# ၁။ Pattern matching ဖြင့် လင့်ခ်များကို လိုက်ရှာခြင်း
|
| 75 |
+
for pattern in patterns:
|
| 76 |
+
matches = re.findall(pattern, html_source)
|
| 77 |
+
for match in matches:
|
| 78 |
+
cleaned = clean_fb_url(match)
|
| 79 |
+
if cleaned and "fbcdn.net" in cleaned:
|
| 80 |
+
if "_hd" in pattern or "hd_src" in pattern or "quality_hd" in pattern:
|
| 81 |
+
if not hd_url: hd_url = cleaned
|
| 82 |
+
else:
|
| 83 |
+
if not sd_url: sd_url = cleaned
|
| 84 |
+
|
| 85 |
+
# ၂။ အကယ်၍ ပုံမှန် Regex နဲ့ ရှာမတွေ့ရင် Raw CDN Link တွေကို ဇွတ်လိုက်ရှာခြင်း
|
| 86 |
+
if not hd_url and not sd_url:
|
| 87 |
+
logs.append("Direct CDN scan active...")
|
| 88 |
+
raw_links = re.findall(r'https?://[^\s"\'\\]+fbcdn\.net/[^\s"\'\\]+', html_source)
|
| 89 |
+
for link in raw_links:
|
| 90 |
+
cleaned = clean_fb_url(link)
|
| 91 |
+
if "/v/" in cleaned and ".mp4" in cleaned:
|
| 92 |
+
if "bytestart" not in cleaned: # အပိုင်းအစတွေ မဟုတ်တာ သေချာအောင်
|
| 93 |
+
hd_url = cleaned
|
| 94 |
+
break
|
| 95 |
+
|
| 96 |
+
if hd_url or sd_url:
|
| 97 |
+
logs.append("Success! Link extracted from source.")
|
| 98 |
+
return {
|
| 99 |
+
"success": True,
|
| 100 |
+
"method": "Aggressive Scraper",
|
| 101 |
+
"video_url": hd_url or sd_url,
|
| 102 |
+
"logs": logs
|
| 103 |
+
}
|
| 104 |
|
| 105 |
+
return {"success": False, "error": "Could not find any video stream. Are you sure you copied the FULL source code?", "logs": logs}
|
|
|
|
|
|
|
| 106 |
|
| 107 |
+
# --- PUBLIC DOWNLOADER ---
|
| 108 |
+
@app.get("/download")
|
| 109 |
+
async def download_fb_video(url: str = Query(...)):
|
| 110 |
+
# ဘရိုရဲ့ အရင်က အောင်မြင်ခဲ့တဲ့ API logic အတိုင်း ထားပေးထားပါတယ်
|
| 111 |
try:
|
| 112 |
api_url = f"https://{RAPID_API_HOST}/get_media"
|
| 113 |
res = requests.post(api_url, json={"url": url}, headers={"x-rapidapi-key": RAPID_API_KEY, "x-rapidapi-host": RAPID_API_HOST}, timeout=15)
|
|
|
|
| 115 |
data = res.json()
|
| 116 |
v_url = data.get("hd") or data.get("sd") or data.get("url")
|
| 117 |
if isinstance(v_url, list): v_url = v_url[0]
|
| 118 |
+
if v_url: return {"success": True, "method": "RapidAPI", "video_url": v_url}
|
|
|
|
| 119 |
except:
|
| 120 |
pass
|
| 121 |
+
return {"success": False, "error": "Public link failed. Try Private Mode."}
|
|
|
|
|
|
|
| 122 |
|
| 123 |
@app.get("/get_file")
|
| 124 |
async def get_file(id: str):
|
| 125 |
file_path = os.path.join(TEMP_DIR, id)
|
| 126 |
if os.path.exists(file_path):
|
| 127 |
return FileResponse(file_path, media_type="video/mp4", filename=f"fb_hq_{id}")
|
| 128 |
+
raise HTTPException(status_code=404, detail="Expired")
|