"""
Ranger — Stremio addon multi-trackers / multi-débrideurs.
v1 : films / séries / anime, contenu français comme étranger.
- Multi-débrideurs avec priorité (AllDebrid, Real-Debrid, TorBox, DebridLink)
- StremThru intégré (contournement blocage IP datacenter)
- Trackers publics (YGG, TPB, EZTV, Nyaa) + privés/semi (C411, Torr9, Tr4ker,
NekoBT, UNIT3D) + Torznab générique (Jackett/Prowlarr)
- TMDB (titres FR, anime, épisode absolu) avec fallback Cinemeta
- Filtres taille/résolution/codec/langue, tri multi-critères, déduplication
- Cache SQLite (dispo débrideur + recherches + métadonnées)
- Compatible AIOStreams (tags [XX+] / statut de cache)
"""
import asyncio
import hmac
import json
import logging
import os
import re
import time
import aiofiles
import aiohttp
from aiohttp import web
from core import cache
from core.config import decode_config, DEFAULT_CONFIG
from core.debrid import build_backends
from core.metadata import get_media_info, compute_absolute_episode
from core.search import run_search
from core import ranking
from core import formatting
logging.basicConfig(level=logging.INFO, format="%(levelname)s:%(name)s:%(message)s")
APP_VERSION = "1.0.0"
ADDON_ID = "community.ranger.addon"
PORT = int(os.getenv("PORT", "7000"))
BASE_PATH = os.path.dirname(os.path.abspath(__file__))
# Token du panel admin (si non défini, le panel est désactivé)
ADMIN_TOKEN = (os.getenv("RANGER_ADMIN_TOKEN") or "").strip()
# Compteurs runtime (dashboard admin)
RUNTIME = {
"started_at": time.time(),
"stream_requests": 0,
"streams_served": 0,
"resolve_requests": 0,
"resolve_ok": 0,
}
_JSON_SCRIPT_ESCAPES = {ord(">"): "\\u003E", ord("<"): "\\u003C", ord("&"): "\\u0026"}
def json_for_script(obj):
"""
Sérialise en JSON pour injection dans un " (ou " et consorts (XSS réfléchie sinon,
# une valeur de config pouvant casser hors du