bsgoal / app.py
xttmctv's picture
Yeni degisiklikler eklendi
1e0ec03
from fastapi import FastAPI, Query
from fastapi.responses import StreamingResponse, PlainTextResponse, Response
import httpx
from urllib.parse import quote, unquote
import base64
app = FastAPI()
async def universal_proxy(url: str):
try:
async with httpx.AsyncClient(timeout=30.0, follow_redirects=True) as client:
r = await client.get(url)
content_type = r.headers.get("content-type", "")
original_text = r.text if "text" in content_type or url.endswith(".m3u8") else None
# M3U8 işleme
if "application/vnd.apple.mpegurl" in content_type or url.endswith(".m3u8"):
base_url = url.rsplit("/", 1)[0] + "/"
lines = original_text.splitlines()
new_lines = []
for line in lines:
line = line.strip()
if line.startswith("#EXT-X-KEY") and "URI=" in line:
key_url = line.split('URI="')[1].split('"')[0]
full_key_url = key_url if key_url.startswith("http") else base_url + key_url
encoded_key = quote(base64.urlsafe_b64encode(full_key_url.encode()).decode())
line = line.replace(key_url, f"/proxy_safe?encoded={encoded_key}")
new_lines.append(line)
elif line and not line.startswith("#"):
full_url = line if line.startswith("http") else base_url + line
encoded_url = quote(base64.urlsafe_b64encode(full_url.encode()).decode())
new_lines.append(f"/proxy_safe?encoded={encoded_url}")
else:
new_lines.append(line)
return PlainTextResponse("\n".join(new_lines), media_type="application/vnd.apple.mpegurl")
# TS, KEY ve JPEG (segment) dosyaları stream et
elif any(ext in url.lower() for ext in [".ts", ".key", ".jpeg", ".jpg", ".avif"]):
async def stream():
async with client.stream("GET", url) as resp:
async for chunk in resp.aiter_bytes():
yield chunk
return StreamingResponse(stream(), media_type=content_type)
# Diğer içerikler direkt dön
return Response(content=r.content, media_type=content_type)
except Exception as e:
return PlainTextResponse(f"Hata: {str(e)}", status_code=500)
@app.get("/proxy_safe")
async def proxy_safe(encoded: str):
try:
decoded_url = base64.urlsafe_b64decode(encoded.encode()).decode()
return await universal_proxy(decoded_url)
except Exception as e:
return PlainTextResponse(f"Base64 çözümleme hatası: {str(e)}", status_code=400)
@app.get("/proxy/ts")
async def proxy_ts(
url: str,
h_User_Agent: str = Query(None),
h_Referer: str = Query(None)
):
headers = {}
if h_User_Agent:
headers["User-Agent"] = h_User_Agent
if h_Referer:
headers["Referer"] = h_Referer
client = httpx.AsyncClient(timeout=30.0, headers=headers, follow_redirects=True)
# Burada client'ı kapatmıyoruz, stream tamamlanana kadar açık kalacak!
async def stream():
async with client.stream("GET", url) as resp:
# Eğer 200 değilse hata fırlatabiliriz veya özel işlem
resp.raise_for_status()
async for chunk in resp.aiter_bytes():
yield chunk
await client.aclose() # stream bittikten sonra client kapanacak
# İçerik tipi için HEAD yapabiliriz, ama basitçe video/mp2t ile başlayalım
# veya doğrudan content-type alabiliriz stream yanıtından, ama stream başlamadan bunu yapmak zordur.
return StreamingResponse(stream(), media_type="application/octet-stream")