mirror of
https://github.com/vatax3/ranger.git
synced 2026-08-03 20:26:04 +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>
188 lines
5.4 KiB
Python
188 lines
5.4 KiB
Python
"""
|
|
Parsing des noms de release : résolution, codec, source, HDR, audio, langues.
|
|
Pensé pour le contenu français (MULTI/VFF/VOSTFR...) comme étranger.
|
|
"""
|
|
|
|
import re
|
|
|
|
RESOLUTIONS = ["4K", "1080p", "720p", "SD"]
|
|
LANGS = ["MULTI", "VFF", "VF", "VFQ", "VOSTFR", "VO"]
|
|
|
|
LANG_FLAGS = {
|
|
"MULTI": "🇫🇷🇬🇧 MULTI",
|
|
"VFF": "🇫🇷 VFF",
|
|
"VF": "🇫🇷 VF",
|
|
"VFQ": "🇨🇦 VFQ",
|
|
"VOSTFR": "🇯🇵🇫🇷 VOSTFR",
|
|
"VO": "🇬🇧 VO",
|
|
}
|
|
|
|
_WORD = lambda w: re.compile(r"(?<![A-Z0-9])" + w + r"(?![A-Z0-9])")
|
|
|
|
_RES_PATTERNS = [
|
|
("4K", re.compile(r"2160P|4K|UHD")),
|
|
("1080p", re.compile(r"1080P")),
|
|
("720p", re.compile(r"720P")),
|
|
("SD", re.compile(r"480P|576P|\bSD\b|DVDRIP")),
|
|
]
|
|
|
|
_CODEC_PATTERNS = [
|
|
("x265", re.compile(r"X265|HEVC|H\.?265")),
|
|
("x264", re.compile(r"X264|AVC|H\.?264")),
|
|
("AV1", _WORD("AV1")),
|
|
]
|
|
|
|
_SOURCE_PATTERNS = [
|
|
("REMUX", _WORD("REMUX")),
|
|
("BluRay", re.compile(r"BLU-?RAY|BRRIP|BDRIP|BDLIGHT|\bBD\b")),
|
|
("WEB-DL", re.compile(r"WEB-?DL")),
|
|
("WEBRip", _WORD("WEBRIP")),
|
|
("WEB", _WORD("WEB")),
|
|
("HDTV", _WORD("HDTV")),
|
|
("DVDRip", _WORD("DVDRIP")),
|
|
("CAM", re.compile(r"\bCAM\b|\bHDCAM\b|\bHDTS\b|HD-TS|\bTELESYNC\b|\bTS\b(?!C)")),
|
|
]
|
|
|
|
_AUDIO_PATTERNS = [
|
|
("Atmos", _WORD("ATMOS")),
|
|
("TrueHD", re.compile(r"TRUE-?HD")),
|
|
("DTS-HD", re.compile(r"DTS-?HD")),
|
|
("DTS", _WORD("DTS")),
|
|
("DD+", re.compile(r"DDP|EAC-?3|DD\+")),
|
|
("AC3", re.compile(r"\bAC-?3\b|\bDD5[. ]?1\b")),
|
|
("AAC", _WORD("AAC")),
|
|
]
|
|
|
|
|
|
def parse_release(name):
|
|
"""Analyse un nom de release et retourne un dict structuré."""
|
|
if not name:
|
|
return {
|
|
"resolution": "", "codec": "", "source": "", "hdr": [],
|
|
"audio": [], "languages": [], "lang_display": "",
|
|
}
|
|
|
|
up = name.upper().replace("_", " ")
|
|
|
|
resolution = ""
|
|
for label, pattern in _RES_PATTERNS:
|
|
if pattern.search(up):
|
|
resolution = label
|
|
break
|
|
|
|
codec = ""
|
|
for label, pattern in _CODEC_PATTERNS:
|
|
if pattern.search(up):
|
|
codec = label
|
|
break
|
|
|
|
source = ""
|
|
for label, pattern in _SOURCE_PATTERNS:
|
|
if pattern.search(up):
|
|
source = label
|
|
break
|
|
|
|
hdr = []
|
|
if re.search(r"\bHDR10\+", up):
|
|
hdr.append("HDR10+")
|
|
elif re.search(r"\bHDR", up):
|
|
hdr.append("HDR")
|
|
if re.search(r"\bDV\b|DOLBY[. ]?VISION|\bDOVI\b", up):
|
|
hdr.append("DV")
|
|
if "10BIT" in up or "10-BIT" in up:
|
|
hdr.append("10bit")
|
|
|
|
audio = [label for label, pattern in _AUDIO_PATTERNS if pattern.search(up)]
|
|
|
|
# Langues — un torrent peut en cumuler (MULTI VFF, VOSTFR + VO...)
|
|
languages = []
|
|
if re.search(r"\bMULTI\b|\bMULTI3\b|\bMULTILANG", up):
|
|
languages.append("MULTI")
|
|
if re.search(r"TRUEFRENCH|\bVFF\b|\bVFI\b|\bVF2\b", up):
|
|
languages.append("VFF")
|
|
if re.search(r"\bVFQ\b", up):
|
|
languages.append("VFQ")
|
|
if re.search(r"\bVOSTFR\b|\bSUBFRENCH\b|\bSTFR\b", up):
|
|
languages.append("VOSTFR")
|
|
if not any(l in languages for l in ("MULTI", "VFF", "VFQ")) and re.search(r"\bFRENCH\b|\bVF\b", up):
|
|
languages.append("VF")
|
|
if not languages:
|
|
# Pas de tag FR : release VO (cas standard des trackers internationaux)
|
|
languages.append("VO")
|
|
|
|
display = " ".join(LANG_FLAGS.get(l, l) for l in languages)
|
|
|
|
return {
|
|
"resolution": resolution,
|
|
"codec": codec,
|
|
"source": source,
|
|
"hdr": hdr,
|
|
"audio": audio,
|
|
"languages": languages,
|
|
"lang_display": display,
|
|
}
|
|
|
|
|
|
def best_language(languages, language_order):
|
|
"""Rang de la meilleure langue du torrent selon l'ordre de préférence."""
|
|
best = len(language_order)
|
|
for lang in languages or []:
|
|
try:
|
|
best = min(best, language_order.index(lang))
|
|
except ValueError:
|
|
continue
|
|
return best
|
|
|
|
|
|
def resolution_rank(resolution, resolution_order):
|
|
try:
|
|
return resolution_order.index(resolution)
|
|
except ValueError:
|
|
return len(resolution_order)
|
|
|
|
|
|
# --- Score de qualité global (plus élevé = meilleur) ---
|
|
|
|
_RES_SCORE = {"4K": 4000, "1080p": 3000, "720p": 2000, "SD": 1000}
|
|
_SOURCE_SCORE = {
|
|
"REMUX": 500, "BluRay": 400, "WEB-DL": 350, "WEBRip": 250,
|
|
"WEB": 220, "HDTV": 120, "DVDRip": 100, "CAM": -2000,
|
|
}
|
|
|
|
|
|
def quality_score(meta, seeders=0, language_order=None):
|
|
"""
|
|
Score de qualité d'une release, indépendant du statut de cache.
|
|
Combine résolution, source, HDR/DV, codec, langue préférée et seeders.
|
|
"""
|
|
score = 0
|
|
score += _RES_SCORE.get(meta.get("resolution"), 500)
|
|
score += _SOURCE_SCORE.get(meta.get("source"), 150)
|
|
|
|
hdr = meta.get("hdr") or []
|
|
if "DV" in hdr:
|
|
score += 120
|
|
if any(h.startswith("HDR") for h in hdr):
|
|
score += 80
|
|
if "10bit" in hdr:
|
|
score += 30
|
|
|
|
if meta.get("codec") == "x265":
|
|
score += 40 # meilleur ratio qualité/taille
|
|
elif meta.get("codec") == "AV1":
|
|
score += 50
|
|
|
|
# Langue préférée : bonus décroissant selon l'ordre de préférence
|
|
if language_order:
|
|
rank = best_language(meta.get("languages") or [], language_order)
|
|
score += max(0, (len(language_order) - rank)) * 25
|
|
|
|
# Seeders : petit bonus logarithmique (fiabilité), plafonné
|
|
try:
|
|
s = int(seeders or 0)
|
|
if s > 0:
|
|
score += min(200, int((s ** 0.5) * 10))
|
|
except (TypeError, ValueError):
|
|
pass
|
|
|
|
return score
|