Add daily traffic limits, auto-sort packages, Debrid-Link multi-key improvements
Daily traffic limits: - Per-provider daily download limit (configurable in GB per provider) - Per Debrid-Link API key daily limit (individual limits per key) - Usage tracking with automatic daily reset at midnight - Provider is skipped when daily limit reached, falls back to next provider - Reset button per provider and per Debrid-Link key in account settings - Hoster routing skips daily-limited providers gracefully Debrid-Link multi-key improvements: - Keys now display with labels (#1, #2...) and masked tokens in account list - Option to show detailed per-key view with individual usage stats - Keys that hit their daily limit are automatically skipped - providerAccountId/providerAccountLabel stored per download item Auto-sort packages by progress: - Active packages automatically sorted to top during downloads - Sorted by completion ratio, then downloaded bytes - Toggle in settings (autoSortPackagesByProgress) UI polish: - Package column headers: flatter, more transparent design - LinkSnappy mode label: "Login" renamed to "Web" - Account list: new toggle for detailed Debrid-Link key display - Account usage stats section with warning styling Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
71b3612e82
commit
e212ccc86f
@@ -7,6 +7,8 @@ import AdmZip from "adm-zip";
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { DownloadManager } from "../src/main/download-manager";
|
||||
import { defaultSettings } from "../src/main/constants";
|
||||
import { parseDebridLinkApiKeys } from "../src/shared/debrid-link-keys";
|
||||
import { getProviderUsageDayKey } from "../src/shared/provider-daily-limits";
|
||||
import { createStoragePaths, emptySession } from "../src/main/storage";
|
||||
|
||||
const tempDirs: string[] = [];
|
||||
@@ -2835,7 +2837,7 @@ describe("download manager", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("retries suspicious mini files under 1 MB until the full file arrives", async () => {
|
||||
it("retries suspicious mini files under 100 KB until the full file arrives", async () => {
|
||||
const root = fs.mkdtempSync(path.join(os.tmpdir(), "rd-dm-"));
|
||||
tempDirs.push(root);
|
||||
const binary = Buffer.alloc(2 * 1024 * 1024, 21);
|
||||
@@ -4857,4 +4859,62 @@ describe("download manager", () => {
|
||||
expect(internal.speedEventsHead).toBe(0);
|
||||
expect(internal.speedBytesLastWindow).toBe(0);
|
||||
});
|
||||
|
||||
it("tracks daily usage on the actual provider key without touching other providers", () => {
|
||||
const root = fs.mkdtempSync(path.join(os.tmpdir(), "rd-dm-"));
|
||||
tempDirs.push(root);
|
||||
|
||||
const manager = new DownloadManager(
|
||||
{
|
||||
...defaultSettings(),
|
||||
megaLogin: "mega-user",
|
||||
megaPassword: "mega-pass",
|
||||
megaDebridApiEnabled: true,
|
||||
providerDailyUsageDay: getProviderUsageDayKey(),
|
||||
providerDailyUsageBytes: { realdebrid: 512 }
|
||||
},
|
||||
emptySession(),
|
||||
createStoragePaths(path.join(root, "state"))
|
||||
);
|
||||
|
||||
const internal = manager as unknown as {
|
||||
recordProviderDownloadedBytes: (provider: "megadebrid", bytes: number) => void;
|
||||
settings: ReturnType<typeof defaultSettings>;
|
||||
};
|
||||
|
||||
internal.recordProviderDownloadedBytes("megadebrid", 1024);
|
||||
|
||||
expect(internal.settings.providerDailyUsageBytes.realdebrid).toBe(512);
|
||||
expect(internal.settings.providerDailyUsageBytes["megadebrid-api"]).toBe(1024);
|
||||
expect((internal.settings.providerDailyUsageBytes as Record<string, number>).megadebrid).toBeUndefined();
|
||||
});
|
||||
|
||||
it("tracks daily usage on the actual Debrid-Link key without touching other keys", () => {
|
||||
const root = fs.mkdtempSync(path.join(os.tmpdir(), "rd-dm-"));
|
||||
tempDirs.push(root);
|
||||
const [firstKey, secondKey] = parseDebridLinkApiKeys("dl-key-one\ndl-key-two");
|
||||
|
||||
const manager = new DownloadManager(
|
||||
{
|
||||
...defaultSettings(),
|
||||
debridLinkApiKeys: "dl-key-one\ndl-key-two",
|
||||
providerDailyUsageDay: getProviderUsageDayKey(),
|
||||
providerDailyUsageBytes: { debridlink: 256 },
|
||||
debridLinkApiKeyDailyUsageBytes: { [secondKey.id]: 512 }
|
||||
},
|
||||
emptySession(),
|
||||
createStoragePaths(path.join(root, "state"))
|
||||
);
|
||||
|
||||
const internal = manager as unknown as {
|
||||
recordProviderDownloadedBytes: (provider: "debridlink", bytes: number, providerAccountId?: string) => void;
|
||||
settings: ReturnType<typeof defaultSettings>;
|
||||
};
|
||||
|
||||
internal.recordProviderDownloadedBytes("debridlink", 1024, firstKey.id);
|
||||
|
||||
expect(internal.settings.providerDailyUsageBytes.debridlink).toBe(1280);
|
||||
expect(internal.settings.debridLinkApiKeyDailyUsageBytes[firstKey.id]).toBe(1024);
|
||||
expect(internal.settings.debridLinkApiKeyDailyUsageBytes[secondKey.id]).toBe(512);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user