Catch bw limit errors and prevent repair loops

This commit is contained in:
Ben Adrian Sarmiento
2024-06-24 00:38:57 +02:00
parent a0c13af94b
commit 449c0f71cf
5 changed files with 139 additions and 83 deletions

View File

@@ -9,6 +9,7 @@ import (
"time"
"github.com/debridmediamanager/zurg/internal/config"
"github.com/debridmediamanager/zurg/pkg/http"
"github.com/debridmediamanager/zurg/pkg/realdebrid"
"github.com/debridmediamanager/zurg/pkg/utils"
mapset "github.com/deckarep/golang-set/v2"
@@ -189,16 +190,30 @@ func (t *TorrentManager) repair(torrent *Torrent, wg *sync.WaitGroup) {
return
}
bwLimitReached := false
// check for other broken file
torrent.SelectedFiles.IterCb(func(_ string, file *File) {
if bwLimitReached {
return
}
if !file.State.Is("ok_file") {
return
}
if t.UnrestrictFile(file, true) == nil {
_, err := t.UnrestrictFile(file, true)
if dlErr, ok := err.(*http.DownloadErrorResponse); ok && dlErr.Message == "bytes_limit_reached" {
bwLimitReached = true
return
}
if err != nil {
file.State.Event(context.Background(), "break_file")
}
})
if bwLimitReached {
t.repairLog.Warnf("Your account has reached the bandwidth limit, cannot continue repairing torrent %s", t.GetKey(torrent))
return
}
brokenFiles, allBroken := t.getBrokenFiles(torrent)
// check if broken files are playable
@@ -240,7 +255,12 @@ func (t *TorrentManager) repair(torrent *Torrent, wg *sync.WaitGroup) {
info, err := t.redownloadTorrent(torrent, []string{}) // reinsert the whole torrent, passing empty selection
if info != nil && info.Progress == 100 {
if !t.isStillBroken(info, brokenFiles) {
err = t.checkIfBroken(info, brokenFiles)
if dlErr, ok := err.(*http.DownloadErrorResponse); ok && dlErr.Message == "bytes_limit_reached" {
t.repairLog.Warnf("Your account has reached the bandwidth limit, cannot continue repairing torrent %s", t.GetKey(torrent))
return
}
if err == nil {
// delete the torrents it replaced
oldDownloadedIDs.Each(func(torrentID string) bool {
t.DeleteByID(torrentID)
@@ -249,10 +269,7 @@ func (t *TorrentManager) repair(torrent *Torrent, wg *sync.WaitGroup) {
t.repairLog.Infof("Successfully repaired torrent %s by redownloading whole torrent", t.GetKey(torrent))
return
}
// if it's still broken, let's delete the newly downloaded torrent
t.DeleteByID(info.ID)
err = fmt.Errorf("links are still broken")
} else if info != nil && info.Progress != 100 {
// it's faster to download just the broken files, so let's delete the newly downloaded torrent
@@ -322,9 +339,14 @@ func (t *TorrentManager) assignLinks(torrent *Torrent) bool {
newUnassignedLinks := cmap.New[*realdebrid.Download]()
var assignedLinks []string
bwLimitReached := false
torrent.UnassignedLinks.Clone().Each(func(link string) bool {
// unrestrict each unassigned link that was filled out during torrent init
unrestrict := t.UnrestrictLink(link, true)
unrestrict, err := t.UnrestrictLink(link, true)
if dlErr, ok := err.(*http.DownloadErrorResponse); ok && dlErr.Message == "bytes_limit_reached" {
bwLimitReached = true
return true
}
if unrestrict == nil {
expiredCount++
return false // next unassigned link
@@ -376,6 +398,11 @@ func (t *TorrentManager) assignLinks(torrent *Torrent) bool {
return false // next unassigned link
})
if bwLimitReached {
t.repairLog.Warnf("Your account has reached the bandwidth limit, cannot continue assigning links to torrent %s", t.GetKey(torrent))
return false
}
// empty/reset the unassigned links as we have assigned them already
if unassignedTotal > 0 {
torrent.UnassignedLinks = mapset.NewSet[string]()
@@ -617,9 +644,9 @@ func (t *TorrentManager) getBrokenFiles(torrent *Torrent) ([]*File, bool) {
return brokenFiles, allBroken
}
// isStillBroken checks if the torrent is still broken
// checkIfBroken checks if the torrent is still broken
// if it's not broken anymore, it will assign the links to the files
func (t *TorrentManager) isStillBroken(info *realdebrid.TorrentInfo, brokenFiles []*File) bool {
func (t *TorrentManager) checkIfBroken(info *realdebrid.TorrentInfo, brokenFiles []*File) error {
var selectedFiles []*File
for _, file := range info.Files {
if file.Selected == 0 {
@@ -633,7 +660,7 @@ func (t *TorrentManager) isStillBroken(info *realdebrid.TorrentInfo, brokenFiles
})
}
if len(selectedFiles) != len(info.Links) {
return true
return fmt.Errorf("number of selected files and links do not match")
}
for i, file := range selectedFiles {
@@ -652,12 +679,15 @@ func (t *TorrentManager) isStillBroken(info *realdebrid.TorrentInfo, brokenFiles
// check if the broken files can now be unrestricted and downloaded
for _, oldFile := range brokenFiles {
for idx, newFile := range selectedFiles {
if oldFile.ID == newFile.ID && t.UnrestrictFile(selectedFiles[idx], true) == nil {
return true
if oldFile.ID != newFile.ID {
continue
}
if _, err := t.UnrestrictFile(selectedFiles[idx], true); err != nil {
return err
}
}
}
return false
return nil
}
func (t *TorrentManager) ResetRepairState() {