diff --git a/internal/handlers/router.go b/internal/handlers/router.go index 799902b..7cd100d 100644 --- a/internal/handlers/router.go +++ b/internal/handlers/router.go @@ -4,6 +4,7 @@ import ( "fmt" "net/http" "path/filepath" + "strings" "github.com/debridmediamanager/zurg/internal/config" "github.com/debridmediamanager/zurg/internal/dav" @@ -100,12 +101,20 @@ func AttachHandlers(router *chi.Mux, downloader *universal.Downloader, torMgr *t func (hs *Handlers) innerRootHandler(resp http.ResponseWriter, req *http.Request, handleFunc func(*torrent.TorrentManager) ([]byte, error), contentType string) { out, err := handleFunc(hs.torMgr) - if err != nil { + if err != nil && strings.Contains(contentType, "xml") { + resp.WriteHeader(http.StatusNotImplemented) + resp.Write([]byte("NotImplementedNot Implemented Method")) + return + } else if err != nil { http.NotFound(resp, req) return } resp.Header().Set("Content-Type", contentType) - resp.WriteHeader(http.StatusOK) + if strings.Contains(contentType, "xml") { + resp.WriteHeader(http.StatusMultiStatus) + } else { + resp.WriteHeader(http.StatusOK) + } resp.Write(out) } @@ -126,12 +135,20 @@ func (hs *Handlers) handleInfuseRoot(resp http.ResponseWriter, req *http.Request func (hs *Handlers) innerTorrentsListHandler(resp http.ResponseWriter, req *http.Request, handleFunc func(string, *torrent.TorrentManager) ([]byte, error), contentType string) { directory := chi.URLParam(req, "directory") out, err := handleFunc(directory, hs.torMgr) - if err != nil { + if err != nil && strings.Contains(contentType, "xml") { + resp.WriteHeader(http.StatusNotImplemented) + resp.Write([]byte("NotImplementedNot Implemented Method")) + return + } else if err != nil { http.NotFound(resp, req) return } resp.Header().Set("Content-Type", contentType) - resp.WriteHeader(http.StatusOK) + if strings.Contains(contentType, "xml") { + resp.WriteHeader(http.StatusMultiStatus) + } else { + resp.WriteHeader(http.StatusOK) + } resp.Write(out) } @@ -174,12 +191,20 @@ func (hs *Handlers) innerFilesListHandler(resp http.ResponseWriter, req *http.Re directory := chi.URLParam(req, "directory") torrentName := chi.URLParam(req, "torrent") out, err := handleFunc(directory, torrentName, hs.torMgr) - if err != nil { + if err != nil && strings.Contains(contentType, "xml") { + resp.WriteHeader(http.StatusNotImplemented) + resp.Write([]byte("NotImplementedNot Implemented Method")) + return + } else if err != nil { http.NotFound(resp, req) return } resp.Header().Set("Content-Type", contentType) - resp.WriteHeader(http.StatusOK) + if strings.Contains(contentType, "xml") { + resp.WriteHeader(http.StatusMultiStatus) + } else { + resp.WriteHeader(http.StatusOK) + } resp.Write(out) } diff --git a/internal/torrent/manager.go b/internal/torrent/manager.go index e496bfb..26bda3e 100644 --- a/internal/torrent/manager.go +++ b/internal/torrent/manager.go @@ -27,6 +27,7 @@ type TorrentManager struct { DirectoryMap cmap.ConcurrentMap[string, cmap.ConcurrentMap[string, *Torrent]] // directory -> accessKey -> Torrent DownloadCache cmap.ConcurrentMap[string, *realdebrid.Download] DownloadMap cmap.ConcurrentMap[string, *realdebrid.Download] + Repairs cmap.ConcurrentMap[string, bool] allAccessKeys mapset.Set[string] forRepairs mapset.Set[string] latestState *LibraryState diff --git a/internal/torrent/refresh.go b/internal/torrent/refresh.go index bffedc9..2bd8406 100644 --- a/internal/torrent/refresh.go +++ b/internal/torrent/refresh.go @@ -24,11 +24,11 @@ func (t *TorrentManager) RefreshTorrents() []string { for i := range instances { idx := i + wg.Add(1) _ = t.workerPool.Submit(func() { defer wg.Done() infoChan <- t.getMoreInfo(instances[idx]) }) - wg.Add(1) } wg.Wait() @@ -168,7 +168,6 @@ func (t *TorrentManager) getMoreInfo(rdTorrent realdebrid.Torrent) *Torrent { OriginalName: info.OriginalName, Added: info.Added, Hash: info.Hash, - Lock: &sync.Mutex{}, } // SelectedFiles is a subset of Files with only the selected ones // it also has a Link field, which can be empty @@ -234,7 +233,6 @@ func (t *TorrentManager) mergeToMain(existing, toMerge *Torrent) Torrent { Unfixable: existing.Unfixable || toMerge.Unfixable, UnassignedLinks: existing.UnassignedLinks.Union(toMerge.UnassignedLinks), BrokenLinks: existing.BrokenLinks.Union(toMerge.BrokenLinks), - Lock: &sync.Mutex{}, } // this function triggers only when we have a new DownloadedID diff --git a/internal/torrent/repair.go b/internal/torrent/repair.go index d0128f0..3ba5a09 100644 --- a/internal/torrent/repair.go +++ b/internal/torrent/repair.go @@ -100,6 +100,12 @@ func (t *TorrentManager) repairAll() { } func (t *TorrentManager) Repair(torrent *Torrent) { + if repairing, ok := t.Repairs.Get(t.GetKey(torrent)); ok && repairing { + t.log.Warnf("Torrent %s is already being repaired, skipping repair", t.GetKey(torrent)) + return + } + t.Repairs.Set(t.GetKey(torrent), true) + if torrent.Unfixable { t.log.Warnf("Torrent %s is unfixable, skipping repair", t.GetKey(torrent)) return @@ -121,17 +127,13 @@ func (t *TorrentManager) Repair(torrent *Torrent) { }) _ = t.workerPool.Submit(func() { t.log.Infof("Repairing torrent %s", t.GetKey(torrent)) - torrent.Lock.Lock() - defer torrent.Lock.Unlock() - torrent.Repairing = true t.repair(torrent) - torrent.Repairing = false t.log.Infof("Finished repairing torrent %s", t.GetKey(torrent)) }) } func (t *TorrentManager) repair(torrent *Torrent) { - if torrent.AnyInProgress() || torrent.Repairing { + if torrent.AnyInProgress() { t.log.Infof("Torrent %s is in progress, skipping repair until download is done", t.GetKey(torrent)) return } @@ -387,14 +389,10 @@ func (t *TorrentManager) markAsUnplayable(torrent *Torrent) { func (t *TorrentManager) markAsUnfixable(torrent *Torrent) { t.log.Warnf("Marking torrent %s as unfixable", t.GetKey(torrent)) - torrent.Lock.Lock() - defer torrent.Lock.Unlock() torrent.Unfixable = true infoCache, _ := t.DirectoryMap.Get(INT_INFO_CACHE) torrent.DownloadedIDs.Each(func(id string) bool { info, _ := infoCache.Get(id) - info.Lock.Lock() - defer info.Lock.Unlock() info.Unfixable = true t.writeTorrentToFile(id, info) return false diff --git a/internal/torrent/types.go b/internal/torrent/types.go index 3259797..27d3f37 100644 --- a/internal/torrent/types.go +++ b/internal/torrent/types.go @@ -3,7 +3,6 @@ package torrent import ( stdjson "encoding/json" "strings" - "sync" "time" "github.com/debridmediamanager/zurg/pkg/realdebrid" @@ -27,9 +26,7 @@ type Torrent struct { Unfixable bool `json:"Unfixable"` // modified over time BrokenLinks mapset.Set[string] `json:"BrokenLinks"` // only relevant on repair - Version string `json:"Version"` // only used for files - Repairing bool `json:"-"` - Lock *sync.Mutex `json:"-"` + Version string `json:"Version"` // only used for files } func (t *Torrent) MarshalJSON() ([]byte, error) {