mirror of
https://github.com/vatax3/ranger.git
synced 2026-07-27 13:22:14 +00:00
- Score qualité global (résolution/source/HDR/codec/langue/seeders) +
critère de tri "quality" (⭐), sélectionnable et par défaut en 2e position.
Tri par défaut élargi à tous les critères (dont priorité tracker).
- Cache court des liens débrideur résolus (TTL 15 min, clé service+hash+SE+ip)
-> seek instantané, ~5x moins d'appels débrideur/StremThru. Table dédiée,
visible et purgeable dans l'admin.
- Mode d'affichage : "detailed" (actuel) ou "simple" (famille) = 1 lien par
résolution, meilleur choix auto (cache puis score qualité).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
162 lines
5.1 KiB
Python
162 lines
5.1 KiB
Python
"""
|
|
Construction des objets stream Stremio.
|
|
|
|
Conventions de nommage compatibles AIOStreams (héritées de Torrentio) :
|
|
- "[AD+]" -> service identifié + confirmé en cache
|
|
- "[AD download]" -> service identifié, torrent non caché (clic = ajout)
|
|
"""
|
|
|
|
from utils import format_size
|
|
|
|
DEBRID_TAGS = {"alldebrid": "AD", "realdebrid": "RD", "torbox": "TB", "debridlink": "DL"}
|
|
|
|
SOURCE_EMOJIS = {
|
|
"ygg": "🐝 YGG",
|
|
"abn": "🎬 ABN",
|
|
"c411": "📡 C411",
|
|
"torr9": "🔥 Torr9",
|
|
"tr4ker": "🎯 Tr4ker",
|
|
"nyaa": "🐈 Nyaa",
|
|
"nekobt": "🐾 NekoBT",
|
|
"apibay": "🏴☠️ TPB",
|
|
"eztv": "📺 EZTV",
|
|
"unit3d": "🌐",
|
|
"torznab": "🗂️",
|
|
}
|
|
|
|
|
|
def _tracker_label(torrent):
|
|
source = torrent.get("source", "")
|
|
label = SOURCE_EMOJIS.get(source, f"🌐 {source}")
|
|
if source in ("unit3d", "torznab"):
|
|
raw = torrent.get("tracker_name", "")
|
|
if raw.startswith("http"):
|
|
from urllib.parse import urlparse
|
|
raw = (urlparse(raw).hostname or raw).split(".")[0].capitalize()
|
|
label = f"{label} {raw}".strip()
|
|
return label
|
|
|
|
|
|
def _description(torrent, prefix=None):
|
|
meta = torrent["_meta"]
|
|
tech = []
|
|
if meta["resolution"]:
|
|
tech.append(f"📺 {meta['resolution']}")
|
|
if meta["source"]:
|
|
tech.append(f"📦 {meta['source']}")
|
|
if meta["codec"]:
|
|
tech.append(f"🎞️ {meta['codec']}")
|
|
if meta["hdr"]:
|
|
tech.append(f"✨ {' '.join(meta['hdr'])}")
|
|
if meta["audio"]:
|
|
tech.append(f"🔊 {' '.join(meta['audio'][:2])}")
|
|
|
|
stats = [f"💾 {format_size(torrent.get('size', 0))}"]
|
|
seeders = torrent.get("seeders")
|
|
if seeders:
|
|
stats.append(f"👤 {seeders}")
|
|
stats.append(_tracker_label(torrent))
|
|
|
|
lines = []
|
|
if prefix:
|
|
lines.append(prefix)
|
|
if tech:
|
|
lines.append(" | ".join(tech))
|
|
if meta["lang_display"]:
|
|
lines.append(meta["lang_display"])
|
|
lines.append(torrent.get("name", ""))
|
|
lines.append(" ".join(stats))
|
|
return "\n".join(lines)
|
|
|
|
|
|
def _behavior_hints(torrent, service=None):
|
|
meta = torrent["_meta"]
|
|
hints = {
|
|
"bingeGroup": f"ranger|{service or 'p2p'}|{meta['resolution']}|{meta['codec']}",
|
|
"filename": torrent.get("name", ""),
|
|
}
|
|
size = torrent.get("size", 0)
|
|
if size:
|
|
hints["videoSize"] = size
|
|
return hints
|
|
|
|
|
|
def _stream_meta_fields(torrent):
|
|
"""
|
|
Champs de métadonnées top-level, lus par AIOStreams pour le parsing/filtrage
|
|
(repris de Frenchio). En complément des tags dans le nom.
|
|
"""
|
|
meta = torrent["_meta"]
|
|
return {
|
|
"size": torrent.get("size", 0),
|
|
"seeders": torrent.get("seeders", 0) or 0,
|
|
"quality": meta["resolution"],
|
|
"codec": meta["codec"],
|
|
"release_type": meta["source"],
|
|
"language": ", ".join(meta["languages"]),
|
|
}
|
|
|
|
|
|
def build_debrid_stream(torrent, service, cached, resolve_url):
|
|
"""Stream débrideur (caché ou non). resolve_url : URL /resolve à la lecture."""
|
|
meta = torrent["_meta"]
|
|
tag = DEBRID_TAGS.get(service, service.upper())
|
|
status = f"[{tag}+]" if cached else f"[{tag} download]"
|
|
res = f" {meta['resolution']}" if meta["resolution"] else ""
|
|
|
|
prefix = None if cached else "📥 Non caché — lecture = ajout au débrideur"
|
|
description = _description(torrent, prefix=prefix)
|
|
|
|
stream = {
|
|
# Le tag [XX+] (convention Torrentio) permet à AIOStreams d'identifier
|
|
# le service et le statut de cache.
|
|
"name": f"Ranger {status}{res}",
|
|
# title + description : compat parsers récents (description) et anciens (title)
|
|
"title": description,
|
|
"description": description,
|
|
"url": resolve_url,
|
|
"behaviorHints": _behavior_hints(torrent, service),
|
|
}
|
|
stream.update(_stream_meta_fields(torrent))
|
|
return stream
|
|
|
|
|
|
def build_simple_stream(torrent, service, cached, resolve_url, resolution):
|
|
"""
|
|
Stream du mode simplifié (famille) : un seul lien par résolution, présenté
|
|
de façon épurée. Le meilleur torrent a déjà été choisi en amont.
|
|
"""
|
|
meta = torrent["_meta"]
|
|
label = resolution or "Auto"
|
|
dot = "🟢" if cached else "🟠"
|
|
lang = meta["lang_display"] or ", ".join(meta["languages"])
|
|
infos = [f"💾 {format_size(torrent.get('size', 0))}"]
|
|
if lang:
|
|
infos.insert(0, lang)
|
|
if not cached:
|
|
infos.append("ajout au débrideur")
|
|
|
|
return {
|
|
"name": f"Ranger\n{dot} {label}",
|
|
"title": " · ".join(infos),
|
|
"description": " · ".join(infos),
|
|
"url": resolve_url,
|
|
"behaviorHints": _behavior_hints(torrent, service),
|
|
**_stream_meta_fields(torrent),
|
|
}
|
|
|
|
|
|
def build_p2p_stream(torrent):
|
|
"""Stream P2P via le moteur torrent intégré de Stremio (sans débrideur)."""
|
|
meta = torrent["_meta"]
|
|
res = f" {meta['resolution']}" if meta["resolution"] else ""
|
|
description = _description(torrent)
|
|
stream = {
|
|
"name": f"Ranger [P2P]{res}",
|
|
"title": description,
|
|
"description": description,
|
|
"infoHash": torrent["info_hash"],
|
|
"behaviorHints": _behavior_hints(torrent),
|
|
}
|
|
stream.update(_stream_meta_fields(torrent))
|
|
return stream
|