From 80a1af378a8ce52ab4f66ada6aee87bd8b24262c Mon Sep 17 00:00:00 2001 From: Ben Sarmiento Date: Sun, 7 Jan 2024 19:00:53 +0100 Subject: [PATCH] Proactive repair --- internal/torrent/refresh.go | 2 +- internal/torrent/repair.go | 38 ++++++++++++++++++++++++++++++++++--- pkg/realdebrid/types.go | 26 +++++++++++++++++++++++-- 3 files changed, 60 insertions(+), 6 deletions(-) diff --git a/internal/torrent/refresh.go b/internal/torrent/refresh.go index bd5d663..e582ee8 100644 --- a/internal/torrent/refresh.go +++ b/internal/torrent/refresh.go @@ -72,7 +72,7 @@ func (t *TorrentManager) RefreshTorrents() []string { directories = append(directories, directory) } }) - t.log.Debugf("Added %s to %v", accessKey, directories) + // t.log.Debugf("Added %s to %v", accessKey, directories) t.allAccessKeys.Add(accessKey) return false }) diff --git a/internal/torrent/repair.go b/internal/torrent/repair.go index eab9f2a..73ef388 100644 --- a/internal/torrent/repair.go +++ b/internal/torrent/repair.go @@ -8,6 +8,7 @@ import ( "github.com/debridmediamanager/zurg/internal/config" "github.com/debridmediamanager/zurg/pkg/realdebrid" + mapset "github.com/deckarep/golang-set/v2" cmap "github.com/orcaman/concurrent-map/v2" ) @@ -23,14 +24,40 @@ func (t *TorrentManager) RepairAll() { func (t *TorrentManager) repairAll() { allTorrents, _ := t.DirectoryMap.Get(INT_ALL) - hashes := make([]string, 0) + var hashGroups []mapset.Set[string] + const maxGroupSize = 399 + + currentGroup := mapset.NewSet[string]() + hashGroups = append(hashGroups, currentGroup) + allTorrents.IterCb(func(_ string, torrent *Torrent) { if torrent.AnyInProgress() || torrent.Unfixable { return } - hashes = append(hashes, torrent.Hash) + // Check if the current group is full + if currentGroup.Cardinality() >= maxGroupSize { + // Create a new group and add it to the hashGroups + currentGroup = mapset.NewSet[string]() + hashGroups = append(hashGroups, currentGroup) + } + // Add the hash to the current group + currentGroup.Add(torrent.Hash) }) + var availabilityChecks = make(map[string]bool) + for i := range hashGroups { + resp, err := t.Api.AvailabilityCheck(hashGroups[i].ToSlice()) + if err != nil { + t.log.Warnf("Cannot check availability: %v", err) + continue + } + + for hash, hosterHash := range resp { + // Check if HosterHash is a map (Variants field is used) + availabilityChecks[hash] = len(hosterHash.Variants) > 0 + } + } + var toRepair []*Torrent allTorrents.IterCb(func(_ string, torrent *Torrent) { if torrent.AnyInProgress() || torrent.Unfixable { @@ -38,6 +65,10 @@ func (t *TorrentManager) repairAll() { } // check 1: for cached status + isCached := true + if _, ok := availabilityChecks[torrent.Hash]; !ok || !availabilityChecks[torrent.Hash] { + isCached = false + } // check 2: for broken files hasBrokenFiles := false @@ -46,7 +77,8 @@ func (t *TorrentManager) repairAll() { hasBrokenFiles = true } }) - if hasBrokenFiles { + + if !isCached || hasBrokenFiles { toRepair = append(toRepair, torrent) } }) diff --git a/pkg/realdebrid/types.go b/pkg/realdebrid/types.go index 8d46785..0dedd42 100644 --- a/pkg/realdebrid/types.go +++ b/pkg/realdebrid/types.go @@ -1,6 +1,7 @@ package realdebrid import ( + "errors" "math" "strings" @@ -134,8 +135,11 @@ type User struct { // key: torrent hash type AvailabilityResponse map[string]HosterHash -// key: "rd" -type HosterHash map[string][]SelectionVariant +type HosterHash struct { + // key: "rd" + Variants map[string][]SelectionVariant + Strings []string +} // key: file id type SelectionVariant map[int]FileData @@ -144,3 +148,21 @@ type FileData struct { Filename string `json:"filename"` Filesize int `json:"filesize"` } + +func (h *HosterHash) UnmarshalJSON(data []byte) error { + // First, try unmarshaling as map[string][]SelectionVariant + var variants map[string][]SelectionVariant + if err := json.Unmarshal(data, &variants); err == nil { + h.Variants = variants + return nil + } + + // If that fails, try unmarshaling as []string + var strings []string + if err := json.Unmarshal(data, &strings); err == nil { + h.Strings = strings + return nil + } + + return errors.New("availability json data did not match expected formats (map or array)") +}