From 89f76d7899a83816bfc70c3d53939a8d9663584f Mon Sep 17 00:00:00 2001 From: zqxiaojin Date: Sat, 27 May 2023 19:36:14 +0800 Subject: [PATCH] feat: add `UC` driver (close #1127 in #4459) Co-authored-by: lj98568 Co-authored-by: Andy Hsu --- README.md | 1 + README_cn.md | 1 + drivers/all.go | 2 +- drivers/quark/meta.go | 26 ------------- drivers/{quark => quark_uc}/driver.go | 36 +++++++++--------- drivers/quark_uc/meta.go | 55 +++++++++++++++++++++++++++ drivers/{quark => quark_uc}/types.go | 0 drivers/{quark => quark_uc}/util.go | 22 +++++------ internal/model/args.go | 2 +- 9 files changed, 89 insertions(+), 56 deletions(-) delete mode 100644 drivers/quark/meta.go rename drivers/{quark => quark_uc}/driver.go (81%) create mode 100644 drivers/quark_uc/meta.go rename drivers/{quark => quark_uc}/types.go (100%) rename drivers/{quark => quark_uc}/util.go (88%) diff --git a/README.md b/README.md index 2e9fb207..76fa3b5b 100755 --- a/README.md +++ b/README.md @@ -62,6 +62,7 @@ English | [中文](./README_cn.md) | [Contributing](./CONTRIBUTING.md) | [CODE_O - [x] [YandexDisk](https://disk.yandex.com/) - [x] [BaiduNetdisk](http://pan.baidu.com/) - [x] [Terabox](https://www.terabox.com/main) + - [x] [UC](https://drive.uc.cn) - [x] [Quark](https://pan.quark.cn) - [x] [Thunder](https://pan.xunlei.com) - [x] [Lanzou](https://www.lanzou.com/) diff --git a/README_cn.md b/README_cn.md index f1106e08..a00647a6 100644 --- a/README_cn.md +++ b/README_cn.md @@ -61,6 +61,7 @@ - [x] [和彩云](https://yun.139.com/) (个人云, 家庭云) - [x] [Yandex.Disk](https://disk.yandex.com/) - [x] [百度网盘](http://pan.baidu.com/) + - [x] [UC网盘](https://drive.uc.cn) - [x] [夸克网盘](https://pan.quark.cn) - [x] [迅雷网盘](https://pan.xunlei.com) - [x] [蓝奏云](https://www.lanzou.com/) diff --git a/drivers/all.go b/drivers/all.go index d41f82bb..7537e12d 100644 --- a/drivers/all.go +++ b/drivers/all.go @@ -28,7 +28,7 @@ import ( _ "github.com/alist-org/alist/v3/drivers/onedrive_app" _ "github.com/alist-org/alist/v3/drivers/pikpak" _ "github.com/alist-org/alist/v3/drivers/pikpak_share" - _ "github.com/alist-org/alist/v3/drivers/quark" + _ "github.com/alist-org/alist/v3/drivers/quark_uc" _ "github.com/alist-org/alist/v3/drivers/s3" _ "github.com/alist-org/alist/v3/drivers/seafile" _ "github.com/alist-org/alist/v3/drivers/sftp" diff --git a/drivers/quark/meta.go b/drivers/quark/meta.go deleted file mode 100644 index ba38738d..00000000 --- a/drivers/quark/meta.go +++ /dev/null @@ -1,26 +0,0 @@ -package quark - -import ( - "github.com/alist-org/alist/v3/internal/driver" - "github.com/alist-org/alist/v3/internal/op" -) - -type Addition struct { - Cookie string `json:"cookie" required:"true"` - driver.RootID - OrderBy string `json:"order_by" type:"select" options:"none,file_type,file_name,updated_at" default:"none"` - OrderDirection string `json:"order_direction" type:"select" options:"asc,desc" default:"asc"` -} - -var config = driver.Config{ - Name: "Quark", - OnlyLocal: true, - DefaultRoot: "0", - NoOverwriteUpload: true, -} - -func init() { - op.RegisterDriver(func() driver.Driver { - return &Quark{} - }) -} diff --git a/drivers/quark/driver.go b/drivers/quark_uc/driver.go similarity index 81% rename from drivers/quark/driver.go rename to drivers/quark_uc/driver.go index f404f54f..96c87518 100644 --- a/drivers/quark/driver.go +++ b/drivers/quark_uc/driver.go @@ -22,29 +22,31 @@ import ( log "github.com/sirupsen/logrus" ) -type Quark struct { +type QuarkOrUC struct { model.Storage Addition + config driver.Config + conf Conf } -func (d *Quark) Config() driver.Config { - return config +func (d *QuarkOrUC) Config() driver.Config { + return d.config } -func (d *Quark) GetAddition() driver.Additional { +func (d *QuarkOrUC) GetAddition() driver.Additional { return &d.Addition } -func (d *Quark) Init(ctx context.Context) error { +func (d *QuarkOrUC) Init(ctx context.Context) error { _, err := d.request("/config", http.MethodGet, nil, nil) return err } -func (d *Quark) Drop(ctx context.Context) error { +func (d *QuarkOrUC) Drop(ctx context.Context) error { return nil } -func (d *Quark) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) { +func (d *QuarkOrUC) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) { files, err := d.GetFiles(dir.GetID()) if err != nil { return nil, err @@ -54,12 +56,12 @@ func (d *Quark) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([ }) } -func (d *Quark) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) { +func (d *QuarkOrUC) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) { data := base.Json{ "fids": []string{file.GetID()}, } var resp DownResp - ua := "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) quark-cloud-drive/2.5.20 Chrome/100.0.4896.160 Electron/18.3.5.4-b478491100 Safari/537.36 Channel/pckk_other_ch" + ua := d.conf.ua _, err := d.request("/file/download", http.MethodPost, func(req *resty.Request) { req.SetHeader("User-Agent", ua). SetBody(data) @@ -103,7 +105,7 @@ func (d *Quark) Link(ctx context.Context, file model.Obj, args model.LinkArgs) ( req.Header.Set("Range", _range) req.Header.Set("User-Agent", ua) req.Header.Set("Cookie", d.Cookie) - req.Header.Set("Referer", "https://pan.quark.cn") + req.Header.Set("Referer", d.conf.referer) resp, err := base.HttpClient.Do(req) if err != nil { return err @@ -125,7 +127,7 @@ func (d *Quark) Link(ctx context.Context, file model.Obj, args model.LinkArgs) ( return &link, nil } -func (d *Quark) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error { +func (d *QuarkOrUC) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error { data := base.Json{ "dir_init_lock": false, "dir_path": "", @@ -141,7 +143,7 @@ func (d *Quark) MakeDir(ctx context.Context, parentDir model.Obj, dirName string return err } -func (d *Quark) Move(ctx context.Context, srcObj, dstDir model.Obj) error { +func (d *QuarkOrUC) Move(ctx context.Context, srcObj, dstDir model.Obj) error { data := base.Json{ "action_type": 1, "exclude_fids": []string{}, @@ -154,7 +156,7 @@ func (d *Quark) Move(ctx context.Context, srcObj, dstDir model.Obj) error { return err } -func (d *Quark) Rename(ctx context.Context, srcObj model.Obj, newName string) error { +func (d *QuarkOrUC) Rename(ctx context.Context, srcObj model.Obj, newName string) error { data := base.Json{ "fid": srcObj.GetID(), "file_name": newName, @@ -165,11 +167,11 @@ func (d *Quark) Rename(ctx context.Context, srcObj model.Obj, newName string) er return err } -func (d *Quark) Copy(ctx context.Context, srcObj, dstDir model.Obj) error { +func (d *QuarkOrUC) Copy(ctx context.Context, srcObj, dstDir model.Obj) error { return errs.NotSupport } -func (d *Quark) Remove(ctx context.Context, obj model.Obj) error { +func (d *QuarkOrUC) Remove(ctx context.Context, obj model.Obj) error { data := base.Json{ "action_type": 1, "exclude_fids": []string{}, @@ -181,7 +183,7 @@ func (d *Quark) Remove(ctx context.Context, obj model.Obj) error { return err } -func (d *Quark) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error { +func (d *QuarkOrUC) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error { tempFile, err := utils.CreateTempFile(stream.GetReadCloser()) if err != nil { return err @@ -266,4 +268,4 @@ func (d *Quark) Put(ctx context.Context, dstDir model.Obj, stream model.FileStre return d.upFinish(pre) } -var _ driver.Driver = (*Quark)(nil) +var _ driver.Driver = (*QuarkOrUC)(nil) diff --git a/drivers/quark_uc/meta.go b/drivers/quark_uc/meta.go new file mode 100644 index 00000000..f3acfe88 --- /dev/null +++ b/drivers/quark_uc/meta.go @@ -0,0 +1,55 @@ +package quark + +import ( + "github.com/alist-org/alist/v3/internal/driver" + "github.com/alist-org/alist/v3/internal/op" +) + +type Addition struct { + Cookie string `json:"cookie" required:"true"` + driver.RootID + OrderBy string `json:"order_by" type:"select" options:"none,file_type,file_name,updated_at" default:"none"` + OrderDirection string `json:"order_direction" type:"select" options:"asc,desc" default:"asc"` +} + +type Conf struct { + ua string + referer string + api string + pr string +} + +func init() { + op.RegisterDriver(func() driver.Driver { + return &QuarkOrUC{ + config: driver.Config{ + Name: "Quark", + OnlyLocal: true, + DefaultRoot: "0", + NoOverwriteUpload: true, + }, + conf: Conf{ + ua: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) quark-cloud-drive/2.5.20 Chrome/100.0.4896.160 Electron/18.3.5.4-b478491100 Safari/537.36 Channel/pckk_other_ch", + referer: "https://pan.quark.cn", + api: "https://drive.quark.cn/1/clouddrive", + pr: "ucpro", + }, + } + }) + op.RegisterDriver(func() driver.Driver { + return &QuarkOrUC{ + config: driver.Config{ + Name: "UC", + OnlyLocal: true, + DefaultRoot: "0", + NoOverwriteUpload: true, + }, + conf: Conf{ + ua: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) uc-cloud-drive/2.5.20 Chrome/100.0.4896.160 Electron/18.3.5.4-b478491100 Safari/537.36 Channel/pckk_other_ch", + referer: "https://drive.uc.cn", + api: "https://pc-api.uc.cn/1/clouddrive", + pr: "UCBrowser", + }, + } + }) +} diff --git a/drivers/quark/types.go b/drivers/quark_uc/types.go similarity index 100% rename from drivers/quark/types.go rename to drivers/quark_uc/types.go diff --git a/drivers/quark/util.go b/drivers/quark_uc/util.go similarity index 88% rename from drivers/quark/util.go rename to drivers/quark_uc/util.go index 50f1eb8d..df27af67 100644 --- a/drivers/quark/util.go +++ b/drivers/quark_uc/util.go @@ -22,15 +22,15 @@ import ( // do others that not defined in Driver interface -func (d *Quark) request(pathname string, method string, callback base.ReqCallback, resp interface{}) ([]byte, error) { - u := "https://drive.quark.cn/1/clouddrive" + pathname +func (d *QuarkOrUC) request(pathname string, method string, callback base.ReqCallback, resp interface{}) ([]byte, error) { + u := d.conf.api + pathname req := base.RestyClient.R() req.SetHeaders(map[string]string{ "Cookie": d.Cookie, "Accept": "application/json, text/plain, */*", - "Referer": "https://pan.quark.cn/", + "Referer": d.conf.referer, }) - req.SetQueryParam("pr", "ucpro") + req.SetQueryParam("pr", d.conf.pr) req.SetQueryParam("fr", "pc") if callback != nil { callback(req) @@ -55,7 +55,7 @@ func (d *Quark) request(pathname string, method string, callback base.ReqCallbac return res.Body(), nil } -func (d *Quark) GetFiles(parent string) ([]File, error) { +func (d *QuarkOrUC) GetFiles(parent string) ([]File, error) { files := make([]File, 0) page := 1 size := 100 @@ -85,7 +85,7 @@ func (d *Quark) GetFiles(parent string) ([]File, error) { return files, nil } -func (d *Quark) upPre(file model.FileStreamer, parentId string) (UpPreResp, error) { +func (d *QuarkOrUC) upPre(file model.FileStreamer, parentId string) (UpPreResp, error) { now := time.Now() data := base.Json{ "ccp_hash_update": true, @@ -105,7 +105,7 @@ func (d *Quark) upPre(file model.FileStreamer, parentId string) (UpPreResp, erro return resp, err } -func (d *Quark) upHash(md5, sha1, taskId string) (bool, error) { +func (d *QuarkOrUC) upHash(md5, sha1, taskId string) (bool, error) { data := base.Json{ "md5": md5, "sha1": sha1, @@ -119,8 +119,8 @@ func (d *Quark) upHash(md5, sha1, taskId string) (bool, error) { return resp.Data.Finish, err } -func (d *Quark) upPart(ctx context.Context, pre UpPreResp, mineType string, partNumber int, bytes []byte) (string, error) { - //func (driver Quark) UpPart(pre UpPreResp, mineType string, partNumber int, bytes []byte, account *model.Account, md5Str, sha1Str string) (string, error) { +func (d *QuarkOrUC) upPart(ctx context.Context, pre UpPreResp, mineType string, partNumber int, bytes []byte) (string, error) { + //func (driver QuarkOrUC) UpPart(pre UpPreResp, mineType string, partNumber int, bytes []byte, account *model.Account, md5Str, sha1Str string) (string, error) { timeStr := time.Now().UTC().Format(http.TimeFormat) data := base.Json{ "auth_info": pre.Data.AuthInfo, @@ -169,7 +169,7 @@ x-oss-user-agent:aliyun-sdk-js/6.6.1 Chrome 98.0.4758.80 on Windows 10 64-bit return res.Header().Get("ETag"), nil } -func (d *Quark) upCommit(pre UpPreResp, md5s []string) error { +func (d *QuarkOrUC) upCommit(pre UpPreResp, md5s []string) error { timeStr := time.Now().UTC().Format(http.TimeFormat) log.Debugf("md5s: %+v", md5s) bodyBuilder := strings.Builder{} @@ -236,7 +236,7 @@ x-oss-user-agent:aliyun-sdk-js/6.6.1 Chrome 98.0.4758.80 on Windows 10 64-bit return nil } -func (d *Quark) upFinish(pre UpPreResp) error { +func (d *QuarkOrUC) upFinish(pre UpPreResp) error { data := base.Json{ "obj_key": pre.Data.ObjKey, "task_id": pre.Data.TaskId, diff --git a/internal/model/args.go b/internal/model/args.go index f40adad8..be8fa7da 100644 --- a/internal/model/args.go +++ b/internal/model/args.go @@ -19,7 +19,7 @@ type LinkArgs struct { type Link struct { URL string `json:"url"` - Header http.Header `json:"header"` // needed header + Header http.Header `json:"header"` // needed header (for url) or response header(for data or writer) Data io.ReadCloser // return file reader directly Status int // status maybe 200 or 206, etc FilePath *string // local file, return the filepath