diff --git a/cmd/zurg/main.go b/cmd/zurg/main.go index 3002151..9887c4a 100644 --- a/cmd/zurg/main.go +++ b/cmd/zurg/main.go @@ -15,7 +15,7 @@ import ( "github.com/debridmediamanager.com/zurg/internal/version" "github.com/panjf2000/ants/v2" - // zurghttp "github.com/debridmediamanager.com/zurg/pkg/http" + zurghttp "github.com/debridmediamanager.com/zurg/pkg/http" "github.com/debridmediamanager.com/zurg/pkg/logutil" "github.com/debridmediamanager.com/zurg/pkg/realdebrid" "github.com/hashicorp/golang-lru/v2/expirable" @@ -43,7 +43,8 @@ func main() { cache := expirable.NewLRU[string, string](1e4, nil, time.Hour) - rd := realdebrid.NewRealDebrid(config.GetToken(), logutil.NewLogger().Named("realdebrid")) + client := zurghttp.NewHTTPClient(config.GetToken(), 3, nil) + rd := realdebrid.NewRealDebrid(config.GetToken(), client, logutil.NewLogger().Named("realdebrid")) p, err := ants.NewPool(config.GetNumOfWorkers()) if err != nil { @@ -70,7 +71,7 @@ func main() { }() // log.Debugf("Initializing chunk manager, cores: %d", runtime.NumCPU()) - // client := zurghttp.NewHTTPClient(config.GetToken(), 10, config) + // client := zurghttp.NewHTTPClient(config.GetToken(), 3, config) // chunkMgr, err := chunk.NewManager( // "", // in-memory chunks // 10485760, // 10MB chunk size diff --git a/internal/torrent/manager.go b/internal/torrent/manager.go index 0660ea6..baf3e7e 100644 --- a/internal/torrent/manager.go +++ b/internal/torrent/manager.go @@ -123,7 +123,8 @@ func NewTorrentManager(cfg config.ConfigInterface, api *realdebrid.RealDebrid, p t.SetChecksum(t.getChecksum()) if t.cfg.EnableRepair() { - go t.repairAll() + t.log.Info("Checking for torrents to repair") + t.repairAll() } go t.startRefreshJob() @@ -317,7 +318,8 @@ func (t *TorrentManager) startRefreshJob() { t.SetChecksum(t.getChecksum()) if t.cfg.EnableRepair() { - go t.repairAll() + t.log.Info("Checking for torrents to repair") + t.repairAll() } go OnLibraryUpdateHook(t.cfg) } @@ -371,11 +373,11 @@ func (t *TorrentManager) getMoreInfo(rdTorrent realdebrid.Torrent) *Torrent { var isChaotic bool selectedFiles, isChaotic = t.organizeChaos(info.Links, selectedFiles) if isChaotic { - t.log.Warnf("Torrent id=%s %s is unplayable; it is always returning a rar file (it will no longer show up in your directories)", info.ID, info.Name) + t.log.Warnf("Torrent id=%s %s is unplayable; it is always returning a rar file (it will no longer show up in your directories, zurg suggests you delete it)", info.ID, info.Name) // t.log.Debugf("You can try fixing it yourself magnet:?xt=urn:btih:%s", info.Hash) return nil } else if streamableCount == 1 { - t.log.Warnf("Torrent id=%s %s is unplayable; the lone streamable link has expired (it will no longer show up in your directories)", info.ID, info.Name) + t.log.Warnf("Torrent id=%s %s is unplayable; the lone streamable link has expired (it will no longer show up in your directories, zurg suggests you delete it)", info.ID, info.Name) // t.log.Debugf("You can try fixing it yourself magnet:?xt=urn:btih:%s", info.Hash) return nil } @@ -523,11 +525,15 @@ func (t *TorrentManager) organizeChaos(links []string, selectedFiles []*File) ([ } func (t *TorrentManager) repairAll() { - t.log.Info("Checking for torrents to repair") + proceed := t.canCapacityHandle() // blocks for approx 45 minutes if active torrents are full + if !proceed { + t.log.Error("Reached the max number of active torrents, cannot start repair") + return + } + allTorrents, _ := t.DirectoryMap.Get(ALL_TORRENTS) allTorrents.IterCb(func(_ string, torrent *Torrent) { if torrent.InProgress() { - t.log.Infof("Torrent %s is in progress, cannot repair", torrent.AccessKey) return } forRepair := false @@ -537,7 +543,8 @@ func (t *TorrentManager) repairAll() { } }) if forRepair { - t.Repair(torrent.AccessKey) + t.log.Infof("Repairing %s", torrent.AccessKey) + go t.Repair(torrent.AccessKey) } }) } @@ -551,7 +558,7 @@ func (t *TorrentManager) Repair(accessKey string) { allTorrents, _ := t.DirectoryMap.Get(ALL_TORRENTS) torrent, _ := allTorrents.Get(accessKey) if torrent == nil { - t.log.Warnf("Cannot find torrent %s anymore to repair it", accessKey) + t.log.Warnf("Cannot find torrent %s anymore so we are not repairing it", accessKey) return } @@ -560,12 +567,6 @@ func (t *TorrentManager) Repair(accessKey string) { return } - proceed := t.canCapacityHandle() // blocks for approx 45 minutes - if !proceed { - t.log.Error("Cannot add more torrents, ignoring repair request") - return - } - // make the file messy t.log.Infof("Evaluating whole torrent to find the correct files for torrent: %s", torrent.AccessKey) @@ -593,6 +594,12 @@ func (t *TorrentManager) Repair(accessKey string) { } } + proceed := t.canCapacityHandle() // blocks for approx 45 minutes if active torrents are full + if !proceed { + t.log.Error("Reached the max number of active torrents, cannot continue with the repair") + return + } + // first solution: add the same selection, maybe it can be fixed by reinsertion? if t.reinsertTorrent(torrent, "") { t.log.Infof("Successfully downloaded torrent %s to repair it", torrent.AccessKey) diff --git a/internal/universal/get.go b/internal/universal/get.go index 2992940..28bccf9 100644 --- a/internal/universal/get.go +++ b/internal/universal/get.go @@ -19,7 +19,7 @@ import ( // HandleGetRequest handles a GET request universally for both WebDAV and HTTP func HandleGetRequest(w http.ResponseWriter, r *http.Request, t *intTor.TorrentManager, c config.ConfigInterface, cache *expirable.LRU[string, string]) { - log := logutil.NewLogger().Named("uniget") + log := logutil.NewLogger().Named("file") requestPath := path.Clean(r.URL.Path) isDav := true @@ -80,26 +80,27 @@ func HandleGetRequest(w http.ResponseWriter, r *http.Request, t *intTor.TorrentM resp := t.UnrestrictUntilOk(link) if resp == nil { + log.Warnf("File %s is no longer available", file.Path) file.Link = "" t.SetChecksum("") // force a recheck - log.Warnf("File %s is no longer available", file.Path) streamErrorVideo("https://www.youtube.com/watch?v=gea_FJrtFVA", w, r, t, c, log) - return - } else if resp.Filename != filename { - // this is possible if there's only 1 streamable file in the torrent - // and then suddenly it's a rar file - actualExt := filepath.Ext(resp.Filename) - expectedExt := filepath.Ext(filename) - if actualExt != expectedExt && resp.Streamable != 1 { - log.Warnf("File was changed and is not streamable: %s and %s", filename, resp.Filename) - streamErrorVideo("https://www.youtube.com/watch?v=t9VgOriBHwE", w, r, t, c, log) - return - } else { - log.Warnf("Filename mismatch: %s and %s", filename, resp.Filename) + } else { + if resp.Filename != filename { + // this is possible if there's only 1 streamable file in the torrent + // and then suddenly it's a rar file + actualExt := filepath.Ext(resp.Filename) + expectedExt := filepath.Ext(filename) + if actualExt != expectedExt && resp.Streamable != 1 { + log.Warnf("File was changed and is not streamable: %s and %s", filename, resp.Filename) + streamErrorVideo("https://www.youtube.com/watch?v=t9VgOriBHwE", w, r, t, c, log) + return + } else { + log.Warnf("Filename mismatch: %s and %s", filename, resp.Filename) + } } + cache.Add(requestPath, resp.Download) + streamFileToResponse(file, resp.Download, w, r, t, c, log) } - cache.Add(requestPath, resp.Download) - streamFileToResponse(file, resp.Download, w, r, t, c, log) } func streamFileToResponse(file *intTor.File, url string, w http.ResponseWriter, r *http.Request, torMgr *intTor.TorrentManager, cfg config.ConfigInterface, log *zap.SugaredLogger) { diff --git a/internal/universal/head.go b/internal/universal/head.go index 62d210f..1e4bd55 100644 --- a/internal/universal/head.go +++ b/internal/universal/head.go @@ -13,7 +13,7 @@ import ( ) func HandleHeadRequest(w http.ResponseWriter, r *http.Request, t *torrent.TorrentManager, cache *expirable.LRU[string, string]) { - log := logutil.NewLogger().Named("unihead") + log := logutil.NewLogger().Named("head") requestPath := path.Clean(r.URL.Path) requestPath = strings.Replace(requestPath, "/http", "", 1) diff --git a/pkg/realdebrid/api.go b/pkg/realdebrid/api.go index 03dfca5..a9c24ca 100644 --- a/pkg/realdebrid/api.go +++ b/pkg/realdebrid/api.go @@ -19,9 +19,7 @@ type RealDebrid struct { client *zurghttp.HTTPClient } -func NewRealDebrid(accessToken string, log *zap.SugaredLogger) *RealDebrid { - maxRetries := 10 - client := zurghttp.NewHTTPClient(accessToken, maxRetries, nil) +func NewRealDebrid(accessToken string, client *zurghttp.HTTPClient, log *zap.SugaredLogger) *RealDebrid { return &RealDebrid{ log: log, client: client, @@ -177,7 +175,7 @@ func (rd *RealDebrid) SelectTorrentFiles(id string, files string) error { } defer resp.Body.Close() - rd.log.Debugf("Started the download for torrent id=%s", len(strings.Split(files, ",")), id) + rd.log.Debugf("Selected %d files and started the download for torrent id=%s", len(strings.Split(files, ",")), id) return nil } diff --git a/pkg/realdebrid/unrestrict.go b/pkg/realdebrid/unrestrict.go index 811b609..14fe635 100644 --- a/pkg/realdebrid/unrestrict.go +++ b/pkg/realdebrid/unrestrict.go @@ -20,9 +20,9 @@ func (rd *RealDebrid) UnrestrictUntilOk(link string) *UnrestrictResponse { } func retryUntilOk[T any](fn func() (T, error)) T { - const initialDelay = 2 * time.Second + const initialDelay = 1 * time.Second const maxDelay = 128 * time.Second - const maxRetries = 5 // Maximum retries for non-429 errors + const maxRetries = 2 // Maximum retries for non-429 errors var result T var err error