mirror of https://github.com/Xhofe/alist
feat(task): add speed monitor (#7655)
parent
db99224126
commit
d7aa1608ac
|
@ -5,6 +5,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
stdpath "path"
|
stdpath "path"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/alist-org/alist/v3/internal/conf"
|
"github.com/alist-org/alist/v3/internal/conf"
|
||||||
"github.com/alist-org/alist/v3/internal/driver"
|
"github.com/alist-org/alist/v3/internal/driver"
|
||||||
|
@ -18,7 +19,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type CopyTask struct {
|
type CopyTask struct {
|
||||||
task.TaskWithCreator
|
task.TaskExtension
|
||||||
Status string `json:"-"` //don't save status to save space
|
Status string `json:"-"` //don't save status to save space
|
||||||
SrcObjPath string `json:"src_path"`
|
SrcObjPath string `json:"src_path"`
|
||||||
DstDirPath string `json:"dst_path"`
|
DstDirPath string `json:"dst_path"`
|
||||||
|
@ -37,6 +38,9 @@ func (t *CopyTask) GetStatus() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *CopyTask) Run() error {
|
func (t *CopyTask) Run() error {
|
||||||
|
t.ClearEndTime()
|
||||||
|
t.SetStartTime(time.Now())
|
||||||
|
defer func() { t.SetEndTime(time.Now()) }()
|
||||||
var err error
|
var err error
|
||||||
if t.srcStorage == nil {
|
if t.srcStorage == nil {
|
||||||
t.srcStorage, err = op.GetStorageByMountPath(t.SrcStorageMp)
|
t.srcStorage, err = op.GetStorageByMountPath(t.SrcStorageMp)
|
||||||
|
@ -54,7 +58,7 @@ var CopyTaskManager *tache.Manager[*CopyTask]
|
||||||
|
|
||||||
// Copy if in the same storage, call move method
|
// Copy if in the same storage, call move method
|
||||||
// if not, add copy task
|
// if not, add copy task
|
||||||
func _copy(ctx context.Context, srcObjPath, dstDirPath string, lazyCache ...bool) (task.TaskInfoWithCreator, error) {
|
func _copy(ctx context.Context, srcObjPath, dstDirPath string, lazyCache ...bool) (task.TaskExtensionInfo, error) {
|
||||||
srcStorage, srcObjActualPath, err := op.GetStorageAndActualPath(srcObjPath)
|
srcStorage, srcObjActualPath, err := op.GetStorageAndActualPath(srcObjPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.WithMessage(err, "failed get src storage")
|
return nil, errors.WithMessage(err, "failed get src storage")
|
||||||
|
@ -93,9 +97,9 @@ func _copy(ctx context.Context, srcObjPath, dstDirPath string, lazyCache ...bool
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// not in the same storage
|
// not in the same storage
|
||||||
taskCreator, _ := ctx.Value("user").(*model.User) // taskCreator is nil when convert failed
|
taskCreator, _ := ctx.Value("user").(*model.User)
|
||||||
t := &CopyTask{
|
t := &CopyTask{
|
||||||
TaskWithCreator: task.TaskWithCreator{
|
TaskExtension: task.TaskExtension{
|
||||||
Creator: taskCreator,
|
Creator: taskCreator,
|
||||||
},
|
},
|
||||||
srcStorage: srcStorage,
|
srcStorage: srcStorage,
|
||||||
|
@ -128,8 +132,8 @@ func copyBetween2Storages(t *CopyTask, srcStorage, dstStorage driver.Driver, src
|
||||||
srcObjPath := stdpath.Join(srcObjPath, obj.GetName())
|
srcObjPath := stdpath.Join(srcObjPath, obj.GetName())
|
||||||
dstObjPath := stdpath.Join(dstDirPath, srcObj.GetName())
|
dstObjPath := stdpath.Join(dstDirPath, srcObj.GetName())
|
||||||
CopyTaskManager.Add(&CopyTask{
|
CopyTaskManager.Add(&CopyTask{
|
||||||
TaskWithCreator: task.TaskWithCreator{
|
TaskExtension: task.TaskExtension{
|
||||||
Creator: t.Creator,
|
Creator: t.GetCreator(),
|
||||||
},
|
},
|
||||||
srcStorage: srcStorage,
|
srcStorage: srcStorage,
|
||||||
dstStorage: dstStorage,
|
dstStorage: dstStorage,
|
||||||
|
@ -150,6 +154,7 @@ func copyFileBetween2Storages(tsk *CopyTask, srcStorage, dstStorage driver.Drive
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithMessagef(err, "failed get src [%s] file", srcFilePath)
|
return errors.WithMessagef(err, "failed get src [%s] file", srcFilePath)
|
||||||
}
|
}
|
||||||
|
tsk.SetTotalBytes(srcFile.GetSize())
|
||||||
link, _, err := op.Link(tsk.Ctx(), srcStorage, srcFilePath, model.LinkArgs{
|
link, _, err := op.Link(tsk.Ctx(), srcStorage, srcFilePath, model.LinkArgs{
|
||||||
Header: http.Header{},
|
Header: http.Header{},
|
||||||
})
|
})
|
||||||
|
|
|
@ -69,7 +69,7 @@ func Move(ctx context.Context, srcPath, dstDirPath string, lazyCache ...bool) er
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func Copy(ctx context.Context, srcObjPath, dstDirPath string, lazyCache ...bool) (task.TaskInfoWithCreator, error) {
|
func Copy(ctx context.Context, srcObjPath, dstDirPath string, lazyCache ...bool) (task.TaskExtensionInfo, error) {
|
||||||
res, err := _copy(ctx, srcObjPath, dstDirPath, lazyCache...)
|
res, err := _copy(ctx, srcObjPath, dstDirPath, lazyCache...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("failed copy %s to %s: %+v", srcObjPath, dstDirPath, err)
|
log.Errorf("failed copy %s to %s: %+v", srcObjPath, dstDirPath, err)
|
||||||
|
@ -101,7 +101,7 @@ func PutDirectly(ctx context.Context, dstDirPath string, file model.FileStreamer
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func PutAsTask(ctx context.Context, dstDirPath string, file model.FileStreamer) (task.TaskInfoWithCreator, error) {
|
func PutAsTask(ctx context.Context, dstDirPath string, file model.FileStreamer) (task.TaskExtensionInfo, error) {
|
||||||
t, err := putAsTask(ctx, dstDirPath, file)
|
t, err := putAsTask(ctx, dstDirPath, file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("failed put %s: %+v", dstDirPath, err)
|
log.Errorf("failed put %s: %+v", dstDirPath, err)
|
||||||
|
|
|
@ -10,10 +10,11 @@ import (
|
||||||
"github.com/alist-org/alist/v3/internal/task"
|
"github.com/alist-org/alist/v3/internal/task"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/xhofe/tache"
|
"github.com/xhofe/tache"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type UploadTask struct {
|
type UploadTask struct {
|
||||||
task.TaskWithCreator
|
task.TaskExtension
|
||||||
storage driver.Driver
|
storage driver.Driver
|
||||||
dstDirActualPath string
|
dstDirActualPath string
|
||||||
file model.FileStreamer
|
file model.FileStreamer
|
||||||
|
@ -28,13 +29,16 @@ func (t *UploadTask) GetStatus() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *UploadTask) Run() error {
|
func (t *UploadTask) Run() error {
|
||||||
|
t.ClearEndTime()
|
||||||
|
t.SetStartTime(time.Now())
|
||||||
|
defer func() { t.SetEndTime(time.Now()) }()
|
||||||
return op.Put(t.Ctx(), t.storage, t.dstDirActualPath, t.file, t.SetProgress, true)
|
return op.Put(t.Ctx(), t.storage, t.dstDirActualPath, t.file, t.SetProgress, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
var UploadTaskManager *tache.Manager[*UploadTask]
|
var UploadTaskManager *tache.Manager[*UploadTask]
|
||||||
|
|
||||||
// putAsTask add as a put task and return immediately
|
// putAsTask add as a put task and return immediately
|
||||||
func putAsTask(ctx context.Context, dstDirPath string, file model.FileStreamer) (task.TaskInfoWithCreator, error) {
|
func putAsTask(ctx context.Context, dstDirPath string, file model.FileStreamer) (task.TaskExtensionInfo, error) {
|
||||||
storage, dstDirActualPath, err := op.GetStorageAndActualPath(dstDirPath)
|
storage, dstDirActualPath, err := op.GetStorageAndActualPath(dstDirPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.WithMessage(err, "failed get storage")
|
return nil, errors.WithMessage(err, "failed get storage")
|
||||||
|
@ -52,13 +56,14 @@ func putAsTask(ctx context.Context, dstDirPath string, file model.FileStreamer)
|
||||||
}
|
}
|
||||||
taskCreator, _ := ctx.Value("user").(*model.User) // taskCreator is nil when convert failed
|
taskCreator, _ := ctx.Value("user").(*model.User) // taskCreator is nil when convert failed
|
||||||
t := &UploadTask{
|
t := &UploadTask{
|
||||||
TaskWithCreator: task.TaskWithCreator{
|
TaskExtension: task.TaskExtension{
|
||||||
Creator: taskCreator,
|
Creator: taskCreator,
|
||||||
},
|
},
|
||||||
storage: storage,
|
storage: storage,
|
||||||
dstDirActualPath: dstDirActualPath,
|
dstDirActualPath: dstDirActualPath,
|
||||||
file: file,
|
file: file,
|
||||||
}
|
}
|
||||||
|
t.SetTotalBytes(file.GetSize())
|
||||||
UploadTaskManager.Add(t)
|
UploadTaskManager.Add(t)
|
||||||
return t, nil
|
return t, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,6 +107,7 @@ func (p *Cloud115) Status(task *tool.DownloadTask) (*tool.Status, error) {
|
||||||
s.Progress = t.Percent
|
s.Progress = t.Percent
|
||||||
s.Status = t.GetStatus()
|
s.Status = t.GetStatus()
|
||||||
s.Completed = t.IsDone()
|
s.Completed = t.IsDone()
|
||||||
|
s.TotalBytes = t.Size
|
||||||
if t.IsFailed() {
|
if t.IsFailed() {
|
||||||
s.Err = fmt.Errorf(t.GetStatus())
|
s.Err = fmt.Errorf(t.GetStatus())
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,7 +82,7 @@ func (a *Aria2) Status(task *tool.DownloadTask) (*tool.Status, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
total, err := strconv.ParseUint(info.TotalLength, 10, 64)
|
total, err := strconv.ParseInt(info.TotalLength, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
total = 0
|
total = 0
|
||||||
}
|
}
|
||||||
|
@ -93,6 +93,7 @@ func (a *Aria2) Status(task *tool.DownloadTask) (*tool.Status, error) {
|
||||||
s := &tool.Status{
|
s := &tool.Status{
|
||||||
Completed: info.Status == "complete",
|
Completed: info.Status == "complete",
|
||||||
Err: err,
|
Err: err,
|
||||||
|
TotalBytes: total,
|
||||||
}
|
}
|
||||||
s.Progress = float64(downloaded) / float64(total) * 100
|
s.Progress = float64(downloaded) / float64(total) * 100
|
||||||
if len(info.FollowedBy) != 0 {
|
if len(info.FollowedBy) != 0 {
|
||||||
|
|
|
@ -83,6 +83,7 @@ func (s SimpleHttp) Run(task *tool.DownloadTask) error {
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
fileSize := resp.ContentLength
|
fileSize := resp.ContentLength
|
||||||
|
task.SetTotalBytes(fileSize)
|
||||||
err = utils.CopyWithCtx(task.Ctx(), file, resp.Body, fileSize, task.SetProgress)
|
err = utils.CopyWithCtx(task.Ctx(), file, resp.Body, fileSize, task.SetProgress)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package pikpak
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"github.com/alist-org/alist/v3/drivers/pikpak"
|
"github.com/alist-org/alist/v3/drivers/pikpak"
|
||||||
"github.com/alist-org/alist/v3/internal/errs"
|
"github.com/alist-org/alist/v3/internal/errs"
|
||||||
|
@ -105,6 +106,10 @@ func (p *PikPak) Status(task *tool.DownloadTask) (*tool.Status, error) {
|
||||||
s.Progress = float64(t.Progress)
|
s.Progress = float64(t.Progress)
|
||||||
s.Status = t.Message
|
s.Status = t.Message
|
||||||
s.Completed = (t.Phase == "PHASE_TYPE_COMPLETE")
|
s.Completed = (t.Phase == "PHASE_TYPE_COMPLETE")
|
||||||
|
s.TotalBytes, err = strconv.ParseInt(t.FileSize, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
s.TotalBytes = 0
|
||||||
|
}
|
||||||
if t.Phase == "PHASE_TYPE_ERROR" {
|
if t.Phase == "PHASE_TYPE_ERROR" {
|
||||||
s.Err = fmt.Errorf(t.Message)
|
s.Err = fmt.Errorf(t.Message)
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,7 @@ func (a *QBittorrent) Status(task *tool.DownloadTask) (*tool.Status, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
s := &tool.Status{}
|
s := &tool.Status{}
|
||||||
|
s.TotalBytes = info.Size
|
||||||
s.Progress = float64(info.Completed) / float64(info.Size) * 100
|
s.Progress = float64(info.Completed) / float64(info.Size) * 100
|
||||||
switch info.State {
|
switch info.State {
|
||||||
case qbittorrent.UPLOADING, qbittorrent.PAUSEDUP, qbittorrent.QUEUEDUP, qbittorrent.STALLEDUP, qbittorrent.FORCEDUP, qbittorrent.CHECKINGUP:
|
case qbittorrent.UPLOADING, qbittorrent.PAUSEDUP, qbittorrent.QUEUEDUP, qbittorrent.STALLEDUP, qbittorrent.FORCEDUP, qbittorrent.CHECKINGUP:
|
||||||
|
|
|
@ -29,7 +29,7 @@ type AddURLArgs struct {
|
||||||
DeletePolicy DeletePolicy
|
DeletePolicy DeletePolicy
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddURL(ctx context.Context, args *AddURLArgs) (task.TaskInfoWithCreator, error) {
|
func AddURL(ctx context.Context, args *AddURLArgs) (task.TaskExtensionInfo, error) {
|
||||||
// get tool
|
// get tool
|
||||||
tool, err := Tools.Get(args.Tool)
|
tool, err := Tools.Get(args.Tool)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -81,7 +81,7 @@ func AddURL(ctx context.Context, args *AddURLArgs) (task.TaskInfoWithCreator, er
|
||||||
|
|
||||||
taskCreator, _ := ctx.Value("user").(*model.User) // taskCreator is nil when convert failed
|
taskCreator, _ := ctx.Value("user").(*model.User) // taskCreator is nil when convert failed
|
||||||
t := &DownloadTask{
|
t := &DownloadTask{
|
||||||
TaskWithCreator: task.TaskWithCreator{
|
TaskExtension: task.TaskExtension{
|
||||||
Creator: taskCreator,
|
Creator: taskCreator,
|
||||||
},
|
},
|
||||||
Url: args.URL,
|
Url: args.URL,
|
||||||
|
|
|
@ -16,6 +16,7 @@ type AddUrlArgs struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Status struct {
|
type Status struct {
|
||||||
|
TotalBytes int64
|
||||||
Progress float64
|
Progress float64
|
||||||
NewGID string
|
NewGID string
|
||||||
Completed bool
|
Completed bool
|
||||||
|
|
|
@ -14,7 +14,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type DownloadTask struct {
|
type DownloadTask struct {
|
||||||
task.TaskWithCreator
|
task.TaskExtension
|
||||||
Url string `json:"url"`
|
Url string `json:"url"`
|
||||||
DstDirPath string `json:"dst_dir_path"`
|
DstDirPath string `json:"dst_dir_path"`
|
||||||
TempDir string `json:"temp_dir"`
|
TempDir string `json:"temp_dir"`
|
||||||
|
@ -28,6 +28,9 @@ type DownloadTask struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *DownloadTask) Run() error {
|
func (t *DownloadTask) Run() error {
|
||||||
|
t.ClearEndTime()
|
||||||
|
t.SetStartTime(time.Now())
|
||||||
|
defer func() { t.SetEndTime(time.Now()) }()
|
||||||
if t.tool == nil {
|
if t.tool == nil {
|
||||||
tool, err := Tools.Get(t.Toolname)
|
tool, err := Tools.Get(t.Toolname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -131,6 +134,7 @@ func (t *DownloadTask) Update() (bool, error) {
|
||||||
}
|
}
|
||||||
t.callStatusRetried = 0
|
t.callStatusRetried = 0
|
||||||
t.SetProgress(info.Progress)
|
t.SetProgress(info.Progress)
|
||||||
|
t.SetTotalBytes(info.TotalBytes)
|
||||||
t.Status = fmt.Sprintf("[%s]: %s", t.tool.Name(), info.Status)
|
t.Status = fmt.Sprintf("[%s]: %s", t.tool.Name(), info.Status)
|
||||||
if info.NewGID != "" {
|
if info.NewGID != "" {
|
||||||
log.Debugf("followen by: %+v", info.NewGID)
|
log.Debugf("followen by: %+v", info.NewGID)
|
||||||
|
@ -171,16 +175,18 @@ func (t *DownloadTask) Complete() error {
|
||||||
// upload files
|
// upload files
|
||||||
for i := range files {
|
for i := range files {
|
||||||
file := files[i]
|
file := files[i]
|
||||||
TransferTaskManager.Add(&TransferTask{
|
tsk := &TransferTask{
|
||||||
TaskWithCreator: task.TaskWithCreator{
|
TaskExtension: task.TaskExtension{
|
||||||
Creator: t.Creator,
|
Creator: t.GetCreator(),
|
||||||
},
|
},
|
||||||
file: file,
|
file: file,
|
||||||
DstDirPath: t.DstDirPath,
|
DstDirPath: t.DstDirPath,
|
||||||
TempDir: t.TempDir,
|
TempDir: t.TempDir,
|
||||||
DeletePolicy: t.DeletePolicy,
|
DeletePolicy: t.DeletePolicy,
|
||||||
FileDir: file.Path,
|
FileDir: file.Path,
|
||||||
})
|
}
|
||||||
|
tsk.SetTotalBytes(file.Size)
|
||||||
|
TransferTaskManager.Add(tsk)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/alist-org/alist/v3/internal/model"
|
"github.com/alist-org/alist/v3/internal/model"
|
||||||
"github.com/alist-org/alist/v3/internal/op"
|
"github.com/alist-org/alist/v3/internal/op"
|
||||||
|
@ -16,7 +17,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type TransferTask struct {
|
type TransferTask struct {
|
||||||
task.TaskWithCreator
|
task.TaskExtension
|
||||||
FileDir string `json:"file_dir"`
|
FileDir string `json:"file_dir"`
|
||||||
DstDirPath string `json:"dst_dir_path"`
|
DstDirPath string `json:"dst_dir_path"`
|
||||||
TempDir string `json:"temp_dir"`
|
TempDir string `json:"temp_dir"`
|
||||||
|
@ -25,6 +26,9 @@ type TransferTask struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TransferTask) Run() error {
|
func (t *TransferTask) Run() error {
|
||||||
|
t.ClearEndTime()
|
||||||
|
t.SetStartTime(time.Now())
|
||||||
|
defer func() { t.SetEndTime(time.Now()) }()
|
||||||
// check dstDir again
|
// check dstDir again
|
||||||
var err error
|
var err error
|
||||||
if (t.file == File{}) {
|
if (t.file == File{}) {
|
||||||
|
|
|
@ -150,6 +150,7 @@ func (t *Transmission) Status(task *tool.DownloadTask) (*tool.Status, error) {
|
||||||
Err: err,
|
Err: err,
|
||||||
}
|
}
|
||||||
s.Progress = *info.PercentDone * 100
|
s.Progress = *info.PercentDone * 100
|
||||||
|
s.TotalBytes = int64(*info.SizeWhenDone / 8)
|
||||||
|
|
||||||
switch *info.Status {
|
switch *info.Status {
|
||||||
case transmissionrpc.TorrentStatusCheckWait,
|
case transmissionrpc.TorrentStatusCheckWait,
|
||||||
|
|
|
@ -3,24 +3,58 @@ package task
|
||||||
import (
|
import (
|
||||||
"github.com/alist-org/alist/v3/internal/model"
|
"github.com/alist-org/alist/v3/internal/model"
|
||||||
"github.com/xhofe/tache"
|
"github.com/xhofe/tache"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TaskWithCreator struct {
|
type TaskExtension struct {
|
||||||
tache.Base
|
tache.Base
|
||||||
Creator *model.User
|
Creator *model.User
|
||||||
|
startTime *time.Time
|
||||||
|
endTime *time.Time
|
||||||
|
totalBytes int64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TaskWithCreator) SetCreator(creator *model.User) {
|
func (t *TaskExtension) SetCreator(creator *model.User) {
|
||||||
t.Creator = creator
|
t.Creator = creator
|
||||||
t.Persist()
|
t.Persist()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TaskWithCreator) GetCreator() *model.User {
|
func (t *TaskExtension) GetCreator() *model.User {
|
||||||
return t.Creator
|
return t.Creator
|
||||||
}
|
}
|
||||||
|
|
||||||
type TaskInfoWithCreator interface {
|
func (t *TaskExtension) SetStartTime(startTime time.Time) {
|
||||||
tache.TaskWithInfo
|
t.startTime = &startTime
|
||||||
SetCreator(creator *model.User)
|
}
|
||||||
GetCreator() *model.User
|
|
||||||
|
func (t *TaskExtension) GetStartTime() *time.Time {
|
||||||
|
return t.startTime
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TaskExtension) SetEndTime(endTime time.Time) {
|
||||||
|
t.endTime = &endTime
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TaskExtension) GetEndTime() *time.Time {
|
||||||
|
return t.endTime
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TaskExtension) ClearEndTime() {
|
||||||
|
t.endTime = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TaskExtension) SetTotalBytes(totalBytes int64) {
|
||||||
|
t.totalBytes = totalBytes
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TaskExtension) GetTotalBytes() int64 {
|
||||||
|
return t.totalBytes
|
||||||
|
}
|
||||||
|
|
||||||
|
type TaskExtensionInfo interface {
|
||||||
|
tache.TaskWithInfo
|
||||||
|
GetCreator() *model.User
|
||||||
|
GetStartTime() *time.Time
|
||||||
|
GetEndTime() *time.Time
|
||||||
|
GetTotalBytes() int64
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,7 +121,7 @@ func FsCopy(c *gin.Context) {
|
||||||
common.ErrorResp(c, err, 403)
|
common.ErrorResp(c, err, 403)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var addedTasks []task.TaskInfoWithCreator
|
var addedTasks []task.TaskExtensionInfo
|
||||||
for i, name := range req.Names {
|
for i, name := range req.Names {
|
||||||
t, err := fs.Copy(c, stdpath.Join(srcDir, name), dstDir, len(req.Names) > i+1)
|
t, err := fs.Copy(c, stdpath.Join(srcDir, name), dstDir, len(req.Names) > i+1)
|
||||||
if t != nil {
|
if t != nil {
|
||||||
|
|
|
@ -57,7 +57,7 @@ func FsStream(c *gin.Context) {
|
||||||
Mimetype: c.GetHeader("Content-Type"),
|
Mimetype: c.GetHeader("Content-Type"),
|
||||||
WebPutAsTask: asTask,
|
WebPutAsTask: asTask,
|
||||||
}
|
}
|
||||||
var t task.TaskInfoWithCreator
|
var t task.TaskExtensionInfo
|
||||||
if asTask {
|
if asTask {
|
||||||
t, err = fs.PutAsTask(c, dir, s)
|
t, err = fs.PutAsTask(c, dir, s)
|
||||||
} else {
|
} else {
|
||||||
|
@ -122,7 +122,7 @@ func FsForm(c *gin.Context) {
|
||||||
Mimetype: file.Header.Get("Content-Type"),
|
Mimetype: file.Header.Get("Content-Type"),
|
||||||
WebPutAsTask: asTask,
|
WebPutAsTask: asTask,
|
||||||
}
|
}
|
||||||
var t task.TaskInfoWithCreator
|
var t task.TaskExtensionInfo
|
||||||
if asTask {
|
if asTask {
|
||||||
s.Reader = struct {
|
s.Reader = struct {
|
||||||
io.Reader
|
io.Reader
|
||||||
|
|
|
@ -133,7 +133,7 @@ func AddOfflineDownload(c *gin.Context) {
|
||||||
common.ErrorResp(c, err, 403)
|
common.ErrorResp(c, err, 403)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var tasks []task.TaskInfoWithCreator
|
var tasks []task.TaskExtensionInfo
|
||||||
for _, url := range req.Urls {
|
for _, url := range req.Urls {
|
||||||
t, err := tool.AddURL(c, &tool.AddURLArgs{
|
t, err := tool.AddURL(c, &tool.AddURLArgs{
|
||||||
URL: url,
|
URL: url,
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"github.com/alist-org/alist/v3/internal/model"
|
"github.com/alist-org/alist/v3/internal/model"
|
||||||
"github.com/alist-org/alist/v3/internal/task"
|
"github.com/alist-org/alist/v3/internal/task"
|
||||||
"math"
|
"math"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/alist-org/alist/v3/internal/fs"
|
"github.com/alist-org/alist/v3/internal/fs"
|
||||||
"github.com/alist-org/alist/v3/internal/offline_download/tool"
|
"github.com/alist-org/alist/v3/internal/offline_download/tool"
|
||||||
|
@ -21,10 +22,13 @@ type TaskInfo struct {
|
||||||
State tache.State `json:"state"`
|
State tache.State `json:"state"`
|
||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
Progress float64 `json:"progress"`
|
Progress float64 `json:"progress"`
|
||||||
|
StartTime *time.Time `json:"start_time"`
|
||||||
|
EndTime *time.Time `json:"end_time"`
|
||||||
|
TotalBytes int64 `json:"total_bytes"`
|
||||||
Error string `json:"error"`
|
Error string `json:"error"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func getTaskInfo[T task.TaskInfoWithCreator](task T) TaskInfo {
|
func getTaskInfo[T task.TaskExtensionInfo](task T) TaskInfo {
|
||||||
errMsg := ""
|
errMsg := ""
|
||||||
if task.GetErr() != nil {
|
if task.GetErr() != nil {
|
||||||
errMsg = task.GetErr().Error()
|
errMsg = task.GetErr().Error()
|
||||||
|
@ -48,11 +52,14 @@ func getTaskInfo[T task.TaskInfoWithCreator](task T) TaskInfo {
|
||||||
State: task.GetState(),
|
State: task.GetState(),
|
||||||
Status: task.GetStatus(),
|
Status: task.GetStatus(),
|
||||||
Progress: progress,
|
Progress: progress,
|
||||||
|
StartTime: task.GetStartTime(),
|
||||||
|
EndTime: task.GetEndTime(),
|
||||||
|
TotalBytes: task.GetTotalBytes(),
|
||||||
Error: errMsg,
|
Error: errMsg,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getTaskInfos[T task.TaskInfoWithCreator](tasks []T) []TaskInfo {
|
func getTaskInfos[T task.TaskExtensionInfo](tasks []T) []TaskInfo {
|
||||||
return utils.MustSliceConvert(tasks, getTaskInfo[T])
|
return utils.MustSliceConvert(tasks, getTaskInfo[T])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,7 +75,7 @@ func getUserInfo(c *gin.Context) (bool, uint, bool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getTargetedHandler[T task.TaskInfoWithCreator](manager *tache.Manager[T], callback func(c *gin.Context, task T)) gin.HandlerFunc {
|
func getTargetedHandler[T task.TaskExtensionInfo](manager *tache.Manager[T], callback func(c *gin.Context, task T)) gin.HandlerFunc {
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
isAdmin, uid, ok := getUserInfo(c)
|
isAdmin, uid, ok := getUserInfo(c)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -90,7 +97,7 @@ func getTargetedHandler[T task.TaskInfoWithCreator](manager *tache.Manager[T], c
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getBatchHandler[T task.TaskInfoWithCreator](manager *tache.Manager[T], callback func(task T)) gin.HandlerFunc {
|
func getBatchHandler[T task.TaskExtensionInfo](manager *tache.Manager[T], callback func(task T)) gin.HandlerFunc {
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
isAdmin, uid, ok := getUserInfo(c)
|
isAdmin, uid, ok := getUserInfo(c)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -115,7 +122,7 @@ func getBatchHandler[T task.TaskInfoWithCreator](manager *tache.Manager[T], call
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func taskRoute[T task.TaskInfoWithCreator](g *gin.RouterGroup, manager *tache.Manager[T]) {
|
func taskRoute[T task.TaskExtensionInfo](g *gin.RouterGroup, manager *tache.Manager[T]) {
|
||||||
g.GET("/undone", func(c *gin.Context) {
|
g.GET("/undone", func(c *gin.Context) {
|
||||||
isAdmin, uid, ok := getUserInfo(c)
|
isAdmin, uid, ok := getUserInfo(c)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
Loading…
Reference in New Issue