Compare commits

..

3 Commits

Author SHA1 Message Date
Sucukdeluxe
d9b02065a2 Release v1.6.72 2026-03-06 10:58:37 +01:00
Sucukdeluxe
aa4f69795f feat: show (API)/(Web) source labels for all providers
Real-Debrid, AllDebrid, and Mega-Debrid now show their active
mode in logs and UI (e.g. "Real-Debrid (API)" or "Real-Debrid (Web)").

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 10:58:09 +01:00
Sucukdeluxe
eb5d960e81 🐛 fix(megadebrid): deduplicate parallel connectUser API calls
Multiple parallel downloads calling connectUser simultaneously caused
token invalidation races. Only one connectUser request now runs at a
time; all parallel callers share the same result.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 10:57:10 +01:00
2 changed files with 23 additions and 3 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "real-debrid-downloader", "name": "real-debrid-downloader",
"version": "1.6.71", "version": "1.6.72",
"description": "Desktop downloader", "description": "Desktop downloader",
"main": "build/main/main/main.js", "main": "build/main/main/main.js",
"author": "Sucukdeluxe", "author": "Sucukdeluxe",

View File

@ -679,6 +679,8 @@ class MegaDebridClient {
private static cachedApiTokenAt = 0; private static cachedApiTokenAt = 0;
private static pendingConnect: Promise<string | null> | null = null;
public constructor(login: string, password: string, preferApi: boolean, megaWebUnrestrict?: MegaWebUnrestrictor) { public constructor(login: string, password: string, preferApi: boolean, megaWebUnrestrict?: MegaWebUnrestrictor) {
this.login = login; this.login = login;
this.password = password; this.password = password;
@ -692,6 +694,18 @@ class MegaDebridClient {
return MegaDebridClient.cachedApiToken; return MegaDebridClient.cachedApiToken;
} }
// Deduplicate parallel connectUser calls — only one in-flight request at a time
if (MegaDebridClient.pendingConnect) {
return MegaDebridClient.pendingConnect;
}
MegaDebridClient.pendingConnect = this.doConnectApi(signal).finally(() => {
MegaDebridClient.pendingConnect = null;
});
return MegaDebridClient.pendingConnect;
}
private async doConnectApi(signal?: AbortSignal): Promise<string | null> {
const url = `${MEGA_DEBRID_API_BASE}?action=connectUser&login=${encodeURIComponent(this.login)}&password=${encodeURIComponent(this.password)}`; const url = `${MEGA_DEBRID_API_BASE}?action=connectUser&login=${encodeURIComponent(this.login)}&password=${encodeURIComponent(this.password)}`;
const response = await fetch(url, { const response = await fetch(url, {
headers: { "User-Agent": DEBRID_USER_AGENT }, headers: { "User-Agent": DEBRID_USER_AGENT },
@ -1714,9 +1728,12 @@ export class DebridService {
if (!result) { if (!result) {
throw new Error("Real-Debrid-Web-Fallback nicht verfügbar"); throw new Error("Real-Debrid-Web-Fallback nicht verfügbar");
} }
result.sourceLabel = "Web";
return result; return result;
} }
return new RealDebridClient(settings.token).unrestrictLink(link, signal); const result = await new RealDebridClient(settings.token).unrestrictLink(link, signal);
result.sourceLabel = "API";
return result;
} }
if (provider === "megadebrid") { if (provider === "megadebrid") {
return new MegaDebridClient(settings.megaLogin, settings.megaPassword, settings.megaDebridPreferApi, this.options.megaWebUnrestrict).unrestrictLink(link, signal); return new MegaDebridClient(settings.megaLogin, settings.megaPassword, settings.megaDebridPreferApi, this.options.megaWebUnrestrict).unrestrictLink(link, signal);
@ -1727,9 +1744,12 @@ export class DebridService {
if (!result) { if (!result) {
throw new Error("AllDebrid-Web-Fallback nicht verfügbar"); throw new Error("AllDebrid-Web-Fallback nicht verfügbar");
} }
result.sourceLabel = "Web";
return result; return result;
} }
return new AllDebridClient(settings.allDebridToken).unrestrictLink(link, signal); const adResult = await new AllDebridClient(settings.allDebridToken).unrestrictLink(link, signal);
adResult.sourceLabel = "API";
return adResult;
} }
if (provider === "ddownload") { if (provider === "ddownload") {
return this.getDdownloadClient(settings.ddownloadLogin, settings.ddownloadPassword).unrestrictLink(link, signal); return this.getDdownloadClient(settings.ddownloadLogin, settings.ddownloadPassword).unrestrictLink(link, signal);