nzbget (usenet, JSON-RPC) and qbittorrent (torrents, WebUI API with manual SID session). Tools: status, queue/torrents, add, pause/resume, delete. Both poll and emit module.<app>.download.added and module.<app>.download.completed — the key plex consumes to rescan; completion is keyed off real success (nzbget history SUCCESS, qbittorrent progress reaching 1), not mere queue disappearance, so a failed or deleted item is not reported as done. Typecheck; manifests parse.
89 lines
3.4 KiB
TypeScript
89 lines
3.4 KiB
TypeScript
// nzbget's tools — ported from the shared hal sdk (novox/hq ADR 0044), importing nzbget's own
|
|
// client. They return structured data (not the pre-formatted text hal returned); the mesh serves
|
|
// them through the sdk's tool harness.
|
|
|
|
import { registerModuleTools, type ToolDefinition } from "@novox/mesh-sdk/tools";
|
|
import { NzbgetClient } from "../client.js";
|
|
|
|
export function getNzbgetTools(nzbget: NzbgetClient): ToolDefinition[] {
|
|
return [
|
|
{
|
|
name: "nzbget_status",
|
|
description: "NZBGet server status: download speed, queue remaining, disk free, paused state.",
|
|
input: {},
|
|
run: async () => nzbget.getStatus(),
|
|
},
|
|
{
|
|
name: "nzbget_queue",
|
|
description: "List the current NZBGet download queue — what is downloading and how far along.",
|
|
input: {},
|
|
run: async () => {
|
|
const items = await nzbget.getQueue();
|
|
return { count: items.length, items };
|
|
},
|
|
},
|
|
{
|
|
name: "nzbget_history",
|
|
description: "Recent NZBGet download history, newest first — completed, failed and deleted items.",
|
|
input: { limit: { type: "number", description: "how many entries (default 20)" } },
|
|
run: async (args) => {
|
|
const items = await nzbget.getHistory(args.limit ? Number(args.limit) : 20);
|
|
return { count: items.length, items };
|
|
},
|
|
},
|
|
{
|
|
name: "nzbget_add",
|
|
description: "Queue an NZB download by URL, optionally into a category.",
|
|
input: {
|
|
url: { type: "string", description: "URL to the NZB file" },
|
|
category: { type: "string", description: "category name (determines download directory)" },
|
|
priority: { type: "number", description: "-100 very low … 0 normal … 100 very high (default 0)" },
|
|
paused: { type: "boolean", description: "add in paused state (default false)" },
|
|
},
|
|
run: async (args) => {
|
|
const id = await nzbget.add(
|
|
String(args.url),
|
|
args.category ? String(args.category) : "",
|
|
args.priority ? Number(args.priority) : 0,
|
|
args.paused === true || args.paused === "true",
|
|
);
|
|
return { added: id, category: args.category ? String(args.category) : null };
|
|
},
|
|
},
|
|
{
|
|
name: "nzbget_pause",
|
|
description: "Pause or resume all NZBGet downloads.",
|
|
input: { resume: { type: "boolean", description: "true to resume, false to pause (default false)" } },
|
|
run: async (args) => {
|
|
const resume = args.resume === true || args.resume === "true";
|
|
if (resume) await nzbget.resumeAll();
|
|
else await nzbget.pauseAll();
|
|
return { paused: !resume };
|
|
},
|
|
},
|
|
{
|
|
name: "nzbget_delete",
|
|
description: "Delete an NZB from the queue or from history by its NZBID.",
|
|
input: {
|
|
id: { type: "number", description: "the NZBID to delete" },
|
|
from: { type: "string", description: "'queue' (default) or 'history'" },
|
|
},
|
|
run: async (args) => {
|
|
const from = args.from === "history" ? "history" : "queue";
|
|
await nzbget.delete(Number(args.id), from);
|
|
return { deleted: Number(args.id), from };
|
|
},
|
|
},
|
|
];
|
|
}
|
|
|
|
// The tools exist only when NZBGet is configured; without a URL and password, nzbget contributes
|
|
// none rather than failing the whole runtime.
|
|
registerModuleTools("nzbget", (env) => {
|
|
try {
|
|
return getNzbgetTools(NzbgetClient.fromEnv(env));
|
|
} catch {
|
|
return [];
|
|
}
|
|
});
|