Handle differently if all are broken

This commit is contained in:
Ben Sarmiento
2024-02-17 04:22:50 +01:00
parent 20d46d9f2b
commit 041e02816b
2 changed files with 78 additions and 17 deletions

View File

@@ -3,6 +3,7 @@ package torrent
import (
"io"
"os"
"strings"
"github.com/debridmediamanager/zurg/pkg/realdebrid"
cmap "github.com/orcaman/concurrent-map/v2"
@@ -36,19 +37,51 @@ func (t *TorrentManager) processFixers(instances []realdebrid.Torrent) {
case "replaced": // id is old torrent id
t.log.Debugf("Deleting old id=%s because it's redundant to fixed %s ", id, instance.Name)
toDelete = append(toDelete, id)
continue
case "download_failed": // id is failed fixer id
t.log.Debugf("Deleting failed fixer id=%s of torrent %s", id, instance.Name)
toDelete = append(toDelete, id)
continue
case "repaired": // this torrent contains broken files
if instance.Progress != 100 {
t.fixers.Set(id, "repaired") // requeue the fixer
t.fixers.Set(id, command) // requeue the fixer
continue
}
torrent := t.getMoreInfo(instance)
t.log.Debugf("Repairing torrent %s again now that fixer id=%s is done", t.GetKey(torrent), id)
repairMe, _ := allTorrents.Get(t.GetKey(torrent))
toRedownload = append(toRedownload, repairMe)
toDelete = append(toDelete, id)
continue
}
// a new case: repaired_with:<id>
if strings.HasPrefix(command, "repaired_with:") {
if instance.Progress != 100 {
t.fixers.Set(id, command) // requeue the fixer
continue
}
otherId := strings.TrimPrefix(command, "repaired_with:")
for _, instance := range instances {
if instance.ID == otherId {
if instance.Progress != 100 {
t.fixers.Set(id, command) // requeue the fixer
break
}
torrent := t.getMoreInfo(instance)
t.log.Debugf("Repairing torrent %s again now that fixers ids=%s and %s are done", t.GetKey(torrent), id, otherId)
repairMe, _ := allTorrents.Get(t.GetKey(torrent))
toRedownload = append(toRedownload, repairMe)
toDelete = append(toDelete, id, otherId)
break
}
}
continue
}
}

View File

@@ -163,7 +163,7 @@ func (t *TorrentManager) repair(torrent *Torrent) {
}
// get all broken files
brokenFiles := getBrokenFiles(torrent)
brokenFiles, allBroken := getBrokenFiles(torrent)
brokenFileIDs := getFileIDs(brokenFiles)
t.log.Debugf("Torrent %s has %d broken files (ids=%s; total is %d), repairing by redownloading", t.GetKey(torrent), len(brokenFiles), brokenFileIDs, torrent.SelectedFiles.Count())
@@ -198,16 +198,10 @@ func (t *TorrentManager) repair(torrent *Torrent) {
return
}
if len(brokenFiles) == torrent.SelectedFiles.Count() {
// all files are broken, nothing we can do
t.log.Warnf("Torrent %s has broken cached files (cached but cannot be downloaded), you can repair it manually, marking as unfixable", t.GetKey(torrent))
t.markAsUnfixable(torrent, "broken cache")
return
}
// second step: download the broken files
if len(brokenFiles) > 0 {
t.log.Infof("Repairing by downloading only the %d broken out of %d files of torrent %s", len(brokenFiles), torrent.SelectedFiles.Count(), t.GetKey(torrent))
if !allBroken {
redownloadedInfo, err := t.redownloadTorrent(torrent, brokenFileIDs)
if err != nil {
t.log.Warnf("Cannot repair torrent %s by downloading broken files (error=%s) giving up", t.GetKey(torrent), err.Error())
@@ -217,6 +211,37 @@ func (t *TorrentManager) repair(torrent *Torrent) {
t.fixerAddCommand(redownloadedInfo.ID, "repaired")
return
}
}
// divide the broken files into 2 groups
group1 := make([]*File, 0)
group2 := make([]*File, 0)
for idx, file := range brokenFiles {
if idx%2 == 0 {
group1 = append(group1, file)
} else {
group2 = append(group2, file)
}
}
brokenFileIDs1 := getFileIDs(group1)
redownloadedInfo1, err1 := t.redownloadTorrent(torrent, brokenFileIDs1)
if err1 != nil {
t.log.Warnf("Cannot repair torrent %s by downloading broken files (error=%s) giving up", t.GetKey(torrent), err1.Error())
return
}
if redownloadedInfo1 != nil {
brokenFileIDs2 := getFileIDs(group2)
redownloadedInfo2, err2 := t.redownloadTorrent(torrent, brokenFileIDs2)
if err2 != nil {
t.log.Warnf("Cannot repair torrent %s by downloading broken files (error=%s) giving up", t.GetKey(torrent), err2.Error())
return
}
if redownloadedInfo2 != nil {
t.fixerAddCommand(redownloadedInfo2.ID, fmt.Sprintf("repaired_with:%s", redownloadedInfo1.ID))
return
}
}
} else {
t.log.Infof("Torrent %s has no broken files to repair", t.GetKey(torrent))
}
@@ -447,14 +472,17 @@ func (t *TorrentManager) markAsUnfixable(torrent *Torrent, reason string) {
}
// getBrokenFiles returns the files that are not http links and not deleted
func getBrokenFiles(torrent *Torrent) []*File {
func getBrokenFiles(torrent *Torrent) ([]*File, bool) {
var brokenFiles []*File
allBroken := true
torrent.SelectedFiles.IterCb(func(_ string, file *File) {
if file.IsBroken && !file.IsDeleted {
brokenFiles = append(brokenFiles, file)
} else {
allBroken = false
}
})
return brokenFiles
return brokenFiles, allBroken
}
// isStillBroken checks if the torrent is still broken