Conversation
Each indexer can now name the download client its grabs go to, like Sonarr's per-indexer client setting. This lets a private tracker use its own torrent client (for example one outside a VPN, with the tracker's seeding rules) while every other indexer keeps using the highest-priority client for its protocol. - indexer_configs.download_client_id, nullable, ON DELETE SET NULL, so deleting a client returns its indexers to the default selection. - The API validates the client exists and takes the indexer's protocol (Torznab -> torrent, Newznab -> Usenet). - A pinned client is never swapped for another: if it is disabled or unavailable the grab fails with a message naming the indexer and client. - Retries and status polling already follow the persisted client id. - Prowlarr and Jackett sync leave the setting alone. - Indexer settings gain a "Download client" dropdown under Advanced Settings, and indexer cards show the pinned client. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E9gUFQEryh4gDJRKvjNUZM
Pinning an indexer to a client is only useful if a second client of the same type can exist, such as a private-tracker qBittorrent next to the default one. The add-client picker and API refused that. - Drop the one-per-type check from the API and the picker. AirDC++ already allowed several. - Status polling resolves the exact client a download was sent to (download_client_config_id), falling back to the type only for older rows recorded without it. It used the first client of the type, which would poll the wrong qBittorrent. - Completed-download path mapping and the cleanup boundary use that same client's Remote Path and Download Directory, so two clients can mount their downloads in different places. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E9gUFQEryh4gDJRKvjNUZM
This branch has not been deployed
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.
Summary
Pullbox sends every torrent grab to the highest-priority torrent client, and every Usenet grab to the highest-priority Usenet client. There is no way to keep one indexer's releases in a particular client.
That matters for private trackers. A common setup is a public-tracker qBittorrent behind a VPN, plus a second qBittorrent outside it whose IP is registered with a private tracker and which follows that tracker's seeding rules. Today, releases from the private tracker land in whichever client has the higher priority.
This adds a per-indexer "Download client" setting, like Sonarr's. Leave it at the default and nothing changes; pick a client and every grab from that indexer goes there.
Related Issues
None filed.
Changes
indexer_configs.download_client_id: nullable foreign key todownload_client_configs,ON DELETE SET NULL. Migrationi6c7d8e9f012adds it, and existing indexers stay unpinned.DownloadService.send_to_clientuses the indexer's pinned client when it has one, and the existing priority-based selection otherwise.download_client_config_idon the download record.download_client_idon create, update and response. The client must exist and take the indexer's protocol: Torznab takes torrent clients, Newznab takes Usenet clients. Sendingnullclears the pin.download_client_config_id) rather than the first client of that type, falling back to the type only for older rows without an ID. Otherwise the second qBittorrent's downloads would be polled and path-mapped through the first one.Checklist
tests/api/test_indexer_download_client.py, repeat-type cases intests/tasks/test_download_monitor_poll.pyandtest_download_post_processing_sources.py, the clients API tests (a second same-type client is now accepted),TestIndexerPinnedClientintests/integration/test_download_clients_integration.py, a migration round-trip intests/integration/test_migrations.py, and a settings render test intests/ui/test_settings_shell_ui_routes.py; the new tests fail ondevelopwithout the change. Full non-browser suite: 14,826 passed; 13 failed, all needing tools my test container lacks (ps, Docker smoke, release tooling), none in code this PR touches.ruff check src/ tests/)mypy --strictondownload_service.py,api/v1/indexers.py,ui/settings_routes.py,models/indexer.py,schemas/indexer.py)ruff format --check src/ tests/ alembic/)CHANGELOG.mdupdated: left for release prep, per the contributing guideScreenshots
The new field sits under Advanced Settings in the indexer dialog, below Priority. I haven't attached screenshots.
🤖 Generated with Claude Code