Release v1.6.81

This commit is contained in:
Sucukdeluxe 2026-03-06 12:09:39 +01:00
parent 359fb93be3
commit 3cf1bc825e
4 changed files with 68 additions and 5 deletions

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{ {
"name": "real-debrid-downloader", "name": "real-debrid-downloader",
"version": "1.6.80", "version": "1.6.81",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "real-debrid-downloader", "name": "real-debrid-downloader",
"version": "1.6.80", "version": "1.6.81",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"adm-zip": "^0.5.16", "adm-zip": "^0.5.16",

View File

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

View File

@ -52,6 +52,32 @@ interface NetscapeCookie {
value: string; value: string;
} }
function normalizeCookieDomain(domain: string): string {
return String(domain || "").trim().replace(/^\./, "").toLowerCase();
}
function dedupeCookies(cookies: NetscapeCookie[]): NetscapeCookie[] {
const deduped = new Map<string, NetscapeCookie>();
for (const cookie of cookies) {
const key = `${normalizeCookieDomain(cookie.domain)}\t${cookie.path}\t${cookie.name}`;
const existing = deduped.get(key);
if (!existing) {
deduped.set(key, cookie);
continue;
}
if (cookie.httpOnly && !existing.httpOnly) {
deduped.set(key, cookie);
continue;
}
if (cookie.expirationDate > existing.expirationDate) {
deduped.set(key, cookie);
}
}
return [...deduped.values()];
}
function parseNetscapeCookieFile(text: string): NetscapeCookie[] { function parseNetscapeCookieFile(text: string): NetscapeCookie[] {
const cookies: NetscapeCookie[] = []; const cookies: NetscapeCookie[] = [];
for (const line of text.split(/\r?\n/)) { for (const line of text.split(/\r?\n/)) {
@ -140,9 +166,9 @@ export class BestDebridWebFallback {
public async importCookiesFromFile(filePath: string): Promise<number> { public async importCookiesFromFile(filePath: string): Promise<number> {
const text = fs.readFileSync(filePath, "utf-8"); const text = fs.readFileSync(filePath, "utf-8");
const cookies = parseNetscapeCookieFile(text); const cookies = parseNetscapeCookieFile(text);
const bestDebridCookies = cookies.filter((c) => const bestDebridCookies = dedupeCookies(cookies.filter((c) =>
c.domain.includes("bestdebrid.com") c.domain.includes("bestdebrid.com")
); ));
if (bestDebridCookies.length === 0) { if (bestDebridCookies.length === 0) {
throw new Error("Keine BestDebrid-Cookies in der Datei gefunden"); throw new Error("Keine BestDebrid-Cookies in der Datei gefunden");
@ -153,6 +179,7 @@ export class BestDebridWebFallback {
} }
const currentSession = session.fromPartition(this.getPartition()); const currentSession = session.fromPartition(this.getPartition());
await this.clearPartitionState(currentSession);
for (const cookie of bestDebridCookies) { for (const cookie of bestDebridCookies) {
const url = `https://${cookie.domain.replace(/^\./, "")}${cookie.path}`; const url = `https://${cookie.domain.replace(/^\./, "")}${cookie.path}`;
@ -309,4 +336,15 @@ export class BestDebridWebFallback {
const text = await response.text(); const text = await response.text();
return isAuthenticatedBestDebridHtml(text); return isAuthenticatedBestDebridHtml(text);
} }
private async clearPartitionState(currentSession: Session): Promise<void> {
await currentSession.clearStorageData({
storages: ["cookies", "indexdb", "localstorage", "serviceworkers", "cachestorage"]
});
try {
await currentSession.clearCache();
} catch {
// ignore cache clear failures
}
}
} }

View File

@ -90,6 +90,10 @@ describe("bestdebrid-web", () => {
const count = await fallback.importCookiesFromFile(filePath); const count = await fallback.importCookiesFromFile(filePath);
expect(count).toBe(2); expect(count).toBe(2);
expect(mockClearStorageData).toHaveBeenCalledTimes(1);
expect(mockClearStorageData).toHaveBeenCalledWith({
storages: ["cookies", "indexdb", "localstorage", "serviceworkers", "cachestorage"]
});
expect(mockCookiesSet).toHaveBeenCalledTimes(2); expect(mockCookiesSet).toHaveBeenCalledTimes(2);
expect(mockCookiesSet).toHaveBeenCalledWith(expect.objectContaining({ expect(mockCookiesSet).toHaveBeenCalledWith(expect.objectContaining({
name: "PHPSESSID", name: "PHPSESSID",
@ -99,6 +103,27 @@ describe("bestdebrid-web", () => {
})); }));
}); });
it("deduplicates conflicting session cookies and prefers the HttpOnly variant", async () => {
const filePath = createCookieFile([
"# Netscape HTTP Cookie File",
"bestdebrid.com\tFALSE\t/\tTRUE\t1803585384\tPHPSESSID\tnon-http-only",
"#HttpOnly_.bestdebrid.com\tTRUE\t/\tTRUE\t1803585385\tPHPSESSID\thttp-only"
].join("\n"));
tempFiles.push(filePath);
const fallback = new BestDebridWebFallback(() => true);
const count = await fallback.importCookiesFromFile(filePath);
expect(count).toBe(1);
expect(mockCookiesSet).toHaveBeenCalledTimes(1);
expect(mockCookiesSet).toHaveBeenCalledWith(expect.objectContaining({
name: "PHPSESSID",
value: "http-only",
httpOnly: true,
domain: ".bestdebrid.com"
}));
});
it("rejects cookie files that only contain tracking cookies", async () => { it("rejects cookie files that only contain tracking cookies", async () => {
const filePath = createCookieFile([ const filePath = createCookieFile([
"# Netscape HTTP Cookie File", "# Netscape HTTP Cookie File",