feat(thunder): allow setting space (#1219)

allows access to files on remote devices via Thunder's tunneling service.
This commit is contained in:
ex-hentai
2025-11-03 10:53:38 +08:00
committed by GitHub
parent 66d9809057
commit 0857478516
3 changed files with 37 additions and 8 deletions

View File

@@ -4,6 +4,7 @@ import (
"context" "context"
"fmt" "fmt"
"net/http" "net/http"
"net/url"
"strconv" "strconv"
"strings" "strings"
@@ -68,6 +69,7 @@ func (x *Thunder) Init(ctx context.Context) (err error) {
PackageName: "com.xunlei.downloadprovider", PackageName: "com.xunlei.downloadprovider",
UserAgent: "ANDROID-com.xunlei.downloadprovider/8.31.0.9726 netWorkType/5G appid/40 deviceName/Xiaomi_M2004j7ac deviceModel/M2004J7AC OSVersion/12 protocolVersion/301 platformVersion/10 sdkVersion/512000 Oauth2Client/0.9 (Linux 4_14_186-perf-gddfs8vbb238b) (JAVA 0)", UserAgent: "ANDROID-com.xunlei.downloadprovider/8.31.0.9726 netWorkType/5G appid/40 deviceName/Xiaomi_M2004j7ac deviceModel/M2004J7AC OSVersion/12 protocolVersion/301 platformVersion/10 sdkVersion/512000 Oauth2Client/0.9 (Linux 4_14_186-perf-gddfs8vbb238b) (JAVA 0)",
DownloadUserAgent: "Dalvik/2.1.0 (Linux; U; Android 12; M2004J7AC Build/SP1A.210812.016)", DownloadUserAgent: "Dalvik/2.1.0 (Linux; U; Android 12; M2004J7AC Build/SP1A.210812.016)",
Space: x.Space,
refreshCTokenCk: func(token string) { refreshCTokenCk: func(token string) {
x.CaptchaToken = token x.CaptchaToken = token
op.MustSaveDriverStorage(x) op.MustSaveDriverStorage(x)
@@ -167,6 +169,7 @@ func (x *ThunderExpert) Init(ctx context.Context) (err error) {
UserAgent: x.UserAgent, UserAgent: x.UserAgent,
DownloadUserAgent: x.DownloadUserAgent, DownloadUserAgent: x.DownloadUserAgent,
UseVideoUrl: x.UseVideoUrl, UseVideoUrl: x.UseVideoUrl,
Space: x.Space,
refreshCTokenCk: func(token string) { refreshCTokenCk: func(token string) {
x.CaptchaToken = token x.CaptchaToken = token
@@ -281,7 +284,7 @@ func (xc *XunLeiCommon) Link(ctx context.Context, file model.Obj, args model.Lin
_, err := xc.Request(FILE_API_URL+"/{fileID}", http.MethodGet, func(r *resty.Request) { _, err := xc.Request(FILE_API_URL+"/{fileID}", http.MethodGet, func(r *resty.Request) {
r.SetContext(ctx) r.SetContext(ctx)
r.SetPathParam("fileID", file.GetID()) r.SetPathParam("fileID", file.GetID())
//r.SetQueryParam("space", "") r.SetQueryParam("space", xc.Space)
}, &lFile) }, &lFile)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -322,6 +325,7 @@ func (xc *XunLeiCommon) MakeDir(ctx context.Context, parentDir model.Obj, dirNam
"kind": FOLDER, "kind": FOLDER,
"name": dirName, "name": dirName,
"parent_id": parentDir.GetID(), "parent_id": parentDir.GetID(),
"space": xc.Space,
}) })
}, nil) }, nil)
return err return err
@@ -331,8 +335,9 @@ func (xc *XunLeiCommon) Move(ctx context.Context, srcObj, dstDir model.Obj) erro
_, err := xc.Request(FILE_API_URL+":batchMove", http.MethodPost, func(r *resty.Request) { _, err := xc.Request(FILE_API_URL+":batchMove", http.MethodPost, func(r *resty.Request) {
r.SetContext(ctx) r.SetContext(ctx)
r.SetBody(&base.Json{ r.SetBody(&base.Json{
"to": base.Json{"parent_id": dstDir.GetID()}, "to": base.Json{"parent_id": dstDir.GetID()},
"ids": []string{srcObj.GetID()}, "ids": []string{srcObj.GetID()},
"space": xc.Space,
}) })
}, nil) }, nil)
return err return err
@@ -342,7 +347,10 @@ func (xc *XunLeiCommon) Rename(ctx context.Context, srcObj model.Obj, newName st
_, err := xc.Request(FILE_API_URL+"/{fileID}", http.MethodPatch, func(r *resty.Request) { _, err := xc.Request(FILE_API_URL+"/{fileID}", http.MethodPatch, func(r *resty.Request) {
r.SetContext(ctx) r.SetContext(ctx)
r.SetPathParam("fileID", srcObj.GetID()) r.SetPathParam("fileID", srcObj.GetID())
r.SetBody(&base.Json{"name": newName}) r.SetBody(&base.Json{
"name": newName,
"space": xc.Space,
})
}, nil) }, nil)
return err return err
} }
@@ -351,8 +359,9 @@ func (xc *XunLeiCommon) Copy(ctx context.Context, srcObj, dstDir model.Obj) erro
_, err := xc.Request(FILE_API_URL+":batchCopy", http.MethodPost, func(r *resty.Request) { _, err := xc.Request(FILE_API_URL+":batchCopy", http.MethodPost, func(r *resty.Request) {
r.SetContext(ctx) r.SetContext(ctx)
r.SetBody(&base.Json{ r.SetBody(&base.Json{
"to": base.Json{"parent_id": dstDir.GetID()}, "to": base.Json{"parent_id": dstDir.GetID()},
"ids": []string{srcObj.GetID()}, "ids": []string{srcObj.GetID()},
"space": xc.Space,
}) })
}, nil) }, nil)
return err return err
@@ -362,6 +371,7 @@ func (xc *XunLeiCommon) Remove(ctx context.Context, obj model.Obj) error {
_, err := xc.Request(FILE_API_URL+"/{fileID}/trash", http.MethodPatch, func(r *resty.Request) { _, err := xc.Request(FILE_API_URL+"/{fileID}/trash", http.MethodPatch, func(r *resty.Request) {
r.SetContext(ctx) r.SetContext(ctx)
r.SetPathParam("fileID", obj.GetID()) r.SetPathParam("fileID", obj.GetID())
r.SetQueryParam("space", xc.Space)
r.SetBody("{}") r.SetBody("{}")
}, nil) }, nil)
return err return err
@@ -387,6 +397,7 @@ func (xc *XunLeiCommon) Put(ctx context.Context, dstDir model.Obj, file model.Fi
"size": file.GetSize(), "size": file.GetSize(),
"hash": gcid, "hash": gcid,
"upload_type": UPLOAD_TYPE_RESUMABLE, "upload_type": UPLOAD_TYPE_RESUMABLE,
"space": xc.Space,
}) })
}, &resp) }, &resp)
if err != nil { if err != nil {
@@ -430,7 +441,7 @@ func (xc *XunLeiCommon) getFiles(ctx context.Context, folderId string) ([]model.
_, err := xc.Request(FILE_API_URL, http.MethodGet, func(r *resty.Request) { _, err := xc.Request(FILE_API_URL, http.MethodGet, func(r *resty.Request) {
r.SetContext(ctx) r.SetContext(ctx)
r.SetQueryParams(map[string]string{ r.SetQueryParams(map[string]string{
"space": "", "space": xc.Space,
"__type": "drive", "__type": "drive",
"refresh": "true", "refresh": "true",
"__sync": "true", "__sync": "true",
@@ -440,6 +451,17 @@ func (xc *XunLeiCommon) getFiles(ctx context.Context, folderId string) ([]model.
"limit": "100", "limit": "100",
"filters": `{"phase":{"eq":"PHASE_TYPE_COMPLETE"},"trashed":{"eq":false}}`, "filters": `{"phase":{"eq":"PHASE_TYPE_COMPLETE"},"trashed":{"eq":false}}`,
}) })
// 获取硬盘挂载目录等
if xc.Space != "" {
r.SetQueryParamsFromValues(url.Values{
"with": []string{
"withCategoryDiskMountPath",
"withCategoryDriveCachePath",
"withCategoryHistoryDownloadPath",
"withReadOnlyFS",
},
})
}
}, &fileList) }, &fileList)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -576,6 +598,7 @@ func (xc *XunLeiCommon) OfflineDownload(ctx context.Context, fileUrl string, par
"name": fileName, "name": fileName,
"parent_id": parentDir.GetID(), "parent_id": parentDir.GetID(),
"upload_type": UPLOAD_TYPE_URL, "upload_type": UPLOAD_TYPE_URL,
"space": xc.Space,
"url": base.Json{ "url": base.Json{
"url": fileUrl, "url": fileUrl,
}, },
@@ -602,6 +625,7 @@ func (xc *XunLeiCommon) OfflineList(ctx context.Context, nextPageToken string) (
"type": "offline", "type": "offline",
"limit": "10000", "limit": "10000",
"page_token": nextPageToken, "page_token": nextPageToken,
"space": xc.Space,
}) })
}, &resp) }, &resp)
@@ -618,6 +642,7 @@ func (xc *XunLeiCommon) DeleteOfflineTasks(ctx context.Context, taskIDs []string
SetQueryParams(map[string]string{ SetQueryParams(map[string]string{
"task_ids": strings.Join(taskIDs, ","), "task_ids": strings.Join(taskIDs, ","),
"delete_files": strconv.FormatBool(deleteFiles), "delete_files": strconv.FormatBool(deleteFiles),
"space": xc.Space,
}) })
}, nil) }, nil)
if err != nil { if err != nil {

View File

@@ -46,6 +46,8 @@ type ExpertAddition struct {
//优先使用视频链接代替下载链接 //优先使用视频链接代替下载链接
UseVideoUrl bool `json:"use_video_url"` UseVideoUrl bool `json:"use_video_url"`
Space string `json:"space" default:"" help:"device id for remote device"`
} }
// 登录特征,用于判断是否重新登录 // 登录特征,用于判断是否重新登录
@@ -80,6 +82,8 @@ type Addition struct {
CreditKey string `json:"credit_key" help:"credit key,used for login"` CreditKey string `json:"credit_key" help:"credit key,used for login"`
// 登录设备ID // 登录设备ID
DeviceID string `json:"device_id" default:""` DeviceID string `json:"device_id" default:""`
Space string `json:"space" default:"" help:"device id for remote device"`
} }
// 登录特征,用于判断是否重新登录 // 登录特征,用于判断是否重新登录
@@ -90,7 +94,6 @@ func (i *Addition) GetIdentity() string {
var config = driver.Config{ var config = driver.Config{
Name: "Thunder", Name: "Thunder",
LocalSort: true, LocalSort: true,
OnlyProxy: true,
} }
var configExpert = driver.Config{ var configExpert = driver.Config{

View File

@@ -68,6 +68,7 @@ type Common struct {
UserAgent string UserAgent string
DownloadUserAgent string DownloadUserAgent string
UseVideoUrl bool UseVideoUrl bool
Space string
// 验证码token刷新成功回调 // 验证码token刷新成功回调
refreshCTokenCk func(token string) refreshCTokenCk func(token string)