diff --git a/backend/integrations/trackers.py b/backend/integrations/trackers.py index 9fe4ecb..9c870f9 100644 --- a/backend/integrations/trackers.py +++ b/backend/integrations/trackers.py @@ -42,9 +42,17 @@ class TrackerStat: ratio: float = 0.0 up_bytes: int = 0 down_bytes: int = 0 + # Affichage envoyé/reçu pré-formaté (si le tracker fournit des libellés tout faits + # plutôt que des octets bruts, ex. yggreborn) ; sinon on formate up_bytes/down_bytes. + up_str: str | None = None + down_str: str | None = None tokens: int | None = None # jetons/points de seed (None = le tracker n'en a pas) tokens_label: str = "jetons" + @property + def has_io(self) -> bool: + return bool(self.up_bytes or self.down_bytes or self.up_str or self.down_str) + @property def tokens_h(self) -> str: return f"{self.tokens:,}".replace(",", " ") if self.tokens is not None else "" @@ -62,11 +70,11 @@ class TrackerStat: @property def up_h(self) -> str: - return self._human(self.up_bytes) + return self.up_str if self.up_str is not None else self._human(self.up_bytes) @property def down_h(self) -> str: - return self._human(self.down_bytes) + return self.down_str if self.down_str is not None else self._human(self.down_bytes) # Sessions réutilisées (cookies httpx) et derniers résultats connus, par tracker. @@ -210,8 +218,9 @@ async def _fetch_tr4ker(spec: TrackerSpec) -> TrackerStat: async def _fetch_yggreborn(spec: TrackerSpec) -> TrackerStat: """yggreborn (YggTorrent) : site rendu serveur (Flask), login form classique avec CSRF. ⚠️ l'`identifier` est l'EMAIL (champ `type=email`), pas le pseudo. Pas de token - API ; le ratio est affiché tel quel dans l'en-tête (« Ratio : 7.63 ») -> on le lit - directement (pas de up/down exposé simplement ; l'user veut juste le ratio).""" + API : on lit la page `/account/` qui affiche les tuiles « 60.55 Go Upload », « 7.94 Go + Download » et « Ratio : 7.63 ». Pas de jetons (non demandé). Les libellés Go/To du site + sont gardés tels quels (up_str/down_str) pour ne pas perdre les décimales.""" if not (spec.base_url and spec.username and spec.password): return TrackerStat(spec.key, spec.label, ok=False, error="non configuré") @@ -227,11 +236,19 @@ async def _fetch_yggreborn(spec: TrackerSpec) -> TrackerStat: }) if "incorrect" in resp.text.lower(): raise _AuthError("identifiants refusés (identifier = email)") - rm = _YGG_RATIO.search(resp.text) - if not rm: - raise _AuthError("ratio introuvable") + acc = await client.get(f"{spec.base_url}/account/") - return TrackerStat(spec.key, spec.label, ok=True, ratio=float(rm.group(1))) + text = re.sub(r"\s+", " ", re.sub(r"<[^>]+>", " ", acc.text)) + rm = _YGG_RATIO.search(text) + if not rm: + raise _AuthError("ratio introuvable") + up = re.search(r"([\d.,]+\s*[KMGT]?o)\s*Upload\b", text) + dn = re.search(r"([\d.,]+\s*[KMGT]?o)\s*Download\b", text) + return TrackerStat( + spec.key, spec.label, ok=True, ratio=float(rm.group(1)), + up_str=up.group(1).strip().replace(".", ",") if up else None, + down_str=dn.group(1).strip().replace(".", ",") if dn else None, + ) _FETCHERS = { diff --git a/backend/templates/dashboard.html b/backend/templates/dashboard.html index 5a81f0b..2e82a40 100644 --- a/backend/templates/dashboard.html +++ b/backend/templates/dashboard.html @@ -215,7 +215,7 @@ {% if t.ok %}{{ t.ratio_h }} {% else %}{{ t.error }}{% endif %} - {% if t.ok %}{% if t.up_bytes or t.down_bytes %}