import { Hono } from "hono"; import { res } from "../response.js"; import type { SeederRegistry } from "../SeederRegistry.js"; export function torrentsRouter(registry: SeederRegistry) { const app = new Hono(); /** List all active torrents with their current stats */ app.get("/", (c) => { return c.json(registry.listTorrents()); }); /** Add a torrent — accepts multipart/form-data with a 'torrent' file field */ app.post("/", async (c) => { const body = await c.req.parseBody(); const file = body.torrent; if (!file || typeof file === "string") { return res.badRequest(c, "Missing 'torrent' file field"); } const buf = Buffer.from(await (file as File).arrayBuffer()); try { const state = await registry.addTorrent(buf); return res.created(c, state); } catch (err) { const msg = err instanceof Error ? err.message : String(err); return res.unprocessable(c, msg); } }); /** Get stats + announce history for a specific torrent */ app.get("/:hash", (c) => { const { hash } = c.req.param(); const list = registry.listTorrents(); const torrent = list.find((t) => t.infoHashHex === hash); if (!torrent) { return res.notFound(c); } return c.json({ ...torrent, history: registry.getHistory(hash), }); }); /** Remove a torrent — sends 'stopped' to trackers then removes it */ app.delete("/:hash", async (c) => { const { hash } = c.req.param(); const removed = await registry.removeTorrent(hash); if (!removed) { return res.notFound(c); } return c.json({ ok: true }); }); return app; }