mirror of
https://github.com/calibrain/shelfmark.git
synced 2026-10-04 11:21:15 +01:00
Add **TorBox** as a torrent download client for Prowlarr releases. Users can select `TorBox` in the download client settings, configure it with the new `TORBOX_API_KEY` environment variable, and verify their credentials with the connection test button. The integration supports both magnet links and `.torrent` files. It tracks the torrent lifecycle through TorBox, downloads supported book and audiobook files from the TorBox CDN, preserves safe nested file paths, and cleans up remote and local download state. Important: Shared HTTP download logs omit full download URLs and URL-bearing exception text to avoid exposing credentials, following best practices. This applies to all clients that use the shared `download_url()` path; URLs remain available to the HTTP operations themselves. --- There is already related work in progress in #1173, which includes both torrent and direct-download support for TorBox. This PR is not intended to replace or compete with that contribution. It offers the tested torrent client functionality as a smaller, focused change that can make TorBox available to the community sooner. The direct-download integration proposed in #1173 remains valuable and could be reviewed or introduced separately. Automated tests cover configuration, connection validation, magnet and torrent-file submission, API errors, status and progress handling, file retrieval, path traversal protection, cancellation, cleanup, and sensitive URL redaction. I also validated the complete flow locally with several magnet links and `.torrent` downloads. TorBox processed the torrents and Shelfmark downloaded the resulting files as expected. AI was used to help with the implementation, with human validation. This PR and long description? Took me some good minutes at night after work, but gives me joy to open this PR to share with the community this improvement.
50 lines
1.9 KiB
Python
50 lines
1.9 KiB
Python
"""TorBox Download Client settings and connection-action tests."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
from shelfmark.core.settings_registry import ActionButton, PasswordField
|
|
|
|
|
|
def _field(fields, key):
|
|
return next(field for field in fields if field.key == key)
|
|
|
|
|
|
def test_torbox_fields_are_registered_with_conditional_visibility():
|
|
from shelfmark.download.clients.settings import prowlarr_clients_settings
|
|
|
|
fields = prowlarr_clients_settings()
|
|
client_field = _field(fields, "PROWLARR_TORRENT_CLIENT")
|
|
api_key_field = _field(fields, "TORBOX_API_KEY")
|
|
test_action = _field(fields, "test_torbox")
|
|
|
|
assert {option["value"] for option in client_field.options} >= {"torbox"}
|
|
assert isinstance(api_key_field, PasswordField)
|
|
assert api_key_field.show_when == {"field": "PROWLARR_TORRENT_CLIENT", "value": "torbox"}
|
|
assert isinstance(test_action, ActionButton)
|
|
assert test_action.show_when == {"field": "PROWLARR_TORRENT_CLIENT", "value": "torbox"}
|
|
|
|
|
|
def test_torbox_connection_action_uses_unsaved_api_key(monkeypatch):
|
|
from shelfmark.core.config import config
|
|
from shelfmark.download.clients import settings as settings_module
|
|
|
|
client = MagicMock()
|
|
client.test_connection.return_value = (True, "Connected")
|
|
client_type = MagicMock(return_value=client)
|
|
monkeypatch.setattr("shelfmark.download.clients.torbox.TorBoxClient", client_type)
|
|
monkeypatch.setattr(config, "get", lambda _key, default="": "saved-key")
|
|
|
|
result = settings_module._test_torbox_connection({"TORBOX_API_KEY": "unsaved-key"})
|
|
|
|
assert result == {"success": True, "message": "Connected"}
|
|
assert client._api_key == "unsaved-key"
|
|
|
|
|
|
def test_torbox_connection_action_requires_api_key():
|
|
from shelfmark.download.clients.settings import _test_torbox_connection
|
|
|
|
assert _test_torbox_connection({"TORBOX_API_KEY": ""}) == {
|
|
"success": False,
|
|
"message": "TorBox API Key is required",
|
|
}
|