|
|
|
@@ -93,7 +93,7 @@ func (t *TorrentManager) mergeToMain(t1, t2 *Torrent) *Torrent {
|
|
|
|
merged := t1
|
|
|
|
merged := t1
|
|
|
|
|
|
|
|
|
|
|
|
// Merge SelectedFiles
|
|
|
|
// Merge SelectedFiles
|
|
|
|
// iteration works!
|
|
|
|
// side note: iteration works!
|
|
|
|
for el := t2.SelectedFiles.Front(); el != nil; el = el.Next() {
|
|
|
|
for el := t2.SelectedFiles.Front(); el != nil; el = el.Next() {
|
|
|
|
if _, ok := merged.SelectedFiles.Get(el.Key); !ok {
|
|
|
|
if _, ok := merged.SelectedFiles.Get(el.Key); !ok {
|
|
|
|
merged.SelectedFiles.Set(el.Key, el.Value)
|
|
|
|
merged.SelectedFiles.Set(el.Key, el.Value)
|
|
|
|
@@ -112,7 +112,9 @@ func (t *TorrentManager) mergeToMain(t1, t2 *Torrent) *Torrent {
|
|
|
|
for _, instance := range merged.Instances {
|
|
|
|
for _, instance := range merged.Instances {
|
|
|
|
if instance.Progress != 100 {
|
|
|
|
if instance.Progress != 100 {
|
|
|
|
merged.InProgress = true
|
|
|
|
merged.InProgress = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
if instance.ForRepair {
|
|
|
|
|
|
|
|
merged.ForRepair = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@@ -121,7 +123,10 @@ func (t *TorrentManager) mergeToMain(t1, t2 *Torrent) *Torrent {
|
|
|
|
|
|
|
|
|
|
|
|
// proxy
|
|
|
|
// proxy
|
|
|
|
func (t *TorrentManager) UnrestrictUntilOk(link string) *realdebrid.UnrestrictResponse {
|
|
|
|
func (t *TorrentManager) UnrestrictUntilOk(link string) *realdebrid.UnrestrictResponse {
|
|
|
|
return t.rd.UnrestrictUntilOk(link)
|
|
|
|
t.workerPool <- true
|
|
|
|
|
|
|
|
ret := t.rd.UnrestrictUntilOk(link)
|
|
|
|
|
|
|
|
<-t.workerPool
|
|
|
|
|
|
|
|
return ret
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
type torrentsResponse struct {
|
|
|
|
type torrentsResponse struct {
|
|
|
|
@@ -211,7 +216,7 @@ func (t *TorrentManager) startRefreshJob() {
|
|
|
|
}(i)
|
|
|
|
}(i)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// iteration works!
|
|
|
|
// side note: iteration works!
|
|
|
|
var toDelete []string
|
|
|
|
var toDelete []string
|
|
|
|
for el := t.TorrentMap.Front(); el != nil; el = el.Next() {
|
|
|
|
for el := t.TorrentMap.Front(); el != nil; el = el.Next() {
|
|
|
|
found := false
|
|
|
|
found := false
|
|
|
|
@@ -295,9 +300,9 @@ func (t *TorrentManager) getMoreInfo(rdTorrent realdebrid.Torrent) *Torrent {
|
|
|
|
// chaotic file means RD will not output the desired file selection
|
|
|
|
// chaotic file means RD will not output the desired file selection
|
|
|
|
// e.g. even if we select just a single mkv, it will output a rar
|
|
|
|
// e.g. even if we select just a single mkv, it will output a rar
|
|
|
|
var isChaotic bool
|
|
|
|
var isChaotic bool
|
|
|
|
selectedFiles, isChaotic = t.organizeChaos(&rdTorrent, selectedFiles)
|
|
|
|
selectedFiles, isChaotic = t.organizeChaos(info.Links, selectedFiles)
|
|
|
|
if isChaotic {
|
|
|
|
if isChaotic {
|
|
|
|
t.log.Errorf("Torrent id=%s %s is unfixable, it's always returning an unstreamable link (it is no longer shown in your directories)", info.ID, info.Name)
|
|
|
|
t.log.Errorf("Torrent id=%s %s is unfixable, it is always returning an unstreamable link (it is no longer shown in your directories)", info.ID, info.Name)
|
|
|
|
t.log.Debugf("You can try fixing it yourself magnet:?xt=urn:btih:%s", info.Hash)
|
|
|
|
t.log.Debugf("You can try fixing it yourself magnet:?xt=urn:btih:%s", info.Hash)
|
|
|
|
return nil
|
|
|
|
return nil
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
@@ -316,7 +321,7 @@ func (t *TorrentManager) getMoreInfo(rdTorrent realdebrid.Torrent) *Torrent {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if selectedFiles.Len() == len(info.Links) {
|
|
|
|
} else if selectedFiles.Len() == len(info.Links) {
|
|
|
|
// all links are still intact! good!
|
|
|
|
// all links are still intact! good!
|
|
|
|
// iteration works!
|
|
|
|
// side note: iteration works!
|
|
|
|
i := 0
|
|
|
|
i := 0
|
|
|
|
for el := selectedFiles.Front(); el != nil; el = el.Next() {
|
|
|
|
for el := selectedFiles.Front(); el != nil; el = el.Next() {
|
|
|
|
if i < len(info.Links) {
|
|
|
|
if i < len(info.Links) {
|
|
|
|
@@ -428,31 +433,27 @@ func (t *TorrentManager) readFromFile(torrentID string) *realdebrid.TorrentInfo
|
|
|
|
return &torrent
|
|
|
|
return &torrent
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (t *TorrentManager) organizeChaos(info *realdebrid.Torrent, selectedFiles *orderedmap.OrderedMap[string, *File]) (*orderedmap.OrderedMap[string, *File], bool) {
|
|
|
|
func (t *TorrentManager) organizeChaos(links []string, selectedFiles *orderedmap.OrderedMap[string, *File]) (*orderedmap.OrderedMap[string, *File], bool) {
|
|
|
|
type Result struct {
|
|
|
|
type Result struct {
|
|
|
|
Response *realdebrid.UnrestrictResponse
|
|
|
|
Response *realdebrid.UnrestrictResponse
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
resultsChan := make(chan Result, len(info.Links))
|
|
|
|
resultsChan := make(chan Result, len(links))
|
|
|
|
var wg sync.WaitGroup
|
|
|
|
var wg sync.WaitGroup
|
|
|
|
|
|
|
|
|
|
|
|
// Limit concurrency
|
|
|
|
for _, link := range links {
|
|
|
|
sem := make(chan bool, t.config.GetNumOfWorkers())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for _, link := range info.Links {
|
|
|
|
|
|
|
|
wg.Add(1)
|
|
|
|
wg.Add(1)
|
|
|
|
sem <- true
|
|
|
|
|
|
|
|
go func(lnk string) {
|
|
|
|
go func(lnk string) {
|
|
|
|
defer wg.Done()
|
|
|
|
defer wg.Done()
|
|
|
|
defer func() { <-sem }()
|
|
|
|
t.workerPool <- true
|
|
|
|
resp := t.rd.UnrestrictUntilOk(lnk)
|
|
|
|
resp := t.rd.UnrestrictUntilOk(lnk)
|
|
|
|
|
|
|
|
<-t.workerPool
|
|
|
|
resultsChan <- Result{Response: resp}
|
|
|
|
resultsChan <- Result{Response: resp}
|
|
|
|
}(link)
|
|
|
|
}(link)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
go func() {
|
|
|
|
wg.Wait()
|
|
|
|
wg.Wait()
|
|
|
|
close(sem)
|
|
|
|
|
|
|
|
close(resultsChan)
|
|
|
|
close(resultsChan)
|
|
|
|
}()
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
|
|
@@ -462,7 +463,7 @@ func (t *TorrentManager) organizeChaos(info *realdebrid.Torrent, selectedFiles *
|
|
|
|
continue
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
found := false
|
|
|
|
found := false
|
|
|
|
// iteration works!
|
|
|
|
// side note: iteration works!
|
|
|
|
for el := selectedFiles.Front(); el != nil; el = el.Next() {
|
|
|
|
for el := selectedFiles.Front(); el != nil; el = el.Next() {
|
|
|
|
if file, _ := selectedFiles.Get(el.Key); strings.Contains(file.Path, result.Response.Filename) {
|
|
|
|
if file, _ := selectedFiles.Get(el.Key); strings.Contains(file.Path, result.Response.Filename) {
|
|
|
|
file.Link = result.Response.Link
|
|
|
|
file.Link = result.Response.Link
|
|
|
|
@@ -490,7 +491,7 @@ func (t *TorrentManager) organizeChaos(info *realdebrid.Torrent, selectedFiles *
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (t *TorrentManager) repairAll() {
|
|
|
|
func (t *TorrentManager) repairAll() {
|
|
|
|
// iteration works!
|
|
|
|
// side note: iteration works!
|
|
|
|
for el := t.TorrentMap.Front(); el != nil; el = el.Next() {
|
|
|
|
for el := t.TorrentMap.Front(); el != nil; el = el.Next() {
|
|
|
|
torrent := el.Value
|
|
|
|
torrent := el.Value
|
|
|
|
// do not repair if in progress
|
|
|
|
// do not repair if in progress
|
|
|
|
@@ -498,199 +499,191 @@ func (t *TorrentManager) repairAll() {
|
|
|
|
continue
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var missingFiles []File
|
|
|
|
// do not repair if all files have links
|
|
|
|
|
|
|
|
forRepair := false
|
|
|
|
for el2 := torrent.SelectedFiles.Front(); el2 != nil; el2 = el2.Next() {
|
|
|
|
for el2 := torrent.SelectedFiles.Front(); el2 != nil; el2 = el2.Next() {
|
|
|
|
file, ok := torrent.SelectedFiles.Get(el2.Key)
|
|
|
|
file := el2.Value
|
|
|
|
if !ok {
|
|
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// check for case of repairs like
|
|
|
|
|
|
|
|
// case 1: missing links
|
|
|
|
|
|
|
|
// case 2: unrestrictable links TODO
|
|
|
|
|
|
|
|
if file.Link == "" {
|
|
|
|
if file.Link == "" {
|
|
|
|
missingFiles = append(missingFiles, *file)
|
|
|
|
forRepair = true
|
|
|
|
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if len(missingFiles) == 0 {
|
|
|
|
if !forRepair {
|
|
|
|
|
|
|
|
// if it was marked for repair, unmark it
|
|
|
|
|
|
|
|
torrent.ForRepair = false
|
|
|
|
|
|
|
|
t.TorrentMap.Set(torrent.AccessKey, torrent)
|
|
|
|
continue
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for _, info := range torrent.Instances {
|
|
|
|
// when getting info, we mark it for repair if it's missing some links
|
|
|
|
if info.ForRepair {
|
|
|
|
if torrent.ForRepair {
|
|
|
|
t.log.Infof("There were less links than was expected on %s %s; fixing...", info.ID, info.Name)
|
|
|
|
t.log.Infof("There were less links than was expected on %s; fixing...", torrent.AccessKey)
|
|
|
|
// t.repair(&info, true)
|
|
|
|
t.Repair(torrent.AccessKey)
|
|
|
|
break // only repair the first one for repair and then move on
|
|
|
|
break // only repair the first one for repair and then move on
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// func (t *TorrentManager) repair(info *realdebrid.TorrentInfo, tryReinsertionFirst bool) {
|
|
|
|
func (t *TorrentManager) Repair(accessKey string) {
|
|
|
|
// // file.Link == "" should be repaired
|
|
|
|
torrent, _ := t.TorrentMap.Get(accessKey)
|
|
|
|
// // then we repair it!
|
|
|
|
if torrent == nil {
|
|
|
|
// t.log.Infof("Repairing torrent id=%s", info.ID)
|
|
|
|
t.log.Errorf("Cannot find torrent %s anymore to repair it", accessKey)
|
|
|
|
// // check if we can still add more downloads
|
|
|
|
return
|
|
|
|
// proceed := t.canCapacityHandle()
|
|
|
|
}
|
|
|
|
// if !proceed {
|
|
|
|
if torrent.InProgress {
|
|
|
|
// t.log.Error("Cannot add more torrents, exiting")
|
|
|
|
t.log.Infof("Torrent %s is in progress, cannot repair", torrent.AccessKey)
|
|
|
|
// return
|
|
|
|
return
|
|
|
|
// }
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// // first solution: add the same selection, maybe it can be fixed by reinsertion?
|
|
|
|
// check if we can still add more downloads
|
|
|
|
// success := false
|
|
|
|
proceed := t.canCapacityHandle()
|
|
|
|
// if tryReinsertionFirst {
|
|
|
|
if !proceed {
|
|
|
|
// success = t.reinsertTorrent(info, "", true)
|
|
|
|
t.log.Error("Cannot add more torrents, ignoring repair request")
|
|
|
|
// }
|
|
|
|
return
|
|
|
|
// if !success {
|
|
|
|
}
|
|
|
|
// // if all the selected files are missing but there are other streamable files
|
|
|
|
|
|
|
|
// var otherStreamableFileIDs []int
|
|
|
|
|
|
|
|
// for _, file := range info.Files {
|
|
|
|
|
|
|
|
// found := false
|
|
|
|
|
|
|
|
// for el := selectedFiles.Front(); el != nil; el = el.Next() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// }
|
|
|
|
// make the file messy
|
|
|
|
// for _, selectedFile := range selectedFiles {
|
|
|
|
var links []string
|
|
|
|
// if selectedFile.ID == file.ID {
|
|
|
|
for el := torrent.SelectedFiles.Front(); el != nil; el = el.Next() {
|
|
|
|
// found = true
|
|
|
|
file := el.Value
|
|
|
|
// break
|
|
|
|
if file.Link != "" {
|
|
|
|
// }
|
|
|
|
links = append(links, file.Link)
|
|
|
|
// }
|
|
|
|
}
|
|
|
|
// if !found && isStreamable(file.Path) {
|
|
|
|
file.Link = ""
|
|
|
|
// otherStreamableFileIDs = append(otherStreamableFileIDs, file.ID)
|
|
|
|
}
|
|
|
|
// }
|
|
|
|
selectedFiles, _ := t.organizeChaos(links, torrent.SelectedFiles)
|
|
|
|
// }
|
|
|
|
torrent.SelectedFiles = selectedFiles
|
|
|
|
// if (len(missingFiles) == len(selectedFiles) || len(missingFiles) == 1) && len(otherStreamableFileIDs) > 0 {
|
|
|
|
t.TorrentMap.Set(torrent.AccessKey, torrent)
|
|
|
|
// // we will download 1 extra streamable file to force a redownload of the missing files
|
|
|
|
|
|
|
|
// // or if there's only 1 missing file, we will download 1 more to prevent a rename
|
|
|
|
|
|
|
|
// missingFilesPlus1 := strings.Join(getFileIDs(missingFiles), ",")
|
|
|
|
|
|
|
|
// t.log.Infof("Redownloading %d missing files", len(missingFiles))
|
|
|
|
|
|
|
|
// t.reinsertTorrent(info, missingFilesPlus1, false)
|
|
|
|
|
|
|
|
// } else if len(selectedFiles) > 1 {
|
|
|
|
|
|
|
|
// // if not, last resort: add only the missing files but do it in 2 batches
|
|
|
|
|
|
|
|
// half := len(missingFiles) / 2
|
|
|
|
|
|
|
|
// missingFiles1 := strings.Join(getFileIDs(missingFiles[:half]), ",")
|
|
|
|
|
|
|
|
// missingFiles2 := strings.Join(getFileIDs(missingFiles[half:]), ",")
|
|
|
|
|
|
|
|
// if missingFiles1 != "" {
|
|
|
|
|
|
|
|
// t.log.Infof("Redownloading %d missing files; batch 1 of 2", len(missingFiles1))
|
|
|
|
|
|
|
|
// t.reinsertTorrent(info, missingFiles1, false)
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// if missingFiles2 != "" {
|
|
|
|
|
|
|
|
// t.log.Infof("Redownloading %d missing files; batch 2 of 2", len(missingFiles2))
|
|
|
|
|
|
|
|
// t.reinsertTorrent(info, missingFiles2, false)
|
|
|
|
|
|
|
|
// } else {
|
|
|
|
|
|
|
|
// t.log.Info("No other missing files left to reinsert")
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// } else {
|
|
|
|
|
|
|
|
// t.log.Infof("Torrent id=%s is unfixable as the only link cached in RD is already broken (it is no longer shown in your directories)", info.ID)
|
|
|
|
|
|
|
|
// t.log.Debugf("You can try fixing it yourself magnet:?xt=urn:btih:%s", info.Hash)
|
|
|
|
|
|
|
|
// return
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// t.log.Info("Waiting for downloads to finish")
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// func (t *TorrentManager) reinsertTorrent(torrent *realdebrid.TorrentInfo, missingFiles string, deleteIfFailed bool) bool {
|
|
|
|
// first solution: add the same selection, maybe it can be fixed by reinsertion?
|
|
|
|
// // if missingFiles is not provided, look for missing files
|
|
|
|
if t.reinsertTorrent(torrent, "") {
|
|
|
|
// if missingFiles == "" {
|
|
|
|
t.log.Infof("Redownloaded torrent %s to repair it", torrent.AccessKey)
|
|
|
|
// var tmpSelection string
|
|
|
|
return
|
|
|
|
// for _, file := range torrent.Files {
|
|
|
|
}
|
|
|
|
// if file.Selected == 0 {
|
|
|
|
// if all the selected files are missing but there are other streamable files
|
|
|
|
// continue
|
|
|
|
var missingFiles []File
|
|
|
|
// }
|
|
|
|
for el := torrent.SelectedFiles.Front(); el != nil; el = el.Next() {
|
|
|
|
// tmpSelection += fmt.Sprintf("%d,", file.ID)
|
|
|
|
file := el.Value
|
|
|
|
// }
|
|
|
|
if file.Link == "" {
|
|
|
|
// if tmpSelection == "" {
|
|
|
|
missingFiles = append(missingFiles, *file)
|
|
|
|
// return false
|
|
|
|
}
|
|
|
|
// }
|
|
|
|
}
|
|
|
|
// if len(tmpSelection) > 0 {
|
|
|
|
if len(missingFiles) > 0 {
|
|
|
|
// missingFiles = tmpSelection[:len(tmpSelection)-1]
|
|
|
|
t.log.Infof("Redownloading %d missing files for torrent %s", len(missingFiles), torrent.AccessKey)
|
|
|
|
// }
|
|
|
|
// if not, last resort: add only the missing files but do it in 2 batches
|
|
|
|
// }
|
|
|
|
half := len(missingFiles) / 2
|
|
|
|
|
|
|
|
missingFiles1 := strings.Join(getFileIDs(missingFiles[:half]), ",")
|
|
|
|
|
|
|
|
missingFiles2 := strings.Join(getFileIDs(missingFiles[half:]), ",")
|
|
|
|
|
|
|
|
if missingFiles1 != "" {
|
|
|
|
|
|
|
|
t.reinsertTorrent(torrent, missingFiles1)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if missingFiles2 != "" {
|
|
|
|
|
|
|
|
t.reinsertTorrent(torrent, missingFiles2)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// // redownload torrent
|
|
|
|
func (t *TorrentManager) reinsertTorrent(torrent *Torrent, missingFiles string) bool {
|
|
|
|
// resp, err := t.rd.AddMagnetHash(torrent.Hash)
|
|
|
|
// if missingFiles is not provided, look for missing files
|
|
|
|
// if err != nil {
|
|
|
|
if missingFiles == "" {
|
|
|
|
// t.log.Errorf("Cannot redownload torrent: %v", err)
|
|
|
|
var tmpSelection string
|
|
|
|
// return false
|
|
|
|
for el := torrent.SelectedFiles.Front(); el != nil; el = el.Next() {
|
|
|
|
// }
|
|
|
|
file := el.Value
|
|
|
|
// newTorrentID := resp.ID
|
|
|
|
tmpSelection += fmt.Sprintf("%d,", file.ID)
|
|
|
|
// err = t.rd.SelectTorrentFiles(newTorrentID, missingFiles)
|
|
|
|
}
|
|
|
|
// if err != nil {
|
|
|
|
if tmpSelection == "" {
|
|
|
|
// t.log.Errorf("Cannot start redownloading: %v", err)
|
|
|
|
return false
|
|
|
|
// }
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(tmpSelection) > 0 {
|
|
|
|
|
|
|
|
missingFiles = tmpSelection[:len(tmpSelection)-1]
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// if deleteIfFailed {
|
|
|
|
// redownload torrent
|
|
|
|
// if err != nil {
|
|
|
|
resp, err := t.rd.AddMagnetHash(torrent.Instances[0].Hash)
|
|
|
|
// t.rd.DeleteTorrent(newTorrentID)
|
|
|
|
if err != nil {
|
|
|
|
// return false
|
|
|
|
t.log.Errorf("Cannot redownload torrent: %v", err)
|
|
|
|
// }
|
|
|
|
return false
|
|
|
|
// time.Sleep(1 * time.Second)
|
|
|
|
}
|
|
|
|
// // see if the torrent is ready
|
|
|
|
time.Sleep(1 * time.Second)
|
|
|
|
// info, err := t.rd.GetTorrentInfo(newTorrentID)
|
|
|
|
|
|
|
|
// if err != nil {
|
|
|
|
|
|
|
|
// t.log.Errorf("Cannot get info on redownloaded torrent id=%s : %v", newTorrentID, err)
|
|
|
|
|
|
|
|
// if deleteIfFailed {
|
|
|
|
|
|
|
|
// t.rd.DeleteTorrent(newTorrentID)
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// return false
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// time.Sleep(1 * time.Second)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// if info.Progress != 100 {
|
|
|
|
// select files
|
|
|
|
// t.log.Infof("Torrent id=%s is not cached anymore so we have to wait until completion, currently %d%%", info.ID, info.Progress)
|
|
|
|
newTorrentID := resp.ID
|
|
|
|
// t.rd.DeleteTorrent(newTorrentID)
|
|
|
|
err = t.rd.SelectTorrentFiles(newTorrentID, missingFiles)
|
|
|
|
// return false
|
|
|
|
if err != nil {
|
|
|
|
// }
|
|
|
|
t.log.Errorf("Cannot start redownloading: %v", err)
|
|
|
|
|
|
|
|
t.rd.DeleteTorrent(newTorrentID)
|
|
|
|
|
|
|
|
return false
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
time.Sleep(10 * time.Second)
|
|
|
|
|
|
|
|
|
|
|
|
// missingCount := len(strings.Split(missingFiles, ","))
|
|
|
|
// see if the torrent is ready
|
|
|
|
// if len(info.Links) != missingCount {
|
|
|
|
info, err := t.rd.GetTorrentInfo(newTorrentID)
|
|
|
|
// t.log.Infof("It didn't fix the issue for id=%s, only got %d files but we need %d, undoing", info.ID, len(info.Links), missingCount)
|
|
|
|
if err != nil {
|
|
|
|
// t.rd.DeleteTorrent(newTorrentID)
|
|
|
|
t.log.Errorf("Cannot get info on redownloaded torrent id=%s : %v", newTorrentID, err)
|
|
|
|
// return false
|
|
|
|
t.rd.DeleteTorrent(newTorrentID)
|
|
|
|
// }
|
|
|
|
return false
|
|
|
|
// t.log.Infof("Redownload successful id=%s, deleting old torrent id=%s", newTorrentID, torrent.ID)
|
|
|
|
}
|
|
|
|
// t.rd.DeleteTorrent(torrent.ID)
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// return true
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// func (t *TorrentManager) canCapacityHandle() bool {
|
|
|
|
if info.Status == "magnet_error" || info.Status == "error" || info.Status == "virus" || info.Status == "dead" {
|
|
|
|
// // max waiting time is 45 minutes
|
|
|
|
t.log.Errorf("Redownloaded torrent id=%s is in error state: %s", newTorrentID, info.Status)
|
|
|
|
// const maxRetries = 50
|
|
|
|
t.rd.DeleteTorrent(newTorrentID)
|
|
|
|
// const baseDelay = 1 * time.Second
|
|
|
|
return false
|
|
|
|
// const maxDelay = 60 * time.Second
|
|
|
|
}
|
|
|
|
// retryCount := 0
|
|
|
|
|
|
|
|
// for {
|
|
|
|
|
|
|
|
// count, err := t.rd.GetActiveTorrentCount()
|
|
|
|
|
|
|
|
// if err != nil {
|
|
|
|
|
|
|
|
// t.log.Errorf("Cannot get active downloads count: %v", err)
|
|
|
|
|
|
|
|
// if retryCount >= maxRetries {
|
|
|
|
|
|
|
|
// t.log.Error("Max retries reached. Exiting.")
|
|
|
|
|
|
|
|
// return false
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// delay := time.Duration(math.Pow(2, float64(retryCount))) * baseDelay
|
|
|
|
|
|
|
|
// if delay > maxDelay {
|
|
|
|
|
|
|
|
// delay = maxDelay
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// time.Sleep(delay)
|
|
|
|
|
|
|
|
// retryCount++
|
|
|
|
|
|
|
|
// continue
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// if count.DownloadingCount < count.MaxNumberOfTorrents {
|
|
|
|
if info.Progress != 100 {
|
|
|
|
// t.log.Infof("We can still add a new torrent, we have capacity for %d more", count.MaxNumberOfTorrents-count.DownloadingCount)
|
|
|
|
t.log.Infof("Torrent id=%s is not cached anymore so we have to wait until completion (this should fix the issue already)", info.ID)
|
|
|
|
// return true
|
|
|
|
return true
|
|
|
|
// }
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// if retryCount >= maxRetries {
|
|
|
|
missingCount := len(strings.Split(missingFiles, ","))
|
|
|
|
// t.log.Error("Max retries reached, exiting")
|
|
|
|
if len(info.Links) != missingCount {
|
|
|
|
// return false
|
|
|
|
t.log.Infof("It did not fix the issue for id=%s, only got %d files but we need %d, undoing", info.ID, len(info.Links), missingCount)
|
|
|
|
// }
|
|
|
|
t.rd.DeleteTorrent(newTorrentID)
|
|
|
|
// delay := time.Duration(math.Pow(2, float64(retryCount))) * baseDelay
|
|
|
|
return false
|
|
|
|
// if delay > maxDelay {
|
|
|
|
}
|
|
|
|
// delay = maxDelay
|
|
|
|
|
|
|
|
// }
|
|
|
|
t.log.Infof("Repair successful id=%s", newTorrentID)
|
|
|
|
// time.Sleep(delay)
|
|
|
|
return true
|
|
|
|
// retryCount++
|
|
|
|
}
|
|
|
|
// }
|
|
|
|
|
|
|
|
// }
|
|
|
|
func (t *TorrentManager) canCapacityHandle() bool {
|
|
|
|
|
|
|
|
// max waiting time is 45 minutes
|
|
|
|
|
|
|
|
const maxRetries = 50
|
|
|
|
|
|
|
|
const baseDelay = 1 * time.Second
|
|
|
|
|
|
|
|
const maxDelay = 60 * time.Second
|
|
|
|
|
|
|
|
retryCount := 0
|
|
|
|
|
|
|
|
for {
|
|
|
|
|
|
|
|
count, err := t.rd.GetActiveTorrentCount()
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
t.log.Errorf("Cannot get active downloads count: %v", err)
|
|
|
|
|
|
|
|
if retryCount >= maxRetries {
|
|
|
|
|
|
|
|
t.log.Error("Max retries reached. Exiting.")
|
|
|
|
|
|
|
|
return false
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
delay := time.Duration(math.Pow(2, float64(retryCount))) * baseDelay
|
|
|
|
|
|
|
|
if delay > maxDelay {
|
|
|
|
|
|
|
|
delay = maxDelay
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
time.Sleep(delay)
|
|
|
|
|
|
|
|
retryCount++
|
|
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if count.DownloadingCount < count.MaxNumberOfTorrents {
|
|
|
|
|
|
|
|
t.log.Infof("We can still add a new torrent, we have capacity for %d more", count.MaxNumberOfTorrents-count.DownloadingCount)
|
|
|
|
|
|
|
|
return true
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if retryCount >= maxRetries {
|
|
|
|
|
|
|
|
t.log.Error("Max retries reached, exiting")
|
|
|
|
|
|
|
|
return false
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
delay := time.Duration(math.Pow(2, float64(retryCount))) * baseDelay
|
|
|
|
|
|
|
|
if delay > maxDelay {
|
|
|
|
|
|
|
|
delay = maxDelay
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
time.Sleep(delay)
|
|
|
|
|
|
|
|
retryCount++
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|