From be859e87c08b45d23217d09d8cfb12736a0d0391 Mon Sep 17 00:00:00 2001 From: Alexander Date: Mon, 11 May 2026 15:54:17 +0200 Subject: [PATCH] Add DeleteTorrent to torrent client interface for cancel cleanup Ultraworked with [Sisyphus](https://github.com/code-yeongyu/claude-agent) Co-authored-by: Sisyphus --- internal/torrent/client.go | 1 + internal/torrent/qbittorrent_client.go | 34 ++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/internal/torrent/client.go b/internal/torrent/client.go index 7d46cba..010bb73 100644 --- a/internal/torrent/client.go +++ b/internal/torrent/client.go @@ -45,5 +45,6 @@ type TorrentClient interface { Find(opts FindOptions) ([]TorrentInfo, error) AddTorrent(file TorrentFile, savePath string) error AddMagnet(magnetURI string, savePath string) error + DeleteTorrent(hash string) error DefaultSavePath() (string, error) } diff --git a/internal/torrent/qbittorrent_client.go b/internal/torrent/qbittorrent_client.go index 99fb094..a70f9b9 100644 --- a/internal/torrent/qbittorrent_client.go +++ b/internal/torrent/qbittorrent_client.go @@ -313,6 +313,40 @@ func (t *QbittorrentListItem) toTorrentInfo() TorrentInfo { } } +func (c *QbittorrentClient) DeleteTorrent(hash string) error { + log.Trace().Str("hash", hash).Msg("qbittorrent deleting torrent") + + data := url.Values{} + data.Set("hashes", hash) + data.Set("deleteFiles", "true") + + req, err := http.NewRequest("POST", c.baseURL+"/api/v2/torrents/delete", strings.NewReader(data.Encode())) + if err != nil { + log.Error().Err(err).Msg("qbittorrent creating delete request failed") + return fmt.Errorf("creating delete request: %w", err) + } + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + req.AddCookie(&http.Cookie{Name: "SID", Value: c.sid}) + + start := time.Now() + resp, err := c.client.Do(req) + if err != nil { + log.Error().Err(err).Msg("qbittorrent delete request failed") + return fmt.Errorf("delete request failed: %w", err) + } + defer resp.Body.Close() + + log.Trace().Int("status", resp.StatusCode).Dur("duration", time.Since(start)).Msg("qbittorrent delete response") + + if resp.StatusCode != http.StatusOK { + log.Error().Int("status", resp.StatusCode).Msg("qbittorrent delete returned non-OK status") + return fmt.Errorf("delete torrent returned status %d", resp.StatusCode) + } + + log.Info().Str("hash", hash).Msg("qbittorrent torrent deleted") + return nil +} + func (c *QbittorrentClient) DefaultSavePath() (string, error) { req, err := http.NewRequest("GET", c.baseURL+"/api/v2/app/defaultSavePath", nil) if err != nil {