mirror of
https://github.com/OpenListTeam/OpenList.git
synced 2025-09-19 04:06:18 +08:00
feat(thunderx,pikpak): add offline download support for ThunderX; add ctx to specific PikPak functions (#879)
* feat(thunderx,pikpak): add offline download support for ThunderX; add ctx to specific PikPak functions * Update internal/offline_download/tool/download.go Co-authored-by: MadDogOwner <xiaoran@xrgzs.top> Signed-off-by: 花月喵梦 <152958106+nekohy@users.noreply.github.com> --------- Signed-off-by: 花月喵梦 <152958106+nekohy@users.noreply.github.com> Co-authored-by: MadDogOwner <xiaoran@xrgzs.top>
This commit is contained in:
@ -140,7 +140,8 @@ func (d *PikPak) Link(ctx context.Context, file model.Obj, args model.LinkArgs)
|
||||
}
|
||||
_, err := d.request(fmt.Sprintf("https://api-drive.mypikpak.net/drive/v1/files/%s", file.GetID()),
|
||||
http.MethodGet, func(req *resty.Request) {
|
||||
req.SetQueryParams(queryParams)
|
||||
req.SetContext(ctx).
|
||||
SetQueryParams(queryParams)
|
||||
}, &resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -159,7 +160,7 @@ func (d *PikPak) Link(ctx context.Context, file model.Obj, args model.LinkArgs)
|
||||
|
||||
func (d *PikPak) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error {
|
||||
_, err := d.request("https://api-drive.mypikpak.net/drive/v1/files", http.MethodPost, func(req *resty.Request) {
|
||||
req.SetBody(base.Json{
|
||||
req.SetContext(ctx).SetBody(base.Json{
|
||||
"kind": "drive#folder",
|
||||
"parent_id": parentDir.GetID(),
|
||||
"name": dirName,
|
||||
@ -170,7 +171,7 @@ func (d *PikPak) MakeDir(ctx context.Context, parentDir model.Obj, dirName strin
|
||||
|
||||
func (d *PikPak) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||
_, err := d.request("https://api-drive.mypikpak.net/drive/v1/files:batchMove", http.MethodPost, func(req *resty.Request) {
|
||||
req.SetBody(base.Json{
|
||||
req.SetContext(ctx).SetBody(base.Json{
|
||||
"ids": []string{srcObj.GetID()},
|
||||
"to": base.Json{
|
||||
"parent_id": dstDir.GetID(),
|
||||
@ -182,7 +183,7 @@ func (d *PikPak) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||
|
||||
func (d *PikPak) Rename(ctx context.Context, srcObj model.Obj, newName string) error {
|
||||
_, err := d.request("https://api-drive.mypikpak.net/drive/v1/files/"+srcObj.GetID(), http.MethodPatch, func(req *resty.Request) {
|
||||
req.SetBody(base.Json{
|
||||
req.SetContext(ctx).SetBody(base.Json{
|
||||
"name": newName,
|
||||
})
|
||||
}, nil)
|
||||
@ -191,7 +192,7 @@ func (d *PikPak) Rename(ctx context.Context, srcObj model.Obj, newName string) e
|
||||
|
||||
func (d *PikPak) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||
_, err := d.request("https://api-drive.mypikpak.net/drive/v1/files:batchCopy", http.MethodPost, func(req *resty.Request) {
|
||||
req.SetBody(base.Json{
|
||||
req.SetContext(ctx).SetBody(base.Json{
|
||||
"ids": []string{srcObj.GetID()},
|
||||
"to": base.Json{
|
||||
"parent_id": dstDir.GetID(),
|
||||
@ -203,7 +204,7 @@ func (d *PikPak) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||
|
||||
func (d *PikPak) Remove(ctx context.Context, obj model.Obj) error {
|
||||
_, err := d.request("https://api-drive.mypikpak.net/drive/v1/files:batchTrash", http.MethodPost, func(req *resty.Request) {
|
||||
req.SetBody(base.Json{
|
||||
req.SetContext(ctx).SetBody(base.Json{
|
||||
"ids": []string{obj.GetID()},
|
||||
})
|
||||
}, nil)
|
||||
@ -277,7 +278,8 @@ func (d *PikPak) OfflineDownload(ctx context.Context, fileUrl string, parentDir
|
||||
|
||||
var resp OfflineDownloadResp
|
||||
_, err := d.request("https://api-drive.mypikpak.net/drive/v1/files", http.MethodPost, func(req *resty.Request) {
|
||||
req.SetBody(requestBody)
|
||||
req.SetContext(ctx).
|
||||
SetBody(requestBody)
|
||||
}, &resp)
|
||||
|
||||
if err != nil {
|
||||
|
@ -2,8 +2,11 @@ package thunderx
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/v4/drivers/base"
|
||||
@ -479,7 +482,8 @@ func (xc *XunLeiXCommon) Request(url string, method string, callback base.ReqCal
|
||||
}
|
||||
}, resp)
|
||||
|
||||
errResp, ok := err.(*ErrResp)
|
||||
var errResp *ErrResp
|
||||
ok := errors.As(err, &errResp)
|
||||
if !ok {
|
||||
return nil, err
|
||||
}
|
||||
@ -558,3 +562,84 @@ func (xc *XunLeiXCommon) IsLogin() bool {
|
||||
_, err := xc.Request(XLUSER_API_URL+"/user/me", http.MethodGet, nil, nil)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// 离线下载文件,都和Pikpak接口一致
|
||||
func (xc *XunLeiXCommon) OfflineDownload(ctx context.Context, fileUrl string, parentDir model.Obj, fileName string) (*OfflineTask, error) {
|
||||
requestBody := base.Json{
|
||||
"kind": "drive#file",
|
||||
"name": fileName,
|
||||
"upload_type": "UPLOAD_TYPE_URL",
|
||||
"url": base.Json{
|
||||
"url": fileUrl,
|
||||
},
|
||||
"params": base.Json{},
|
||||
"parent_id": parentDir.GetID(),
|
||||
}
|
||||
var resp OfflineDownloadResp // 一样的
|
||||
_, err := xc.Request(FILE_API_URL, http.MethodPost, func(req *resty.Request) {
|
||||
req.SetContext(ctx).
|
||||
SetBody(requestBody)
|
||||
}, &resp)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &resp.Task, err
|
||||
}
|
||||
|
||||
// 获取离线下载任务列表
|
||||
func (xc *XunLeiXCommon) OfflineList(ctx context.Context, nextPageToken string, phase []string) ([]OfflineTask, error) {
|
||||
res := make([]OfflineTask, 0)
|
||||
if len(phase) == 0 {
|
||||
phase = []string{"PHASE_TYPE_RUNNING", "PHASE_TYPE_ERROR", "PHASE_TYPE_COMPLETE", "PHASE_TYPE_PENDING"}
|
||||
}
|
||||
params := map[string]string{
|
||||
"type": "offline",
|
||||
"thumbnail_size": "SIZE_SMALL",
|
||||
"limit": "10000",
|
||||
"page_token": nextPageToken,
|
||||
"with": "reference_resource",
|
||||
}
|
||||
|
||||
// 处理 phase 参数
|
||||
if len(phase) > 0 {
|
||||
filters := base.Json{
|
||||
"phase": map[string]string{
|
||||
"in": strings.Join(phase, ","),
|
||||
},
|
||||
}
|
||||
filtersJSON, err := json.Marshal(filters)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to marshal filters: %w", err)
|
||||
}
|
||||
params["filters"] = string(filtersJSON)
|
||||
}
|
||||
|
||||
var resp OfflineListResp
|
||||
_, err := xc.Request(TASKS_API_URL, http.MethodGet, func(req *resty.Request) {
|
||||
req.SetContext(ctx).
|
||||
SetQueryParams(params)
|
||||
}, &resp)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get offline list: %w", err)
|
||||
}
|
||||
res = append(res, resp.Tasks...)
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (xc *XunLeiXCommon) DeleteOfflineTasks(ctx context.Context, taskIDs []string, deleteFiles bool) error {
|
||||
params := map[string]string{
|
||||
"task_ids": strings.Join(taskIDs, ","),
|
||||
"delete_files": strconv.FormatBool(deleteFiles),
|
||||
}
|
||||
_, err := xc.Request(TASKS_API_URL, http.MethodDelete, func(req *resty.Request) {
|
||||
req.SetContext(ctx).
|
||||
SetQueryParams(params)
|
||||
}, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete tasks %v: %w", taskIDs, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -204,3 +204,102 @@ type UploadTaskResponse struct {
|
||||
|
||||
File Files `json:"file"`
|
||||
}
|
||||
|
||||
// 添加离线下载响应
|
||||
type OfflineDownloadResp struct {
|
||||
File *string `json:"file"`
|
||||
Task OfflineTask `json:"task"`
|
||||
UploadType string `json:"upload_type"`
|
||||
URL struct {
|
||||
Kind string `json:"kind"`
|
||||
} `json:"url"`
|
||||
}
|
||||
|
||||
// 离线下载列表
|
||||
type OfflineListResp struct {
|
||||
ExpiresIn int64 `json:"expires_in"`
|
||||
NextPageToken string `json:"next_page_token"`
|
||||
Tasks []OfflineTask `json:"tasks"`
|
||||
}
|
||||
|
||||
// offlineTask
|
||||
type OfflineTask struct {
|
||||
Callback string `json:"callback"`
|
||||
CreatedTime string `json:"created_time"`
|
||||
FileID string `json:"file_id"`
|
||||
FileName string `json:"file_name"`
|
||||
FileSize string `json:"file_size"`
|
||||
IconLink string `json:"icon_link"`
|
||||
ID string `json:"id"`
|
||||
Kind string `json:"kind"`
|
||||
Message string `json:"message"`
|
||||
Name string `json:"name"`
|
||||
Params Params `json:"params"`
|
||||
Phase string `json:"phase"` // PHASE_TYPE_RUNNING, PHASE_TYPE_ERROR, PHASE_TYPE_COMPLETE, PHASE_TYPE_PENDING
|
||||
Progress int64 `json:"progress"`
|
||||
ReferenceResource ReferenceResource `json:"reference_resource"`
|
||||
Space string `json:"space"`
|
||||
StatusSize int64 `json:"status_size"`
|
||||
Statuses []string `json:"statuses"`
|
||||
ThirdTaskID string `json:"third_task_id"`
|
||||
Type string `json:"type"`
|
||||
UpdatedTime string `json:"updated_time"`
|
||||
UserID string `json:"user_id"`
|
||||
}
|
||||
|
||||
type Params struct {
|
||||
Age string `json:"age"`
|
||||
MIMEType *string `json:"mime_type,omitempty"`
|
||||
PredictType string `json:"predict_type"`
|
||||
URL string `json:"url"`
|
||||
}
|
||||
|
||||
type ReferenceResource struct {
|
||||
Type string `json:"@type"`
|
||||
Audit interface{} `json:"audit"`
|
||||
Hash string `json:"hash"`
|
||||
IconLink string `json:"icon_link"`
|
||||
ID string `json:"id"`
|
||||
Kind string `json:"kind"`
|
||||
Medias []Media `json:"medias"`
|
||||
MIMEType string `json:"mime_type"`
|
||||
Name string `json:"name"`
|
||||
Params map[string]interface{} `json:"params"`
|
||||
ParentID string `json:"parent_id"`
|
||||
Phase string `json:"phase"`
|
||||
Size string `json:"size"`
|
||||
Space string `json:"space"`
|
||||
Starred bool `json:"starred"`
|
||||
Tags []string `json:"tags"`
|
||||
ThumbnailLink string `json:"thumbnail_link"`
|
||||
}
|
||||
|
||||
type Media struct {
|
||||
MediaId string `json:"media_id"`
|
||||
MediaName string `json:"media_name"`
|
||||
Video struct {
|
||||
Height int `json:"height"`
|
||||
Width int `json:"width"`
|
||||
Duration int `json:"duration"`
|
||||
BitRate int `json:"bit_rate"`
|
||||
FrameRate int `json:"frame_rate"`
|
||||
VideoCodec string `json:"video_codec"`
|
||||
AudioCodec string `json:"audio_codec"`
|
||||
VideoType string `json:"video_type"`
|
||||
} `json:"video"`
|
||||
Link struct {
|
||||
Url string `json:"url"`
|
||||
Token string `json:"token"`
|
||||
Expire time.Time `json:"expire"`
|
||||
} `json:"link"`
|
||||
NeedMoreQuota bool `json:"need_more_quota"`
|
||||
VipTypes []interface{} `json:"vip_types"`
|
||||
RedirectLink string `json:"redirect_link"`
|
||||
IconLink string `json:"icon_link"`
|
||||
IsDefault bool `json:"is_default"`
|
||||
Priority int `json:"priority"`
|
||||
IsOrigin bool `json:"is_origin"`
|
||||
ResolutionName string `json:"resolution_name"`
|
||||
IsVisible bool `json:"is_visible"`
|
||||
Category string `json:"category"`
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ import (
|
||||
const (
|
||||
API_URL = "https://api-pan.xunleix.com/drive/v1"
|
||||
FILE_API_URL = API_URL + "/files"
|
||||
TASKS_API_URL = API_URL + "/tasks"
|
||||
XLUSER_API_URL = "https://xluser-ssl.xunleix.com/v1"
|
||||
)
|
||||
|
||||
|
Reference in New Issue
Block a user