import { fetchWithTimeout } from '../base.js'; import type { SafeResponse } from '$lib/server/utils/safeFetch.js'; export interface DelugeTorrent { readonly name: string; readonly progress: number; readonly state: string; readonly download_payload_rate: number; readonly upload_payload_rate: number; readonly eta: number; readonly total_size: number; } export interface DelugeUIResponse { readonly result: { readonly torrents: Record; readonly stats: { readonly download_rate: number; readonly upload_rate: number; }; }; } export interface DelugeFreeSpaceResponse { readonly result: number; } function rpcUrl(appUrl: string): string { return `${appUrl.replace(/\/$/, '')}/json`; } async function rpcCall( url: string, method: string, params: unknown[], id: number, cookie?: string ): Promise { const headers: Record = { 'Content-Type': 'application/json' }; if (cookie) { headers['Cookie'] = cookie; } const res = await fetchWithTimeout(url, { method: 'POST', headers, body: JSON.stringify({ method, params, id }) }); if (!res.ok) { throw new Error(`Deluge API returned ${res.status}`); } return res; } function extractCookie(res: SafeResponse): string { const setCookie = res.headers.get('set-cookie'); if (!setCookie) return ''; const match = setCookie.match(/^([^;]+)/); return match ? match[1] : ''; } export async function authenticate(appUrl: string, password: string): Promise { const url = rpcUrl(appUrl); const res = await rpcCall(url, 'auth.login', [password], 1); const body = (await res.json()) as { result?: boolean }; if (!body.result) { throw new Error('Deluge authentication failed — invalid password'); } const cookie = extractCookie(res); if (!cookie) { throw new Error('Deluge did not return a session cookie'); } return cookie; } export async function fetchUIData( appUrl: string, cookie: string ): Promise { const url = rpcUrl(appUrl); const fields = [ 'name', 'progress', 'state', 'download_payload_rate', 'upload_payload_rate', 'eta', 'total_size' ]; const res = await rpcCall(url, 'web.update_ui', [fields, {}], 2, cookie); return res.json(); } export async function fetchFreeSpace( appUrl: string, cookie: string, path = '/' ): Promise { const url = rpcUrl(appUrl); const res = await rpcCall(url, 'core.get_free_space', [path], 3, cookie); return res.json(); }