diff --git a/internal/torrent/fixer.go b/internal/torrent/fixer.go index e727738..f28a512 100644 --- a/internal/torrent/fixer.go +++ b/internal/torrent/fixer.go @@ -76,9 +76,6 @@ func (t *TorrentManager) processFixers(instances []realdebrid.Torrent) { 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 { diff --git a/internal/torrent/manager.go b/internal/torrent/manager.go index 4f4355c..66b61a3 100644 --- a/internal/torrent/manager.go +++ b/internal/torrent/manager.go @@ -137,8 +137,17 @@ func (t *TorrentManager) GetPath(file *File) string { /// torrent functions +func (t *TorrentManager) getTorrentFiles() mapset.Set[string] { + files, err := filepath.Glob("data/*.torrent_zurg") + if err != nil { + t.log.Warnf("Cannot get files in data directory: %v", err) + return nil + } + return mapset.NewSet[string](files...) +} + func (t *TorrentManager) writeTorrentToFile(torrent *Torrent) { - filePath := "data/" + torrent.Hash + ".json" + filePath := "data/" + torrent.Hash + ".torrent_zurg" file, err := os.Create(filePath) if err != nil { t.log.Warnf("Cannot create file %s: %v", filePath, err) @@ -163,7 +172,7 @@ func (t *TorrentManager) writeTorrentToFile(torrent *Torrent) { } func (t *TorrentManager) readTorrentFromFile(hash string) *Torrent { - filePath := "data/" + hash + ".json" + filePath := "data/" + hash + ".torrent_zurg" file, err := os.Open(filePath) if err != nil { if os.IsNotExist(err) { @@ -190,7 +199,7 @@ func (t *TorrentManager) readTorrentFromFile(hash string) *Torrent { } func (t *TorrentManager) deleteTorrentFile(hash string) { - filePath := "data/" + hash + ".json" + filePath := "data/" + hash + ".torrent_zurg" err := os.Remove(filePath) if err != nil { t.log.Warnf("Cannot delete file %s: %v", filePath, err) @@ -201,8 +210,17 @@ func (t *TorrentManager) deleteTorrentFile(hash string) { /// info functions +func (t *TorrentManager) getInfoFiles() mapset.Set[string] { + files, err := filepath.Glob("data/*.info_zurg") + if err != nil { + t.log.Warnf("Cannot get files in data directory: %v", err) + return nil + } + return mapset.NewSet[string](files...) +} + func (t *TorrentManager) writeInfoToFile(info *realdebrid.TorrentInfo) { - filePath := "data/" + info.ID + ".info" + filePath := "data/" + info.ID + ".info_zurg" file, err := os.Create(filePath) if err != nil { t.log.Warnf("Cannot create info file %s: %v", filePath, err) @@ -225,7 +243,7 @@ func (t *TorrentManager) writeInfoToFile(info *realdebrid.TorrentInfo) { } func (t *TorrentManager) readInfoFromFile(torrentID string) *realdebrid.TorrentInfo { - filePath := "data/" + torrentID + ".info" + filePath := "data/" + torrentID + ".info_zurg" file, err := os.Open(filePath) if err != nil { if os.IsNotExist(err) { @@ -246,7 +264,7 @@ func (t *TorrentManager) readInfoFromFile(torrentID string) *realdebrid.TorrentI } func (t *TorrentManager) deleteInfoFile(torrentID string) { - filePath := "data/" + torrentID + ".info" + filePath := "data/" + torrentID + ".info_zurg" err := os.Remove(filePath) if err != nil { t.log.Warnf("Cannot delete info file %s: %v", filePath, err) diff --git a/internal/torrent/refresh.go b/internal/torrent/refresh.go index 162cde4..3f56149 100644 --- a/internal/torrent/refresh.go +++ b/internal/torrent/refresh.go @@ -39,8 +39,28 @@ func (t *TorrentManager) refreshTorrents(isInitialRun bool) []string { var updatedPaths []string noInfoCount := 0 + allTorrents, _ := t.DirectoryMap.Get(INT_ALL) freshAccessKeys := mapset.NewSet[string]() + + allHashes := mapset.NewSet[string]() + t.getTorrentFiles().Each(func(path string) bool { + path = filepath.Base(path) + hash := strings.TrimSuffix(path, ".torrent_zurg") + allHashes.Add(hash) + return false + }) + freshHashes := mapset.NewSet[string]() + + allIDs := mapset.NewSet[string]() + t.getInfoFiles().Each(func(path string) bool { + path = filepath.Base(path) + torrentID := strings.TrimSuffix(path, ".info_zurg") + allIDs.Add(torrentID) + return false + }) + freshIDs := mapset.NewSet[string]() + for torrent := range torChan { if torrent == nil { noInfoCount++ @@ -54,6 +74,8 @@ func (t *TorrentManager) refreshTorrents(isInitialRun bool) []string { } accessKey := t.GetKey(torrent) freshAccessKeys.Add(accessKey) + freshHashes.Add(torrent.Hash) + freshIDs.Add(tInfo.ID) // update allTorrents isNewID := false @@ -77,8 +99,13 @@ func (t *TorrentManager) refreshTorrents(isInitialRun bool) []string { updatedPaths = append(updatedPaths, fmt.Sprintf("%s/%s", directory, accessKey)) }) + // write torrent to file + if !allHashes.Contains(mainTorrent.Hash) { + t.writeTorrentToFile(mainTorrent) + } } } + // removed torrents allAccessKeys := mapset.NewSet[string](allTorrents.Keys()...) allAccessKeys.Difference(freshAccessKeys).Each(func(accessKey string) bool { @@ -88,6 +115,18 @@ func (t *TorrentManager) refreshTorrents(isInitialRun bool) []string { t.log.Infof("Compiled into %d torrents, %d were missing info", allTorrents.Count(), noInfoCount) + // data directory cleanup + allHashes.Difference(freshHashes).Each(func(hash string) bool { + t.log.Infof("Deleting stale torrent file %s", hash) + t.deleteTorrentFile(hash) + return false + }) + allIDs.Difference(freshIDs).Each(func(id string) bool { + t.log.Infof("Deleting stale info file %s", id) + t.deleteInfoFile(id) + return false + }) + if t.Config.EnableRepair() { if isInitialRun { t.removeExpiredFixers(instances) @@ -136,6 +175,7 @@ func (t *TorrentManager) getMoreInfo(rdTorrent realdebrid.Torrent) *Torrent { diskTor := t.readTorrentFromFile(rdTorrent.Hash) if diskTor != nil { if diskInfo, ok := diskTor.Components[rdTorrent.ID]; ok && diskInfo.Progress == 100 { + diskTor.Components = map[string]*realdebrid.TorrentInfo{rdTorrent.ID: diskInfo} return diskTor } } diff --git a/internal/torrent/repair.go b/internal/torrent/repair.go index 97cd9fb..58ff7c0 100644 --- a/internal/torrent/repair.go +++ b/internal/torrent/repair.go @@ -473,6 +473,9 @@ func (t *TorrentManager) canCapacityHandle() bool { } func (t *TorrentManager) markAsUnplayable(torrent *Torrent, reason string) { + if torrent.State.Is("unplayable") { + return + } t.log.Warnf("Marking torrent %s as unplayable - %s", t.GetKey(torrent), reason) err := torrent.State.Event(context.Background(), "mark_as_unplayable") if err != nil {