Prowlarr: grab search results to the download client - #101
Open
ndandan wants to merge 2 commits into
Open
Conversation
…links — upstream Shoshuo#71 Shoshuo#35 Adds a Grab action to Prowlarr manual-search results and makes the result title a link to the tracker's detail page when Prowlarr provides one. - ProwlarrClient::grab(guid, indexerId) POSTs to /api/v1/search, the same endpoint Prowlarr's own UI uses to route a grab to the indexer's configured download client (no client picker on our side). - New POST /prowlarr/grab route (prowlarr_grab) validates guid/indexerId and 400s with {ok:false,error:'invalid_request'} before touching the upstream client; otherwise returns ProwlarrClient::grab()'s result verbatim. - doSearch() rows gain an Actions column (grab button) and wrap the title in an <a href="infoUrl" target="_blank" rel="noopener"> when the indexer supplied one (folding in Shoshuo#35's spirit for this page). One delegated click listener on the results container handles the grab request, toasting success/failure and re-enabling the button on failure. - New prowlarr.search.* keys in both locale files (grab, grab_sent, grab_failed_tpl); reuses the existing prowlarr.common.actions key for the new column header. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…cker links Fix-round-1 for the Shoshuo#71 grab-action commit: - esc() (prowlarr/index.html.twig) escaped only & < > via the textContent->innerHTML round-trip. That's fine for text nodes but this page also interpolates esc() output into attributes (href, data-guid, data-indexer-id) — a `"` in indexer-supplied guid/infoUrl broke out of the attribute. Appends .replace(/"/g, '"') to the existing helper: behavior-preserving for text contexts, closes the attribute-injection gap for the new grab button + tracker link. - ProwlarrClient::search() now maps infoUrl through a new private static safeInfoUrl(), only passing through http(s) URLs (case-insensitive scheme match) — this fork's CSP blocks javascript: navigation, but this commit becomes a standalone upstream PR and upstream has no such CSP. Mirrors the scheme-allowlist pattern used by the parallel Radarr/Sonarr infoUrl task. Adds ProwlarrSafeInfoUrlTest (reflection-invoked, same convention as ClientErrorExtractionTest since the guard is private static): rejects javascript:/data:/scheme-relative/non-string/empty, keeps http(s) including an uppercase-scheme URL. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #71.
Manual search results on the Prowlarr page get an Actions column with a Grab button per release, plus tracker links on the titles (the search payload already carried
infoUrlunused — same idea as #35).ProwlarrClient::grab(guid, indexerId)POSTs Prowlarr's own/api/v1/searchgrab endpoint via the existingrequestWithError()pattern, so the release is sent to whatever download client the indexer is configured with in Prowlarr.POST /prowlarr/grabroute (admin-gated like the rest of the controller):400 {ok:false, error:"invalid_request"}on missing/invalid input, otherwise the client result passes through verbatim, and the UI toasts success or the server's error string.esc()helper now escapes"(it previously didn't, andguid/infoUrlare indexer-controlled values newly interpolated into attribute contexts), andinfoUrlgoes through anhttp(s)-only allowlist in the search mapping.Tests: controller validation + passthrough (
ProwlarrGrabTest, asserts the client is never called on invalid input) and the URL allowlist (ProwlarrSafeInfoUrlTest). 11 tests / 22 assertions green,lint:twigclean, EN+FR keys included. Verified against a live Prowlarr instance.🤖 Generated with Claude Code