Fix repairs for rared torrents

This commit is contained in:
Ben Adrian Sarmiento
2024-06-06 01:49:17 +02:00
parent cc19423420
commit 5a6b6b1546
5 changed files with 52 additions and 36 deletions

View File

@@ -13,7 +13,7 @@ const BINS_FILE = "data/bins.json"
// initializeBins reads from bins.json and assigns values to t.trashBin and t.repairBin
func (t *TorrentManager) initializeBins() {
if _, err := os.Stat(BINS_FILE); os.IsNotExist(err) {
t.repairLog.Warn("data/bins.json does not exist. Initializing empty bins.")
t.repairLog.Info("data/bins.json does not exist. Initializing empty bins.")
t.ImmediateBin = mapset.NewSet[string]()
t.OnceDoneBin = mapset.NewSet[string]()
return
@@ -120,6 +120,7 @@ func (t *TorrentManager) binImmediately(torrentId string) bool {
t.repairLog.Warnf("Failed to delete torrent %s: %v", torrentId, err)
}
t.ImmediateBin.Remove(torrentId)
t.repairLog.Debugf("Bin: immediate deletion of torrent %s", torrentId)
t.persistBins()
return true
}
@@ -128,21 +129,27 @@ func (t *TorrentManager) binImmediately(torrentId string) bool {
// binOnceDoneErrorCheck checks if the torrent is in error states and then checks if it should be deleted
func (t *TorrentManager) binOnceDoneErrorCheck(torrentId, status string) bool {
if status == "downloading" || status == "downloaded" || status == "uploading" || status == "queued" || status == "compressing" {
if status == "downloading" || status == "downloaded" || status == "uploading" || status == "queued" || status == "compressing" || status == "waiting_files_selection" {
return false
}
return t.binOnceDone(torrentId)
t.repairLog.Errorf("Bin: error status=%s, checking if %s should be deleted", status, torrentId)
return t.binOnceDone(torrentId, true)
}
// binOnceDone checks if the torrent is in the OnceDoneBin and deletes it if it is.
// returns true if the torrent was in the bin and was deleted, false otherwise
func (t *TorrentManager) binOnceDone(completedTorrentId string) bool {
func (t *TorrentManager) binOnceDone(completedTorrentId string, errorCheck bool) bool {
if t.OnceDoneBin.Contains(completedTorrentId) {
if err := t.api.DeleteTorrent(completedTorrentId); err != nil {
t.repairLog.Warnf("Failed to delete torrent %s: %v", completedTorrentId, err)
}
t.deleteInfoFile(completedTorrentId)
t.OnceDoneBin.Remove(completedTorrentId)
if errorCheck {
t.repairLog.Errorf("Bin: error deletion of torrent %s", completedTorrentId)
} else {
t.repairLog.Debugf("Bin: done deletion of torrent %s", completedTorrentId)
}
t.persistBins()
return true
}
@@ -152,14 +159,22 @@ func (t *TorrentManager) binOnceDone(completedTorrentId string) bool {
if !t.OnceDoneBin.Contains(specialCase) {
return false
}
t.OnceDoneBin.Remove(specialCase)
t.OnceDoneBin.Clone().Each(func(entry string) bool {
if strings.Contains(entry, specialCase) {
idToDelete := strings.Split(entry, "-")[1]
if err := t.api.DeleteTorrent(idToDelete); err != nil {
t.repairLog.Warnf("Failed to delete torrent %s: %v", idToDelete, err)
if errorCheck {
if err := t.api.DeleteTorrent(completedTorrentId); err != nil {
t.repairLog.Warnf("Failed to delete torrent %s: %v", completedTorrentId, err)
}
t.OnceDoneBin.Remove(entry)
t.repairLog.Errorf("Bin: error deletion of torrent %s", completedTorrentId)
} else {
idToDelete := strings.Split(entry, "-")[1]
if err := t.api.DeleteTorrent(idToDelete); err != nil {
t.repairLog.Warnf("Failed to delete torrent %s: %v", idToDelete, err)
}
t.OnceDoneBin.Remove(entry)
t.repairLog.Debugf("Bin: %s completed, done deletion of torrent %s", completedTorrentId, idToDelete)
}
t.OnceDoneBin.Remove(entry)
}
return false
})

View File

@@ -45,13 +45,6 @@ func (se *ScriptExecutor) Execute() (string, error) {
return out.String(), nil
}
func (t *TorrentManager) TriggerHookOnLibraryUpdate(updatedPaths []string) {
_ = t.workerPool.Submit(func() {
OnLibraryUpdateHook(updatedPaths, t.Config, t.log)
t.log.Debugf("Triggered hook on_library_update for %d path(s)", len(updatedPaths))
})
}
func OnLibraryUpdateHook(paths []string, config config.ConfigInterface, log *logutil.Logger) {
executor := &ScriptExecutor{
Script: config.GetOnLibraryUpdate(),

View File

@@ -113,7 +113,7 @@ func NewTorrentManager(cfg config.ConfigInterface, api *realdebrid.RealDebrid, r
return false
})
t.refreshTorrents()
t.refreshTorrents(true)
})
t.workerPool.Submit(func() {
defer wg.Done()

View File

@@ -20,7 +20,7 @@ func inProgressStatus(status string) bool {
return status == "downloading" || status == "uploading" || status == "queued" || status == "compressing"
}
func (t *TorrentManager) refreshTorrents() {
func (t *TorrentManager) refreshTorrents(initialRun bool) {
t.inProgressHashes = mapset.NewSet[string]()
instances, _, err := t.api.GetTorrents(false)
if err != nil {
@@ -62,7 +62,7 @@ func (t *TorrentManager) refreshTorrents() {
if !exists {
allTorrents.Set(accessKey, torrent)
t.writeTorrentToFile(torrent)
t.assignDirectory(torrent, true)
t.assignDirectory(torrent, !initialRun)
} else if !mainTorrent.DownloadedIDs.Contains(tInfo.ID) {
forMerging = torrent
}
@@ -94,7 +94,7 @@ func (t *TorrentManager) refreshTorrents() {
mainTorrent := t.mergeTorrents(existing, torrent)
allTorrents.Set(accessKey, mainTorrent)
t.writeTorrentToFile(mainTorrent)
t.assignDirectory(mainTorrent, true)
t.assignDirectory(mainTorrent, !initialRun)
}
// removed torrents
@@ -106,19 +106,17 @@ func (t *TorrentManager) refreshTorrents() {
t.log.Infof("Compiled into %d unique torrents", allTorrents.Count())
t.workerPool.Submit(func() {
// delete info files that are no longer present
t.getInfoFiles().Each(func(path string) bool {
path = filepath.Base(path)
torrentID := strings.TrimSuffix(path, ".zurginfo")
// if binOnceDone returns true, it means the info file is deleted
// if false, then we check if it's one of the torrents we just fetched
// if not, then we delete the info file
if !t.binOnceDone(torrentID) && !freshIDs.Contains(torrentID) {
t.deleteInfoFile(torrentID)
}
return false
})
// delete info files that are no longer present
t.getInfoFiles().Each(func(path string) bool {
path = filepath.Base(path)
torrentID := strings.TrimSuffix(path, ".zurginfo")
// if binOnceDone returns true, it means the info file is deleted
// if false, then we check if it's one of the torrents we just fetched
// if not (both are false), then we delete the info file
if !t.binOnceDone(torrentID, false) && !freshIDs.Contains(torrentID) {
t.deleteInfoFile(torrentID)
}
return false
})
t.workerPool.Submit(func() {
@@ -152,7 +150,7 @@ func (t *TorrentManager) StartRefreshJob() {
}
t.setNewLatestState(checksum)
t.refreshTorrents()
t.refreshTorrents(false)
t.log.Info("Finished refreshing torrents")
case <-t.RefreshKillSwitch:
t.log.Info("Stopping periodic refresh job")
@@ -293,6 +291,8 @@ func (t *TorrentManager) mergeTorrents(existing, toMerge *Torrent) *Torrent {
if !ok || !f.State.Is("ok_file") {
mergedTorrent.SelectedFiles.Set(key, file)
}
// get the file again, set the media info
f, ok = mergedTorrent.SelectedFiles.Get(key)
if ok && f.MediaInfo == nil && mediaInfo != nil {
f.MediaInfo = mediaInfo
}
@@ -328,6 +328,8 @@ func (t *TorrentManager) mergeTorrents(existing, toMerge *Torrent) *Torrent {
mergedTorrent.State.Event(context.Background(), "mark_as_repaired")
}
t.log.Debugf("Merged torrent %s has %d broken files", t.GetKey(mergedTorrent), brokenCount)
return mergedTorrent
}
@@ -366,6 +368,7 @@ func (t *TorrentManager) assignDirectory(tor *Torrent, triggerHook bool) {
// Map torrents to directories
switch t.Config.GetVersion() {
case "v1":
updatedPaths := make([]string, 0)
configV1 := t.Config.(*config.ZurgConfigV1)
for _, directories := range configV1.GetGroupMap() {
for _, directory := range directories {
@@ -374,12 +377,15 @@ func (t *TorrentManager) assignDirectory(tor *Torrent, triggerHook bool) {
listing.Set(accessKey, tor)
if triggerHook {
t.TriggerHookOnLibraryUpdate([]string{fmt.Sprintf("%s/%s", directory, accessKey)})
updatedPaths = append(updatedPaths, fmt.Sprintf("%s/%s", directory, accessKey))
}
break
}
}
}
if triggerHook {
OnLibraryUpdateHook(updatedPaths, t.Config, t.log)
}
}
}

View File

@@ -190,6 +190,7 @@ func (t *TorrentManager) repair(torrent *Torrent) {
allPlayable = false
if t.Config.GetRarAction() == "extract" && file.ID != 0 {
t.repairLog.Debugf("Extracting file %s from rar'ed torrent %s", file.Path, t.GetKey(torrent))
info, _ := t.redownloadTorrent(torrent, []string{fmt.Sprintf("%d", file.ID)})
if info != nil {
t.setToBinOnceDone(info.ID)
@@ -381,7 +382,8 @@ func (t *TorrentManager) assignLinks(torrent *Torrent) bool {
torrent.SelectedFiles.IterCb(func(_ string, file *File) {
if utils.IsPlayable(file.Path) {
videoFiles = append(videoFiles, fmt.Sprintf("%d", file.ID))
} else {
} else if file.ID != 0 {
t.repairLog.Debugf("Extracting file %s from rar'ed torrent %s", file.Path, t.GetKey(torrent))
info, _ := t.redownloadTorrent(torrent, []string{fmt.Sprintf("%d", file.ID)})
if info != nil {
t.setToBinOnceDone(info.ID)