diff --git a/internal/torrent/repair.go b/internal/torrent/repair.go index bd45e15..1ce9ae0 100644 --- a/internal/torrent/repair.go +++ b/internal/torrent/repair.go @@ -371,6 +371,8 @@ func (t *TorrentManager) redownloadTorrent(torrent *Torrent, selection []string) } // redownload torrent + var newTorrentID string + prevState := t.latestState resp, err := t.api.AddMagnetHash(torrent.Hash) if err != nil { if strings.Contains(err.Error(), "infringing") { @@ -386,10 +388,20 @@ func (t *TorrentManager) redownloadTorrent(torrent *Torrent, selection []string) } else if strings.Contains(err.Error(), "allowed") { t.markAsUnfixable(torrent, "torrent not allowed") } - return nil, fmt.Errorf("cannot add magnet of torrent %s (hash=%s): %v", t.GetKey(torrent), torrent.Hash, err) + if strings.Contains(err.Error(), "timeout") { + newState := t.getCurrentState() + if prevState.Eq(newState) { + return t.redownloadTorrent(torrent, selection) + } + newTorrentID = t.latestState.FirstTorrentId + } else { + return nil, fmt.Errorf("cannot add magnet of torrent %s (hash=%s): %v", t.GetKey(torrent), torrent.Hash, err) + } } - newTorrentID := resp.ID + if resp != nil { + newTorrentID = resp.ID + } time.Sleep(2 * time.Second) diff --git a/pkg/http/client.go b/pkg/http/client.go index dc77c22..2d4b0e7 100644 --- a/pkg/http/client.go +++ b/pkg/http/client.go @@ -159,9 +159,6 @@ func (r *HTTPClient) Do(req *http.Request) (*http.Response, error) { req.Header.Set("Authorization", "Bearer "+r.bearerToken) } - // check if Range header is set - reqHasRangeHeader := req.Header.Get("Range") != "" && !strings.HasPrefix(req.Header.Get("Range"), "bytes=0-") - var resp *http.Response var err error @@ -196,7 +193,7 @@ func (r *HTTPClient) Do(req *http.Request) (*http.Response, error) { } } - incr := r.shouldRetry(resp, reqHasRangeHeader, err, r.cfg.GetRateLimitSleepSecs()) + incr := r.shouldRetry(req, resp, err, r.cfg.GetRateLimitSleepSecs()) if incr > 0 { attempt += incr if attempt > r.maxRetries { @@ -211,7 +208,8 @@ func (r *HTTPClient) Do(req *http.Request) (*http.Response, error) { break } } - if err != nil && strings.Contains(err.Error(), "timeout") && req.Host == "api.real-debrid.com" && !strings.HasSuffix(req.URL.Path, "unrestrict/link") { + okWithTimeout := strings.HasSuffix(req.URL.Path, "unrestrict/link") && strings.HasSuffix(req.URL.Path, "torrents/addMagnet") + if err != nil && strings.Contains(err.Error(), "timeout") && req.Host == "api.real-debrid.com" && !okWithTimeout { r.log.Warnf("Adjust your API timeout settings, request to %s timed out", req.URL.String()) } return resp, err @@ -253,7 +251,10 @@ func (r *HTTPClient) proxyDialer(proxyURL *url.URL) (proxy.Dialer, error) { return nil, fmt.Errorf("unsupported proxy scheme: %s", proxyURL.Scheme) } -func (r *HTTPClient) shouldRetry(resp *http.Response, reqHasRangeHeader bool, err error, rateLimitSleep int) int { +func (r *HTTPClient) shouldRetry(req *http.Request, resp *http.Response, err error, rateLimitSleep int) int { + if strings.HasSuffix(req.URL.Path, "torrents/addMagnet") { + return -1 // don't retry to prevent duplicate torrents + } if err != nil && strings.HasPrefix(err.Error(), "api response error:") { if apiErr, ok := err.(*ApiErrorResponse); ok { switch apiErr.Code { @@ -300,7 +301,8 @@ func (r *HTTPClient) shouldRetry(resp *http.Response, reqHasRangeHeader bool, er return -1 } // if the request has a Range header but the server doesn't respond with a Content-Range header - if resp.StatusCode/100 == 2 && resp.Header.Get("Content-Range") == "" && reqHasRangeHeader { + hasRangeHeader := req.Header.Get("Range") != "" && !strings.HasPrefix(req.Header.Get("Range"), "bytes=0-") + if hasRangeHeader && resp.StatusCode/100 == 2 && resp.Header.Get("Content-Range") == "" { time.Sleep(10 * time.Millisecond) return 0 }