|
|
|
|
@@ -16,8 +16,9 @@ const EXPIRED_LINK_TOLERANCE_HOURS = 24
|
|
|
|
|
|
|
|
|
|
func (t *TorrentManager) RepairAll() {
|
|
|
|
|
_ = t.repairWorker.Submit(func() {
|
|
|
|
|
t.log.Info("Repairing all broken torrents")
|
|
|
|
|
t.repairAll()
|
|
|
|
|
t.log.Debug("Finished repairing all torrents")
|
|
|
|
|
t.log.Info("Finished repairing all torrents")
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -44,7 +45,9 @@ func (t *TorrentManager) repairAll() {
|
|
|
|
|
currentGroup.Add(torrent.Hash)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.log.Debug("Checking if torrents are still cached")
|
|
|
|
|
var availabilityChecks = make(map[string]bool)
|
|
|
|
|
uncachedCount := 0
|
|
|
|
|
for i := range hashGroups {
|
|
|
|
|
resp, err := t.Api.AvailabilityCheck(hashGroups[i].ToSlice())
|
|
|
|
|
if err != nil {
|
|
|
|
|
@@ -55,8 +58,12 @@ func (t *TorrentManager) repairAll() {
|
|
|
|
|
for hash, hosterHash := range resp {
|
|
|
|
|
// Check if HosterHash is a map (Variants field is used)
|
|
|
|
|
availabilityChecks[hash] = len(hosterHash.Variants) > 0
|
|
|
|
|
if !availabilityChecks[hash] {
|
|
|
|
|
uncachedCount++
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
t.log.Debugf("Found %d torrents that are no longer cached", uncachedCount)
|
|
|
|
|
|
|
|
|
|
var toRepair []*Torrent
|
|
|
|
|
allTorrents.IterCb(func(_ string, torrent *Torrent) {
|
|
|
|
|
@@ -69,6 +76,7 @@ func (t *TorrentManager) repairAll() {
|
|
|
|
|
if _, ok := availabilityChecks[torrent.Hash]; !ok || !availabilityChecks[torrent.Hash] {
|
|
|
|
|
isCached = false
|
|
|
|
|
}
|
|
|
|
|
// todo: also handle file ID checks
|
|
|
|
|
|
|
|
|
|
// check 2: for broken files
|
|
|
|
|
hasBrokenFiles := false
|
|
|
|
|
@@ -82,7 +90,7 @@ func (t *TorrentManager) repairAll() {
|
|
|
|
|
toRepair = append(toRepair, torrent)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
t.log.Debugf("Found %d torrents to repair", len(toRepair))
|
|
|
|
|
t.log.Debugf("Found %d broken torrents to repair in total", len(toRepair))
|
|
|
|
|
for i := range toRepair {
|
|
|
|
|
torrent := toRepair[i]
|
|
|
|
|
t.log.Infof("Repairing %s", torrent.AccessKey)
|
|
|
|
|
@@ -122,8 +130,11 @@ func (t *TorrentManager) repair(torrent *Torrent) {
|
|
|
|
|
if t.reinsertTorrent(torrent, "") {
|
|
|
|
|
t.log.Infof("Successfully downloaded torrent %s to repair it", torrent.AccessKey)
|
|
|
|
|
return
|
|
|
|
|
} else {
|
|
|
|
|
} else if !torrent.Unfixable {
|
|
|
|
|
t.log.Warnf("Failed to repair by reinserting torrent %s, will only redownload broken files...", torrent.AccessKey)
|
|
|
|
|
} else {
|
|
|
|
|
t.log.Warnf("Cannot repair torrent %s", torrent.AccessKey)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
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)
|
|
|
|
|
@@ -217,8 +228,7 @@ func (t *TorrentManager) repair(torrent *Torrent) {
|
|
|
|
|
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)
|
|
|
|
|
t.markAsUnplayable(torrent)
|
|
|
|
|
t.log.Warnf("Cannot repair torrent %s", torrent.AccessKey)
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
t.log.Warnf("Torrent %s has no broken files to repair", torrent.AccessKey)
|
|
|
|
|
@@ -247,6 +257,9 @@ func (t *TorrentManager) reinsertTorrent(torrent *Torrent, brokenFiles string) b
|
|
|
|
|
resp, err := t.Api.AddMagnetHash(torrent.Hash)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.log.Warnf("Cannot redownload torrent: %v", err)
|
|
|
|
|
if strings.Contains(err.Error(), "infringing_file") {
|
|
|
|
|
t.markAsUnfixable(torrent)
|
|
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
time.Sleep(1 * time.Second)
|
|
|
|
|
@@ -342,10 +355,21 @@ func (t *TorrentManager) canCapacityHandle() bool {
|
|
|
|
|
|
|
|
|
|
func (t *TorrentManager) markAsUnplayable(torrent *Torrent) {
|
|
|
|
|
t.log.Warnf("Marking torrent %s as unplayable", torrent.AccessKey)
|
|
|
|
|
torrent.Unfixable = true
|
|
|
|
|
t.markAsUnfixable(torrent)
|
|
|
|
|
t.DirectoryMap.IterCb(func(directory string, torrents cmap.ConcurrentMap[string, *Torrent]) {
|
|
|
|
|
torrents.Remove(torrent.AccessKey)
|
|
|
|
|
})
|
|
|
|
|
torrents, _ := t.DirectoryMap.Get(config.UNPLAYABLE_TORRENTS)
|
|
|
|
|
torrents.Set(torrent.AccessKey, torrent)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (t *TorrentManager) markAsUnfixable(torrent *Torrent) {
|
|
|
|
|
torrent.Unfixable = true
|
|
|
|
|
infoCache, _ := t.DirectoryMap.Get(INT_INFO_CACHE)
|
|
|
|
|
torrent.DownloadedIDs.Each(func(id string) bool {
|
|
|
|
|
info, _ := infoCache.Get(id)
|
|
|
|
|
info.Unfixable = true
|
|
|
|
|
t.writeTorrentToFile(id, torrent)
|
|
|
|
|
return false
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|