Fix: Mega-Debrid "Fichier supprime" ist transient, nicht tot -- korrigiert v1.7.210
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.
This commit is contained in:
@@ -1303,6 +1303,42 @@ describe("debrid service", () => {
|
||||
expect(megaWeb).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
it("treats a Mega-Debrid 'Fichier supprimé' as transient: no account cooldown, German message, retryable", async () => {
|
||||
const settings = {
|
||||
...defaultSettings(),
|
||||
token: "",
|
||||
bestToken: "",
|
||||
allDebridToken: "",
|
||||
megaLogin: "user",
|
||||
megaPassword: "pass",
|
||||
megaCredentials: "user:pass",
|
||||
megaDebridApiEnabled: true,
|
||||
megaDebridWebEnabled: false,
|
||||
providerPrimary: "megadebrid-api" as const,
|
||||
providerSecondary: "none" as const,
|
||||
providerTertiary: "none" as const,
|
||||
autoProviderFallback: true
|
||||
};
|
||||
|
||||
globalThis.fetch = (async (input: RequestInfo | URL): Promise<Response> => {
|
||||
const url = typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
|
||||
if (url.includes("action=connectUser")) {
|
||||
return new Response(JSON.stringify({ response_code: "ok", token: "tok", vip_end: Math.floor(Date.now() / 1000) + 999999 }), { status: 200, headers: { "Content-Type": "application/json" } });
|
||||
}
|
||||
if (url.includes("action=getLink")) {
|
||||
return new Response(JSON.stringify({ response_code: "error", response_text: "Fichier supprimé chez l'hébergeur" }), { status: 200, headers: { "Content-Type": "application/json" } });
|
||||
}
|
||||
return new Response("not-found", { status: 404 });
|
||||
}) as typeof fetch;
|
||||
|
||||
const service = new DebridService(settings);
|
||||
const err = await service.unrestrictLink("https://rapidgator.net/file/maybe-dead.rar.html").then(() => null, (e: unknown) => e);
|
||||
expect(err).toBeTruthy();
|
||||
expect(String(err)).toMatch(/nicht abrufbar/i);
|
||||
expect(String(err)).not.toMatch(/supprim/i);
|
||||
expect(getMegaDebridAccountCooldownState(`${getMegaDebridAccountId("user")}:api`)).toBeNull();
|
||||
});
|
||||
|
||||
it("uses Mega Web only when it is configured as a separate fallback provider", async () => {
|
||||
const settings = {
|
||||
...defaultSettings(),
|
||||
|
||||
Reference in New Issue
Block a user