diff --git a/drivers/139/driver.go b/drivers/139/driver.go new file mode 100644 index 00000000..18aec2a3 --- /dev/null +++ b/drivers/139/driver.go @@ -0,0 +1,326 @@ +package _139 + +import ( + "bytes" + "context" + "fmt" + "io" + "math" + "net/http" + "strconv" + + "github.com/alist-org/alist/v3/drivers/base" + "github.com/alist-org/alist/v3/internal/driver" + "github.com/alist-org/alist/v3/internal/errs" + "github.com/alist-org/alist/v3/internal/model" + "github.com/alist-org/alist/v3/pkg/utils" + log "github.com/sirupsen/logrus" +) + +type Yun139 struct { + model.Storage + Addition +} + +func (d *Yun139) Config() driver.Config { + return config +} + +func (d *Yun139) GetAddition() driver.Additional { + return d.Addition +} + +func (d *Yun139) Init(ctx context.Context, storage model.Storage) error { + d.Storage = storage + err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition) + if err != nil { + return err + } + _, err = d.post("/orchestration/personalCloud/user/v1.0/qryUserExternInfo", base.Json{ + "qryUserExternInfoReq": base.Json{ + "commonAccountInfo": base.Json{ + "account": d.Account, + "accountType": 1, + }, + }, + }, nil) + return err +} + +func (d *Yun139) Drop(ctx context.Context) error { + return nil +} + +func (d *Yun139) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) { + if d.isFamily() { + return d.familyGetFiles(dir.GetID()) + } else { + return d.getFiles(dir.GetID()) + } +} + +//func (d *Yun139) Get(ctx context.Context, path string) (model.Obj, error) { +// // this is optional +// return nil, errs.NotImplement +//} + +func (d *Yun139) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) { + u, err := d.getLink(file.GetID()) + if err != nil { + return nil, err + } + return &model.Link{URL: u}, nil +} + +func (d *Yun139) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error { + data := base.Json{ + "createCatalogExtReq": base.Json{ + "parentCatalogID": parentDir.GetID(), + "newCatalogName": dirName, + "commonAccountInfo": base.Json{ + "account": d.Account, + "accountType": 1, + }, + }, + } + pathname := "/orchestration/personalCloud/catalog/v1.0/createCatalogExt" + if d.isFamily() { + data = base.Json{ + "cloudID": d.CloudID, + "commonAccountInfo": base.Json{ + "account": d.Account, + "accountType": 1, + }, + "docLibName": dirName, + } + pathname = "/orchestration/familyCloud/cloudCatalog/v1.0/createCloudDoc" + } + _, err := d.post(pathname, + data, nil) + return err +} + +func (d *Yun139) Move(ctx context.Context, srcObj, dstDir model.Obj) error { + if d.isFamily() { + return errs.NotImplement + } + var contentInfoList []string + var catalogInfoList []string + if srcObj.IsDir() { + catalogInfoList = append(catalogInfoList, srcObj.GetID()) + } else { + contentInfoList = append(contentInfoList, srcObj.GetID()) + } + data := base.Json{ + "createBatchOprTaskReq": base.Json{ + "taskType": 3, + "actionType": "304", + "taskInfo": base.Json{ + "contentInfoList": contentInfoList, + "catalogInfoList": catalogInfoList, + "newCatalogID": dstDir.GetID(), + }, + "commonAccountInfo": base.Json{ + "account": d.Account, + "accountType": 1, + }, + }, + } + pathname := "/orchestration/personalCloud/batchOprTask/v1.0/createBatchOprTask" + _, err := d.post(pathname, data, nil) + return err +} + +func (d *Yun139) Rename(ctx context.Context, srcObj model.Obj, newName string) error { + if d.isFamily() { + return errs.NotImplement + } + var data base.Json + var pathname string + if srcObj.IsDir() { + data = base.Json{ + "catalogID": srcObj.GetID(), + "catalogName": newName, + "commonAccountInfo": base.Json{ + "account": d.Account, + "accountType": 1, + }, + } + pathname = "/orchestration/personalCloud/catalog/v1.0/updateCatalogInfo" + } else { + data = base.Json{ + "contentID": srcObj.GetID(), + "contentName": newName, + "commonAccountInfo": base.Json{ + "account": d.Account, + "accountType": 1, + }, + } + pathname = "/orchestration/personalCloud/content/v1.0/updateContentInfo" + } + _, err := d.post(pathname, data, nil) + return err +} + +func (d *Yun139) Copy(ctx context.Context, srcObj, dstDir model.Obj) error { + if d.isFamily() { + return errs.NotImplement + } + var contentInfoList []string + var catalogInfoList []string + if srcObj.IsDir() { + catalogInfoList = append(catalogInfoList, srcObj.GetID()) + } else { + contentInfoList = append(contentInfoList, srcObj.GetID()) + } + data := base.Json{ + "createBatchOprTaskReq": base.Json{ + "taskType": 3, + "actionType": 309, + "taskInfo": base.Json{ + "contentInfoList": contentInfoList, + "catalogInfoList": catalogInfoList, + "newCatalogID": dstDir.GetID(), + }, + "commonAccountInfo": base.Json{ + "account": d.Account, + "accountType": 1, + }, + }, + } + pathname := "/orchestration/personalCloud/batchOprTask/v1.0/createBatchOprTask" + _, err := d.post(pathname, data, nil) + return err +} + +func (d *Yun139) Remove(ctx context.Context, obj model.Obj) error { + var contentInfoList []string + var catalogInfoList []string + if obj.IsDir() { + catalogInfoList = append(catalogInfoList, obj.GetID()) + } else { + contentInfoList = append(contentInfoList, obj.GetID()) + } + data := base.Json{ + "createBatchOprTaskReq": base.Json{ + "taskType": 2, + "actionType": 201, + "taskInfo": base.Json{ + "newCatalogID": "", + "contentInfoList": contentInfoList, + "catalogInfoList": catalogInfoList, + }, + "commonAccountInfo": base.Json{ + "account": d.Account, + "accountType": 1, + }, + }, + } + pathname := "/orchestration/personalCloud/batchOprTask/v1.0/createBatchOprTask" + if d.isFamily() { + data = base.Json{ + "catalogList": catalogInfoList, + "contentList": contentInfoList, + "commonAccountInfo": base.Json{ + "account": d.Account, + "accountType": 1, + }, + "sourceCatalogType": 1002, + "taskType": 2, + } + pathname = "/orchestration/familyCloud/batchOprTask/v1.0/createBatchOprTask" + } + _, err := d.post(pathname, data, nil) + return err +} + +func (d *Yun139) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error { + data := base.Json{ + "manualRename": 2, + "operation": 0, + "fileCount": 1, + "totalSize": stream.GetSize(), + "uploadContentList": []base.Json{{ + "contentName": stream.GetName(), + "contentSize": stream.GetSize(), + // "digest": "5a3231986ce7a6b46e408612d385bafa" + }}, + "parentCatalogID": dstDir.GetID(), + "newCatalogName": "", + "commonAccountInfo": base.Json{ + "account": d.Account, + "accountType": 1, + }, + } + pathname := "/orchestration/personalCloud/uploadAndDownload/v1.0/pcUploadFileRequest" + if d.isFamily() { + data = d.newJson(base.Json{ + "fileCount": 1, + "manualRename": 2, + "operation": 0, + "path": "", + "seqNo": "", + "totalSize": stream.GetSize(), + "uploadContentList": []base.Json{{ + "contentName": stream.GetName(), + "contentSize": stream.GetSize(), + // "digest": "5a3231986ce7a6b46e408612d385bafa" + }}, + }) + pathname = "/orchestration/familyCloud/content/v1.0/getFileUploadURL" + return errs.NotImplement + } + var resp UploadResp + _, err := d.post(pathname, data, &resp) + if err != nil { + return err + } + var Default int64 = 10485760 + part := int(math.Ceil(float64(stream.GetSize()) / float64(Default))) + var start int64 = 0 + for i := 0; i < part; i++ { + byteSize := stream.GetSize() - start + if byteSize > Default { + byteSize = Default + } + byteData := make([]byte, byteSize) + _, err = io.ReadFull(stream, byteData) + if err != nil { + return err + } + req, err := http.NewRequest("POST", resp.Data.UploadResult.RedirectionURL, bytes.NewBuffer(byteData)) + if err != nil { + return err + } + headers := map[string]string{ + "Accept": "*/*", + "Content-Type": "text/plain;name=" + unicode(stream.GetName()), + "contentSize": strconv.FormatInt(stream.GetSize(), 10), + "range": fmt.Sprintf("bytes=%d-%d", start, start+byteSize-1), + "content-length": strconv.FormatInt(byteSize, 10), + "uploadtaskID": resp.Data.UploadResult.UploadTaskID, + "rangeType": "0", + "Referer": "https://yun.139.com/", + "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36 Edg/95.0.1020.44", + "x-SvcType": "1", + } + for k, v := range headers { + req.Header.Set(k, v) + } + res, err := base.HttpClient.Do(req) + if err != nil { + return err + } + log.Debugf("%+v", res) + res.Body.Close() + start += byteSize + up(i * 100 / part) + } + return nil +} + +func (d *Yun139) Other(ctx context.Context, args model.OtherArgs) (interface{}, error) { + return nil, errs.NotSupport +} + +var _ driver.Driver = (*Yun139)(nil) diff --git a/drivers/139/meta.go b/drivers/139/meta.go new file mode 100644 index 00000000..d1f4c2e1 --- /dev/null +++ b/drivers/139/meta.go @@ -0,0 +1,25 @@ +package _139 + +import ( + "github.com/alist-org/alist/v3/internal/driver" + "github.com/alist-org/alist/v3/internal/op" +) + +type Addition struct { + Account string `json:"account" required:"true"` + Cookie string `json:"cookie" type:"text" required:"true"` + driver.RootID + Type string `json:"type" type:"select" options:"personal,family" default:"personal"` + CloudID string `json:"cloud_id"` +} + +var config = driver.Config{ + Name: "139Yun", + LocalSort: true, +} + +func init() { + op.RegisterDriver(config, func() driver.Driver { + return &Yun139{} + }) +} diff --git a/drivers/139/types.go b/drivers/139/types.go new file mode 100644 index 00000000..ef0b2477 --- /dev/null +++ b/drivers/139/types.go @@ -0,0 +1,187 @@ +package _139 + +type BaseResp struct { + Success bool `json:"success"` + Code string `json:"code"` + Message string `json:"message"` +} + +type Catalog struct { + CatalogID string `json:"catalogID"` + CatalogName string `json:"catalogName"` + //CatalogType int `json:"catalogType"` + //CreateTime string `json:"createTime"` + UpdateTime string `json:"updateTime"` + //IsShared bool `json:"isShared"` + //CatalogLevel int `json:"catalogLevel"` + //ShareDoneeCount int `json:"shareDoneeCount"` + //OpenType int `json:"openType"` + //ParentCatalogID string `json:"parentCatalogId"` + //DirEtag int `json:"dirEtag"` + //Tombstoned int `json:"tombstoned"` + //ProxyID interface{} `json:"proxyID"` + //Moved int `json:"moved"` + //IsFixedDir int `json:"isFixedDir"` + //IsSynced interface{} `json:"isSynced"` + //Owner string `json:"owner"` + //Modifier interface{} `json:"modifier"` + //Path string `json:"path"` + //ShareType int `json:"shareType"` + //SoftLink interface{} `json:"softLink"` + //ExtProp1 interface{} `json:"extProp1"` + //ExtProp2 interface{} `json:"extProp2"` + //ExtProp3 interface{} `json:"extProp3"` + //ExtProp4 interface{} `json:"extProp4"` + //ExtProp5 interface{} `json:"extProp5"` + //ETagOprType int `json:"ETagOprType"` +} + +type Content struct { + ContentID string `json:"contentID"` + ContentName string `json:"contentName"` + //ContentSuffix string `json:"contentSuffix"` + ContentSize int64 `json:"contentSize"` + //ContentDesc string `json:"contentDesc"` + //ContentType int `json:"contentType"` + //ContentOrigin int `json:"contentOrigin"` + UpdateTime string `json:"updateTime"` + //CommentCount int `json:"commentCount"` + ThumbnailURL string `json:"thumbnailURL"` + //BigthumbnailURL string `json:"bigthumbnailURL"` + //PresentURL string `json:"presentURL"` + //PresentLURL string `json:"presentLURL"` + //PresentHURL string `json:"presentHURL"` + //ContentTAGList interface{} `json:"contentTAGList"` + //ShareDoneeCount int `json:"shareDoneeCount"` + //Safestate int `json:"safestate"` + //Transferstate int `json:"transferstate"` + //IsFocusContent int `json:"isFocusContent"` + //UpdateShareTime interface{} `json:"updateShareTime"` + //UploadTime string `json:"uploadTime"` + //OpenType int `json:"openType"` + //AuditResult int `json:"auditResult"` + //ParentCatalogID string `json:"parentCatalogId"` + //Channel string `json:"channel"` + //GeoLocFlag string `json:"geoLocFlag"` + //Digest string `json:"digest"` + //Version string `json:"version"` + //FileEtag string `json:"fileEtag"` + //FileVersion string `json:"fileVersion"` + //Tombstoned int `json:"tombstoned"` + //ProxyID string `json:"proxyID"` + //Moved int `json:"moved"` + //MidthumbnailURL string `json:"midthumbnailURL"` + //Owner string `json:"owner"` + //Modifier string `json:"modifier"` + //ShareType int `json:"shareType"` + //ExtInfo struct { + // Uploader string `json:"uploader"` + // Address string `json:"address"` + //} `json:"extInfo"` + //Exif struct { + // CreateTime string `json:"createTime"` + // Longitude interface{} `json:"longitude"` + // Latitude interface{} `json:"latitude"` + // LocalSaveTime interface{} `json:"localSaveTime"` + //} `json:"exif"` + //CollectionFlag interface{} `json:"collectionFlag"` + //TreeInfo interface{} `json:"treeInfo"` + //IsShared bool `json:"isShared"` + //ETagOprType int `json:"ETagOprType"` +} + +type GetDiskResp struct { + BaseResp + Data struct { + Result struct { + ResultCode string `json:"resultCode"` + ResultDesc interface{} `json:"resultDesc"` + } `json:"result"` + GetDiskResult struct { + ParentCatalogID string `json:"parentCatalogID"` + NodeCount int `json:"nodeCount"` + CatalogList []Catalog `json:"catalogList"` + ContentList []Content `json:"contentList"` + IsCompleted int `json:"isCompleted"` + } `json:"getDiskResult"` + } `json:"data"` +} + +type UploadResp struct { + BaseResp + Data struct { + Result struct { + ResultCode string `json:"resultCode"` + ResultDesc interface{} `json:"resultDesc"` + } `json:"result"` + UploadResult struct { + UploadTaskID string `json:"uploadTaskID"` + RedirectionURL string `json:"redirectionUrl"` + NewContentIDList []struct { + ContentID string `json:"contentID"` + ContentName string `json:"contentName"` + IsNeedUpload string `json:"isNeedUpload"` + FileEtag int64 `json:"fileEtag"` + FileVersion int64 `json:"fileVersion"` + OverridenFlag int `json:"overridenFlag"` + } `json:"newContentIDList"` + CatalogIDList interface{} `json:"catalogIDList"` + IsSlice interface{} `json:"isSlice"` + } `json:"uploadResult"` + } `json:"data"` +} + +type CloudContent struct { + ContentID string `json:"contentID"` + //Modifier string `json:"modifier"` + //Nickname string `json:"nickname"` + //CloudNickName string `json:"cloudNickName"` + ContentName string `json:"contentName"` + //ContentType int `json:"contentType"` + //ContentSuffix string `json:"contentSuffix"` + ContentSize int64 `json:"contentSize"` + //ContentDesc string `json:"contentDesc"` + //CreateTime string `json:"createTime"` + //Shottime interface{} `json:"shottime"` + LastUpdateTime string `json:"lastUpdateTime"` + ThumbnailURL string `json:"thumbnailURL"` + //MidthumbnailURL string `json:"midthumbnailURL"` + //BigthumbnailURL string `json:"bigthumbnailURL"` + //PresentURL string `json:"presentURL"` + //PresentLURL string `json:"presentLURL"` + //PresentHURL string `json:"presentHURL"` + //ParentCatalogID string `json:"parentCatalogID"` + //Uploader string `json:"uploader"` + //UploaderNickName string `json:"uploaderNickName"` + //TreeInfo interface{} `json:"treeInfo"` + //UpdateTime interface{} `json:"updateTime"` + //ExtInfo struct { + // Uploader string `json:"uploader"` + //} `json:"extInfo"` + //EtagOprType interface{} `json:"etagOprType"` +} + +type CloudCatalog struct { + CatalogID string `json:"catalogID"` + CatalogName string `json:"catalogName"` + //CloudID string `json:"cloudID"` + //CreateTime string `json:"createTime"` + LastUpdateTime string `json:"lastUpdateTime"` + //Creator string `json:"creator"` + //CreatorNickname string `json:"creatorNickname"` +} + +type QueryContentListResp struct { + BaseResp + Data struct { + Result struct { + ResultCode string `json:"resultCode"` + ResultDesc string `json:"resultDesc"` + } `json:"result"` + Path string `json:"path"` + CloudContentList []CloudContent `json:"cloudContentList"` + CloudCatalogList []CloudCatalog `json:"cloudCatalogList"` + TotalCount int `json:"totalCount"` + RecallContent interface{} `json:"recallContent"` + } `json:"data"` +} diff --git a/drivers/139/util.go b/drivers/139/util.go new file mode 100644 index 00000000..79622147 --- /dev/null +++ b/drivers/139/util.go @@ -0,0 +1,247 @@ +package _139 + +import ( + "encoding/base64" + "errors" + "fmt" + "net/http" + "net/url" + "sort" + "strconv" + "strings" + "time" + + "github.com/alist-org/alist/v3/drivers/base" + "github.com/alist-org/alist/v3/internal/model" + "github.com/alist-org/alist/v3/pkg/utils" + "github.com/alist-org/alist/v3/pkg/utils/random" + "github.com/go-resty/resty/v2" + jsoniter "github.com/json-iterator/go" + log "github.com/sirupsen/logrus" +) + +// do others that not defined in Driver interface +func (d *Yun139) isFamily() bool { + return d.Type == "family" +} + +func encodeURIComponent(str string) string { + r := url.QueryEscape(str) + r = strings.Replace(r, "+", "%20", -1) + return r +} + +func calSign(body, ts, randStr string) string { + body = strings.ReplaceAll(body, "\n", "") + body = strings.ReplaceAll(body, " ", "") + body = encodeURIComponent(body) + strs := strings.Split(body, "") + sort.Strings(strs) + body = strings.Join(strs, "") + body = base64.StdEncoding.EncodeToString([]byte(body)) + res := utils.GetMD5Encode(body) + utils.GetMD5Encode(ts+":"+randStr) + res = strings.ToUpper(utils.GetMD5Encode(res)) + return res +} + +func getTime(t string) time.Time { + stamp, _ := time.ParseInLocation("20060102150405", t, time.Local) + return stamp +} + +func (d *Yun139) request(pathname string, method string, callback base.ReqCallback, resp interface{}) ([]byte, error) { + url := "https://yun.139.com" + pathname + req := base.RestyClient.R() + randStr := random.String(16) + ts := time.Now().Format("2006-01-02 15:04:05") + if callback != nil { + callback(req) + } + body, err := utils.Json.Marshal(req.Body) + if err != nil { + return nil, err + } + sign := calSign(string(body), ts, randStr) + svcType := "1" + if d.isFamily() { + svcType = "2" + } + req.SetHeaders(map[string]string{ + "Accept": "application/json, text/plain, */*", + "CMS-DEVICE": "default", + "Cookie": d.Cookie, + "mcloud-channel": "1000101", + "mcloud-client": "10701", + //"mcloud-route": "001", + "mcloud-sign": fmt.Sprintf("%s,%s,%s", ts, randStr, sign), + //"mcloud-skey":"", + "mcloud-version": "6.6.0", + "Origin": "https://yun.139.com", + "Referer": "https://yun.139.com/w/", + "x-DeviceInfo": "||9|6.6.0|chrome|95.0.4638.69|uwIy75obnsRPIwlJSd7D9GhUvFwG96ce||macos 10.15.2||zh-CN|||", + "x-huawei-channelSrc": "10000034", + "x-inner-ntwk": "2", + "x-m4c-caller": "PC", + "x-m4c-src": "10002", + "x-SvcType": svcType, + }) + + var e BaseResp + req.SetResult(&e) + res, err := req.Execute(method, url) + log.Debugln(res.String()) + if !e.Success { + return nil, errors.New(e.Message) + } + if resp != nil { + err = utils.Json.Unmarshal(res.Body(), resp) + if err != nil { + return nil, err + } + } + return res.Body(), nil +} +func (d *Yun139) post(pathname string, data interface{}, resp interface{}) ([]byte, error) { + return d.request(pathname, http.MethodPost, func(req *resty.Request) { + req.SetBody(data) + }, resp) +} + +func (d *Yun139) getFiles(catalogID string) ([]model.Obj, error) { + start := 0 + limit := 100 + files := make([]model.Obj, 0) + for { + data := base.Json{ + "catalogID": catalogID, + "sortDirection": 1, + "startNumber": start + 1, + "endNumber": start + limit, + "filterType": 0, + "catalogSortType": 0, + "contentSortType": 0, + "commonAccountInfo": base.Json{ + "account": d.Account, + "accountType": 1, + }, + } + var resp GetDiskResp + _, err := d.post("/orchestration/personalCloud/catalog/v1.0/getDisk", data, &resp) + if err != nil { + return nil, err + } + for _, catalog := range resp.Data.GetDiskResult.CatalogList { + f := model.Object{ + ID: catalog.CatalogID, + Name: catalog.CatalogName, + Size: 0, + Modified: getTime(catalog.UpdateTime), + IsFolder: true, + } + files = append(files, &f) + } + for _, content := range resp.Data.GetDiskResult.ContentList { + f := model.ObjThumb{ + Object: model.Object{ + ID: content.ContentID, + Name: content.ContentName, + Size: content.ContentSize, + Modified: getTime(content.UpdateTime), + }, + Thumbnail: model.Thumbnail{Thumbnail: content.ThumbnailURL}, + //Thumbnail: content.BigthumbnailURL, + } + files = append(files, &f) + } + if start+limit >= resp.Data.GetDiskResult.NodeCount { + break + } + start += limit + } + return files, nil +} + +func (d *Yun139) newJson(data map[string]interface{}) base.Json { + common := map[string]interface{}{ + "catalogType": 3, + "cloudID": d.CloudID, + "cloudType": 1, + "commonAccountInfo": base.Json{ + "account": d.Account, + "accountType": 1, + }, + } + return utils.MergeMap(data, common) +} + +func (d *Yun139) familyGetFiles(catalogID string) ([]model.Obj, error) { + pageNum := 1 + files := make([]model.Obj, 0) + for { + data := d.newJson(base.Json{ + "catalogID": catalogID, + "contentSortType": 0, + "pageInfo": base.Json{ + "pageNum": pageNum, + "pageSize": 100, + }, + "sortDirection": 1, + }) + var resp QueryContentListResp + _, err := d.post("/orchestration/familyCloud/content/v1.0/queryContentList", data, &resp) + if err != nil { + return nil, err + } + for _, catalog := range resp.Data.CloudCatalogList { + f := model.Object{ + ID: catalog.CatalogID, + Name: catalog.CatalogName, + Size: 0, + IsFolder: true, + Modified: getTime(catalog.LastUpdateTime), + } + files = append(files, &f) + } + for _, content := range resp.Data.CloudContentList { + f := model.ObjThumb{ + Object: model.Object{ + ID: content.ContentID, + Name: content.ContentName, + Size: content.ContentSize, + Modified: getTime(content.LastUpdateTime), + }, + Thumbnail: model.Thumbnail{Thumbnail: content.ThumbnailURL}, + //Thumbnail: content.BigthumbnailURL, + } + files = append(files, &f) + } + if 100*pageNum > resp.Data.TotalCount { + break + } + pageNum++ + } + return files, nil +} + +func (d *Yun139) getLink(contentId string) (string, error) { + data := base.Json{ + "appName": "", + "contentID": contentId, + "commonAccountInfo": base.Json{ + "account": d.Account, + "accountType": 1, + }, + } + res, err := d.post("/orchestration/personalCloud/uploadAndDownload/v1.0/downloadRequest", + data, nil) + if err != nil { + return "", err + } + return jsoniter.Get(res, "data", "downloadURL").ToString(), nil +} + +func unicode(str string) string { + textQuoted := strconv.QuoteToASCII(str) + textUnquoted := textQuoted[1 : len(textQuoted)-1] + return textUnquoted +} diff --git a/drivers/all.go b/drivers/all.go index b387fde9..6a800d60 100644 --- a/drivers/all.go +++ b/drivers/all.go @@ -2,6 +2,7 @@ package drivers import ( _ "github.com/alist-org/alist/v3/drivers/123" + _ "github.com/alist-org/alist/v3/drivers/139" _ "github.com/alist-org/alist/v3/drivers/aliyundrive" _ "github.com/alist-org/alist/v3/drivers/baidu_netdisk" _ "github.com/alist-org/alist/v3/drivers/ftp" diff --git a/drivers/template/meta.go b/drivers/template/meta.go index 02f15306..ded19705 100644 --- a/drivers/template/meta.go +++ b/drivers/template/meta.go @@ -24,10 +24,8 @@ var config = driver.Config{ DefaultRoot: "root, / or other", } -func New() driver.Driver { - return &Template{} -} - func init() { - op.RegisterDriver(config, New) + op.RegisterDriver(config, func() driver.Driver { + return &Template{} + }) } diff --git a/pkg/utils/map.go b/pkg/utils/map.go new file mode 100644 index 00000000..378ed1c1 --- /dev/null +++ b/pkg/utils/map.go @@ -0,0 +1,11 @@ +package utils + +func MergeMap(mObj ...map[string]interface{}) map[string]interface{} { + newObj := map[string]interface{}{} + for _, m := range mObj { + for k, v := range m { + newObj[k] = v + } + } + return newObj +}