From 223354eff9b0c5098d0191702f0e0064eeaf5132 Mon Sep 17 00:00:00 2001 From: ookami125 Date: Tue, 23 Jun 2026 01:01:36 -0400 Subject: [PATCH] webui: manual add-from-feed/search endpoint; close RSS+Search (#6) Add POST /api/rss/download so the UI can grab a torrent from a feed article or a search result (magnet or .torrent URL) via the same tested add path as the auto-downloader. Marks ISSUES #6 done. Co-Authored-By: Claude Opus 4.8 --- ISSUES.md | 2 +- plugins/webui/webui.c | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/ISSUES.md b/ISSUES.md index ae25aa8..79b8a25 100644 --- a/ISSUES.md +++ b/ISSUES.md @@ -3,7 +3,7 @@ - ✅ Adding a Category means I can't have none selected on adding a torrent. - ✅ Category default download location does nothing as changing it doesn't change the download location. Download location should be greyed out by default with the default location shown. Clicking should allow you to change the location. If the location is set it shouldn't change if the category is changed. - ✅ Automation variables at half window width makes the script unseeable. It should be displayed above the script if the window is to narrow. -- ⬛ We need to implement the RSS and Search Tabs. +- ✅ We need to implement the RSS and Search Tabs. - ✅ I need to be able to add Tags on adding a torrent. - ✅ Categories aren't saved across restart. - ✅ Pausing a torrent will go back into Downloading and Seeding. diff --git a/plugins/webui/webui.c b/plugins/webui/webui.c index a8f81d7..72d397a 100644 --- a/plugins/webui/webui.c +++ b/plugins/webui/webui.c @@ -2263,6 +2263,27 @@ static void api_rss_rule(int fd, const char *body, size_t len, bool remove) { api_rss_rules_list(fd); } +/* POST /api/rss/download {magnet|torrentUrl, category, savePath, paused} + * Manually grab a torrent from a feed article or search result. Reuses the + * same add path as the auto-downloader (handles magnets and .torrent URLs). */ +static void api_rss_download(int fd, const char *body, size_t len) { + json_t *req = read_body_json(body, len); + const char *magnet = json_string_or(req, "magnet", ""); + const char *url = json_string_or(req, "torrentUrl", ""); + const char *cat = json_string_or(req, "category", ""); + const char *path = json_string_or(req, "savePath", ""); + bool paused = json_boolean_value(json_object_get(req, "paused")); + bool ok = rss_download(magnet, url, cat, path, paused); + json_decref(req); + if (ok) { + json_t *reply = json_pack("{s:b}", "ok", 1); + http_json(fd, 200, reply); + json_decref(reply); + } else { + http_text(fd, 502, "Bad Gateway", "could not add torrent from this item"); + } +} + /* POST /api/indexers upserts a Torznab indexer; .../delete removes one. */ static void api_indexer(int fd, const char *body, size_t len, bool remove) { json_t *req = read_body_json(body, len); @@ -2629,6 +2650,8 @@ static void handle_api(int fd, const char *method, char *path, api_rss_rule(fd, body, body_len, false); } else if (strcmp(path, "/api/rss/rules/delete") == 0 && strcmp(method, "POST") == 0) { api_rss_rule(fd, body, body_len, true); + } else if (strcmp(path, "/api/rss/download") == 0 && strcmp(method, "POST") == 0) { + api_rss_download(fd, body, body_len); } else if (strcmp(path, "/api/indexers") == 0 && strcmp(method, "POST") == 0) { api_indexer(fd, body, body_len, false); } else if (strcmp(path, "/api/indexers/delete") == 0 && strcmp(method, "POST") == 0) {