Skip to content

Commit dba5c27

Browse files
authored
fix(guangyapan): allow user input folder path in driver root path
fix #9493 allow users to mount a guangyapan subfolder
1 parent 527ad89 commit dba5c27

2 files changed

Lines changed: 121 additions & 20 deletions

File tree

drivers/guangyapan/driver.go

Lines changed: 119 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ type GuangYaPan struct {
3333

3434
accountClient *resty.Client
3535
apiClient *resty.Client
36+
37+
resolvedRootFolderID string
38+
rootFolderResolved bool
3639
}
3740

3841
func (d *GuangYaPan) Config() driver.Config {
@@ -62,12 +65,15 @@ func (d *GuangYaPan) Init(ctx context.Context) error {
6265
d.SortType = 1
6366
}
6467

68+
d.RootPath = strings.TrimSpace(d.RootPath)
6569
d.AccessToken = strings.TrimSpace(d.AccessToken)
6670
d.RefreshToken = strings.TrimSpace(d.RefreshToken)
6771
d.PhoneNumber = strings.TrimSpace(d.PhoneNumber)
6872
d.VerifyCode = strings.TrimSpace(d.VerifyCode)
6973
d.CaptchaToken = strings.TrimSpace(d.CaptchaToken)
7074
d.VerificationID = strings.TrimSpace(d.VerificationID)
75+
d.resolvedRootFolderID = ""
76+
d.rootFolderResolved = false
7177

7278
d.accountClient = base.NewRestyClient().
7379
SetBaseURL(accountBaseURL).
@@ -99,14 +105,14 @@ func (d *GuangYaPan) Init(ctx context.Context) error {
99105
// Priority: access_token -> refresh_token -> sms login.
100106
if d.AccessToken != "" {
101107
if err := d.validateToken(ctx); err == nil {
102-
return nil
108+
return d.prepareRootFolder(ctx)
103109
}
104110
d.AccessToken = ""
105111
}
106112
if d.RefreshToken != "" {
107113
if err := d.refreshToken(ctx); err == nil {
108114
if err2 := d.validateToken(ctx); err2 == nil {
109-
return nil
115+
return d.prepareRootFolder(ctx)
110116
}
111117
}
112118
}
@@ -118,7 +124,10 @@ func (d *GuangYaPan) Init(ctx context.Context) error {
118124
if err := d.loginBySMSCode(ctx); err != nil {
119125
return err
120126
}
121-
return d.validateToken(ctx)
127+
if err := d.validateToken(ctx); err != nil {
128+
return err
129+
}
130+
return d.prepareRootFolder(ctx)
122131
}
123132
if d.SendCode {
124133
d.setTempStatus("SMS sending in progress...")
@@ -138,15 +147,27 @@ func (d *GuangYaPan) Drop(ctx context.Context) error {
138147
return nil
139148
}
140149

150+
func (d *GuangYaPan) GetRoot(ctx context.Context) (model.Obj, error) {
151+
rootID, err := d.getRootFolderID(ctx)
152+
if err != nil {
153+
return nil, err
154+
}
155+
return &model.Object{
156+
ID: rootID,
157+
Path: "/",
158+
Name: "root",
159+
Size: 0,
160+
Modified: d.Modified,
161+
IsFolder: true,
162+
}, nil
163+
}
164+
141165
func (d *GuangYaPan) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
142166
if err := d.ensureAccessToken(ctx); err != nil {
143167
return nil, err
144168
}
145169

146170
parentID := dir.GetID()
147-
if parentID == d.RootFolderID {
148-
parentID = ""
149-
}
150171

151172
res := make([]model.Obj, 0, d.PageSize)
152173
for page := 0; ; page++ {
@@ -219,9 +240,6 @@ func (d *GuangYaPan) MakeDir(ctx context.Context, parentDir model.Obj, dirName s
219240
}
220241

221242
parentID := parentDir.GetID()
222-
if parentID == d.RootFolderID {
223-
parentID = ""
224-
}
225243

226244
var out createDirResp
227245
if err := d.postAPI(ctx, "/nd.bizuserres.s/v1/file/create_dir", map[string]any{
@@ -301,9 +319,6 @@ func (d *GuangYaPan) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
301319
return errors.New("file id is empty")
302320
}
303321
parentID := dstDir.GetID()
304-
if parentID == d.RootFolderID {
305-
parentID = ""
306-
}
307322

308323
var out deleteResp
309324
if err := d.postAPI(ctx, "/nd.bizuserres.s/v1/file/move_file", map[string]any{
@@ -332,9 +347,6 @@ func (d *GuangYaPan) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
332347
return errors.New("file id is empty")
333348
}
334349
parentID := dstDir.GetID()
335-
if parentID == d.RootFolderID {
336-
parentID = ""
337-
}
338350

339351
var out deleteResp
340352
if err := d.postAPI(ctx, "/nd.bizuserres.s/v1/file/copy_file", map[string]any{
@@ -369,9 +381,6 @@ func (d *GuangYaPan) Put(ctx context.Context, dstDir model.Obj, file model.FileS
369381
}
370382

371383
parentID := dstDir.GetID()
372-
if parentID == d.RootFolderID {
373-
parentID = ""
374-
}
375384

376385
token, code, err := d.getUploadToken(ctx, parentID, name, file.GetSize())
377386
if err != nil {
@@ -415,6 +424,97 @@ func (d *GuangYaPan) Put(ctx context.Context, dstDir model.Obj, file model.FileS
415424
return d.waitUploadTaskInfo(ctx, taskID)
416425
}
417426

427+
func (d *GuangYaPan) getRootFolderID(ctx context.Context) (string, error) {
428+
if d.rootFolderResolved {
429+
return d.resolvedRootFolderID, nil
430+
}
431+
if err := d.ensureAccessToken(ctx); err != nil {
432+
return "", err
433+
}
434+
if err := d.prepareRootFolder(ctx); err != nil {
435+
return "", err
436+
}
437+
return d.resolvedRootFolderID, nil
438+
}
439+
440+
func (d *GuangYaPan) prepareRootFolder(ctx context.Context) error {
441+
rootID, err := d.resolveConfiguredRootFolderID(ctx)
442+
if err != nil {
443+
return err
444+
}
445+
d.resolvedRootFolderID = rootID
446+
d.rootFolderResolved = true
447+
return nil
448+
}
449+
450+
func (d *GuangYaPan) resolveConfiguredRootFolderID(ctx context.Context) (string, error) {
451+
root := strings.TrimSpace(d.RootPath)
452+
if root == "" {
453+
return "", nil
454+
}
455+
return d.resolveFolderPath(ctx, root)
456+
}
457+
458+
func (d *GuangYaPan) resolveFolderPath(ctx context.Context, rootPath string) (string, error) {
459+
cleanPath := strings.Trim(strings.ReplaceAll(strings.TrimSpace(rootPath), "\\", "/"), "/")
460+
if cleanPath == "" {
461+
return "", nil
462+
}
463+
464+
parentID := ""
465+
for _, name := range strings.Split(cleanPath, "/") {
466+
if name == "" {
467+
continue
468+
}
469+
childID, err := d.findChildFolderID(ctx, parentID, name)
470+
if err != nil {
471+
return "", err
472+
}
473+
parentID = childID
474+
}
475+
return parentID, nil
476+
}
477+
478+
func (d *GuangYaPan) findChildFolderID(ctx context.Context, parentID, name string) (string, error) {
479+
pageSize := d.PageSize
480+
if pageSize <= 0 {
481+
pageSize = 100
482+
}
483+
484+
seen := 0
485+
for page := 0; ; page++ {
486+
var resp listResp
487+
body := map[string]any{
488+
"parentId": parentID,
489+
"page": page,
490+
"pageSize": pageSize,
491+
"orderBy": d.OrderBy,
492+
"sortType": d.SortType,
493+
"fileTypes": []int{},
494+
}
495+
if err := d.postAPI(ctx, "/nd.bizuserres.s/v1/file/get_file_list", body, &resp); err != nil {
496+
return "", err
497+
}
498+
for _, item := range resp.Data.List {
499+
seen++
500+
if item.ResType == 2 && item.FileName == name {
501+
return item.FileID, nil
502+
}
503+
}
504+
if len(resp.Data.List) < pageSize {
505+
break
506+
}
507+
if resp.Data.Total > 0 && seen >= resp.Data.Total {
508+
break
509+
}
510+
}
511+
512+
if parentID == "" {
513+
return "", fmt.Errorf("resolve root folder path failed: folder %q not found under /", name)
514+
}
515+
return "", fmt.Errorf("resolve root folder path failed: folder %q not found under parent %s", name, parentID)
516+
}
517+
418518
func (d *GuangYaPan) ensureAccessToken(ctx context.Context) error {
419519
if strings.TrimSpace(d.AccessToken) != "" {
420520
return nil
@@ -948,3 +1048,4 @@ func randomDeviceID() string {
9481048
}
9491049

9501050
var _ driver.Driver = (*GuangYaPan)(nil)
1051+
var _ driver.GetRooter = (*GuangYaPan)(nil)

drivers/guangyapan/meta.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import (
66
)
77

88
type Addition struct {
9-
driver.RootID
9+
RootPath string `json:"root_path" help:"光鸭云盘中的完整路径"`
1010
PhoneNumber string `json:"phone_number" type:"text" help:"Phone number for SMS login, e.g. +86 13800000000"`
1111
CaptchaToken string `json:"captcha_token" type:"text" help:"Captcha token required by /v1/auth/verification"`
1212
SendCode bool `json:"send_code" type:"bool" help:"Set true and save to send SMS code, it auto-resets to false after sending"`
@@ -39,4 +39,4 @@ func init() {
3939
op.RegisterDriver(func() driver.Driver {
4040
return &GuangYaPan{}
4141
})
42-
}
42+
}

0 commit comments

Comments
 (0)