Skip to content

Commit 101c7ed

Browse files
nekohyxrgzs
authored andcommitted
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 <[email protected]> Signed-off-by: 花月喵梦 <[email protected]> --------- Signed-off-by: 花月喵梦 <[email protected]> Co-authored-by: MadDogOwner <[email protected]>
1 parent bb17edd commit 101c7ed

File tree

12 files changed

+441
-10
lines changed

12 files changed

+441
-10
lines changed

drivers/pikpak/driver.go

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,8 @@ func (d *PikPak) Link(ctx context.Context, file model.Obj, args model.LinkArgs)
140140
}
141141
_, err := d.request(fmt.Sprintf("https://api-drive.mypikpak.net/drive/v1/files/%s", file.GetID()),
142142
http.MethodGet, func(req *resty.Request) {
143-
req.SetQueryParams(queryParams)
143+
req.SetContext(ctx).
144+
SetQueryParams(queryParams)
144145
}, &resp)
145146
if err != nil {
146147
return nil, err
@@ -159,7 +160,7 @@ func (d *PikPak) Link(ctx context.Context, file model.Obj, args model.LinkArgs)
159160

160161
func (d *PikPak) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error {
161162
_, err := d.request("https://api-drive.mypikpak.net/drive/v1/files", http.MethodPost, func(req *resty.Request) {
162-
req.SetBody(base.Json{
163+
req.SetContext(ctx).SetBody(base.Json{
163164
"kind": "drive#folder",
164165
"parent_id": parentDir.GetID(),
165166
"name": dirName,
@@ -170,7 +171,7 @@ func (d *PikPak) MakeDir(ctx context.Context, parentDir model.Obj, dirName strin
170171

171172
func (d *PikPak) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
172173
_, err := d.request("https://api-drive.mypikpak.net/drive/v1/files:batchMove", http.MethodPost, func(req *resty.Request) {
173-
req.SetBody(base.Json{
174+
req.SetContext(ctx).SetBody(base.Json{
174175
"ids": []string{srcObj.GetID()},
175176
"to": base.Json{
176177
"parent_id": dstDir.GetID(),
@@ -182,7 +183,7 @@ func (d *PikPak) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
182183

183184
func (d *PikPak) Rename(ctx context.Context, srcObj model.Obj, newName string) error {
184185
_, err := d.request("https://api-drive.mypikpak.net/drive/v1/files/"+srcObj.GetID(), http.MethodPatch, func(req *resty.Request) {
185-
req.SetBody(base.Json{
186+
req.SetContext(ctx).SetBody(base.Json{
186187
"name": newName,
187188
})
188189
}, nil)
@@ -191,7 +192,7 @@ func (d *PikPak) Rename(ctx context.Context, srcObj model.Obj, newName string) e
191192

192193
func (d *PikPak) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
193194
_, err := d.request("https://api-drive.mypikpak.net/drive/v1/files:batchCopy", http.MethodPost, func(req *resty.Request) {
194-
req.SetBody(base.Json{
195+
req.SetContext(ctx).SetBody(base.Json{
195196
"ids": []string{srcObj.GetID()},
196197
"to": base.Json{
197198
"parent_id": dstDir.GetID(),
@@ -203,7 +204,7 @@ func (d *PikPak) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
203204

204205
func (d *PikPak) Remove(ctx context.Context, obj model.Obj) error {
205206
_, err := d.request("https://api-drive.mypikpak.net/drive/v1/files:batchTrash", http.MethodPost, func(req *resty.Request) {
206-
req.SetBody(base.Json{
207+
req.SetContext(ctx).SetBody(base.Json{
207208
"ids": []string{obj.GetID()},
208209
})
209210
}, nil)
@@ -277,7 +278,8 @@ func (d *PikPak) OfflineDownload(ctx context.Context, fileUrl string, parentDir
277278

278279
var resp OfflineDownloadResp
279280
_, err := d.request("https://api-drive.mypikpak.net/drive/v1/files", http.MethodPost, func(req *resty.Request) {
280-
req.SetBody(requestBody)
281+
req.SetContext(ctx).
282+
SetBody(requestBody)
281283
}, &resp)
282284

283285
if err != nil {

drivers/thunderx/driver.go

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@ package thunderx
22

33
import (
44
"context"
5+
"encoding/json"
6+
"errors"
57
"fmt"
68
"net/http"
9+
"strconv"
710
"strings"
811

912
"github.com/OpenListTeam/OpenList/v4/drivers/base"
@@ -479,7 +482,8 @@ func (xc *XunLeiXCommon) Request(url string, method string, callback base.ReqCal
479482
}
480483
}, resp)
481484

482-
errResp, ok := err.(*ErrResp)
485+
var errResp *ErrResp
486+
ok := errors.As(err, &errResp)
483487
if !ok {
484488
return nil, err
485489
}
@@ -558,3 +562,84 @@ func (xc *XunLeiXCommon) IsLogin() bool {
558562
_, err := xc.Request(XLUSER_API_URL+"/user/me", http.MethodGet, nil, nil)
559563
return err == nil
560564
}
565+
566+
// 离线下载文件,都和Pikpak接口一致
567+
func (xc *XunLeiXCommon) OfflineDownload(ctx context.Context, fileUrl string, parentDir model.Obj, fileName string) (*OfflineTask, error) {
568+
requestBody := base.Json{
569+
"kind": "drive#file",
570+
"name": fileName,
571+
"upload_type": "UPLOAD_TYPE_URL",
572+
"url": base.Json{
573+
"url": fileUrl,
574+
},
575+
"params": base.Json{},
576+
"parent_id": parentDir.GetID(),
577+
}
578+
var resp OfflineDownloadResp // 一样的
579+
_, err := xc.Request(FILE_API_URL, http.MethodPost, func(req *resty.Request) {
580+
req.SetContext(ctx).
581+
SetBody(requestBody)
582+
}, &resp)
583+
584+
if err != nil {
585+
return nil, err
586+
}
587+
588+
return &resp.Task, err
589+
}
590+
591+
// 获取离线下载任务列表
592+
func (xc *XunLeiXCommon) OfflineList(ctx context.Context, nextPageToken string, phase []string) ([]OfflineTask, error) {
593+
res := make([]OfflineTask, 0)
594+
if len(phase) == 0 {
595+
phase = []string{"PHASE_TYPE_RUNNING", "PHASE_TYPE_ERROR", "PHASE_TYPE_COMPLETE", "PHASE_TYPE_PENDING"}
596+
}
597+
params := map[string]string{
598+
"type": "offline",
599+
"thumbnail_size": "SIZE_SMALL",
600+
"limit": "10000",
601+
"page_token": nextPageToken,
602+
"with": "reference_resource",
603+
}
604+
605+
// 处理 phase 参数
606+
if len(phase) > 0 {
607+
filters := base.Json{
608+
"phase": map[string]string{
609+
"in": strings.Join(phase, ","),
610+
},
611+
}
612+
filtersJSON, err := json.Marshal(filters)
613+
if err != nil {
614+
return nil, fmt.Errorf("failed to marshal filters: %w", err)
615+
}
616+
params["filters"] = string(filtersJSON)
617+
}
618+
619+
var resp OfflineListResp
620+
_, err := xc.Request(TASKS_API_URL, http.MethodGet, func(req *resty.Request) {
621+
req.SetContext(ctx).
622+
SetQueryParams(params)
623+
}, &resp)
624+
625+
if err != nil {
626+
return nil, fmt.Errorf("failed to get offline list: %w", err)
627+
}
628+
res = append(res, resp.Tasks...)
629+
return res, nil
630+
}
631+
632+
func (xc *XunLeiXCommon) DeleteOfflineTasks(ctx context.Context, taskIDs []string, deleteFiles bool) error {
633+
params := map[string]string{
634+
"task_ids": strings.Join(taskIDs, ","),
635+
"delete_files": strconv.FormatBool(deleteFiles),
636+
}
637+
_, err := xc.Request(TASKS_API_URL, http.MethodDelete, func(req *resty.Request) {
638+
req.SetContext(ctx).
639+
SetQueryParams(params)
640+
}, nil)
641+
if err != nil {
642+
return fmt.Errorf("failed to delete tasks %v: %w", taskIDs, err)
643+
}
644+
return nil
645+
}

drivers/thunderx/types.go

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,3 +204,102 @@ type UploadTaskResponse struct {
204204

205205
File Files `json:"file"`
206206
}
207+
208+
// 添加离线下载响应
209+
type OfflineDownloadResp struct {
210+
File *string `json:"file"`
211+
Task OfflineTask `json:"task"`
212+
UploadType string `json:"upload_type"`
213+
URL struct {
214+
Kind string `json:"kind"`
215+
} `json:"url"`
216+
}
217+
218+
// 离线下载列表
219+
type OfflineListResp struct {
220+
ExpiresIn int64 `json:"expires_in"`
221+
NextPageToken string `json:"next_page_token"`
222+
Tasks []OfflineTask `json:"tasks"`
223+
}
224+
225+
// offlineTask
226+
type OfflineTask struct {
227+
Callback string `json:"callback"`
228+
CreatedTime string `json:"created_time"`
229+
FileID string `json:"file_id"`
230+
FileName string `json:"file_name"`
231+
FileSize string `json:"file_size"`
232+
IconLink string `json:"icon_link"`
233+
ID string `json:"id"`
234+
Kind string `json:"kind"`
235+
Message string `json:"message"`
236+
Name string `json:"name"`
237+
Params Params `json:"params"`
238+
Phase string `json:"phase"` // PHASE_TYPE_RUNNING, PHASE_TYPE_ERROR, PHASE_TYPE_COMPLETE, PHASE_TYPE_PENDING
239+
Progress int64 `json:"progress"`
240+
ReferenceResource ReferenceResource `json:"reference_resource"`
241+
Space string `json:"space"`
242+
StatusSize int64 `json:"status_size"`
243+
Statuses []string `json:"statuses"`
244+
ThirdTaskID string `json:"third_task_id"`
245+
Type string `json:"type"`
246+
UpdatedTime string `json:"updated_time"`
247+
UserID string `json:"user_id"`
248+
}
249+
250+
type Params struct {
251+
Age string `json:"age"`
252+
MIMEType *string `json:"mime_type,omitempty"`
253+
PredictType string `json:"predict_type"`
254+
URL string `json:"url"`
255+
}
256+
257+
type ReferenceResource struct {
258+
Type string `json:"@type"`
259+
Audit interface{} `json:"audit"`
260+
Hash string `json:"hash"`
261+
IconLink string `json:"icon_link"`
262+
ID string `json:"id"`
263+
Kind string `json:"kind"`
264+
Medias []Media `json:"medias"`
265+
MIMEType string `json:"mime_type"`
266+
Name string `json:"name"`
267+
Params map[string]interface{} `json:"params"`
268+
ParentID string `json:"parent_id"`
269+
Phase string `json:"phase"`
270+
Size string `json:"size"`
271+
Space string `json:"space"`
272+
Starred bool `json:"starred"`
273+
Tags []string `json:"tags"`
274+
ThumbnailLink string `json:"thumbnail_link"`
275+
}
276+
277+
type Media struct {
278+
MediaId string `json:"media_id"`
279+
MediaName string `json:"media_name"`
280+
Video struct {
281+
Height int `json:"height"`
282+
Width int `json:"width"`
283+
Duration int `json:"duration"`
284+
BitRate int `json:"bit_rate"`
285+
FrameRate int `json:"frame_rate"`
286+
VideoCodec string `json:"video_codec"`
287+
AudioCodec string `json:"audio_codec"`
288+
VideoType string `json:"video_type"`
289+
} `json:"video"`
290+
Link struct {
291+
Url string `json:"url"`
292+
Token string `json:"token"`
293+
Expire time.Time `json:"expire"`
294+
} `json:"link"`
295+
NeedMoreQuota bool `json:"need_more_quota"`
296+
VipTypes []interface{} `json:"vip_types"`
297+
RedirectLink string `json:"redirect_link"`
298+
IconLink string `json:"icon_link"`
299+
IsDefault bool `json:"is_default"`
300+
Priority int `json:"priority"`
301+
IsOrigin bool `json:"is_origin"`
302+
ResolutionName string `json:"resolution_name"`
303+
IsVisible bool `json:"is_visible"`
304+
Category string `json:"category"`
305+
}

drivers/thunderx/util.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
const (
2020
API_URL = "https://api-pan.xunleix.com/drive/v1"
2121
FILE_API_URL = API_URL + "/files"
22+
TASKS_API_URL = API_URL + "/tasks"
2223
XLUSER_API_URL = "https://xluser-ssl.xunleix.com/v1"
2324
)
2425

internal/conf/const.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ const (
7272
// thunder
7373
ThunderTempDir = "thunder_temp_dir"
7474

75+
// thunderx
76+
ThunderXTempDir = "thunderx_temp_dir"
77+
7578
// thunder_browser
7679
ThunderBrowserTempDir = "thunder_browser_temp_dir"
7780

internal/offline_download/all.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@ import (
99
_ "github.com/OpenListTeam/OpenList/v4/internal/offline_download/qbit"
1010
_ "github.com/OpenListTeam/OpenList/v4/internal/offline_download/thunder"
1111
_ "github.com/OpenListTeam/OpenList/v4/internal/offline_download/thunder_browser"
12+
_ "github.com/OpenListTeam/OpenList/v4/internal/offline_download/thunderx"
1213
_ "github.com/OpenListTeam/OpenList/v4/internal/offline_download/transmission"
1314
)

0 commit comments

Comments
 (0)