real-debrid-downloader/src/main/realdebrid.ts
Sucukdeluxe cbc1ffa18b
Some checks are pending
Build and Release / build (push) Waiting to run
Add multi-provider fallback with AllDebrid and fix packaged UI path
2026-02-27 04:02:31 +01:00

82 lines
2.4 KiB
TypeScript

import { API_BASE_URL, REQUEST_RETRIES } from "./constants";
import { compactErrorText, sleep } from "./utils";
export interface UnrestrictedLink {
fileName: string;
directUrl: string;
fileSize: number | null;
retriesUsed: number;
}
function shouldRetryStatus(status: number): boolean {
return status === 429 || status >= 500;
}
function retryDelay(attempt: number): number {
return Math.min(5000, 400 * 2 ** attempt);
}
function parseErrorBody(status: number, body: string): string {
const clean = compactErrorText(body);
return clean || `HTTP ${status}`;
}
export class RealDebridClient {
private token: string;
public constructor(token: string) {
this.token = token;
}
public async unrestrictLink(link: string): Promise<UnrestrictedLink> {
let lastError = "";
for (let attempt = 1; attempt <= REQUEST_RETRIES; attempt += 1) {
try {
const body = new URLSearchParams({ link });
const response = await fetch(`${API_BASE_URL}/unrestrict/link`, {
method: "POST",
headers: {
Authorization: `Bearer ${this.token}`,
"Content-Type": "application/x-www-form-urlencoded",
"User-Agent": "RD-Node-Downloader/1.1.12"
},
body
});
const text = await response.text();
if (!response.ok) {
const parsed = parseErrorBody(response.status, text);
if (shouldRetryStatus(response.status) && attempt < REQUEST_RETRIES) {
await sleep(retryDelay(attempt));
continue;
}
throw new Error(parsed);
}
const payload = JSON.parse(text) as Record<string, unknown>;
const directUrl = String(payload.download || payload.link || "").trim();
if (!directUrl) {
throw new Error("Unrestrict ohne Download-URL");
}
const fileName = String(payload.filename || "download.bin").trim() || "download.bin";
const fileSizeRaw = Number(payload.filesize ?? NaN);
return {
fileName,
directUrl,
fileSize: Number.isFinite(fileSizeRaw) && fileSizeRaw > 0 ? Math.floor(fileSizeRaw) : null,
retriesUsed: attempt - 1
};
} catch (error) {
lastError = compactErrorText(error);
if (attempt >= REQUEST_RETRIES) {
break;
}
await sleep(retryDelay(attempt));
}
}
throw new Error(lastError || "Unrestrict fehlgeschlagen");
}
}