Refactor
This commit is contained in:
144
backend/api.py
Normal file
144
backend/api.py
Normal file
@@ -0,0 +1,144 @@
|
||||
from io import BytesIO
|
||||
import requests
|
||||
import os
|
||||
from backend.utils import format_size, calculate_age
|
||||
|
||||
YGG_PASSKEY = os.getenv("YGG_PASSKEY")
|
||||
ALLDEBRID_API_KEY = os.getenv("ALLDEBRID_API_KEY")
|
||||
NTFY_TOPIC_URL = os.getenv("NTFY_TOPIC_URL")
|
||||
NTFY_TOKEN = os.getenv("NTFY_TOKEN")
|
||||
|
||||
MAX_SIZE_BYTES = 5*1024**3
|
||||
NB_PAGES = 2
|
||||
|
||||
def check_alldebrid_status():
|
||||
# Retourne True si premium actif, False sinon
|
||||
try:
|
||||
r = requests.get(
|
||||
"https://api.alldebrid.com/v4/user",
|
||||
params={"agent": "ygg-service", "apikey": ALLDEBRID_API_KEY},
|
||||
timeout=5
|
||||
)
|
||||
data = r.json()
|
||||
return data.get("data", {}).get("user", {}).get("isPremium", False)
|
||||
except Exception as e:
|
||||
print("Erreur AllDebrid:", e)
|
||||
return False
|
||||
|
||||
def send_ntfy(title, message):
|
||||
# Envoie une notification sur le topic ntfy, avec token si nécessaire
|
||||
headers = {"Title": title}
|
||||
if NTFY_TOKEN:
|
||||
headers["Authorization"] = f"Bearer {NTFY_TOKEN}"
|
||||
|
||||
try:
|
||||
r = requests.post(
|
||||
NTFY_TOPIC_URL,
|
||||
data=message.encode("utf-8"),
|
||||
headers=headers,
|
||||
timeout=5
|
||||
)
|
||||
if r.status_code not in (200, 201):
|
||||
print(f"❌ Échec notification ({r.status_code}): {r.text}")
|
||||
else:
|
||||
print(f"✅ Notification envoyée : {title}")
|
||||
except Exception as e:
|
||||
print("Erreur ntfy:", e)
|
||||
|
||||
def search_torrents(query: str, category_id: str | None = None) -> list[dict]:
|
||||
"""Recherche des torrents sur l'API Yggtorrent, retourne la liste brute."""
|
||||
url = "https://yggapi.eu/torrents"
|
||||
params = {
|
||||
"page": 1,
|
||||
"q": query,
|
||||
"order_by": "uploaded_at",
|
||||
"per_page": 100
|
||||
}
|
||||
if category_id:
|
||||
params["category_id"] = category_id
|
||||
|
||||
results = []
|
||||
try:
|
||||
for page in range(1, NB_PAGES + 1):
|
||||
params['page'] = page
|
||||
r = requests.get(url, params=params, timeout=5)
|
||||
r.raise_for_status()
|
||||
data = r.json()
|
||||
results.extend(data)
|
||||
except requests.exceptions.RequestException as e:
|
||||
print("Erreur API Yggtorrent:", e)
|
||||
results = []
|
||||
|
||||
return results
|
||||
|
||||
def filter_and_format_torrents(torrents: list[dict]) -> list[dict]:
|
||||
"""Filtre les torrents trop gros et formate la taille et l'âge."""
|
||||
filtered = []
|
||||
for t in torrents:
|
||||
if t['size'] <= MAX_SIZE_BYTES:
|
||||
t['size'] = format_size(t['size'])
|
||||
days, human = calculate_age(t['uploaded_at'])
|
||||
t['age_days'] = days
|
||||
t['age_human'] = human
|
||||
filtered.append(t)
|
||||
return filtered
|
||||
|
||||
def download_torrent_ygg(torrent_id: str) -> tuple[bytes, str]:
|
||||
# Télécharge le fichier .torrent depuis Yggtorrent
|
||||
url = f"https://yggapi.eu/torrent/{torrent_id}/download"
|
||||
params = {
|
||||
"passkey": YGG_PASSKEY,
|
||||
"tracker_domain": "tracker.p2p-world.net"
|
||||
}
|
||||
r = requests.get(url, params=params, timeout=10, allow_redirects=True)
|
||||
r.raise_for_status()
|
||||
filename = f"{torrent_id}.torrent"
|
||||
return r.content, filename
|
||||
|
||||
def upload_to_alldebrid(torrent_content: bytes, filename: str) -> str:
|
||||
# Upload du torrent sur Alldebrid, retourne l'ID
|
||||
headers = {"Authorization": f"Bearer {ALLDEBRID_API_KEY}"}
|
||||
files = {'files[]': (filename, BytesIO(torrent_content))}
|
||||
r = requests.post("https://api.alldebrid.com/v4/magnet/upload/file", headers=headers, files=files, timeout=20)
|
||||
r.raise_for_status()
|
||||
data = r.json()
|
||||
if data.get("status") != "success":
|
||||
raise RuntimeError(f"Upload Alldebrid échoué : {data}")
|
||||
return data["data"]["files"][0]["id"]
|
||||
|
||||
def get_alldebrid_links(debrid_id: str) -> list[dict]:
|
||||
# Récupère les liens directs Alldebrid à partir d'un ID
|
||||
headers = {"Authorization": f"Bearer {ALLDEBRID_API_KEY}"}
|
||||
|
||||
# Récupération des fichiers du magnet
|
||||
r = requests.get("https://api.alldebrid.com/v4/magnet/files", headers=headers, params={"id[]": debrid_id}, timeout=10)
|
||||
r.raise_for_status()
|
||||
data = r.json()
|
||||
if data.get("status") != "success":
|
||||
raise RuntimeError(f"Récupération liens Alldebrid échouée : {data}")
|
||||
|
||||
alldebrid_links = []
|
||||
for magnet in data.get("data", {}).get("magnets", []):
|
||||
for file in magnet.get("files", []):
|
||||
if "e" in file:
|
||||
for entry in file["e"]:
|
||||
if "l" in entry:
|
||||
alldebrid_links.append(entry["l"])
|
||||
elif "l" in file:
|
||||
alldebrid_links.append(file["l"])
|
||||
|
||||
# Débloquer les liens
|
||||
direct_links = []
|
||||
for link in alldebrid_links:
|
||||
r2 = requests.get("https://api.alldebrid.com/v4/link/unlock", headers=headers, params={"link": link}, timeout=10)
|
||||
r2.raise_for_status()
|
||||
info = r2.json()
|
||||
if info.get("status") != "success":
|
||||
raise RuntimeError(f"Déblocage lien Alldebrid échoué : {info}")
|
||||
direct_links.append({
|
||||
"name": info["data"]["filename"],
|
||||
"size": info["data"]["filesize"],
|
||||
"link": info["data"]["link"]
|
||||
})
|
||||
|
||||
return direct_links
|
||||
Reference in New Issue
Block a user