Ajouter markhs.py

This commit is contained in:
2026-04-02 08:38:56 +00:00
commit 603cbe9c34

169
markhs.py Normal file
View File

@@ -0,0 +1,169 @@
#!/usr/bin/env python3
"""
SABnzbd Post-Processing Script — UNFR Mark HS
=====================================================
En cas d'échec de vérification/réparation (statut 1),
parse le NZB original (gzippé) pour extraire le randomid
depuis <meta type="tag"> et appelle l'API UNFR markhs.
Installation :
1. Éditez la variable API_KEY ci-dessous avec votre clé UNFR.
2. Copiez ce script dans le dossier "scripts" de SABnzbd.
3. Rendez le script exécutable (chmod +x sabnzbd_markhs.py) si vous êtes sous Linux/macOS.
4. Dans SABnzbd → Config → Dossiers → Dossier des scripts, assurez-vous que le dossier est correct.
5. Assignez ce script à la catégorie voulue (ou en post-processing par défaut).
Variables d'environnement SABnzbd utilisées :
SAB_ORIG_NZB_GZ = Chemin vers le NZB original compressé (.nzb.gz)
Arguments positionnels SABnzbd :
7 = Statut post-processing (1 = échec vérification/réparation)
"""
import sys
import os
import gzip
import xml.etree.ElementTree as ET
import urllib.request
import urllib.parse
import urllib.error
# ──────────────────────────────────────────────
# CONFIGURATION UNFR
# ──────────────────────────────────────────────
# Remplacez "METTRE_VOTRE_CLE_ICI" par votre clé API UNFR
API_KEY = "METTRE_VOTRE_CLE_ICI"
API_BASE_URL = "https://unfr.pw/api_verif_hs.php"
# ──────────────────────────────────────────────
def log_info(msg):
"""Affiche un message d'information visible dans les logs SABnzbd."""
print(f"[INFO] {msg}", flush=True)
def log_error(msg):
"""Affiche un message d'erreur visible dans les logs SABnzbd."""
print(f"[ERROR] {msg}", flush=True)
def extract_randomid(nzb_gz_path):
"""
Décompresse le NZB gzippé, parse le XML et retourne
la valeur de <meta type="tag">...</meta>.
"""
log_info(f"Lecture NZB : {nzb_gz_path}")
with gzip.open(nzb_gz_path, "rb") as f:
xml_data = f.read()
root = ET.fromstring(xml_data)
# Le namespace NZB standard
ns = {"nzb": "http://www.newzbin.com/DTD/2003/nzb"}
# Cherche <meta type="tag">value</meta> avec namespace
for meta in root.findall(".//nzb:head/nzb:meta", ns):
if meta.get("type") == "tag" and meta.text:
return meta.text.strip()
# Fallback sans namespace (certains NZB n'en ont pas)
for meta in root.findall(".//head/meta"):
if meta.get("type") == "tag" and meta.text:
return meta.text.strip()
# Dernier fallback : chercher partout
for meta in root.iter():
tag_local = meta.tag.split("}")[-1] if "}" in meta.tag else meta.tag
if tag_local == "meta" and meta.get("type") == "tag" and meta.text:
return meta.text.strip()
return None
def call_markhs(randomid, extra_info=""):
"""Appelle l'API UNFR pour marquer la release HS."""
params = {
"apikey": API_KEY,
"action": "markhs",
"randomid": randomid,
}
if extra_info:
params["extra_info"] = extra_info
query = urllib.parse.urlencode(params, quote_via=urllib.parse.quote)
url = f"{API_BASE_URL}?{query}"
# Masquage de la clé API et décodage pour un affichage propre dans les logs
log_url = url.replace(API_KEY, "***")
log_info(f"Appel API : {urllib.parse.unquote(log_url)}")
try:
req = urllib.request.Request(url, method="GET")
with urllib.request.urlopen(req, timeout=30) as resp:
body = resp.read().decode("utf-8", errors="replace")
log_info(f"Réponse API ({resp.status}) : {body[:500]}")
return resp.status == 200
except urllib.error.HTTPError as e:
body = e.read().decode("utf-8", errors="replace")
log_error(f"Erreur HTTP {e.code} : {e.reason} | body={body[:500]}")
except urllib.error.URLError as e:
log_error(f"Erreur réseau : {e.reason}")
except Exception as e:
log_error(f"Erreur inattendue : {e}")
return False
def main():
log_info(f"Script démarré - python {sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}")
if len(sys.argv) < 8:
log_error("Pas assez d'arguments — ce script doit être lancé par SABnzbd lors du post-processing.")
sys.exit(0)
clean_name = sys.argv[3]
category = sys.argv[5]
status = sys.argv[7]
log_info(f"Job : {clean_name}")
log_info(f"Catégorie : {category}")
log_info(f"Statut : {status}")
# ── Seul le statut 1 (échec vérification/réparation) nous intéresse ──
if status != "1":
log_info("Statut non concerné (téléchargement réussi) — rien à signaler.")
sys.exit(0)
if API_KEY == "METTRE_VOTRE_CLE_ICI" or not API_KEY:
log_error("L'API Key n'a pas été configurée dans le script. Veuillez éditer sabnzbd_markhs.py.")
sys.exit(0)
# ── Récupérer le chemin du NZB gzippé ──
nzb_gz_path = os.environ.get("SAB_ORIG_NZB_GZ", "")
if not nzb_gz_path or not os.path.isfile(nzb_gz_path):
log_error(f"SAB_ORIG_NZB_GZ introuvable ou invalide ({nzb_gz_path})")
sys.exit(0)
# ── Extraire le randomid depuis <meta type="tag"> ──
try:
randomid = extract_randomid(nzb_gz_path)
except Exception as e:
log_error(f"Erreur lors du parsing du fichier NZB : {e}")
sys.exit(0)
if not randomid:
log_info("Aucune balise <meta type=\"tag\"> trouvée dans le NZB. Abandon.")
sys.exit(0)
log_info(f"Random ID : {randomid}")
# ── Appel API ──
extra_info = f"SABnzbd: Echec verification / reparation | job={clean_name}"
success = call_markhs(randomid, extra_info)
if success:
log_info("Release marquée HS avec succès sur UNFR.")
else:
log_error("Impossible de marquer la release HS sur UNFR.")
sys.exit(0)
if __name__ == "__main__":
main()