mirror of https://github.com/Xhofe/alist
feat: add `Reference` interface to driver (#7805)
* feat: add `Reference` interface to driver * feat(123_share): support reference 123panpull/7851/head
parent
880cc7abca
commit
ab22cf8233
|
@ -6,13 +6,14 @@ import (
|
|||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"golang.org/x/time/rate"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"golang.org/x/time/rate"
|
||||
|
||||
"github.com/alist-org/alist/v3/drivers/base"
|
||||
"github.com/alist-org/alist/v3/internal/driver"
|
||||
"github.com/alist-org/alist/v3/internal/errs"
|
||||
|
@ -41,12 +42,12 @@ func (d *Pan123) GetAddition() driver.Additional {
|
|||
}
|
||||
|
||||
func (d *Pan123) Init(ctx context.Context) error {
|
||||
_, err := d.request(UserInfo, http.MethodGet, nil, nil)
|
||||
_, err := d.Request(UserInfo, http.MethodGet, nil, nil)
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *Pan123) Drop(ctx context.Context) error {
|
||||
_, _ = d.request(Logout, http.MethodPost, func(req *resty.Request) {
|
||||
_, _ = d.Request(Logout, http.MethodPost, func(req *resty.Request) {
|
||||
req.SetBody(base.Json{})
|
||||
}, nil)
|
||||
return nil
|
||||
|
@ -81,8 +82,8 @@ func (d *Pan123) Link(ctx context.Context, file model.Obj, args model.LinkArgs)
|
|||
"size": f.Size,
|
||||
"type": f.Type,
|
||||
}
|
||||
resp, err := d.request(DownloadInfo, http.MethodPost, func(req *resty.Request) {
|
||||
|
||||
resp, err := d.Request(DownloadInfo, http.MethodPost, func(req *resty.Request) {
|
||||
|
||||
req.SetBody(data).SetHeaders(headers)
|
||||
}, nil)
|
||||
if err != nil {
|
||||
|
@ -135,7 +136,7 @@ func (d *Pan123) MakeDir(ctx context.Context, parentDir model.Obj, dirName strin
|
|||
"size": 0,
|
||||
"type": 1,
|
||||
}
|
||||
_, err := d.request(Mkdir, http.MethodPost, func(req *resty.Request) {
|
||||
_, err := d.Request(Mkdir, http.MethodPost, func(req *resty.Request) {
|
||||
req.SetBody(data)
|
||||
}, nil)
|
||||
return err
|
||||
|
@ -146,7 +147,7 @@ func (d *Pan123) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
|
|||
"fileIdList": []base.Json{{"FileId": srcObj.GetID()}},
|
||||
"parentFileId": dstDir.GetID(),
|
||||
}
|
||||
_, err := d.request(Move, http.MethodPost, func(req *resty.Request) {
|
||||
_, err := d.Request(Move, http.MethodPost, func(req *resty.Request) {
|
||||
req.SetBody(data)
|
||||
}, nil)
|
||||
return err
|
||||
|
@ -158,7 +159,7 @@ func (d *Pan123) Rename(ctx context.Context, srcObj model.Obj, newName string) e
|
|||
"fileId": srcObj.GetID(),
|
||||
"fileName": newName,
|
||||
}
|
||||
_, err := d.request(Rename, http.MethodPost, func(req *resty.Request) {
|
||||
_, err := d.Request(Rename, http.MethodPost, func(req *resty.Request) {
|
||||
req.SetBody(data)
|
||||
}, nil)
|
||||
return err
|
||||
|
@ -175,7 +176,7 @@ func (d *Pan123) Remove(ctx context.Context, obj model.Obj) error {
|
|||
"operation": true,
|
||||
"fileTrashInfoList": []File{f},
|
||||
}
|
||||
_, err := d.request(Trash, http.MethodPost, func(req *resty.Request) {
|
||||
_, err := d.Request(Trash, http.MethodPost, func(req *resty.Request) {
|
||||
req.SetBody(data)
|
||||
}, nil)
|
||||
return err
|
||||
|
@ -213,7 +214,7 @@ func (d *Pan123) Put(ctx context.Context, dstDir model.Obj, stream model.FileStr
|
|||
"type": 0,
|
||||
}
|
||||
var resp UploadResp
|
||||
res, err := d.request(UploadRequest, http.MethodPost, func(req *resty.Request) {
|
||||
res, err := d.Request(UploadRequest, http.MethodPost, func(req *resty.Request) {
|
||||
req.SetBody(data).SetContext(ctx)
|
||||
}, &resp)
|
||||
if err != nil {
|
||||
|
@ -248,7 +249,7 @@ func (d *Pan123) Put(ctx context.Context, dstDir model.Obj, stream model.FileStr
|
|||
}
|
||||
_, err = uploader.UploadWithContext(ctx, input)
|
||||
}
|
||||
_, err = d.request(UploadComplete, http.MethodPost, func(req *resty.Request) {
|
||||
_, err = d.Request(UploadComplete, http.MethodPost, func(req *resty.Request) {
|
||||
req.SetBody(base.Json{
|
||||
"fileId": resp.Data.FileId,
|
||||
}).SetContext(ctx)
|
||||
|
|
|
@ -25,7 +25,7 @@ func (d *Pan123) getS3PreSignedUrls(ctx context.Context, upReq *UploadResp, star
|
|||
"StorageNode": upReq.Data.StorageNode,
|
||||
}
|
||||
var s3PreSignedUrls S3PreSignedURLs
|
||||
_, err := d.request(S3PreSignedUrls, http.MethodPost, func(req *resty.Request) {
|
||||
_, err := d.Request(S3PreSignedUrls, http.MethodPost, func(req *resty.Request) {
|
||||
req.SetBody(data).SetContext(ctx)
|
||||
}, &s3PreSignedUrls)
|
||||
if err != nil {
|
||||
|
@ -44,7 +44,7 @@ func (d *Pan123) getS3Auth(ctx context.Context, upReq *UploadResp, start, end in
|
|||
"uploadId": upReq.Data.UploadId,
|
||||
}
|
||||
var s3PreSignedUrls S3PreSignedURLs
|
||||
_, err := d.request(S3Auth, http.MethodPost, func(req *resty.Request) {
|
||||
_, err := d.Request(S3Auth, http.MethodPost, func(req *resty.Request) {
|
||||
req.SetBody(data).SetContext(ctx)
|
||||
}, &s3PreSignedUrls)
|
||||
if err != nil {
|
||||
|
@ -63,7 +63,7 @@ func (d *Pan123) completeS3(ctx context.Context, upReq *UploadResp, file model.F
|
|||
"key": upReq.Data.Key,
|
||||
"uploadId": upReq.Data.UploadId,
|
||||
}
|
||||
_, err := d.request(UploadCompleteV2, http.MethodPost, func(req *resty.Request) {
|
||||
_, err := d.Request(UploadCompleteV2, http.MethodPost, func(req *resty.Request) {
|
||||
req.SetBody(data).SetContext(ctx)
|
||||
}, nil)
|
||||
return err
|
||||
|
|
|
@ -194,7 +194,9 @@ func (d *Pan123) login() error {
|
|||
// return &authKey, nil
|
||||
//}
|
||||
|
||||
func (d *Pan123) request(url string, method string, callback base.ReqCallback, resp interface{}) ([]byte, error) {
|
||||
func (d *Pan123) Request(url string, method string, callback base.ReqCallback, resp interface{}) ([]byte, error) {
|
||||
isRetry := false
|
||||
do:
|
||||
req := base.RestyClient.R()
|
||||
req.SetHeaders(map[string]string{
|
||||
"origin": "https://www.123pan.com",
|
||||
|
@ -223,12 +225,13 @@ func (d *Pan123) request(url string, method string, callback base.ReqCallback, r
|
|||
body := res.Body()
|
||||
code := utils.Json.Get(body, "code").ToInt()
|
||||
if code != 0 {
|
||||
if code == 401 {
|
||||
if !isRetry && code == 401 {
|
||||
err := d.login()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return d.request(url, method, callback, resp)
|
||||
isRetry = true
|
||||
goto do
|
||||
}
|
||||
return nil, errors.New(jsoniter.Get(body, "message").ToString())
|
||||
}
|
||||
|
@ -260,7 +263,7 @@ func (d *Pan123) getFiles(ctx context.Context, parentId string, name string) ([]
|
|||
"operateType": "4",
|
||||
"inDirectSpace": "false",
|
||||
}
|
||||
_res, err := d.request(FileList, http.MethodGet, func(req *resty.Request) {
|
||||
_res, err := d.Request(FileList, http.MethodGet, func(req *resty.Request) {
|
||||
req.SetQueryParams(query)
|
||||
}, &resp)
|
||||
if err != nil {
|
||||
|
|
|
@ -4,12 +4,14 @@ import (
|
|||
"context"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"golang.org/x/time/rate"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"golang.org/x/time/rate"
|
||||
|
||||
_123 "github.com/alist-org/alist/v3/drivers/123"
|
||||
"github.com/alist-org/alist/v3/drivers/base"
|
||||
"github.com/alist-org/alist/v3/internal/driver"
|
||||
"github.com/alist-org/alist/v3/internal/errs"
|
||||
|
@ -23,6 +25,7 @@ type Pan123Share struct {
|
|||
model.Storage
|
||||
Addition
|
||||
apiRateLimit sync.Map
|
||||
ref *_123.Pan123
|
||||
}
|
||||
|
||||
func (d *Pan123Share) Config() driver.Config {
|
||||
|
@ -39,7 +42,17 @@ func (d *Pan123Share) Init(ctx context.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (d *Pan123Share) InitReference(storage driver.Driver) error {
|
||||
refStorage, ok := storage.(*_123.Pan123)
|
||||
if ok {
|
||||
d.ref = refStorage
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("ref: storage is not 123Pan")
|
||||
}
|
||||
|
||||
func (d *Pan123Share) Drop(ctx context.Context) error {
|
||||
d.ref = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -53,6 +53,9 @@ func GetApi(rawUrl string) string {
|
|||
}
|
||||
|
||||
func (d *Pan123Share) request(url string, method string, callback base.ReqCallback, resp interface{}) ([]byte, error) {
|
||||
if d.ref != nil {
|
||||
return d.ref.Request(url, method, callback, resp)
|
||||
}
|
||||
req := base.RestyClient.R()
|
||||
req.SetHeaders(map[string]string{
|
||||
"origin": "https://www.123pan.com",
|
||||
|
|
|
@ -26,6 +26,7 @@ type Yun139 struct {
|
|||
Addition
|
||||
cron *cron.Cron
|
||||
Account string
|
||||
ref *Yun139
|
||||
}
|
||||
|
||||
func (d *Yun139) Config() driver.Config {
|
||||
|
@ -37,61 +38,73 @@ func (d *Yun139) GetAddition() driver.Additional {
|
|||
}
|
||||
|
||||
func (d *Yun139) Init(ctx context.Context) error {
|
||||
if d.Authorization == "" {
|
||||
return fmt.Errorf("authorization is empty")
|
||||
}
|
||||
d.cron = cron.NewCron(time.Hour * 24 * 7)
|
||||
d.cron.Do(func() {
|
||||
err := d.refreshToken()
|
||||
if err != nil {
|
||||
log.Errorf("%+v", err)
|
||||
if d.ref == nil {
|
||||
if d.Authorization == "" {
|
||||
return fmt.Errorf("authorization is empty")
|
||||
}
|
||||
})
|
||||
d.cron = cron.NewCron(time.Hour * 24 * 7)
|
||||
d.cron.Do(func() {
|
||||
err := d.refreshToken()
|
||||
if err != nil {
|
||||
log.Errorf("%+v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
switch d.Addition.Type {
|
||||
case MetaPersonalNew:
|
||||
if len(d.Addition.RootFolderID) == 0 {
|
||||
d.RootFolderID = "/"
|
||||
}
|
||||
return nil
|
||||
case MetaPersonal:
|
||||
if len(d.Addition.RootFolderID) == 0 {
|
||||
d.RootFolderID = "root"
|
||||
}
|
||||
fallthrough
|
||||
case MetaGroup:
|
||||
if len(d.Addition.RootFolderID) == 0 {
|
||||
d.RootFolderID = d.CloudID
|
||||
}
|
||||
fallthrough
|
||||
case MetaFamily:
|
||||
decode, err := base64.StdEncoding.DecodeString(d.Authorization)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
decodeStr := string(decode)
|
||||
splits := strings.Split(decodeStr, ":")
|
||||
if len(splits) < 2 {
|
||||
return fmt.Errorf("authorization is invalid, splits < 2")
|
||||
}
|
||||
d.Account = splits[1]
|
||||
_, 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
|
||||
default:
|
||||
return errs.NotImplement
|
||||
}
|
||||
if d.ref != nil {
|
||||
return nil
|
||||
}
|
||||
decode, err := base64.StdEncoding.DecodeString(d.Authorization)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
decodeStr := string(decode)
|
||||
splits := strings.Split(decodeStr, ":")
|
||||
if len(splits) < 2 {
|
||||
return fmt.Errorf("authorization is invalid, splits < 2")
|
||||
}
|
||||
d.Account = splits[1]
|
||||
_, err = d.post("/orchestration/personalCloud/user/v1.0/qryUserExternInfo", base.Json{
|
||||
"qryUserExternInfoReq": base.Json{
|
||||
"commonAccountInfo": base.Json{
|
||||
"account": d.getAccount(),
|
||||
"accountType": 1,
|
||||
},
|
||||
},
|
||||
}, nil)
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *Yun139) InitReference(storage driver.Driver) error {
|
||||
refStorage, ok := storage.(*Yun139)
|
||||
if ok {
|
||||
d.ref = refStorage
|
||||
return nil
|
||||
}
|
||||
return errs.NotSupport
|
||||
}
|
||||
|
||||
func (d *Yun139) Drop(ctx context.Context) error {
|
||||
if d.cron != nil {
|
||||
d.cron.Stop()
|
||||
}
|
||||
d.ref = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -150,7 +163,7 @@ func (d *Yun139) MakeDir(ctx context.Context, parentDir model.Obj, dirName strin
|
|||
"parentCatalogID": parentDir.GetID(),
|
||||
"newCatalogName": dirName,
|
||||
"commonAccountInfo": base.Json{
|
||||
"account": d.Account,
|
||||
"account": d.getAccount(),
|
||||
"accountType": 1,
|
||||
},
|
||||
},
|
||||
|
@ -161,7 +174,7 @@ func (d *Yun139) MakeDir(ctx context.Context, parentDir model.Obj, dirName strin
|
|||
data := base.Json{
|
||||
"cloudID": d.CloudID,
|
||||
"commonAccountInfo": base.Json{
|
||||
"account": d.Account,
|
||||
"account": d.getAccount(),
|
||||
"accountType": 1,
|
||||
},
|
||||
"docLibName": dirName,
|
||||
|
@ -173,7 +186,7 @@ func (d *Yun139) MakeDir(ctx context.Context, parentDir model.Obj, dirName strin
|
|||
data := base.Json{
|
||||
"catalogName": dirName,
|
||||
"commonAccountInfo": base.Json{
|
||||
"account": d.Account,
|
||||
"account": d.getAccount(),
|
||||
"accountType": 1,
|
||||
},
|
||||
"groupID": d.CloudID,
|
||||
|
@ -219,7 +232,7 @@ func (d *Yun139) Move(ctx context.Context, srcObj, dstDir model.Obj) (model.Obj,
|
|||
"contentList": contentList,
|
||||
"catalogList": catalogList,
|
||||
"commonAccountInfo": base.Json{
|
||||
"account": d.Account,
|
||||
"account": d.getAccount(),
|
||||
"accountType": 1,
|
||||
},
|
||||
}
|
||||
|
@ -247,7 +260,7 @@ func (d *Yun139) Move(ctx context.Context, srcObj, dstDir model.Obj) (model.Obj,
|
|||
"newCatalogID": dstDir.GetID(),
|
||||
},
|
||||
"commonAccountInfo": base.Json{
|
||||
"account": d.Account,
|
||||
"account": d.getAccount(),
|
||||
"accountType": 1,
|
||||
},
|
||||
},
|
||||
|
@ -282,7 +295,7 @@ func (d *Yun139) Rename(ctx context.Context, srcObj model.Obj, newName string) e
|
|||
"catalogID": srcObj.GetID(),
|
||||
"catalogName": newName,
|
||||
"commonAccountInfo": base.Json{
|
||||
"account": d.Account,
|
||||
"account": d.getAccount(),
|
||||
"accountType": 1,
|
||||
},
|
||||
}
|
||||
|
@ -292,7 +305,7 @@ func (d *Yun139) Rename(ctx context.Context, srcObj model.Obj, newName string) e
|
|||
"contentID": srcObj.GetID(),
|
||||
"contentName": newName,
|
||||
"commonAccountInfo": base.Json{
|
||||
"account": d.Account,
|
||||
"account": d.getAccount(),
|
||||
"accountType": 1,
|
||||
},
|
||||
}
|
||||
|
@ -309,7 +322,7 @@ func (d *Yun139) Rename(ctx context.Context, srcObj model.Obj, newName string) e
|
|||
"modifyCatalogName": newName,
|
||||
"path": srcObj.GetPath(),
|
||||
"commonAccountInfo": base.Json{
|
||||
"account": d.Account,
|
||||
"account": d.getAccount(),
|
||||
"accountType": 1,
|
||||
},
|
||||
}
|
||||
|
@ -321,7 +334,7 @@ func (d *Yun139) Rename(ctx context.Context, srcObj model.Obj, newName string) e
|
|||
"contentName": newName,
|
||||
"path": srcObj.GetPath(),
|
||||
"commonAccountInfo": base.Json{
|
||||
"account": d.Account,
|
||||
"account": d.getAccount(),
|
||||
"accountType": 1,
|
||||
},
|
||||
}
|
||||
|
@ -338,7 +351,7 @@ func (d *Yun139) Rename(ctx context.Context, srcObj model.Obj, newName string) e
|
|||
// "catalogID": srcObj.GetID(),
|
||||
// "catalogName": newName,
|
||||
// "commonAccountInfo": base.Json{
|
||||
// "account": d.Account,
|
||||
// "account": d.getAccount(),
|
||||
// "accountType": 1,
|
||||
// },
|
||||
// "path": srcObj.GetPath(),
|
||||
|
@ -350,7 +363,7 @@ func (d *Yun139) Rename(ctx context.Context, srcObj model.Obj, newName string) e
|
|||
"contentID": srcObj.GetID(),
|
||||
"contentName": newName,
|
||||
"commonAccountInfo": base.Json{
|
||||
"account": d.Account,
|
||||
"account": d.getAccount(),
|
||||
"accountType": 1,
|
||||
},
|
||||
"path": srcObj.GetPath(),
|
||||
|
@ -393,7 +406,7 @@ func (d *Yun139) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
|
|||
"newCatalogID": dstDir.GetID(),
|
||||
},
|
||||
"commonAccountInfo": base.Json{
|
||||
"account": d.Account,
|
||||
"account": d.getAccount(),
|
||||
"accountType": 1,
|
||||
},
|
||||
},
|
||||
|
@ -430,7 +443,7 @@ func (d *Yun139) Remove(ctx context.Context, obj model.Obj) error {
|
|||
"contentList": contentList,
|
||||
"catalogList": catalogList,
|
||||
"commonAccountInfo": base.Json{
|
||||
"account": d.Account,
|
||||
"account": d.getAccount(),
|
||||
"accountType": 1,
|
||||
},
|
||||
}
|
||||
|
@ -457,7 +470,7 @@ func (d *Yun139) Remove(ctx context.Context, obj model.Obj) error {
|
|||
"catalogInfoList": catalogInfoList,
|
||||
},
|
||||
"commonAccountInfo": base.Json{
|
||||
"account": d.Account,
|
||||
"account": d.getAccount(),
|
||||
"accountType": 1,
|
||||
},
|
||||
},
|
||||
|
@ -468,7 +481,7 @@ func (d *Yun139) Remove(ctx context.Context, obj model.Obj) error {
|
|||
"catalogList": catalogInfoList,
|
||||
"contentList": contentInfoList,
|
||||
"commonAccountInfo": base.Json{
|
||||
"account": d.Account,
|
||||
"account": d.getAccount(),
|
||||
"accountType": 1,
|
||||
},
|
||||
"sourceCloudID": d.CloudID,
|
||||
|
@ -598,7 +611,7 @@ func (d *Yun139) Put(ctx context.Context, dstDir model.Obj, stream model.FileStr
|
|||
"uploadId": resp.Data.UploadId,
|
||||
"partInfos": batchPartInfos,
|
||||
"commonAccountInfo": base.Json{
|
||||
"account": d.Account,
|
||||
"account": d.getAccount(),
|
||||
"accountType": 1,
|
||||
},
|
||||
}
|
||||
|
@ -735,7 +748,7 @@ func (d *Yun139) Put(ctx context.Context, dstDir model.Obj, stream model.FileStr
|
|||
"parentCatalogID": dstDir.GetID(),
|
||||
"newCatalogName": "",
|
||||
"commonAccountInfo": base.Json{
|
||||
"account": d.Account,
|
||||
"account": d.getAccount(),
|
||||
"accountType": 1,
|
||||
},
|
||||
}
|
||||
|
|
|
@ -54,6 +54,9 @@ func getTime(t string) time.Time {
|
|||
}
|
||||
|
||||
func (d *Yun139) refreshToken() error {
|
||||
if d.ref == nil {
|
||||
return d.ref.refreshToken()
|
||||
}
|
||||
url := "https://aas.caiyun.feixin.10086.cn:443/tellin/authTokenRefresh.do"
|
||||
var resp RefreshTokenResp
|
||||
decode, err := base64.StdEncoding.DecodeString(d.Authorization)
|
||||
|
@ -99,7 +102,7 @@ func (d *Yun139) request(pathname string, method string, callback base.ReqCallba
|
|||
req.SetHeaders(map[string]string{
|
||||
"Accept": "application/json, text/plain, */*",
|
||||
"CMS-DEVICE": "default",
|
||||
"Authorization": "Basic " + d.Authorization,
|
||||
"Authorization": "Basic " + d.getAuthorization(),
|
||||
"mcloud-channel": "1000101",
|
||||
"mcloud-client": "10701",
|
||||
//"mcloud-route": "001",
|
||||
|
@ -151,7 +154,7 @@ func (d *Yun139) getFiles(catalogID string) ([]model.Obj, error) {
|
|||
"catalogSortType": 0,
|
||||
"contentSortType": 0,
|
||||
"commonAccountInfo": base.Json{
|
||||
"account": d.Account,
|
||||
"account": d.getAccount(),
|
||||
"accountType": 1,
|
||||
},
|
||||
}
|
||||
|
@ -199,7 +202,7 @@ func (d *Yun139) newJson(data map[string]interface{}) base.Json {
|
|||
"cloudID": d.CloudID,
|
||||
"cloudType": 1,
|
||||
"commonAccountInfo": base.Json{
|
||||
"account": d.Account,
|
||||
"account": d.getAccount(),
|
||||
"accountType": 1,
|
||||
},
|
||||
}
|
||||
|
@ -320,7 +323,7 @@ func (d *Yun139) getLink(contentId string) (string, error) {
|
|||
"appName": "",
|
||||
"contentID": contentId,
|
||||
"commonAccountInfo": base.Json{
|
||||
"account": d.Account,
|
||||
"account": d.getAccount(),
|
||||
"accountType": 1,
|
||||
},
|
||||
}
|
||||
|
@ -383,7 +386,7 @@ func (d *Yun139) personalRequest(pathname string, method string, callback base.R
|
|||
}
|
||||
req.SetHeaders(map[string]string{
|
||||
"Accept": "application/json, text/plain, */*",
|
||||
"Authorization": "Basic " + d.Authorization,
|
||||
"Authorization": "Basic " + d.getAuthorization(),
|
||||
"Caller": "web",
|
||||
"Cms-Device": "default",
|
||||
"Mcloud-Channel": "1000101",
|
||||
|
@ -514,3 +517,16 @@ func (d *Yun139) personalGetLink(fileId string) (string, error) {
|
|||
return jsoniter.Get(res, "data", "url").ToString(), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Yun139) getAuthorization() string {
|
||||
if d.ref != nil {
|
||||
return d.ref.getAuthorization()
|
||||
}
|
||||
return d.Authorization
|
||||
}
|
||||
func (d *Yun139) getAccount() string {
|
||||
if d.ref != nil {
|
||||
return d.ref.getAccount()
|
||||
}
|
||||
return d.Account
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ type Cloud189PC struct {
|
|||
cleanFamilyTransferFile func()
|
||||
|
||||
storageConfig driver.Config
|
||||
ref *Cloud189PC
|
||||
}
|
||||
|
||||
func (y *Cloud189PC) Config() driver.Config {
|
||||
|
@ -64,20 +65,22 @@ func (y *Cloud189PC) Init(ctx context.Context) (err error) {
|
|||
y.uploadThread, y.UploadThread = 3, "3"
|
||||
}
|
||||
|
||||
// 初始化请求客户端
|
||||
if y.client == nil {
|
||||
y.client = base.NewRestyClient().SetHeaders(map[string]string{
|
||||
"Accept": "application/json;charset=UTF-8",
|
||||
"Referer": WEB_URL,
|
||||
})
|
||||
}
|
||||
if y.ref == nil {
|
||||
// 初始化请求客户端
|
||||
if y.client == nil {
|
||||
y.client = base.NewRestyClient().SetHeaders(map[string]string{
|
||||
"Accept": "application/json;charset=UTF-8",
|
||||
"Referer": WEB_URL,
|
||||
})
|
||||
}
|
||||
|
||||
// 避免重复登陆
|
||||
identity := utils.GetMD5EncodeStr(y.Username + y.Password)
|
||||
if !y.isLogin() || y.identity != identity {
|
||||
y.identity = identity
|
||||
if err = y.login(); err != nil {
|
||||
return
|
||||
// 避免重复登陆
|
||||
identity := utils.GetMD5EncodeStr(y.Username + y.Password)
|
||||
if !y.isLogin() || y.identity != identity {
|
||||
y.identity = identity
|
||||
if err = y.login(); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,7 +106,17 @@ func (y *Cloud189PC) Init(ctx context.Context) (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func (d *Cloud189PC) InitReference(storage driver.Driver) error {
|
||||
refStorage, ok := storage.(*Cloud189PC)
|
||||
if ok {
|
||||
d.ref = refStorage
|
||||
return nil
|
||||
}
|
||||
return errs.NotSupport
|
||||
}
|
||||
|
||||
func (y *Cloud189PC) Drop(ctx context.Context) error {
|
||||
y.ref = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -57,11 +57,11 @@ const (
|
|||
|
||||
func (y *Cloud189PC) SignatureHeader(url, method, params string, isFamily bool) map[string]string {
|
||||
dateOfGmt := getHttpDateStr()
|
||||
sessionKey := y.tokenInfo.SessionKey
|
||||
sessionSecret := y.tokenInfo.SessionSecret
|
||||
sessionKey := y.getTokenInfo().SessionKey
|
||||
sessionSecret := y.getTokenInfo().SessionSecret
|
||||
if isFamily {
|
||||
sessionKey = y.tokenInfo.FamilySessionKey
|
||||
sessionSecret = y.tokenInfo.FamilySessionSecret
|
||||
sessionKey = y.getTokenInfo().FamilySessionKey
|
||||
sessionSecret = y.getTokenInfo().FamilySessionSecret
|
||||
}
|
||||
|
||||
header := map[string]string{
|
||||
|
@ -74,9 +74,9 @@ func (y *Cloud189PC) SignatureHeader(url, method, params string, isFamily bool)
|
|||
}
|
||||
|
||||
func (y *Cloud189PC) EncryptParams(params Params, isFamily bool) string {
|
||||
sessionSecret := y.tokenInfo.SessionSecret
|
||||
sessionSecret := y.getTokenInfo().SessionSecret
|
||||
if isFamily {
|
||||
sessionSecret = y.tokenInfo.FamilySessionSecret
|
||||
sessionSecret = y.getTokenInfo().FamilySessionSecret
|
||||
}
|
||||
if params != nil {
|
||||
return AesECBEncrypt(params.Encode(), sessionSecret[:16])
|
||||
|
@ -85,7 +85,7 @@ func (y *Cloud189PC) EncryptParams(params Params, isFamily bool) string {
|
|||
}
|
||||
|
||||
func (y *Cloud189PC) request(url, method string, callback base.ReqCallback, params Params, resp interface{}, isFamily ...bool) ([]byte, error) {
|
||||
req := y.client.R().SetQueryParams(clientSuffix())
|
||||
req := y.getClient().R().SetQueryParams(clientSuffix())
|
||||
|
||||
// 设置params
|
||||
paramsData := y.EncryptParams(params, isBool(isFamily...))
|
||||
|
@ -403,6 +403,9 @@ func (y *Cloud189PC) initLoginParam() error {
|
|||
|
||||
// 刷新会话
|
||||
func (y *Cloud189PC) refreshSession() (err error) {
|
||||
if y.ref != nil {
|
||||
return y.ref.refreshSession()
|
||||
}
|
||||
var erron RespErr
|
||||
var userSessionResp UserSessionResp
|
||||
_, err = y.client.R().
|
||||
|
@ -620,7 +623,7 @@ func (y *Cloud189PC) FastUpload(ctx context.Context, dstDir model.Obj, file mode
|
|||
}
|
||||
|
||||
// 尝试恢复进度
|
||||
uploadProgress, ok := base.GetUploadProgress[*UploadProgress](y, y.tokenInfo.SessionKey, fileMd5Hex)
|
||||
uploadProgress, ok := base.GetUploadProgress[*UploadProgress](y, y.getTokenInfo().SessionKey, fileMd5Hex)
|
||||
if !ok {
|
||||
//step.2 预上传
|
||||
params := Params{
|
||||
|
@ -687,7 +690,7 @@ func (y *Cloud189PC) FastUpload(ctx context.Context, dstDir model.Obj, file mode
|
|||
if err = threadG.Wait(); err != nil {
|
||||
if errors.Is(err, context.Canceled) {
|
||||
uploadProgress.UploadParts = utils.SliceFilter(uploadProgress.UploadParts, func(s string) bool { return s != "" })
|
||||
base.SaveUploadProgress(y, uploadProgress, y.tokenInfo.SessionKey, fileMd5Hex)
|
||||
base.SaveUploadProgress(y, uploadProgress, y.getTokenInfo().SessionKey, fileMd5Hex)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
@ -1008,7 +1011,7 @@ func (y *Cloud189PC) getFamilyID() (string, error) {
|
|||
return "", fmt.Errorf("cannot get automatically,please input family_id")
|
||||
}
|
||||
for _, info := range infos {
|
||||
if strings.Contains(y.tokenInfo.LoginName, info.RemarkName) {
|
||||
if strings.Contains(y.getTokenInfo().LoginName, info.RemarkName) {
|
||||
return fmt.Sprint(info.FamilyID), nil
|
||||
}
|
||||
}
|
||||
|
@ -1142,3 +1145,17 @@ func (y *Cloud189PC) WaitBatchTask(aType string, taskID string, t time.Duration)
|
|||
time.Sleep(t)
|
||||
}
|
||||
}
|
||||
|
||||
func (y *Cloud189PC) getTokenInfo() *AppSessionResp {
|
||||
if y.ref != nil {
|
||||
return y.ref.getTokenInfo()
|
||||
}
|
||||
return y.tokenInfo
|
||||
}
|
||||
|
||||
func (y *Cloud189PC) getClient() *resty.Client {
|
||||
if y.ref != nil {
|
||||
return y.ref.getClient()
|
||||
}
|
||||
return y.client
|
||||
}
|
||||
|
|
|
@ -19,12 +19,12 @@ import (
|
|||
type AliyundriveOpen struct {
|
||||
model.Storage
|
||||
Addition
|
||||
base string
|
||||
|
||||
DriveId string
|
||||
|
||||
limitList func(ctx context.Context, data base.Json) (*Files, error)
|
||||
limitLink func(ctx context.Context, file model.Obj) (*model.Link, error)
|
||||
ref *AliyundriveOpen
|
||||
}
|
||||
|
||||
func (d *AliyundriveOpen) Config() driver.Config {
|
||||
|
@ -58,7 +58,17 @@ func (d *AliyundriveOpen) Init(ctx context.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (d *AliyundriveOpen) InitReference(storage driver.Driver) error {
|
||||
refStorage, ok := storage.(*AliyundriveOpen)
|
||||
if ok {
|
||||
d.ref = refStorage
|
||||
return nil
|
||||
}
|
||||
return errs.NotSupport
|
||||
}
|
||||
|
||||
func (d *AliyundriveOpen) Drop(ctx context.Context) error {
|
||||
d.ref = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -32,11 +32,10 @@ var config = driver.Config{
|
|||
DefaultRoot: "root",
|
||||
NoOverwriteUpload: true,
|
||||
}
|
||||
var API_URL = "https://openapi.alipan.com"
|
||||
|
||||
func init() {
|
||||
op.RegisterDriver(func() driver.Driver {
|
||||
return &AliyundriveOpen{
|
||||
base: "https://openapi.alipan.com",
|
||||
}
|
||||
return &AliyundriveOpen{}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -126,7 +126,7 @@ func getProofRange(input string, size int64) (*ProofRange, error) {
|
|||
}
|
||||
|
||||
func (d *AliyundriveOpen) calProofCode(stream model.FileStreamer) (string, error) {
|
||||
proofRange, err := getProofRange(d.AccessToken, stream.GetSize())
|
||||
proofRange, err := getProofRange(d.getAccessToken(), stream.GetSize())
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ import (
|
|||
// do others that not defined in Driver interface
|
||||
|
||||
func (d *AliyundriveOpen) _refreshToken() (string, string, error) {
|
||||
url := d.base + "/oauth/access_token"
|
||||
url := API_URL + "/oauth/access_token"
|
||||
if d.OauthTokenURL != "" && d.ClientID == "" {
|
||||
url = d.OauthTokenURL
|
||||
}
|
||||
|
@ -74,6 +74,9 @@ func getSub(token string) (string, error) {
|
|||
}
|
||||
|
||||
func (d *AliyundriveOpen) refreshToken() error {
|
||||
if d.ref != nil {
|
||||
return d.ref.refreshToken()
|
||||
}
|
||||
refresh, access, err := d._refreshToken()
|
||||
for i := 0; i < 3; i++ {
|
||||
if err == nil {
|
||||
|
@ -100,7 +103,7 @@ func (d *AliyundriveOpen) request(uri, method string, callback base.ReqCallback,
|
|||
func (d *AliyundriveOpen) requestReturnErrResp(uri, method string, callback base.ReqCallback, retry ...bool) ([]byte, error, *ErrResp) {
|
||||
req := base.RestyClient.R()
|
||||
// TODO check whether access_token is expired
|
||||
req.SetHeader("Authorization", "Bearer "+d.AccessToken)
|
||||
req.SetHeader("Authorization", "Bearer "+d.getAccessToken())
|
||||
if method == http.MethodPost {
|
||||
req.SetHeader("Content-Type", "application/json")
|
||||
}
|
||||
|
@ -109,7 +112,7 @@ func (d *AliyundriveOpen) requestReturnErrResp(uri, method string, callback base
|
|||
}
|
||||
var e ErrResp
|
||||
req.SetError(&e)
|
||||
res, err := req.Execute(method, d.base+uri)
|
||||
res, err := req.Execute(method, API_URL+uri)
|
||||
if err != nil {
|
||||
if res != nil {
|
||||
log.Errorf("[aliyundrive_open] request error: %s", res.String())
|
||||
|
@ -118,7 +121,7 @@ func (d *AliyundriveOpen) requestReturnErrResp(uri, method string, callback base
|
|||
}
|
||||
isRetry := len(retry) > 0 && retry[0]
|
||||
if e.Code != "" {
|
||||
if !isRetry && (utils.SliceContains([]string{"AccessTokenInvalid", "AccessTokenExpired", "I400JD"}, e.Code) || d.AccessToken == "") {
|
||||
if !isRetry && (utils.SliceContains([]string{"AccessTokenInvalid", "AccessTokenExpired", "I400JD"}, e.Code) || d.getAccessToken() == "") {
|
||||
err = d.refreshToken()
|
||||
if err != nil {
|
||||
return nil, err, nil
|
||||
|
@ -176,3 +179,10 @@ func getNowTime() (time.Time, string) {
|
|||
nowTimeStr := nowTime.Format("2006-01-02T15:04:05.000Z")
|
||||
return nowTime, nowTimeStr
|
||||
}
|
||||
|
||||
func (d *AliyundriveOpen) getAccessToken() string {
|
||||
if d.ref != nil {
|
||||
return d.ref.getAccessToken()
|
||||
}
|
||||
return d.AccessToken
|
||||
}
|
||||
|
|
|
@ -144,3 +144,7 @@ func NewProgress(total int64, up UpdateProgress) *Progress {
|
|||
up: up,
|
||||
}
|
||||
}
|
||||
|
||||
type Reference interface {
|
||||
InitReference(storage Driver) error
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
|
||||
"github.com/alist-org/alist/v3/internal/db"
|
||||
"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/generic_sync"
|
||||
"github.com/alist-org/alist/v3/pkg/utils"
|
||||
|
@ -106,6 +107,29 @@ func initStorage(ctx context.Context, storage model.Storage, storageDriver drive
|
|||
}()
|
||||
// Unmarshal Addition
|
||||
err = utils.Json.UnmarshalFromString(driverStorage.Addition, storageDriver.GetAddition())
|
||||
if err == nil {
|
||||
if ref, ok := storageDriver.(driver.Reference); ok {
|
||||
if strings.HasPrefix(driverStorage.Remark, "ref:/") {
|
||||
refMountPath := driverStorage.Remark
|
||||
i := strings.Index(refMountPath, "\n")
|
||||
if i > 0 {
|
||||
refMountPath = refMountPath[4:i]
|
||||
} else {
|
||||
refMountPath = refMountPath[4:]
|
||||
}
|
||||
var refStorage driver.Driver
|
||||
refStorage, err = GetStorageByMountPath(refMountPath)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("ref: %w", err)
|
||||
} else {
|
||||
err = ref.InitReference(refStorage)
|
||||
if err != nil && errs.IsNotSupportError(err) {
|
||||
err = fmt.Errorf("ref: storage is not %s", storageDriver.Config().Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
err = storageDriver.Init(ctx)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue