Compare commits
No commits in common. "6c5927dbc589166161488e11de8def9eda97451a" and "18f29a6a2c58762016e5938fb75725ab6a846ae7" have entirely different histories.
6c5927dbc5
...
18f29a6a2c
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "real-debrid-downloader",
|
"name": "real-debrid-downloader",
|
||||||
"version": "1.7.197",
|
"version": "1.7.196",
|
||||||
"description": "Desktop downloader",
|
"description": "Desktop downloader",
|
||||||
"main": "build/main/main/main.js",
|
"main": "build/main/main/main.js",
|
||||||
"author": "Sucukdeluxe",
|
"author": "Sucukdeluxe",
|
||||||
|
|||||||
@ -296,8 +296,6 @@ function getMegaDebridAbortMinRunMs(): number {
|
|||||||
const megaDebridEmptyResponseStreaks = new Map<string, number>();
|
const megaDebridEmptyResponseStreaks = new Map<string, number>();
|
||||||
export const MEGA_DEBRID_EMPTY_STREAK_UNTIL_RESTART = 3;
|
export const MEGA_DEBRID_EMPTY_STREAK_UNTIL_RESTART = 3;
|
||||||
|
|
||||||
let megaDebridRotationCursor = 0;
|
|
||||||
|
|
||||||
export function recordMegaDebridEmptyResponseStreak(accountId: string): number {
|
export function recordMegaDebridEmptyResponseStreak(accountId: string): number {
|
||||||
const streak = (megaDebridEmptyResponseStreaks.get(accountId) || 0) + 1;
|
const streak = (megaDebridEmptyResponseStreaks.get(accountId) || 0) + 1;
|
||||||
megaDebridEmptyResponseStreaks.set(accountId, streak);
|
megaDebridEmptyResponseStreaks.set(accountId, streak);
|
||||||
@ -311,7 +309,6 @@ export function clearMegaDebridEmptyResponseStreak(accountId: string): void {
|
|||||||
export function resetMegaDebridRuntimeStateForTests(): void {
|
export function resetMegaDebridRuntimeStateForTests(): void {
|
||||||
megaDebridAccountCooldowns.clear();
|
megaDebridAccountCooldowns.clear();
|
||||||
megaDebridEmptyResponseStreaks.clear();
|
megaDebridEmptyResponseStreaks.clear();
|
||||||
megaDebridRotationCursor = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function pruneExpiredMegaDebridRuntimeState(now = Date.now()): number {
|
export function pruneExpiredMegaDebridRuntimeState(now = Date.now()): number {
|
||||||
@ -1908,15 +1905,7 @@ class MegaDebridClient {
|
|||||||
const providerName = `Mega-Debrid ${mode === "api" ? "API" : "Web"}`;
|
const providerName = `Mega-Debrid ${mode === "api" ? "API" : "Web"}`;
|
||||||
const linkShort = String(link || "").slice(0, 80);
|
const linkShort = String(link || "").slice(0, 80);
|
||||||
|
|
||||||
// Round-Robin statt First-Wins: ohne den Cursor startete jede Link-Aufloesung
|
for (let idx = 0; idx < accounts.length; idx += 1) {
|
||||||
// bei Account 1 und endete beim ersten brauchbaren — ein spaeterer Account kam
|
|
||||||
// nur dran, wenn ALLE davor am Limit/Cooldown waren. Live-Folge: Account 1-2
|
|
||||||
// liefen staendig ins Tageslimit, Account 3 trug den Rest allein und Account 4
|
|
||||||
// wurde nie auch nur angeschaut. Der Cursor laesst jede Aufloesung beim Account
|
|
||||||
// NACH dem zuletzt getesteten starten, alle Skip-/Cooldown-Checks bleiben.
|
|
||||||
const startOffset = ((megaDebridRotationCursor % accounts.length) + accounts.length) % accounts.length;
|
|
||||||
for (let step = 0; step < accounts.length; step += 1) {
|
|
||||||
const idx = (startOffset + step) % accounts.length;
|
|
||||||
const account = accounts[idx];
|
const account = accounts[idx];
|
||||||
const accountLabel = ` (${account.label}/${totalAccounts}, ${account.maskedLogin})`;
|
const accountLabel = ` (${account.label}/${totalAccounts}, ${account.maskedLogin})`;
|
||||||
const rotationLabel = `${account.label}/${totalAccounts} (${account.maskedLogin})`;
|
const rotationLabel = `${account.label}/${totalAccounts} (${account.maskedLogin})`;
|
||||||
@ -1960,7 +1949,6 @@ class MegaDebridClient {
|
|||||||
const testStartedAt = Date.now();
|
const testStartedAt = Date.now();
|
||||||
|
|
||||||
usableAccountSeen = true;
|
usableAccountSeen = true;
|
||||||
megaDebridRotationCursor = idx + 1;
|
|
||||||
try {
|
try {
|
||||||
const client = new MegaDebridClient(account.login, account.password, mode, allowApiFallback, megaWebUnrestrict);
|
const client = new MegaDebridClient(account.login, account.password, mode, allowApiFallback, megaWebUnrestrict);
|
||||||
const result = await client.unrestrictLink(link, signal);
|
const result = await client.unrestrictLink(link, signal);
|
||||||
@ -2039,8 +2027,8 @@ class MegaDebridClient {
|
|||||||
? `, Cooldown ${Math.ceil(failure.cooldownMs / 1000)}s`
|
? `, Cooldown ${Math.ceil(failure.cooldownMs / 1000)}s`
|
||||||
: "";
|
: "";
|
||||||
let nextLabel = "ENDE";
|
let nextLabel = "ENDE";
|
||||||
for (let nextStep = step + 1; nextStep < accounts.length; nextStep += 1) {
|
for (let nextIdx = idx + 1; nextIdx < accounts.length; nextIdx += 1) {
|
||||||
const nextAcc = accounts[(startOffset + nextStep) % accounts.length];
|
const nextAcc = accounts[nextIdx];
|
||||||
if (!isMegaDebridAccountDisabled(settings, nextAcc.id) && !isMegaDebridAccountDailyLimitReached(settings, nextAcc.id) && !getMegaDebridAccountCooldownState(`${nextAcc.id}:${mode}`)) {
|
if (!isMegaDebridAccountDisabled(settings, nextAcc.id) && !isMegaDebridAccountDailyLimitReached(settings, nextAcc.id) && !getMegaDebridAccountCooldownState(`${nextAcc.id}:${mode}`)) {
|
||||||
nextLabel = `${nextAcc.label}/${totalAccounts} (${nextAcc.maskedLogin})`;
|
nextLabel = `${nextAcc.label}/${totalAccounts} (${nextAcc.maskedLogin})`;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -2,7 +2,6 @@ import fs from "node:fs";
|
|||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import AdmZip from "adm-zip";
|
import AdmZip from "adm-zip";
|
||||||
import { APP_VERSION } from "./constants";
|
import { APP_VERSION } from "./constants";
|
||||||
import { getAccountRotationLogPath } from "./account-rotation-log";
|
|
||||||
import { getAuditLogPath } from "./audit-log";
|
import { getAuditLogPath } from "./audit-log";
|
||||||
import { getDebugSetupCheck } from "./debug-setup";
|
import { getDebugSetupCheck } from "./debug-setup";
|
||||||
import { getLogFilePath } from "./logger";
|
import { getLogFilePath } from "./logger";
|
||||||
@ -189,8 +188,6 @@ export function buildSupportBundle(manager: DownloadManager, baseDir: string, op
|
|||||||
addFileIfExists(zip, getSessionLogPath(), "logs/session.log");
|
addFileIfExists(zip, getSessionLogPath(), "logs/session.log");
|
||||||
addFileIfExists(zip, getTraceLogPath(), "logs/trace.log");
|
addFileIfExists(zip, getTraceLogPath(), "logs/trace.log");
|
||||||
addFileIfExists(zip, getTraceLogPath() ? `${getTraceLogPath()}.old` : null, "logs/trace.log.old");
|
addFileIfExists(zip, getTraceLogPath() ? `${getTraceLogPath()}.old` : null, "logs/trace.log.old");
|
||||||
addFileIfExists(zip, getAccountRotationLogPath(), "logs/account-rotation.log");
|
|
||||||
addFileIfExists(zip, getAccountRotationLogPath() ? `${getAccountRotationLogPath()}.old` : null, "logs/account-rotation.log.old");
|
|
||||||
|
|
||||||
const SUPPORT_BUNDLE_LOG_WINDOW_MS = 8 * 60 * 60 * 1000;
|
const SUPPORT_BUNDLE_LOG_WINDOW_MS = 8 * 60 * 60 * 1000;
|
||||||
addDirectoryIfExists(zip, path.join(baseDir, "session-logs"), "logs/session-logs");
|
addDirectoryIfExists(zip, path.join(baseDir, "session-logs"), "logs/session-logs");
|
||||||
|
|||||||
@ -1379,90 +1379,6 @@ describe("debrid service", () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it("verteilt Links per Round-Robin ueber ALLE Mega-Debrid-Accounts statt immer beim ersten zu starten", async () => {
|
|
||||||
const settings = {
|
|
||||||
...defaultSettings(),
|
|
||||||
token: "",
|
|
||||||
bestToken: "",
|
|
||||||
allDebridToken: "",
|
|
||||||
megaLogin: "user1",
|
|
||||||
megaPassword: "pass1",
|
|
||||||
megaCredentials: "user1:pass1\nuser2:pass2\nuser3:pass3\nuser4:pass4",
|
|
||||||
megaDebridPreferApi: false,
|
|
||||||
providerOrder: [] as const,
|
|
||||||
providerPrimary: "megadebrid" as const,
|
|
||||||
providerSecondary: "none" as const,
|
|
||||||
providerTertiary: "none" as const,
|
|
||||||
autoProviderFallback: false
|
|
||||||
};
|
|
||||||
|
|
||||||
globalThis.fetch = (async () => new Response("error", { status: 500 })) as typeof fetch;
|
|
||||||
|
|
||||||
const megaWeb = vi.fn(async () => ({
|
|
||||||
fileName: "ok.rar",
|
|
||||||
directUrl: "https://mega-web.example/ok.rar",
|
|
||||||
fileSize: null,
|
|
||||||
retriesUsed: 0
|
|
||||||
}));
|
|
||||||
|
|
||||||
const service = new DebridService(settings, { megaWebUnrestrict: megaWeb });
|
|
||||||
const usedIds: (string | undefined)[] = [];
|
|
||||||
for (let i = 0; i < 5; i += 1) {
|
|
||||||
const result = await service.unrestrictLink(`https://rapidgator.net/file/rr-${i}`);
|
|
||||||
usedIds.push((result as { sourceAccountId?: string }).sourceAccountId);
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(usedIds).toEqual([
|
|
||||||
getMegaDebridAccountId("user1"),
|
|
||||||
getMegaDebridAccountId("user2"),
|
|
||||||
getMegaDebridAccountId("user3"),
|
|
||||||
getMegaDebridAccountId("user4"),
|
|
||||||
getMegaDebridAccountId("user1")
|
|
||||||
]);
|
|
||||||
}, 30000);
|
|
||||||
|
|
||||||
it("Round-Robin respektiert Cooldowns: gesperrter Account wird in der Reihe uebersprungen", async () => {
|
|
||||||
const settings = {
|
|
||||||
...defaultSettings(),
|
|
||||||
token: "",
|
|
||||||
bestToken: "",
|
|
||||||
allDebridToken: "",
|
|
||||||
megaLogin: "user1",
|
|
||||||
megaPassword: "pass1",
|
|
||||||
megaCredentials: "user1:pass1\nuser2:pass2\nuser3:pass3",
|
|
||||||
megaDebridPreferApi: false,
|
|
||||||
providerOrder: [] as const,
|
|
||||||
providerPrimary: "megadebrid" as const,
|
|
||||||
providerSecondary: "none" as const,
|
|
||||||
providerTertiary: "none" as const,
|
|
||||||
autoProviderFallback: false
|
|
||||||
};
|
|
||||||
|
|
||||||
globalThis.fetch = (async () => new Response("error", { status: 500 })) as typeof fetch;
|
|
||||||
|
|
||||||
const megaWeb = vi.fn(async () => ({
|
|
||||||
fileName: "ok.rar",
|
|
||||||
directUrl: "https://mega-web.example/ok.rar",
|
|
||||||
fileSize: null,
|
|
||||||
retriesUsed: 0
|
|
||||||
}));
|
|
||||||
|
|
||||||
primeMegaDebridUntilRestartForTests(`${getMegaDebridAccountId("user2")}:web`);
|
|
||||||
|
|
||||||
const service = new DebridService(settings, { megaWebUnrestrict: megaWeb });
|
|
||||||
const usedIds: (string | undefined)[] = [];
|
|
||||||
for (let i = 0; i < 3; i += 1) {
|
|
||||||
const result = await service.unrestrictLink(`https://rapidgator.net/file/rr-skip-${i}`);
|
|
||||||
usedIds.push((result as { sourceAccountId?: string }).sourceAccountId);
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(usedIds).toEqual([
|
|
||||||
getMegaDebridAccountId("user1"),
|
|
||||||
getMegaDebridAccountId("user3"),
|
|
||||||
getMegaDebridAccountId("user1")
|
|
||||||
]);
|
|
||||||
}, 30000);
|
|
||||||
|
|
||||||
it("rotates to the next Mega-Debrid account when one hits its daily limit (error-based)", async () => {
|
it("rotates to the next Mega-Debrid account when one hits its daily limit (error-based)", async () => {
|
||||||
const settings = {
|
const settings = {
|
||||||
...defaultSettings(),
|
...defaultSettings(),
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user