82 lines
2.4 KiB
TypeScript
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");
|
|
}
|
|
}
|