fix: panic when torrent not exist

This commit is contained in:
Simon Ding
2024-09-21 21:47:26 +08:00
parent 37dfb0fe94
commit 40c6e2df5c
5 changed files with 98 additions and 48 deletions

View File

@@ -1,14 +1,14 @@
package pkg package pkg
type Torrent interface { type Torrent interface {
Name() string Name() (string, error)
Progress() int Progress() (int, error)
Stop() error Stop() error
Start() error Start() error
Remove() error Remove() error
Save() string Save() string
Exists() bool Exists() bool
SeedRatio() *float64 SeedRatio() (float64, error)
} }

View File

@@ -113,12 +113,15 @@ func (t *Torrent) reloadClient() error {
return nil return nil
} }
func (t *Torrent) getTorrent() transmissionrpc.Torrent { func (t *Torrent) getTorrent() (transmissionrpc.Torrent, error) {
r, err := t.c.TorrentGetAllForHashes(context.TODO(), []string{t.Hash}) r, err := t.c.TorrentGetAllForHashes(context.TODO(), []string{t.Hash})
if err != nil { if err != nil {
log.Errorf("get torrent info for error: %v", err) log.Errorf("get torrent info for error: %v", err)
} }
return r[0] if len(r) == 0 {
return transmissionrpc.Torrent{}, fmt.Errorf("no torrent")
}
return r[0], nil
} }
func (t *Torrent) Exists() bool { func (t *Torrent) Exists() bool {
@@ -129,37 +132,50 @@ func (t *Torrent) Exists() bool {
return len(r) > 0 return len(r) > 0
} }
func (t *Torrent) Name() string {
if !t.Exists() { func (t *Torrent) Name() (string, error) {
return "" tt, err := t.getTorrent()
if err != nil {
return "", err
} }
return *t.getTorrent().Name return *tt.Name, nil
} }
func (t *Torrent) Progress() int { func (t *Torrent) Progress() (int, error) {
if t.getTorrent().IsFinished != nil && *t.getTorrent().IsFinished { tt, err := t.getTorrent()
return 100 if err != nil {
return 0, err
} }
if t.getTorrent().PercentComplete != nil && *t.getTorrent().PercentComplete >= 1 { if tt.IsFinished != nil && *tt.IsFinished {
return 100 return 100, nil
}
if tt.PercentComplete != nil && *tt.PercentComplete >= 1 {
return 100, nil
} }
if t.getTorrent().PercentComplete != nil { if tt.PercentComplete != nil {
p := int(*t.getTorrent().PercentComplete * 100) p := int(*tt.PercentComplete * 100)
if p == 100 { if p == 100 {
p = 99 p = 99
} }
return p return p, nil
} }
return 0 return 0, nil
} }
func (t *Torrent) Stop() error { func (t *Torrent) Stop() error {
return t.c.TorrentStopHashes(context.TODO(), []string{t.Hash}) return t.c.TorrentStopHashes(context.TODO(), []string{t.Hash})
} }
func (t *Torrent) SeedRatio() *float64 { func (t *Torrent) SeedRatio() (float64, error) {
return t.getTorrent().UploadRatio tt, err := t.getTorrent()
if err != nil {
return 0, err
}
if tt.UploadRatio == nil {
return 0, nil
}
return *tt.UploadRatio, nil
} }
func (t *Torrent) Start() error { func (t *Torrent) Start() error {
@@ -167,15 +183,22 @@ func (t *Torrent) Start() error {
} }
func (t *Torrent) Remove() error { func (t *Torrent) Remove() error {
tt := t.getTorrent() tt, err := t.getTorrent()
if err != nil {
return errors.Wrap(err, "get torrent")
}
return t.c.TorrentRemove(context.TODO(), transmissionrpc.TorrentRemovePayload{ return t.c.TorrentRemove(context.TODO(), transmissionrpc.TorrentRemovePayload{
IDs: []int64{*tt.ID}, IDs: []int64{*tt.ID},
DeleteLocalData: true, DeleteLocalData: true,
}) })
} }
func (t *Torrent) Size() int { func (t *Torrent) Size() (int, error) {
return int(t.getTorrent().TotalSize.Byte()) tt, err := t.getTorrent()
if err != nil {
return 0, errors.Wrap(err, "get torrent")
}
return int(tt.TotalSize.Byte()), nil
} }
func (t *Torrent) Save() string { func (t *Torrent) Save() string {

View File

@@ -16,7 +16,7 @@ import (
type Activity struct { type Activity struct {
*ent.History *ent.History
Progress int `json:"progress"` Progress int `json:"progress"`
SeedRatio float32 `json:"seed_ratio"` SeedRatio float64 `json:"seed_ratio"`
} }
func (s *Server) GetAllActivities(c *gin.Context) (interface{}, error) { func (s *Server) GetAllActivities(c *gin.Context) (interface{}, error) {
@@ -30,8 +30,18 @@ func (s *Server) GetAllActivities(c *gin.Context) (interface{}, error) {
} }
for id, task := range s.core.GetTasks() { for id, task := range s.core.GetTasks() {
if h.ID == id && task.Exists() { if h.ID == id && task.Exists() {
a.Progress = task.Progress() p, err := task.Progress()
a.SeedRatio = float32(*task.SeedRatio()) if err != nil {
log.Warnf("get task progress error: %v", err)
} else {
a.Progress = p
}
r, err := task.SeedRatio()
if err != nil {
log.Warnf("get task seed ratio error: %v", err)
} else {
a.SeedRatio = r
}
} }
} }
activities = append(activities, a) activities = append(activities, a)
@@ -73,7 +83,6 @@ func (s *Server) RemoveActivity(c *gin.Context) (interface{}, error) {
return nil, errors.Wrap(err, "db") return nil, errors.Wrap(err, "db")
} }
if his.EpisodeID != 0 { if his.EpisodeID != 0 {
if !s.db.IsEpisodeDownloadingOrDownloaded(his.EpisodeID) { if !s.db.IsEpisodeDownloadingOrDownloaded(his.EpisodeID) {
s.db.SetEpisodeStatus(his.EpisodeID, episode.StatusMissing) s.db.SetEpisodeStatus(his.EpisodeID, episode.StatusMissing)
@@ -108,7 +117,7 @@ func (s *Server) GetMediaDownloadHistory(c *gin.Context) (interface{}, error) {
type TorrentInfo struct { type TorrentInfo struct {
Name string `json:"name"` Name string `json:"name"`
ID string `json:"id"` ID string `json:"id"`
SeedRatio float32 `json:"seed_ratio"` SeedRatio float32 `json:"seed_ratio"`
Progress int `json:"progress"` Progress int `json:"progress"`
} }
@@ -127,10 +136,12 @@ func (s *Server) GetAllTorrents(c *gin.Context) (interface{}, error) {
if !t.Exists() { if !t.Exists() {
continue continue
} }
name, _ := t.Name()
p, _ := t.Progress()
infos = append(infos, TorrentInfo{ infos = append(infos, TorrentInfo{
Name: t.Name(), Name: name,
ID: t.Hash, ID: t.Hash,
Progress: t.Progress(), Progress: p,
}) })
} }
return infos, nil return infos, nil

View File

@@ -257,7 +257,11 @@ func (c *Client) findEpisodeFilesPreMoving(historyId int) error {
isSingleEpisode := his.EpisodeID > 0 isSingleEpisode := his.EpisodeID > 0
downloadDir := c.db.GetDownloadDir() downloadDir := c.db.GetDownloadDir()
task := c.tasks[historyId] task := c.tasks[historyId]
target := filepath.Join(downloadDir, task.Name()) name, err := task.Name()
if err != nil {
return err
}
target := filepath.Join(downloadDir, name)
fi, err := os.Stat(target) fi, err := os.Stat(target)
if err != nil { if err != nil {
return errors.Wrapf(err, "read dir %v", target) return errors.Wrapf(err, "read dir %v", target)

View File

@@ -63,24 +63,33 @@ func (c *Client) checkTasks() error {
delete(c.tasks, id) delete(c.tasks, id)
continue continue
} }
log.Infof("task (%s) percentage done: %d%%", t.Name(), t.Progress()) name, err := t.Name()
if t.Progress() == 100 { if err != nil {
return errors.Wrap(err, "get name")
}
progress, err := t.Progress()
if err != nil {
return errors.Wrap(err, "get progress")
}
log.Infof("task (%s) percentage done: %d%%", name, progress)
if progress == 100 {
if r.Status == history.StatusSeeding { if r.Status == history.StatusSeeding {
//task already success, check seed ratio //task already success, check seed ratio
torrent := c.tasks[id] torrent := c.tasks[id]
ok := c.isSeedRatioLimitReached(r.IndexerID, torrent) ratio, ok := c.isSeedRatioLimitReached(r.IndexerID, torrent)
if ok { if ok {
log.Infof("torrent file seed ratio reached, remove: %v, current seed ratio: %v", torrent.Name(), *torrent.SeedRatio()) log.Infof("torrent file seed ratio reached, remove: %v, current seed ratio: %v", name, ratio)
torrent.Remove() torrent.Remove()
delete(c.tasks, id) delete(c.tasks, id)
} else { } else {
log.Infof("torrent file still sedding: %v, current seed ratio: %v", torrent.Name(), *torrent.SeedRatio()) log.Infof("torrent file still sedding: %v, current seed ratio: %v", name, ratio)
} }
continue continue
} }
log.Infof("task is done: %v", t.Name()) log.Infof("task is done: %v", name)
c.sendMsg(fmt.Sprintf(message.DownloadComplete, t.Name())) c.sendMsg(fmt.Sprintf(message.DownloadComplete, name))
go c.postTaskProcessing(id) go c.postTaskProcessing(id)
} }
@@ -122,7 +131,10 @@ func (c *Client) moveCompletedTask(id int) (err1 error) {
log.Errorf("get task download client error: %v, use default one", err) log.Errorf("get task download client error: %v, use default one", err)
downloadclient = &ent.DownloadClients{RemoveCompletedDownloads: true, RemoveFailedDownloads: true} downloadclient = &ent.DownloadClients{RemoveCompletedDownloads: true, RemoveFailedDownloads: true}
} }
torrentName := torrent.Name() torrentName, err := torrent.Name()
if err != nil {
return err
}
defer func() { defer func() {
@@ -169,9 +181,9 @@ func (c *Client) moveCompletedTask(id int) (err1 error) {
c.sendMsg(fmt.Sprintf(message.ProcessingComplete, torrentName)) c.sendMsg(fmt.Sprintf(message.ProcessingComplete, torrentName))
//判断是否需要删除本地文件 //判断是否需要删除本地文件
ok := c.isSeedRatioLimitReached(r.IndexerID, torrent) r1, ok := c.isSeedRatioLimitReached(r.IndexerID, torrent)
if downloadclient.RemoveCompletedDownloads && ok { if downloadclient.RemoveCompletedDownloads && ok {
log.Debugf("download complete,remove torrent and files related, torrent: %v, seed ratio: %v", torrentName, *torrent.SeedRatio()) log.Debugf("download complete,remove torrent and files related, torrent: %v, seed ratio: %v", torrentName, r1)
c.db.SetHistoryStatus(r.ID, history.StatusSuccess) c.db.SetHistoryStatus(r.ID, history.StatusSuccess)
delete(c.tasks, r.ID) delete(c.tasks, r.ID)
torrent.Remove() torrent.Remove()
@@ -428,15 +440,15 @@ func (c *Client) checkSeiesNewSeason(media *ent.Media) error {
return nil return nil
} }
func (c *Client) isSeedRatioLimitReached(indexId int, t pkg.Torrent) bool { func (c *Client) isSeedRatioLimitReached(indexId int, t pkg.Torrent)(float64,bool) {
indexer, err := c.db.GetIndexer(indexId) indexer, err := c.db.GetIndexer(indexId)
if err != nil { if err != nil {
return true return 0, true
} }
currentRatio := t.SeedRatio() currentRatio, err := t.SeedRatio()
if currentRatio == nil { if err != nil {
log.Warnf("get current seed ratio error, current ratio is nil") log.Warnf("get current seed ratio error: %v", err)
return indexer.SeedRatio == 0 return currentRatio, indexer.SeedRatio == 0
} }
return *currentRatio >= float64(indexer.SeedRatio) return currentRatio, currentRatio >= float64(indexer.SeedRatio)
} }