diff --git a/internal/qbittorrent/client.go b/internal/qbittorrent/client.go index ce7adf59..dec69ad5 100644 --- a/internal/qbittorrent/client.go +++ b/internal/qbittorrent/client.go @@ -242,6 +242,19 @@ type TorrentInfo struct { Upspeed int `json:"upspeed"` // 上传速度(字节/秒) } +type InfoNotFoundError struct { + Id string + Err error +} + +func (i InfoNotFoundError) Error() string { + return "there should be exactly one task with tag \"alist-" + i.Id + "\"" +} + +func NewInfoNotFoundError(id string) InfoNotFoundError { + return InfoNotFoundError{Id: id} +} + func (c *client) GetInfo(id string) (TorrentInfo, error) { var infos []TorrentInfo @@ -266,7 +279,7 @@ func (c *client) GetInfo(id string) (TorrentInfo, error) { return TorrentInfo{}, err } if len(infos) != 1 { - return TorrentInfo{}, errors.New("there should be exactly one task with tag \"alist-" + id + "\"") + return TorrentInfo{}, NewInfoNotFoundError(id) } return infos[0], nil } diff --git a/internal/qbittorrent/monitor.go b/internal/qbittorrent/monitor.go index 7d12e749..36883c40 100644 --- a/internal/qbittorrent/monitor.go +++ b/internal/qbittorrent/monitor.go @@ -9,7 +9,6 @@ import ( "github.com/pkg/errors" log "github.com/sirupsen/logrus" "os" - "path" "path/filepath" "sync" "sync/atomic" @@ -29,6 +28,30 @@ func (m *Monitor) Loop() error { completed bool ) m.finish = make(chan struct{}) + + // wait for qbittorrent to parse torrent and create task + m.tsk.SetStatus("waiting for qbittorrent to parse torrent and create task") + waitCount := 0 + for { + _, err := qbclient.GetInfo(m.tsk.ID) + if err == nil { + break + } + switch err.(type) { + case InfoNotFoundError: + break + default: + return err + } + + waitCount += 1 + if waitCount >= 60 { + return errors.New("torrent parse timeout") + } + timer := time.NewTimer(time.Second) + <-timer.C + } + outer: for { select { @@ -61,29 +84,13 @@ func (m *Monitor) update() (bool, error) { progress := float64(info.Completed) / float64(info.Size) * 100 m.tsk.SetProgress(int(progress)) switch info.State { - case UPLOADING: - case PAUSEDUP: - case QUEUEDUP: - case STALLEDUP: - case FORCEDUP: - case CHECKINGUP: + case UPLOADING, PAUSEDUP, QUEUEDUP, STALLEDUP, FORCEDUP, CHECKINGUP: err = m.complete() return true, errors.WithMessage(err, "failed to transfer file") - case ALLOCATING: - case DOWNLOADING: - case METADL: - case PAUSEDDL: - case QUEUEDDL: - case STALLEDDL: - case CHECKINGDL: - case FORCEDDL: - case CHECKINGRESUMEDATA: - case MOVING: - case UNKNOWN: // or maybe should return an error for UNKNOWN? + case ALLOCATING, DOWNLOADING, METADL, PAUSEDDL, QUEUEDDL, STALLEDDL, CHECKINGDL, FORCEDDL, CHECKINGRESUMEDATA, MOVING: m.tsk.SetStatus("qbittorrent downloading") return false, nil - case ERROR: - case MISSINGFILES: + case ERROR, MISSINGFILES, UNKNOWN: return true, errors.Errorf("failed to download %s, error: %s", m.tsk.ID, info.State) } return true, errors.New("unknown error occurred downloading qbittorrent") // should never happen @@ -130,7 +137,7 @@ func (m *Monitor) complete() error { } stream := &model.FileStream{ Obj: &model.Object{ - Name: path.Base(filePath), + Name: file.Name, Size: size, Modified: time.Now(), IsFolder: false, @@ -138,8 +145,7 @@ func (m *Monitor) complete() error { ReadCloser: f, Mimetype: mimetype, } - newDistDir := filepath.Join(dstDirActualPath, file.Name) - return op.Put(tsk.Ctx, storage, newDistDir, stream, tsk.SetProgress) + return op.Put(tsk.Ctx, storage, dstDirActualPath, stream, tsk.SetProgress) }, })) }