Restart repository history from target event

This commit is contained in:
2026-07-18 16:54:26 +01:00
commit e08aa0a667
71 changed files with 15963 additions and 0 deletions
+98
View File
@@ -0,0 +1,98 @@
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;
}