- Revamp decypharr arch \n

- Add callback_ur, download_folder to addContent API \n
- Fix few bugs \n
- More declarative UI keywords
- Speed up repairs
- Few other improvements/bug fixes
This commit is contained in:
Mukhtar Akere
2025-06-02 12:57:36 +01:00
parent 1cd09239f9
commit 9c6c44d785
67 changed files with 1726 additions and 1464 deletions

View File

@@ -3,6 +3,8 @@ package repair
import (
"fmt"
"github.com/sirrobot01/decypharr/pkg/arr"
"github.com/sirrobot01/decypharr/pkg/debrid/store"
"github.com/sirrobot01/decypharr/pkg/debrid/types"
"os"
"path/filepath"
)
@@ -82,3 +84,96 @@ func collectFiles(media arr.Content) map[string][]arr.ContentFile {
}
return uniqueParents
}
func (r *Repair) checkTorrentFiles(torrentPath string, files []arr.ContentFile, clients map[string]types.Client, caches map[string]*store.Cache) []arr.ContentFile {
brokenFiles := make([]arr.ContentFile, 0)
r.logger.Debug().Msgf("Checking %s", torrentPath)
// Get the debrid client
dir := filepath.Dir(torrentPath)
debridName := r.findDebridForPath(dir, clients)
if debridName == "" {
r.logger.Debug().Msgf("No debrid found for %s. Skipping", torrentPath)
return files // Return all files as broken if no debrid found
}
cache, ok := caches[debridName]
if !ok {
r.logger.Debug().Msgf("No cache found for %s. Skipping", debridName)
return files // Return all files as broken if no cache found
}
// Check if torrent exists
torrentName := filepath.Clean(filepath.Base(torrentPath))
torrent := cache.GetTorrentByName(torrentName)
if torrent == nil {
r.logger.Debug().Msgf("No torrent found for %s. Skipping", torrentName)
return files // Return all files as broken if torrent not found
}
// Batch check files
filePaths := make([]string, len(files))
for i, file := range files {
filePaths[i] = file.TargetPath
}
brokenFilePaths := cache.GetBrokenFiles(torrent, filePaths)
if len(brokenFilePaths) > 0 {
r.logger.Debug().Msgf("%d broken files found in %s", len(brokenFilePaths), torrentName)
// Create a set for O(1) lookup
brokenSet := make(map[string]bool, len(brokenFilePaths))
for _, brokenPath := range brokenFilePaths {
brokenSet[brokenPath] = true
}
// Filter broken files
for _, contentFile := range files {
if brokenSet[contentFile.TargetPath] {
brokenFiles = append(brokenFiles, contentFile)
}
}
}
return brokenFiles
}
func (r *Repair) findDebridForPath(dir string, clients map[string]types.Client) string {
// Check cache first
r.cacheMutex.RLock()
if r.debridPathCache == nil {
r.debridPathCache = make(map[string]string)
}
if debridName, exists := r.debridPathCache[dir]; exists {
r.cacheMutex.RUnlock()
return debridName
}
r.cacheMutex.RUnlock()
// Find debrid client
for _, client := range clients {
mountPath := client.GetMountPath()
if mountPath == "" {
continue
}
if filepath.Clean(mountPath) == filepath.Clean(dir) {
debridName := client.GetName()
// Cache the result
r.cacheMutex.Lock()
r.debridPathCache[dir] = debridName
r.cacheMutex.Unlock()
return debridName
}
}
// Cache empty result to avoid repeated lookups
r.cacheMutex.Lock()
r.debridPathCache[dir] = ""
r.cacheMutex.Unlock()
return ""
}