""" 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