Skip to content

Commit b454275

Browse files
UcnacDx2Copilot
andauthored
feat(drivers/139): user authentication and file batch operations (#1534)
* feat(139): Enhance 139 driver with password login and root path handling - Added support for password-based login in the 139 driver. - Introduced RootPath field to store the root directory path. - Updated Init method to handle family and group types more effectively. - Implemented new methods for handling file operations in family and group contexts. - Enhanced error handling and logging for better debugging. - Added new request and response structures for batch operations and document modifications. - Improved encryption and decryption methods for secure communication. * Update drivers/139/util.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: UcnacDx2 <127503808+UcnacDx2@users.noreply.github.com> * Update drivers/139/util.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: UcnacDx2 <127503808+UcnacDx2@users.noreply.github.com> * Update drivers/139/util.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: UcnacDx2 <127503808+UcnacDx2@users.noreply.github.com> * Update drivers/139/util.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: UcnacDx2 <127503808+UcnacDx2@users.noreply.github.com> * Update drivers/139/util.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: UcnacDx2 <127503808+UcnacDx2@users.noreply.github.com> --------- Signed-off-by: UcnacDx2 <127503808+UcnacDx2@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 2a99c97 commit b454275

File tree

4 files changed

+885
-24
lines changed

4 files changed

+885
-24
lines changed

drivers/139/driver.go

Lines changed: 121 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/OpenListTeam/OpenList/v4/internal/driver"
1515
"github.com/OpenListTeam/OpenList/v4/internal/errs"
1616
"github.com/OpenListTeam/OpenList/v4/internal/model"
17+
"github.com/OpenListTeam/OpenList/v4/internal/op"
1718
streamPkg "github.com/OpenListTeam/OpenList/v4/internal/stream"
1819
"github.com/OpenListTeam/OpenList/v4/pkg/cron"
1920
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
@@ -28,6 +29,7 @@ type Yun139 struct {
2829
Account string
2930
ref *Yun139
3031
PersonalCloudHost string
32+
RootPath string
3133
}
3234

3335
func (d *Yun139) Config() driver.Config {
@@ -41,7 +43,16 @@ func (d *Yun139) GetAddition() driver.Additional {
4143
func (d *Yun139) Init(ctx context.Context) error {
4244
if d.ref == nil {
4345
if len(d.Authorization) == 0 {
44-
return fmt.Errorf("authorization is empty")
46+
if d.Username != "" && d.Password != "" {
47+
log.Infof("139yun: authorization is empty, trying to login with password.")
48+
newAuth, err := d.loginWithPassword()
49+
log.Debugf("newAuth: Ok: %s", newAuth)
50+
if err != nil {
51+
return fmt.Errorf("login with password failed: %w", err)
52+
}
53+
} else {
54+
return fmt.Errorf("authorization is empty and username/password is not provided")
55+
}
4556
}
4657
err := d.refreshToken()
4758
if err != nil {
@@ -92,7 +103,22 @@ func (d *Yun139) Init(ctx context.Context) error {
92103
if len(d.Addition.RootFolderID) == 0 {
93104
d.RootFolderID = d.CloudID
94105
}
106+
_, err := d.groupGetFiles(d.RootFolderID)
107+
if err != nil {
108+
return err
109+
}
95110
case MetaFamily:
111+
if len(d.Addition.RootFolderID) == 0 {
112+
// Attempt to obtain data.path as the root via a query and persist it.
113+
if root, err := d.getFamilyRootPath(d.CloudID); err == nil && root != "" {
114+
d.RootFolderID = root
115+
op.MustSaveDriverStorage(d)
116+
}
117+
}
118+
_, err := d.familyGetFiles(d.RootFolderID)
119+
if err != nil {
120+
return err
121+
}
96122
default:
97123
return errs.NotImplement
98124
}
@@ -279,6 +305,42 @@ func (d *Yun139) Move(ctx context.Context, srcObj, dstDir model.Obj) (model.Obj,
279305
return nil, err
280306
}
281307
return srcObj, nil
308+
case MetaFamily:
309+
pathname := "/isbo/openApi/createBatchOprTask"
310+
var contentList []string
311+
var catalogList []string
312+
if srcObj.IsDir() {
313+
catalogList = append(catalogList, path.Join(srcObj.GetPath(), srcObj.GetID()))
314+
} else {
315+
contentList = append(contentList, path.Join(srcObj.GetPath(), srcObj.GetID()))
316+
}
317+
318+
body := base.Json{
319+
"catalogList": catalogList,
320+
"accountInfo": base.Json{
321+
"accountName": d.getAccount(),
322+
"accountType": "1",
323+
},
324+
"contentList": contentList,
325+
"destCatalogID": dstDir.GetID(),
326+
"destGroupID": d.CloudID,
327+
"destPath": path.Join(dstDir.GetPath(), dstDir.GetID()),
328+
"destType": 0,
329+
"srcGroupID": d.CloudID,
330+
"srcType": 0,
331+
"taskType": 3,
332+
}
333+
334+
var resp CreateBatchOprTaskResp
335+
_, err := d.isboPost(pathname, body, &resp)
336+
if err != nil {
337+
return nil, err
338+
}
339+
log.Debugf("[139] Move MetaFamily CreateBatchOprTaskResp.Result.ResultCode: %s", resp.Result.ResultCode)
340+
if resp.Result.ResultCode != "0" {
341+
return nil, fmt.Errorf("failed to move in family cloud: %s", resp.Result.ResultDesc)
342+
}
343+
return srcObj, nil
282344
default:
283345
return nil, errs.NotImplement
284346
}
@@ -353,19 +415,27 @@ func (d *Yun139) Rename(ctx context.Context, srcObj model.Obj, newName string) e
353415
var data base.Json
354416
var pathname string
355417
if srcObj.IsDir() {
356-
// 网页接口不支持重命名家庭云文件夹
357-
// data = base.Json{
358-
// "catalogType": 3,
359-
// "catalogID": srcObj.GetID(),
360-
// "catalogName": newName,
361-
// "commonAccountInfo": base.Json{
362-
// "account": d.getAccount(),
363-
// "accountType": 1,
364-
// },
365-
// "path": srcObj.GetPath(),
366-
// }
367-
// pathname = "/orchestration/familyCloud-rebuild/photoContent/v1.0/modifyCatalogInfo"
368-
return errs.NotImplement
418+
pathname = "/modifyCloudDocV2"
419+
data = base.Json{
420+
"catalogType": 3,
421+
"cloudID": d.CloudID,
422+
"commonAccountInfo": base.Json{
423+
"account": d.getAccount(),
424+
"accountType": "1",
425+
},
426+
"docLibName": newName,
427+
"docLibraryID": srcObj.GetID(),
428+
"path": path.Join(srcObj.GetPath(), srcObj.GetID()),
429+
}
430+
var resp ModifyCloudDocV2Resp
431+
_, err = d.andAlbumRequest(pathname, data, &resp)
432+
if err != nil {
433+
return err
434+
}
435+
if resp.Result.ResultCode != "0" {
436+
return fmt.Errorf("failed to rename family folder: %s", resp.Result.ResultDesc)
437+
}
438+
return nil
369439
} else {
370440
data = base.Json{
371441
"contentID": srcObj.GetID(),
@@ -421,6 +491,33 @@ func (d *Yun139) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
421491
}
422492
pathname := "/orchestration/personalCloud/batchOprTask/v1.0/createBatchOprTask"
423493
_, err = d.post(pathname, data, nil)
494+
case MetaGroup:
495+
err = d.handleMetaGroupCopy(ctx, srcObj, dstDir)
496+
case MetaFamily:
497+
pathname := "/copyContentCatalog"
498+
var sourceContentIDs []string
499+
var sourceCatalogIDs []string
500+
if srcObj.IsDir() {
501+
sourceCatalogIDs = append(sourceCatalogIDs, srcObj.GetID())
502+
} else {
503+
sourceContentIDs = append(sourceContentIDs, srcObj.GetID())
504+
}
505+
506+
body := base.Json{
507+
"commonAccountInfo": base.Json{
508+
"accountType": "1",
509+
"accountUserId": d.ref.UserDomainID,
510+
},
511+
"destCatalogID": dstDir.GetID(),
512+
"destCloudID": d.CloudID,
513+
"sourceCatalogIDs": sourceCatalogIDs,
514+
"sourceCloudID": d.CloudID,
515+
"sourceContentIDs": sourceContentIDs,
516+
}
517+
518+
var resp base.Json // Assuming a generic JSON response for success/failure
519+
_, err = d.andAlbumRequest(pathname, body, &resp)
520+
// For now, we assume no error means success.
424521
default:
425522
err = errs.NotImplement
426523
}
@@ -680,6 +777,8 @@ func (d *Yun139) Put(ctx context.Context, dstDir model.Obj, stream model.FileStr
680777
return nil
681778
case MetaPersonal:
682779
fallthrough
780+
case MetaGroup:
781+
fallthrough
683782
case MetaFamily:
684783
// 处理冲突
685784
// 获取文件列表
@@ -727,12 +826,17 @@ func (d *Yun139) Put(ctx context.Context, dstDir model.Obj, stream model.FileStr
727826
},
728827
}
729828
pathname := "/orchestration/personalCloud/uploadAndDownload/v1.0/pcUploadFileRequest"
730-
if d.isFamily() {
829+
if d.isFamily() || d.Addition.Type == MetaGroup {
830+
uploadPath := path.Join(dstDir.GetPath(), dstDir.GetID())
831+
// if dstDir is root folder
832+
if dstDir.GetID() == d.RootFolderID {
833+
uploadPath = d.RootPath
834+
}
731835
data = d.newJson(base.Json{
732836
"fileCount": 1,
733837
"manualRename": 2,
734838
"operation": 0,
735-
"path": path.Join(dstDir.GetPath(), dstDir.GetID()),
839+
"path": uploadPath,
736840
"seqNo": random.String(32), // 序列号不能为空
737841
"totalSize": reportSize,
738842
"uploadContentList": []base.Json{{
@@ -744,6 +848,7 @@ func (d *Yun139) Put(ctx context.Context, dstDir model.Obj, stream model.FileStr
744848
pathname = "/orchestration/familyCloud-rebuild/content/v1.0/getFileUploadURL"
745849
}
746850
var resp UploadResp
851+
log.Debugf("[139] upload request body: %+v", data)
747852
_, err = d.post(pathname, data, &resp)
748853
if err != nil {
749854
return err

drivers/139/meta.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ import (
88
type Addition struct {
99
//Account string `json:"account" required:"true"`
1010
Authorization string `json:"authorization" type:"text" required:"true"`
11+
Username string `json:"username" required:"true"`
12+
Password string `json:"password" required:"true" secret:"true"`
13+
MailCookies string `json:"mail_cookies" required:"true" type:"text" help:"Cookies from mail.139.com used for login authentication."`
1114
driver.RootID
1215
Type string `json:"type" type:"select" options:"personal_new,family,group,personal" default:"personal_new"`
1316
CloudID string `json:"cloud_id"`

drivers/139/types.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,3 +329,62 @@ type FamilyDiskInfoResp struct {
329329
DiskSize string `json:"diskSize"`
330330
} `json:"data"`
331331
}
332+
333+
type AndAlbumUploadResp struct {
334+
Result struct {
335+
ResultCode string `json:"resultCode"`
336+
ResultDesc string `json:"resultDesc"`
337+
} `json:"result"`
338+
UploadResult struct {
339+
UploadTaskID string `json:"uploadTaskID"`
340+
RedirectionURL string `json:"redirectionUrl"`
341+
NewContentIDList []struct {
342+
ContentID string `json:"contentID"`
343+
ContentName string `json:"contentName"`
344+
} `json:"newContentIDList"`
345+
} `json:"uploadResult"`
346+
}
347+
348+
type ModifyCloudDocV2Req struct {
349+
CatalogType int `json:"catalogType"`
350+
CloudID string `json:"cloudID"`
351+
CommonAccountInfo struct {
352+
Account string `json:"account"`
353+
AccountType string `json:"accountType"`
354+
} `json:"commonAccountInfo"`
355+
DocLibName string `json:"docLibName"`
356+
DocLibraryID string `json:"docLibraryID"`
357+
Path string `json:"path"`
358+
}
359+
360+
type ModifyCloudDocV2Resp struct {
361+
Result struct {
362+
ResultCode string `json:"resultCode"`
363+
ResultDesc string `json:"resultDesc"`
364+
} `json:"result"`
365+
}
366+
367+
type CreateBatchOprTaskReq struct {
368+
CatalogList []string `json:"catalogList"`
369+
CommonAccountInfo struct {
370+
Account string `json:"account"`
371+
AccountType string `json:"accountType"`
372+
} `json:"commonAccountInfo"`
373+
ContentList []string `json:"contentList"`
374+
DestCatalogID string `json:"destCatalogID"`
375+
DestGroupID string `json:"destGroupID"`
376+
DestPath string `json:"destPath"`
377+
DestType int `json:"destType"`
378+
SourceCatalogType int `json:"sourceCatalogType"`
379+
SourceCloudID string `json:"sourceCloudID"`
380+
SourceType int `json:"sourceType"`
381+
TaskType int `json:"taskType"`
382+
}
383+
384+
type CreateBatchOprTaskResp struct {
385+
Result struct {
386+
ResultCode string `json:"resultCode"`
387+
ResultDesc string `json:"resultDesc"`
388+
} `json:"result"`
389+
TaskID string `json:"taskID"`
390+
}

0 commit comments

Comments
 (0)