Skip to content

feat: add .torrent-first submission flow with persisted tracker policy - #389

Open
buzzromain wants to merge 10 commits into
sirrobot01:betafrom
buzzromain:feat/torrent-file-storage
Open

buzzromain wants to merge 10 commits into
sirrobot01:betafrom
buzzromain:feat/torrent-file-storage

Conversation

@buzzromain

Copy link
Copy Markdown

Summary

Adds a .torrent-first submission flow while keeping full backward compatibility with magnet-link workflows:

  • use_torrent_file config option (default true, backward-compatible): when a .torrent file is available, upload it directly to the debrid provider instead of only sending a magnet link. Improves re-insertion reliability, since a .torrent file carries metadata a bare magnet link doesn't.
  • Persisted .torrent bytes: the file is saved to disk on submission and reloaded on later reinsertion (repair, managed-only auto-reinsertion), so reinsertion doesn't have to fall back to a magnet-only resubmission.
  • .torrent upload support added across AllDebrid, DebridLink, RealDebrid, and Torbox.
  • Tracker-stripping policy moved to apply at debrid-submission time only (previously at ingestion), and the original per-request choice (remove tracker URLs) is now preserved on the entry itself, so it's honoured again on reinsertion/queue-rebuild instead of only reflecting the current global setting.

Changes

  • internal/config/debrid.gouse_torrent_file field, defaults to true
  • internal/utils/magnet.go.torrent parsing/sanitization helpers (GetTorrentInfo)
  • pkg/storage/torrent_files.go — save/load/delete .torrent bytes on disk, keyed by infohash
  • pkg/storage/types.go, proto.go, storage.proto, storage.pb.go — persisted RmTrackerUrls field on Entry
  • pkg/debrid/providers/{alldebrid,realdebrid,debridlink,torbox}.torrent upload support
  • pkg/manager/{processor,fixer,active_queue}.go — wiring into submission, reinsertion, and queue-rebuild
  • pkg/server/api.go, pkg/server/qbit/torrent.go — API surface for .torrent uploads
  • Tests: internal/utils/magnet_test.go (extended), pkg/storage/torrent_files_test.go, pkg/manager/tracker_policy_test.go, pkg/debrid/providers/debridlink/debrid_link_test.go

Configuration example

{
  "debrids": [
    {
      "provider": "realdebrid",
      "api_key": "...",
      "use_torrent_file": true
    }
  ]
}

GetMagnetFromFile and GetMagnetFromUrl no longer take rmTrackerUrls —
since "apply tracker policy at debrid submission only" the stripping
happens in GetTorrentInfo/GetMagnetInfo, called just before handing the
magnet to a provider.

The Strip{True,False} pairs are kept and now route through
applyTrackerPolicy, which mirrors what the manager does at submission,
so the end-to-end behaviour stays covered.
AddNewTorrent saved the .torrent before queueing, but the retry path
added upstream — queueTorrentRetry, taken when the provider reports too
many active downloads — queued the entry without saving anything. The
Fixer then had no file to re-insert with, precisely for the torrents
held back because the provider was saturated.

Both paths now call persistTorrentFile just before queue.Add. Keeping it
there rather than before the debrid submission avoids orphaning a file
when submission fails outright, since Storage.Delete is what removes it.
doPostMultipart discarded the response body before SubmitMagnet's
multipart branch could use it, so a real API rejection only ever
surfaced as "Status: %d" — unlike the magnet-link branch, which
already included the body. Threads the body through so both branches
report the same amount of detail on failure.
RmTrackerUrls only lived on the short-lived ImportRequest, so
reinsertion (fixer.go) and queue-rebuild (active_queue.go) could only
ever consult the current global always_rm_tracker_urls setting — a
torrent added with "remove tracker URLs" checked one-off silently lost
that choice the moment it needed to be resubmitted.

Entry gains a persisted RmTrackerUrls field (EntryProto field 40), set
at creation from the original request and honoured alongside the
global setting on every later resubmission.
No test exercised SaveTorrentFile/LoadTorrentFile/DeleteTorrentFile.
The reinsertion path treats a load failure as "fall back to magnet"
rather than a hard error, so a round-trip bug here would silently
degrade reinsertions instead of surfacing anywhere obvious.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant