v1.7.155 Mega.nz Filename-Pre-Resolve via Public API

UX: Beim Hinzufuegen von mega.nz Links wurden bisher nur die opaken
URL-Fragmente angezeigt ("pZl1wBRQ" etc.). Echte Filenames kamen erst
beim Mega-Debrid Unrestrict-Call, d.h. unmittelbar vor Download-Start.

Fix: Neuer src/main/mega-public-api.ts holt Filename + Groesse direkt
von Mega's Public API (g.api.mega.co.nz/cs) ohne Mega-Debrid-Quota
anzufassen. AES-128-CBC Decryption der Attribute mit dem Key aus
dem URL-Fragment.

resolveFilenames (debrid.ts) ruft den neuen Resolver fuer alle
erkannten mega.nz Links auf (concurrency 4). Auf Fehler/Rate-Limit
fallback auf den bestehenden Unrestrict-Pfad.

19 neue Tests fuer URL-Parser, AES-Decryption, Mocked-Fetch.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Sucukdeluxe
2026-05-23 01:00:08 +02:00
co-authored by Claude Opus 4.7
parent 342b4180a1
commit 6a90eb500e
3 changed files with 352 additions and 0 deletions
+24
View File
@@ -6,6 +6,7 @@ import { APP_VERSION, REQUEST_RETRIES } from "./constants";
import { logger } from "./logger";
import { logAccountRotation } from "./account-rotation-log";
import { RealDebridClient, UnrestrictedLink } from "./realdebrid";
import { isMegaFileUrl, resolveMegaFilename } from "./mega-public-api";
import { compactErrorText, filenameFromUrl, looksLikeOpaqueFilename, sleep } from "./utils";
const API_TIMEOUT_MS = 30000;
@@ -3576,6 +3577,29 @@ export class DebridService {
}
}
// Mega.nz Pre-Resolve via Public API (kein Mega-Debrid-Quota-Verbrauch).
// Liefert echten Filename sobald Links in die Queue kommen, anstatt erst
// beim Unrestrict. Concurrency 4 — Mega's Public API ist tolerant gegen
// kleine Bursts.
const megaLinks = unresolved.filter((link) => !clean.has(link) && isMegaFileUrl(link));
if (megaLinks.length > 0) {
await runWithConcurrency(megaLinks, 4, async (link) => {
try {
const info = await resolveMegaFilename(link, signal);
if (info?.name) {
reportResolved(link, info.name);
}
} catch (error) {
const errorText = compactErrorText(error);
if (signal?.aborted || (/aborted/i.test(errorText) && !/timeout/i.test(errorText))) {
throw error;
}
// Schluck — Public API kann fehlen oder rate-limiten; faellt auf
// den normalen Mega-Debrid Unrestrict-Pfad zurueck.
}
});
}
const remaining = unresolved.filter((link) => !clean.has(link) && isRapidgatorLink(link));
await runWithConcurrency(remaining, 6, async (link) => {
const fromPage = await resolveRapidgatorFilename(link, signal);