147 lines
3.7 KiB
Go
147 lines
3.7 KiB
Go
package torrent
|
|
|
|
import (
|
|
"io"
|
|
"os"
|
|
|
|
"github.com/debridmediamanager/zurg/pkg/realdebrid"
|
|
cmap "github.com/orcaman/concurrent-map/v2"
|
|
)
|
|
|
|
// fixers are commands that will be run on the next refresh
|
|
// they are stored in a file so that they can be run on startup
|
|
// they follow the format of:
|
|
// key: <id_trigger> value: <command>
|
|
// id_trigger: this means a specific torrent id's completion
|
|
// commands: delete | repair
|
|
|
|
func (t *TorrentManager) registerFixer(torrentId, command string) {
|
|
t.log.Debugf("Adding fixer command: %s %s", torrentId, command)
|
|
t.fixers.Set(torrentId, command)
|
|
t.writeFixersToFile()
|
|
}
|
|
|
|
func (t *TorrentManager) processFixers(instances []realdebrid.Torrent) {
|
|
t.log.Debugf("Processing fixers (%d left: %v)", t.fixers.Count(), t.fixers.Keys())
|
|
var toDelete []string
|
|
var toRedownload []*Torrent
|
|
allTorrents, _ := t.DirectoryMap.Get(INT_ALL)
|
|
for _, instance := range instances {
|
|
if !t.fixers.Has(instance.ID) {
|
|
continue
|
|
}
|
|
|
|
oldTorrentId := instance.ID
|
|
command, _ := t.fixers.Pop(oldTorrentId) // delete the fixer if it's done
|
|
switch command {
|
|
|
|
case "replaced": // id is old torrent id
|
|
t.log.Debugf("Deleting old id=%s because it's redundant to fixed torrent %s ", oldTorrentId, instance.Name)
|
|
toDelete = append(toDelete, oldTorrentId)
|
|
continue
|
|
|
|
case "download_failed": // id is failed fixer id
|
|
t.log.Debugf("Deleting failed fixer id=%s of torrent %s", oldTorrentId, instance.Name)
|
|
toDelete = append(toDelete, oldTorrentId)
|
|
continue
|
|
|
|
case "repaired": // this torrent contains broken files
|
|
if instance.Progress != 100 {
|
|
t.fixers.Set(oldTorrentId, command) // requeue the fixer, it's not done yet
|
|
continue
|
|
}
|
|
|
|
fixedTorrent := t.getMoreInfo(instance)
|
|
t.log.Debugf("Repairing torrent %s again now that fixer id=%s is done", t.GetKey(fixedTorrent), oldTorrentId)
|
|
repairMe, _ := allTorrents.Get(t.GetKey(fixedTorrent))
|
|
toRedownload = append(toRedownload, repairMe)
|
|
toDelete = append(toDelete, oldTorrentId)
|
|
continue
|
|
}
|
|
}
|
|
|
|
infoCache, _ := t.DirectoryMap.Get(INT_INFO_CACHE)
|
|
for _, id := range toDelete {
|
|
t.api.DeleteTorrent(id)
|
|
infoCache.Remove(id)
|
|
t.deleteTorrentFile(id)
|
|
}
|
|
|
|
for _, torrent := range toRedownload {
|
|
t.redownloadTorrent(torrent, "")
|
|
}
|
|
|
|
t.writeFixersToFile()
|
|
|
|
t.log.Debugf("Finished processing fixers")
|
|
}
|
|
|
|
func (t *TorrentManager) removeExpiredFixers(instances []realdebrid.Torrent) {
|
|
fixers := t.fixers.Keys()
|
|
if len(fixers) == 0 {
|
|
return
|
|
}
|
|
for _, fixerID := range fixers {
|
|
found := false
|
|
for _, instance := range instances {
|
|
if instance.ID == fixerID {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
if !found {
|
|
t.log.Debugf("Removing expired fixer id=%s", fixerID)
|
|
t.fixers.Remove(fixerID)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (t *TorrentManager) writeFixersToFile() {
|
|
filePath := "data/fixers.json"
|
|
file, err := os.Create(filePath)
|
|
if err != nil {
|
|
t.log.Warnf("Cannot create fixer file %s: %v", filePath, err)
|
|
return
|
|
}
|
|
defer file.Close()
|
|
|
|
fileData, err := t.fixers.MarshalJSON()
|
|
if err != nil {
|
|
t.log.Warnf("Cannot marshal fixers: %v", err)
|
|
return
|
|
}
|
|
|
|
_, err = file.Write(fileData)
|
|
if err != nil {
|
|
t.log.Warnf("Cannot write to fixer file %s: %v", filePath, err)
|
|
return
|
|
}
|
|
}
|
|
|
|
func (t *TorrentManager) readFixersFromFile() (ret cmap.ConcurrentMap[string, string]) {
|
|
ret = cmap.New[string]()
|
|
filePath := "data/fixers.json"
|
|
file, err := os.Open(filePath)
|
|
if err != nil {
|
|
if os.IsNotExist(err) {
|
|
return
|
|
}
|
|
t.log.Warnf("Cannot open fixer file %s: %v", filePath, err)
|
|
return
|
|
}
|
|
defer file.Close()
|
|
fileData, err := io.ReadAll(file)
|
|
if err != nil {
|
|
t.log.Warnf("Cannot read fixer file %s: %v", filePath, err)
|
|
return
|
|
}
|
|
|
|
err = ret.UnmarshalJSON(fileData)
|
|
if err != nil {
|
|
t.log.Warnf("Cannot unmarshal fixer file %s: %v", filePath, err)
|
|
return
|
|
}
|
|
|
|
return
|
|
}
|