v1.7.210 hat den franzoesischen Mega-Debrid-Fehler "Fichier supprime chez l'hebergeur" als permanent toten Link behandelt (Item sofort gescheitert, kein Web-Fallback). Die Support-Bundle-Logs widerlegen das: von 18 Links mit diesem Fehler haben 4 Sekunden spaeter ein OK geliefert -- 1x ueber Web, 3x ueber API-Retry (7-66s). Der Fehler ist TRANSIENT; v1.7.210 haette diese erholbaren Links faelschlich dauerhaft gekillt und den rettenden Web-Fallback abgeklemmt. Korrektur: - classifyAccountFailure: "supprime"/"introuvable" -> temporaer, cooldownMs 0, NICHT fatal. Der eigentliche Stall-Verursacher (30s Account-Cooldown, der bei nur einem Account auch alle gesunden Links via SKIP_COOLDOWN blockierte) ist damit weg, OHNE die erholbaren Links zu verlieren. - isPermanentLinkError: franzoesische Phrasen wieder entfernt (nur echte permanente engl. Signale fuer RD/AllDebrid bleiben). - Provider-Kette + interner Web-Fallback: Kurzschluss entfernt -> Web-Fallback wird wieder versucht (hat 1/4 der Links gerettet). - Pacing kommt vom bestehenden 5s-Exponential-Backoff (unrestrictDelayMs) pro Item, nicht vom Account-Cooldown -> weit unter Mega-Debrid 50 req/s, kein IP-Ban-Risiko. - Anzeige: deutsche, transient formulierte Meldung "Datei beim Hoster gerade nicht abrufbar" statt franzoesisch und statt "tot". - shared/dead-link.ts -> shared/mega-debrid-errors.ts, Semantik korrekt benannt. Tests: tests/mega-debrid-errors.test.ts + behavioraler Test in debrid.test.ts (supprime -> kein Account-Cooldown, deutsche Meldung, retrybar). Volle Suite 822/822 gruen. Behebt die Queue-Quervergiftung; macht echte tote Links bei retryLimit 0 NICHT aufgeben (vorbestehend, unveraendert). Parallel-Umwandlung folgt separat.
41 lines
1.9 KiB
TypeScript
41 lines
1.9 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { isMegaDebridResolveFailure, germanMegaDebridResolveReason } from "../src/shared/mega-debrid-errors";
|
|
|
|
describe("isMegaDebridResolveFailure", () => {
|
|
it("detects the real Mega-Debrid French resolve-failure phrase", () => {
|
|
expect(isMegaDebridResolveFailure("Mega-Debrid API: Fichier supprimé chez l'hébergeur")).toBe(true);
|
|
});
|
|
|
|
it("matches inside the aggregated provider-chain error (api fail | web timeout)", () => {
|
|
const aggregated = "Unrestrict fehlgeschlagen: Mega-Debrid API: Mega-Debrid (API): Fichier supprimé chez l'hébergeur | Mega-Debrid Web: Mega-Debrid (Web): Abbruch/Timeout nach 60s";
|
|
expect(isMegaDebridResolveFailure(aggregated)).toBe(true);
|
|
});
|
|
|
|
it("matches the de-accented variant", () => {
|
|
expect(isMegaDebridResolveFailure("Fichier supprime chez l'hebergeur")).toBe(true);
|
|
});
|
|
|
|
it("matches other Mega-Debrid resolve phrases", () => {
|
|
expect(isMegaDebridResolveFailure("Fichier introuvable")).toBe(true);
|
|
expect(isMegaDebridResolveFailure("Le fichier n'existe plus")).toBe(true);
|
|
});
|
|
|
|
it("does NOT match unrelated/transient text", () => {
|
|
expect(isMegaDebridResolveFailure("Abbruch/Timeout nach 60s")).toBe(false);
|
|
expect(isMegaDebridResolveFailure("Quota/Limit erreicht")).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe("germanMegaDebridResolveReason (transient wording, NOT 'tot')", () => {
|
|
it("renders 'supprimé' as a transient, retryable German reason", () => {
|
|
const reason = germanMegaDebridResolveReason("Mega-Debrid API: Fichier supprimé chez l'hébergeur");
|
|
expect(reason).toBe("Datei beim Hoster gerade nicht abrufbar");
|
|
expect(reason.toLowerCase()).not.toContain("tot");
|
|
expect(reason.toLowerCase()).not.toContain("gelöscht");
|
|
});
|
|
|
|
it("renders not-found phrases in German", () => {
|
|
expect(germanMegaDebridResolveReason("Fichier introuvable")).toBe("Datei beim Hoster nicht gefunden");
|
|
});
|
|
});
|