Repair rework

This commit is contained in:
Ben Sarmiento
2024-01-07 03:00:25 +01:00
parent 5d733b8be4
commit e5f0f4d7bd
5 changed files with 50 additions and 47 deletions

View File

@@ -20,10 +20,16 @@ func (t *TorrentManager) repairAll() {
allTorrents, _ := t.DirectoryMap.Get(INT_ALL)
var toRepair []*Torrent
allTorrents.IterCb(func(_ string, torrent *Torrent) {
if torrent.AnyInProgress() && torrent.ForRepair {
t.log.Warnf("Skipping %s for repairs because it is still in progress", torrent.AccessKey)
if torrent.AnyInProgress() || torrent.Unfixable {
return
} else if torrent.ForRepair && !torrent.Unfixable {
}
hasBrokenFiles := false
torrent.SelectedFiles.IterCb(func(_ string, file *File) {
if file.Link == "repair" || file.Link == "" {
hasBrokenFiles = true
}
})
if hasBrokenFiles {
toRepair = append(toRepair, torrent)
}
})
@@ -68,54 +74,60 @@ func (t *TorrentManager) repair(torrent *Torrent) {
t.log.Infof("Successfully downloaded torrent %s to repair it", torrent.AccessKey)
return
} else {
t.log.Warnf("Failed to repair by reinserting torrent %s", torrent.AccessKey)
t.log.Warnf("Failed to repair by reinserting torrent %s, will only redownload broken files...", torrent.AccessKey)
}
} else {
t.log.Warnf("Torrent %s is not older than %d hours to be repaired by reinsertion", torrent.AccessKey, EXPIRED_LINK_TOLERANCE_HOURS)
t.log.Warnf("Torrent %s is not older than %d hours to be repaired by reinsertion, will only redownload broken files...", torrent.AccessKey, EXPIRED_LINK_TOLERANCE_HOURS)
}
// sleep for 30 seconds to let the torrent accumulate more broken files if scanning
time.Sleep(30 * time.Second)
// second solution: add only the missing files
var missingFiles []File
// second solution: add only the broken files
var brokenFiles []File
torrent.SelectedFiles.IterCb(func(_ string, file *File) {
if file.Link == "repair" || file.Link == "" {
missingFiles = append(missingFiles, *file)
brokenFiles = append(brokenFiles, *file)
file.Link = "repairing"
}
})
t.log.Debugf("During repair, zurg found %d broken files for torrent %s", len(missingFiles), torrent.AccessKey)
t.log.Debugf("During repair, zurg found %d broken files for torrent %s", len(brokenFiles), torrent.AccessKey)
if len(missingFiles) == 1 && torrent.SelectedFiles.Count() == 1 {
t.log.Warnf("Torrent %s is unrepairable, the lone file is expired but still cached in Real-Debrid", torrent.AccessKey)
return
} else if len(missingFiles) == 1 && torrent.SelectedFiles.Count() > 1 {
// todo: to verify removed logic when there's only 1 selected file selected and it's broken
// todo: handle rar'ed torrents
if len(brokenFiles) == 1 && torrent.SelectedFiles.Count() > 1 {
// if we download a single file, it will be named differently
// so we need to download 1 extra file to preserve the name
// this is only relevant if we enable retain_rd_torrent_name
// add the first file link encountered with a prefix of http
t.log.Debugf("Torrent %s has only 1 missing file, adding 1 extra file to preserve the name", torrent.AccessKey)
t.log.Debugf("Torrent %s has only 1 broken file, adding 1 extra file to preserve the name", torrent.AccessKey)
for _, file := range torrent.SelectedFiles.Items() {
if strings.HasPrefix(file.Link, "http") {
missingFiles = append(missingFiles, *file)
brokenFiles = append(brokenFiles, *file)
break
}
}
}
if len(missingFiles) > 0 {
t.log.Infof("Redownloading the %d missing files for torrent %s", len(missingFiles), torrent.AccessKey)
missingFileIDs := strings.Join(getFileIDs(missingFiles), ",")
t.reinsertTorrent(torrent, missingFileIDs)
if len(brokenFiles) > 0 {
t.log.Infof("Redownloading the %d broken files for torrent %s", len(brokenFiles), torrent.AccessKey)
brokenFileIDs := strings.Join(getFileIDs(brokenFiles), ",")
if t.reinsertTorrent(torrent, brokenFileIDs) {
t.log.Infof("Successfully downloaded torrent %s to repair it", torrent.AccessKey)
} else {
t.log.Warnf("Failed to repair torrent %s", torrent.AccessKey)
torrent.Unfixable = true
}
} else {
t.log.Warnf("Torrent %s has no missing files to repair", torrent.AccessKey)
t.log.Warnf("Torrent %s has no broken files to repair", torrent.AccessKey)
}
}
func (t *TorrentManager) reinsertTorrent(torrent *Torrent, missingFiles string) bool {
func (t *TorrentManager) reinsertTorrent(torrent *Torrent, brokenFiles string) bool {
oldTorrentIDs := make([]string, 0)
// missing files means missing links
// if missingFiles is not provided
if missingFiles == "" {
// broken files means broken links
// if brokenFiles is not provided
if brokenFiles == "" {
// only replace the torrent if we are reinserting all files
oldTorrentIDs = torrent.DownloadedIDs.ToSlice()
tmpSelection := ""
@@ -125,7 +137,7 @@ func (t *TorrentManager) reinsertTorrent(torrent *Torrent, missingFiles string)
if tmpSelection == "" {
return true // nothing to repair
} else {
missingFiles = tmpSelection[:len(tmpSelection)-1]
brokenFiles = tmpSelection[:len(tmpSelection)-1]
}
}
@@ -139,7 +151,7 @@ func (t *TorrentManager) reinsertTorrent(torrent *Torrent, missingFiles string)
// select files
newTorrentID := resp.ID
err = t.Api.SelectTorrentFiles(newTorrentID, missingFiles)
err = t.Api.SelectTorrentFiles(newTorrentID, brokenFiles)
if err != nil {
t.log.Warnf("Cannot start redownloading: %v", err)
t.Api.DeleteTorrent(newTorrentID)
@@ -169,9 +181,9 @@ func (t *TorrentManager) reinsertTorrent(torrent *Torrent, missingFiles string)
return true
}
missingCount := len(strings.Split(missingFiles, ","))
if len(info.Links) != missingCount {
t.log.Infof("It did not fix the issue for id=%s, only got %d files but we need %d, undoing", info.ID, len(info.Links), missingCount)
brokenCount := len(strings.Split(brokenFiles, ","))
if len(info.Links) != brokenCount {
t.log.Infof("It did not fix the issue for id=%s, only got %d files but we need %d, undoing", info.ID, len(info.Links), brokenCount)
t.Api.DeleteTorrent(newTorrentID)
return false
}