99 lines
2.8 KiB
TypeScript
99 lines
2.8 KiB
TypeScript
import parseTorrent from 'parse-torrent';
|
|
|
|
const QBIT_URL = process.env.QUI_CLIENT_PROXY;
|
|
|
|
if (!QBIT_URL) {
|
|
console.warn("QUI_CLIENT_PROXY is not set. qBittorrent integration will not work.");
|
|
}
|
|
|
|
export async function addTorrent(fileBuffer: Buffer, filename: string, category: string = 'RED'): Promise<string> {
|
|
if (!QBIT_URL) throw new Error("QUI_CLIENT_PROXY not configured");
|
|
|
|
// Parse torrent to get hash
|
|
const parsed = await parseTorrent(fileBuffer);
|
|
const hash = parsed.infoHash;
|
|
|
|
if (!hash) throw new Error("Could not parse info hash from torrent file");
|
|
|
|
const formData = new FormData();
|
|
const blob = new Blob([new Uint8Array(fileBuffer)], { type: 'application/x-bittorrent' });
|
|
formData.append('torrents', blob, filename);
|
|
formData.append('stopped', 'true'); // Add in paused state
|
|
formData.append('tags', 'Crossfade');
|
|
formData.append('category', category); // Add category
|
|
formData.append('skip_checking', 'true');
|
|
// formData.append('autoTMM', 'false');
|
|
// formData.append('savepath', '/downloads/'); // Optional: let qbit use default
|
|
|
|
const res = await fetch(`${QBIT_URL}/api/v2/torrents/add`, {
|
|
method: 'POST',
|
|
body: formData,
|
|
});
|
|
|
|
if (!res.ok) {
|
|
throw new Error(`Failed to add torrent: ${res.statusText}`);
|
|
}
|
|
|
|
return hash;
|
|
}
|
|
|
|
export async function recheckTorrent(hash: string) {
|
|
if (!QBIT_URL) throw new Error("QUI_CLIENT_PROXY not configured");
|
|
|
|
const formData = new FormData();
|
|
formData.append('hashes', hash);
|
|
|
|
const res = await fetch(`${QBIT_URL}/api/v2/torrents/recheck`, {
|
|
method: 'POST',
|
|
body: formData,
|
|
});
|
|
|
|
if (!res.ok) {
|
|
throw new Error(`Failed to trigger recheck: ${res.statusText}`);
|
|
}
|
|
}
|
|
|
|
export async function resumeTorrent(hash: string) {
|
|
if (!QBIT_URL) throw new Error("QUI_CLIENT_PROXY not configured");
|
|
|
|
const formData = new FormData();
|
|
formData.append('hashes', hash);
|
|
|
|
const res = await fetch(`${QBIT_URL}/api/v2/torrents/start`, {
|
|
method: 'POST',
|
|
body: formData,
|
|
});
|
|
|
|
if (!res.ok) {
|
|
throw new Error(`Failed to resume torrent: ${res.statusText}`);
|
|
}
|
|
}
|
|
|
|
export interface TorrentInfo {
|
|
hash: string;
|
|
name: string;
|
|
state: string;
|
|
progress: number;
|
|
size: number;
|
|
added_on: number;
|
|
completion_on: number;
|
|
}
|
|
|
|
export async function getTorrentInfo(hash: string): Promise<TorrentInfo | null> {
|
|
if (!QBIT_URL) throw new Error("QUI_CLIENT_PROXY not configured");
|
|
|
|
const res = await fetch(`${QBIT_URL}/api/v2/torrents/info?hashes=${hash}`);
|
|
|
|
if (!res.ok) {
|
|
throw new Error(`Failed to get torrent info: ${res.statusText}`);
|
|
}
|
|
|
|
const data = await res.json();
|
|
if (Array.isArray(data) && data.length > 0) {
|
|
//console.log(data);
|
|
return data[0] as TorrentInfo;
|
|
}
|
|
|
|
return null;
|
|
}
|