feat: add baidu_netdisk
driver
This commit is contained in:
parent
decea4a739
commit
611457c0e7
@ -62,7 +62,7 @@ func (d *Pan123) List(ctx context.Context, dir model.Obj, args model.ListArgs) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
//func (d *Pan123) Get(ctx context.Context, path string) (model.Obj, error) {
|
//func (d *Pan123) Get(ctx context.Context, path string) (model.Obj, error) {
|
||||||
// // TODO this is optional
|
// // this is optional
|
||||||
// return nil, errs.NotImplement
|
// return nil, errs.NotImplement
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
@ -30,6 +30,10 @@ type File struct {
|
|||||||
DownloadUrl string `json:"DownloadUrl"`
|
DownloadUrl string `json:"DownloadUrl"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f File) GetPath() string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
func (f File) GetSize() int64 {
|
func (f File) GetSize() int64 {
|
||||||
return f.Size
|
return f.Size
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ func (d *Pan123) login() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Pan123) request(url string, method string, callback func(*resty.Request), resp interface{}) ([]byte, error) {
|
func (d *Pan123) request(url string, method string, callback base.ReqCallback, resp interface{}) ([]byte, error) {
|
||||||
req := base.RestyClient.R()
|
req := base.RestyClient.R()
|
||||||
req.SetHeader("Authorization", "Bearer "+d.AccessToken)
|
req.SetHeader("Authorization", "Bearer "+d.AccessToken)
|
||||||
if callback != nil {
|
if callback != nil {
|
||||||
|
@ -34,7 +34,7 @@ func (d *AliDrive) refreshToken() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *AliDrive) request(url, method string, callback func(*resty.Request), resp interface{}) ([]byte, error, RespErr) {
|
func (d *AliDrive) request(url, method string, callback base.ReqCallback, resp interface{}) ([]byte, error, RespErr) {
|
||||||
req := base.RestyClient.R()
|
req := base.RestyClient.R()
|
||||||
req.SetHeader("Authorization", "Bearer\t"+d.AccessToken)
|
req.SetHeader("Authorization", "Bearer\t"+d.AccessToken)
|
||||||
req.SetHeader("content-type", "application/json")
|
req.SetHeader("content-type", "application/json")
|
||||||
|
@ -3,6 +3,7 @@ package drivers
|
|||||||
import (
|
import (
|
||||||
_ "github.com/alist-org/alist/v3/drivers/123"
|
_ "github.com/alist-org/alist/v3/drivers/123"
|
||||||
_ "github.com/alist-org/alist/v3/drivers/aliyundrive"
|
_ "github.com/alist-org/alist/v3/drivers/aliyundrive"
|
||||||
|
_ "github.com/alist-org/alist/v3/drivers/baidu_netdisk"
|
||||||
_ "github.com/alist-org/alist/v3/drivers/local"
|
_ "github.com/alist-org/alist/v3/drivers/local"
|
||||||
_ "github.com/alist-org/alist/v3/drivers/onedrive"
|
_ "github.com/alist-org/alist/v3/drivers/onedrive"
|
||||||
_ "github.com/alist-org/alist/v3/drivers/pikpak"
|
_ "github.com/alist-org/alist/v3/drivers/pikpak"
|
||||||
|
252
drivers/baidu_netdisk/driver.go
Normal file
252
drivers/baidu_netdisk/driver.go
Normal file
@ -0,0 +1,252 @@
|
|||||||
|
package baidu_netdisk
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"crypto/md5"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"math"
|
||||||
|
"os"
|
||||||
|
stdpath "path"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/alist-org/alist/v3/drivers/base"
|
||||||
|
"github.com/alist-org/alist/v3/internal/conf"
|
||||||
|
"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 BaiduNetdisk struct {
|
||||||
|
model.Storage
|
||||||
|
Addition
|
||||||
|
AccessToken string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *BaiduNetdisk) Config() driver.Config {
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *BaiduNetdisk) GetAddition() driver.Additional {
|
||||||
|
return d.Addition
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *BaiduNetdisk) 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
|
||||||
|
}
|
||||||
|
return d.refreshToken()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *BaiduNetdisk) Drop(ctx context.Context) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *BaiduNetdisk) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
|
||||||
|
files, err := d.getFiles(dir.GetPath())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
objs := make([]model.Obj, len(files))
|
||||||
|
for i := 0; i < len(files); i++ {
|
||||||
|
objs[i] = fileToObj(files[i])
|
||||||
|
}
|
||||||
|
return objs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//func (d *BaiduNetdisk) Get(ctx context.Context, path string) (model.Obj, error) {
|
||||||
|
// // this is optional
|
||||||
|
// return nil, errs.NotImplement
|
||||||
|
//}
|
||||||
|
|
||||||
|
func (d *BaiduNetdisk) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||||
|
if d.DownloadAPI == "crack" {
|
||||||
|
return d.linkCrack(file, args)
|
||||||
|
}
|
||||||
|
return d.linkOfficial(file, args)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *BaiduNetdisk) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error {
|
||||||
|
_, err := d.create(stdpath.Join(parentDir.GetPath(), dirName), 0, 1, "", "")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *BaiduNetdisk) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||||
|
data := []base.Json{
|
||||||
|
{
|
||||||
|
"path": srcObj.GetPath(),
|
||||||
|
"dest": dstDir.GetPath(),
|
||||||
|
"newname": srcObj.GetName(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
_, err := d.manage("move", data)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *BaiduNetdisk) Rename(ctx context.Context, srcObj model.Obj, newName string) error {
|
||||||
|
data := []base.Json{
|
||||||
|
{
|
||||||
|
"path": srcObj.GetPath(),
|
||||||
|
"newname": newName,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
_, err := d.manage("rename", data)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *BaiduNetdisk) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||||
|
dest, newname := stdpath.Split(dstDir.GetPath())
|
||||||
|
data := []base.Json{
|
||||||
|
{
|
||||||
|
"path": srcObj.GetPath(),
|
||||||
|
"dest": dest,
|
||||||
|
"newname": newname,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
_, err := d.manage("copy", data)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *BaiduNetdisk) Remove(ctx context.Context, obj model.Obj) error {
|
||||||
|
data := []string{obj.GetPath()}
|
||||||
|
_, err := d.manage("delete", data)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *BaiduNetdisk) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error {
|
||||||
|
var tempFile *os.File
|
||||||
|
var err error
|
||||||
|
if f, ok := stream.GetReadCloser().(*os.File); ok {
|
||||||
|
tempFile = f
|
||||||
|
} else {
|
||||||
|
tempFile, err = os.CreateTemp(conf.Conf.TempDir, "file-*")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
_ = tempFile.Close()
|
||||||
|
_ = os.Remove(tempFile.Name())
|
||||||
|
}()
|
||||||
|
_, err = io.Copy(tempFile, stream)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = tempFile.Seek(0, io.SeekStart)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var Default int64 = 4 * 1024 * 1024
|
||||||
|
defaultByteData := make([]byte, Default)
|
||||||
|
count := int(math.Ceil(float64(stream.GetSize()) / float64(Default)))
|
||||||
|
var SliceSize int64 = 256 * 1024
|
||||||
|
// cal md5
|
||||||
|
h1 := md5.New()
|
||||||
|
h2 := md5.New()
|
||||||
|
block_list := make([]string, 0)
|
||||||
|
content_md5 := ""
|
||||||
|
slice_md5 := ""
|
||||||
|
left := stream.GetSize()
|
||||||
|
for i := 0; i < count; i++ {
|
||||||
|
byteSize := Default
|
||||||
|
var byteData []byte
|
||||||
|
if left < Default {
|
||||||
|
byteSize = left
|
||||||
|
byteData = make([]byte, byteSize)
|
||||||
|
} else {
|
||||||
|
byteData = defaultByteData
|
||||||
|
}
|
||||||
|
left -= byteSize
|
||||||
|
_, err = io.ReadFull(tempFile, byteData)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
h1.Write(byteData)
|
||||||
|
h2.Write(byteData)
|
||||||
|
block_list = append(block_list, fmt.Sprintf("\"%s\"", hex.EncodeToString(h2.Sum(nil))))
|
||||||
|
h2.Reset()
|
||||||
|
}
|
||||||
|
content_md5 = hex.EncodeToString(h1.Sum(nil))
|
||||||
|
_, err = tempFile.Seek(0, io.SeekStart)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if stream.GetSize() <= SliceSize {
|
||||||
|
slice_md5 = content_md5
|
||||||
|
} else {
|
||||||
|
sliceData := make([]byte, SliceSize)
|
||||||
|
_, err = io.ReadFull(tempFile, sliceData)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
h2.Write(sliceData)
|
||||||
|
slice_md5 = hex.EncodeToString(h2.Sum(nil))
|
||||||
|
_, err = tempFile.Seek(0, io.SeekStart)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
path := encodeURIComponent(stdpath.Join(dstDir.GetPath(), stream.GetName()))
|
||||||
|
block_list_str := fmt.Sprintf("[%s]", strings.Join(block_list, ","))
|
||||||
|
data := fmt.Sprintf("path=%s&size=%d&isdir=0&autoinit=1&block_list=%s&content-md5=%s&slice-md5=%s",
|
||||||
|
path, stream.GetSize(),
|
||||||
|
block_list_str,
|
||||||
|
content_md5, slice_md5)
|
||||||
|
params := map[string]string{
|
||||||
|
"method": "precreate",
|
||||||
|
}
|
||||||
|
var precreateResp PrecreateResp
|
||||||
|
_, err = d.post("/xpan/file", params, data, &precreateResp)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
log.Debugf("%+v", precreateResp)
|
||||||
|
if precreateResp.ReturnType == 2 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
params = map[string]string{
|
||||||
|
"method": "upload",
|
||||||
|
"access_token": d.AccessToken,
|
||||||
|
"type": "tmpfile",
|
||||||
|
"path": path,
|
||||||
|
"uploadid": precreateResp.Uploadid,
|
||||||
|
}
|
||||||
|
left = stream.GetSize()
|
||||||
|
for _, partseq := range precreateResp.BlockList {
|
||||||
|
byteSize := Default
|
||||||
|
var byteData []byte
|
||||||
|
if left < Default {
|
||||||
|
byteSize = left
|
||||||
|
byteData = make([]byte, byteSize)
|
||||||
|
} else {
|
||||||
|
byteData = defaultByteData
|
||||||
|
}
|
||||||
|
left -= byteSize
|
||||||
|
_, err = io.ReadFull(tempFile, byteData)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
u := "https://d.pcs.baidu.com/rest/2.0/pcs/superfile2"
|
||||||
|
params["partseq"] = strconv.Itoa(partseq)
|
||||||
|
res, err := base.RestyClient.R().SetQueryParams(params).SetFileReader("file", stream.GetName(), bytes.NewReader(byteData)).Post(u)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
log.Debugln(res.String())
|
||||||
|
}
|
||||||
|
_, err = d.create(path, stream.GetSize(), 0, precreateResp.Uploadid, block_list_str)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *BaiduNetdisk) Other(ctx context.Context, args model.OtherArgs) (interface{}, error) {
|
||||||
|
return nil, errs.NotSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ driver.Driver = (*BaiduNetdisk)(nil)
|
35
drivers/baidu_netdisk/meta.go
Normal file
35
drivers/baidu_netdisk/meta.go
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package baidu_netdisk
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/alist-org/alist/v3/internal/driver"
|
||||||
|
"github.com/alist-org/alist/v3/internal/op"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Addition struct {
|
||||||
|
RefreshToken string `json:"refresh_token" required:"true"`
|
||||||
|
driver.RootFolderPath
|
||||||
|
OrderBy string `json:"order_by" type:"select" options:"name,time,size" default:"name"`
|
||||||
|
OrderDirection string `json:"order_direction" type:"select" options:"asc,desc" default:"asc"`
|
||||||
|
DownloadAPI string `json:"download_api" type:"select" options:"official,crack" default:"official"`
|
||||||
|
ClientID string `json:"client_id" required:"true" default:"iYCeC9g08h5vuP9UqvPHKKSVrKFXGa1v"`
|
||||||
|
ClientSecret string `json:"client_secret" required:"true" default:"jXiFMOPVPCWlO2M5CwWQzffpNPaGTRBG"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var config = driver.Config{
|
||||||
|
Name: "BaiduNetdisk",
|
||||||
|
LocalSort: false,
|
||||||
|
OnlyLocal: false,
|
||||||
|
OnlyProxy: false,
|
||||||
|
NoCache: false,
|
||||||
|
NoUpload: false,
|
||||||
|
NeedMs: false,
|
||||||
|
DefaultRoot: "root, / or other",
|
||||||
|
}
|
||||||
|
|
||||||
|
func New() driver.Driver {
|
||||||
|
return &BaiduNetdisk{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
op.RegisterDriver(config, New)
|
||||||
|
}
|
163
drivers/baidu_netdisk/types.go
Normal file
163
drivers/baidu_netdisk/types.go
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
package baidu_netdisk
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/alist-org/alist/v3/internal/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TokenErrResp struct {
|
||||||
|
ErrorDescription string `json:"error_description"`
|
||||||
|
Error string `json:"error"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type File struct {
|
||||||
|
//TkbindId int `json:"tkbind_id"`
|
||||||
|
//OwnerType int `json:"owner_type"`
|
||||||
|
//Category int `json:"category"`
|
||||||
|
//RealCategory string `json:"real_category"`
|
||||||
|
FsId int64 `json:"fs_id"`
|
||||||
|
ServerMtime int64 `json:"server_mtime"`
|
||||||
|
//OperId int `json:"oper_id"`
|
||||||
|
//ServerCtime int `json:"server_ctime"`
|
||||||
|
Thumbs struct {
|
||||||
|
//Icon string `json:"icon"`
|
||||||
|
Url3 string `json:"url3"`
|
||||||
|
//Url2 string `json:"url2"`
|
||||||
|
//Url1 string `json:"url1"`
|
||||||
|
} `json:"thumbs"`
|
||||||
|
//Wpfile int `json:"wpfile"`
|
||||||
|
//LocalMtime int `json:"local_mtime"`
|
||||||
|
Size int64 `json:"size"`
|
||||||
|
//ExtentTinyint7 int `json:"extent_tinyint7"`
|
||||||
|
Path string `json:"path"`
|
||||||
|
//Share int `json:"share"`
|
||||||
|
//ServerAtime int `json:"server_atime"`
|
||||||
|
//Pl int `json:"pl"`
|
||||||
|
//LocalCtime int `json:"local_ctime"`
|
||||||
|
ServerFilename string `json:"server_filename"`
|
||||||
|
//Md5 string `json:"md5"`
|
||||||
|
//OwnerId int `json:"owner_id"`
|
||||||
|
//Unlist int `json:"unlist"`
|
||||||
|
Isdir int `json:"isdir"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func fileToObj(f File) *model.ObjThumb {
|
||||||
|
return &model.ObjThumb{
|
||||||
|
Object: model.Object{
|
||||||
|
ID: strconv.FormatInt(f.FsId, 10),
|
||||||
|
Name: f.ServerFilename,
|
||||||
|
Size: f.Size,
|
||||||
|
Modified: time.Unix(f.ServerMtime, 0),
|
||||||
|
IsFolder: f.Isdir == 1,
|
||||||
|
},
|
||||||
|
Thumbnail: model.Thumbnail{Thumbnail: f.Thumbs.Url3},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListResp struct {
|
||||||
|
Errno int `json:"errno"`
|
||||||
|
GuidInfo string `json:"guid_info"`
|
||||||
|
List []File `json:"list"`
|
||||||
|
RequestId int64 `json:"request_id"`
|
||||||
|
Guid int `json:"guid"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DownloadResp struct {
|
||||||
|
Errmsg string `json:"errmsg"`
|
||||||
|
Errno int `json:"errno"`
|
||||||
|
List []struct {
|
||||||
|
//Category int `json:"category"`
|
||||||
|
//DateTaken int `json:"date_taken,omitempty"`
|
||||||
|
Dlink string `json:"dlink"`
|
||||||
|
//Filename string `json:"filename"`
|
||||||
|
//FsId int64 `json:"fs_id"`
|
||||||
|
//Height int `json:"height,omitempty"`
|
||||||
|
//Isdir int `json:"isdir"`
|
||||||
|
//Md5 string `json:"md5"`
|
||||||
|
//OperId int `json:"oper_id"`
|
||||||
|
//Path string `json:"path"`
|
||||||
|
//ServerCtime int `json:"server_ctime"`
|
||||||
|
//ServerMtime int `json:"server_mtime"`
|
||||||
|
//Size int `json:"size"`
|
||||||
|
//Thumbs struct {
|
||||||
|
// Icon string `json:"icon,omitempty"`
|
||||||
|
// Url1 string `json:"url1,omitempty"`
|
||||||
|
// Url2 string `json:"url2,omitempty"`
|
||||||
|
// Url3 string `json:"url3,omitempty"`
|
||||||
|
//} `json:"thumbs"`
|
||||||
|
//Width int `json:"width,omitempty"`
|
||||||
|
} `json:"list"`
|
||||||
|
//Names struct {
|
||||||
|
//} `json:"names"`
|
||||||
|
RequestId string `json:"request_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DownloadResp2 struct {
|
||||||
|
Errno int `json:"errno"`
|
||||||
|
Info []struct {
|
||||||
|
//ExtentTinyint4 int `json:"extent_tinyint4"`
|
||||||
|
//ExtentTinyint1 int `json:"extent_tinyint1"`
|
||||||
|
//Bitmap string `json:"bitmap"`
|
||||||
|
//Category int `json:"category"`
|
||||||
|
//Isdir int `json:"isdir"`
|
||||||
|
//Videotag int `json:"videotag"`
|
||||||
|
Dlink string `json:"dlink"`
|
||||||
|
//OperID int64 `json:"oper_id"`
|
||||||
|
//PathMd5 int `json:"path_md5"`
|
||||||
|
//Wpfile int `json:"wpfile"`
|
||||||
|
//LocalMtime int `json:"local_mtime"`
|
||||||
|
/*Thumbs struct {
|
||||||
|
Icon string `json:"icon"`
|
||||||
|
URL3 string `json:"url3"`
|
||||||
|
URL2 string `json:"url2"`
|
||||||
|
URL1 string `json:"url1"`
|
||||||
|
} `json:"thumbs"`*/
|
||||||
|
//PlaySource int `json:"play_source"`
|
||||||
|
//Share int `json:"share"`
|
||||||
|
//FileKey string `json:"file_key"`
|
||||||
|
//Errno int `json:"errno"`
|
||||||
|
//LocalCtime int `json:"local_ctime"`
|
||||||
|
//Rotate int `json:"rotate"`
|
||||||
|
//Metadata time.Time `json:"metadata"`
|
||||||
|
//Height int `json:"height"`
|
||||||
|
//SampleRate int `json:"sample_rate"`
|
||||||
|
//Width int `json:"width"`
|
||||||
|
//OwnerType int `json:"owner_type"`
|
||||||
|
//Privacy int `json:"privacy"`
|
||||||
|
//ExtentInt3 int64 `json:"extent_int3"`
|
||||||
|
//RealCategory string `json:"real_category"`
|
||||||
|
//SrcLocation string `json:"src_location"`
|
||||||
|
//MetaInfo string `json:"meta_info"`
|
||||||
|
//ID string `json:"id"`
|
||||||
|
//Duration int `json:"duration"`
|
||||||
|
//FileSize string `json:"file_size"`
|
||||||
|
//Channels int `json:"channels"`
|
||||||
|
//UseSegment int `json:"use_segment"`
|
||||||
|
//ServerCtime int `json:"server_ctime"`
|
||||||
|
//Resolution string `json:"resolution"`
|
||||||
|
//OwnerID int `json:"owner_id"`
|
||||||
|
//ExtraInfo string `json:"extra_info"`
|
||||||
|
//Size int `json:"size"`
|
||||||
|
//FsID int64 `json:"fs_id"`
|
||||||
|
//ExtentTinyint3 int `json:"extent_tinyint3"`
|
||||||
|
//Md5 string `json:"md5"`
|
||||||
|
//Path string `json:"path"`
|
||||||
|
//FrameRate int `json:"frame_rate"`
|
||||||
|
//ExtentTinyint2 int `json:"extent_tinyint2"`
|
||||||
|
//ServerFilename string `json:"server_filename"`
|
||||||
|
//ServerMtime int `json:"server_mtime"`
|
||||||
|
//TkbindID int `json:"tkbind_id"`
|
||||||
|
} `json:"info"`
|
||||||
|
RequestID int64 `json:"request_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PrecreateResp struct {
|
||||||
|
Path string `json:"path"`
|
||||||
|
Uploadid string `json:"uploadid"`
|
||||||
|
ReturnType int `json:"return_type"`
|
||||||
|
BlockList []int `json:"block_list"`
|
||||||
|
Errno int `json:"errno"`
|
||||||
|
RequestId int64 `json:"request_id"`
|
||||||
|
}
|
199
drivers/baidu_netdisk/util.go
Normal file
199
drivers/baidu_netdisk/util.go
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
package baidu_netdisk
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/alist-org/alist/v3/drivers/base"
|
||||||
|
"github.com/alist-org/alist/v3/internal/errs"
|
||||||
|
"github.com/alist-org/alist/v3/internal/model"
|
||||||
|
"github.com/alist-org/alist/v3/internal/op"
|
||||||
|
"github.com/alist-org/alist/v3/pkg/utils"
|
||||||
|
"github.com/go-resty/resty/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
// do others that not defined in Driver interface
|
||||||
|
|
||||||
|
func (d *BaiduNetdisk) refreshToken() error {
|
||||||
|
err := d._refreshToken()
|
||||||
|
if err != nil && err == errs.EmptyToken {
|
||||||
|
err = d._refreshToken()
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *BaiduNetdisk) _refreshToken() error {
|
||||||
|
u := "https://openapi.baidu.com/oauth/2.0/token"
|
||||||
|
var resp base.TokenResp
|
||||||
|
var e TokenErrResp
|
||||||
|
_, err := base.RestyClient.R().SetResult(&resp).SetError(&e).SetQueryParams(map[string]string{
|
||||||
|
"grant_type": "refresh_token",
|
||||||
|
"refresh_token": d.RefreshToken,
|
||||||
|
"client_id": d.ClientID,
|
||||||
|
"client_secret": d.ClientSecret,
|
||||||
|
}).Get(u)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if e.Error != "" {
|
||||||
|
return fmt.Errorf("%s : %s", e.Error, e.ErrorDescription)
|
||||||
|
}
|
||||||
|
if resp.RefreshToken == "" {
|
||||||
|
return errs.EmptyToken
|
||||||
|
}
|
||||||
|
d.AccessToken, d.RefreshToken = resp.AccessToken, resp.RefreshToken
|
||||||
|
op.MustSaveDriverStorage(d)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *BaiduNetdisk) request(furl string, method string, callback base.ReqCallback, resp interface{}) ([]byte, error) {
|
||||||
|
req := base.RestyClient.R()
|
||||||
|
req.SetQueryParam("access_token", d.AccessToken)
|
||||||
|
if callback != nil {
|
||||||
|
callback(req)
|
||||||
|
}
|
||||||
|
if resp != nil {
|
||||||
|
req.SetResult(resp)
|
||||||
|
}
|
||||||
|
res, err := req.Execute(method, furl)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
errno := utils.Json.Get(res.Body(), "errno").ToInt()
|
||||||
|
if errno != 0 {
|
||||||
|
if errno == -6 {
|
||||||
|
err = d.refreshToken()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return d.request(furl, method, callback, resp)
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("errno: %d, refer to https://pan.baidu.com/union/doc/", errno)
|
||||||
|
}
|
||||||
|
return res.Body(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *BaiduNetdisk) get(pathname string, params map[string]string, resp interface{}) ([]byte, error) {
|
||||||
|
return d.request("https://pan.baidu.com/rest/2.0"+pathname, http.MethodGet, func(req *resty.Request) {
|
||||||
|
req.SetQueryParams(params)
|
||||||
|
}, resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *BaiduNetdisk) post(pathname string, params map[string]string, data interface{}, resp interface{}) ([]byte, error) {
|
||||||
|
return d.request("https://pan.baidu.com/rest/2.0"+pathname, http.MethodPost, func(req *resty.Request) {
|
||||||
|
req.SetQueryParams(params)
|
||||||
|
req.SetBody(data)
|
||||||
|
}, resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *BaiduNetdisk) getFiles(dir string) ([]File, error) {
|
||||||
|
start := 0
|
||||||
|
limit := 200
|
||||||
|
params := map[string]string{
|
||||||
|
"method": "list",
|
||||||
|
"dir": dir,
|
||||||
|
"web": "web",
|
||||||
|
}
|
||||||
|
if d.OrderBy != "" {
|
||||||
|
params["order"] = d.OrderBy
|
||||||
|
if d.OrderDirection == "desc" {
|
||||||
|
params["desc"] = "1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res := make([]File, 0)
|
||||||
|
for {
|
||||||
|
params["start"] = strconv.Itoa(start)
|
||||||
|
params["limit"] = strconv.Itoa(limit)
|
||||||
|
start += limit
|
||||||
|
var resp ListResp
|
||||||
|
_, err := d.get("/xpan/file", params, &resp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(resp.List) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
res = append(res, resp.List...)
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *BaiduNetdisk) linkOfficial(file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||||
|
var resp DownloadResp
|
||||||
|
params := map[string]string{
|
||||||
|
"method": "filemetas",
|
||||||
|
"fsids": fmt.Sprintf("[%s]", file.GetID()),
|
||||||
|
"dlink": "1",
|
||||||
|
}
|
||||||
|
_, err := d.get("/xpan/multimedia", params, &resp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
u := fmt.Sprintf("%s&access_token=%s", resp.List[0].Dlink, d.AccessToken)
|
||||||
|
res, err := base.NoRedirectClient.R().SetHeader("User-Agent", "pan.baidu.com").Head(u)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
//if res.StatusCode() == 302 {
|
||||||
|
u = res.Header().Get("location")
|
||||||
|
//}
|
||||||
|
return &model.Link{
|
||||||
|
URL: u,
|
||||||
|
Header: http.Header{
|
||||||
|
"User-Agent": []string{"pan.baidu.com"},
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *BaiduNetdisk) linkCrack(file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||||
|
var resp DownloadResp2
|
||||||
|
param := map[string]string{
|
||||||
|
"target": fmt.Sprintf("[\"%s\"]", file.GetPath()),
|
||||||
|
"dlink": "1",
|
||||||
|
"web": "5",
|
||||||
|
"origin": "dlna",
|
||||||
|
}
|
||||||
|
_, err := d.get("https://pan.baidu.com/api/filemetas", param, &resp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &model.Link{
|
||||||
|
URL: resp.Info[0].Dlink,
|
||||||
|
Header: http.Header{
|
||||||
|
"User-Agent": []string{"pan.baidu.com"},
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *BaiduNetdisk) manage(opera string, filelist interface{}) ([]byte, error) {
|
||||||
|
params := map[string]string{
|
||||||
|
"method": "filemanager",
|
||||||
|
"opera": opera,
|
||||||
|
}
|
||||||
|
marshal, err := utils.Json.Marshal(filelist)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
data := fmt.Sprintf("async=0&filelist=%s&ondup=newcopy", string(marshal))
|
||||||
|
return d.post("/xpan/file", params, data, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *BaiduNetdisk) create(path string, size int64, isdir int, uploadid, block_list string) ([]byte, error) {
|
||||||
|
params := map[string]string{
|
||||||
|
"method": "create",
|
||||||
|
}
|
||||||
|
data := fmt.Sprintf("path=%s&size=%d&isdir=%d", path, size, isdir)
|
||||||
|
if uploadid != "" {
|
||||||
|
data += fmt.Sprintf("&uploadid=%s&block_list=%s", uploadid, block_list)
|
||||||
|
}
|
||||||
|
return d.post("/xpan/file", params, data, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func encodeURIComponent(str string) string {
|
||||||
|
r := url.QueryEscape(str)
|
||||||
|
r = strings.ReplaceAll(r, "+", "%20")
|
||||||
|
return r
|
||||||
|
}
|
@ -1,8 +1,12 @@
|
|||||||
package base
|
package base
|
||||||
|
|
||||||
|
import "github.com/go-resty/resty/v2"
|
||||||
|
|
||||||
type Json map[string]interface{}
|
type Json map[string]interface{}
|
||||||
|
|
||||||
type TokenResp struct {
|
type TokenResp struct {
|
||||||
AccessToken string `json:"access_token"`
|
AccessToken string `json:"access_token"`
|
||||||
RefreshToken string `json:"refresh_token"`
|
RefreshToken string `json:"refresh_token"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ReqCallback func(req *resty.Request)
|
||||||
|
@ -62,7 +62,7 @@ func (d *Local) GetAddition() driver.Additional {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *Local) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
|
func (d *Local) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
|
||||||
fullPath := dir.GetID()
|
fullPath := dir.GetPath()
|
||||||
rawFiles, err := ioutil.ReadDir(fullPath)
|
rawFiles, err := ioutil.ReadDir(fullPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -103,7 +103,7 @@ func (d *Local) Get(ctx context.Context, path string) (model.Obj, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
file := model.Object{
|
file := model.Object{
|
||||||
ID: path,
|
Path: path,
|
||||||
Name: f.Name(),
|
Name: f.Name(),
|
||||||
Modified: f.ModTime(),
|
Modified: f.ModTime(),
|
||||||
Size: f.Size(),
|
Size: f.Size(),
|
||||||
@ -113,7 +113,7 @@ func (d *Local) Get(ctx context.Context, path string) (model.Obj, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *Local) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
func (d *Local) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||||
fullPath := file.GetID()
|
fullPath := file.GetPath()
|
||||||
var link model.Link
|
var link model.Link
|
||||||
if args.Type == "thumb" && utils.Ext(file.GetName()) != "svg" {
|
if args.Type == "thumb" && utils.Ext(file.GetName()) != "svg" {
|
||||||
imgData, err := ioutil.ReadFile(fullPath)
|
imgData, err := ioutil.ReadFile(fullPath)
|
||||||
@ -143,7 +143,7 @@ func (d *Local) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *Local) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error {
|
func (d *Local) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error {
|
||||||
fullPath := filepath.Join(parentDir.GetID(), dirName)
|
fullPath := filepath.Join(parentDir.GetPath(), dirName)
|
||||||
err := os.MkdirAll(fullPath, 0700)
|
err := os.MkdirAll(fullPath, 0700)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -152,8 +152,8 @@ func (d *Local) MakeDir(ctx context.Context, parentDir model.Obj, dirName string
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *Local) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
|
func (d *Local) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||||
srcPath := srcObj.GetID()
|
srcPath := srcObj.GetPath()
|
||||||
dstPath := filepath.Join(dstDir.GetID(), srcObj.GetName())
|
dstPath := filepath.Join(dstDir.GetPath(), srcObj.GetName())
|
||||||
err := os.Rename(srcPath, dstPath)
|
err := os.Rename(srcPath, dstPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -162,7 +162,7 @@ func (d *Local) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *Local) Rename(ctx context.Context, srcObj model.Obj, newName string) error {
|
func (d *Local) Rename(ctx context.Context, srcObj model.Obj, newName string) error {
|
||||||
srcPath := srcObj.GetID()
|
srcPath := srcObj.GetPath()
|
||||||
dstPath := filepath.Join(filepath.Dir(srcPath), newName)
|
dstPath := filepath.Join(filepath.Dir(srcPath), newName)
|
||||||
err := os.Rename(srcPath, dstPath)
|
err := os.Rename(srcPath, dstPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -172,8 +172,8 @@ func (d *Local) Rename(ctx context.Context, srcObj model.Obj, newName string) er
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *Local) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
|
func (d *Local) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||||
srcPath := srcObj.GetID()
|
srcPath := srcObj.GetPath()
|
||||||
dstPath := filepath.Join(dstDir.GetID(), srcObj.GetName())
|
dstPath := filepath.Join(dstDir.GetPath(), srcObj.GetName())
|
||||||
var err error
|
var err error
|
||||||
if srcObj.IsDir() {
|
if srcObj.IsDir() {
|
||||||
err = copyDir(srcPath, dstPath)
|
err = copyDir(srcPath, dstPath)
|
||||||
@ -189,9 +189,9 @@ func (d *Local) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
|
|||||||
func (d *Local) Remove(ctx context.Context, obj model.Obj) error {
|
func (d *Local) Remove(ctx context.Context, obj model.Obj) error {
|
||||||
var err error
|
var err error
|
||||||
if obj.IsDir() {
|
if obj.IsDir() {
|
||||||
err = os.RemoveAll(obj.GetID())
|
err = os.RemoveAll(obj.GetPath())
|
||||||
} else {
|
} else {
|
||||||
err = os.Remove(obj.GetID())
|
err = os.Remove(obj.GetPath())
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -200,7 +200,7 @@ func (d *Local) Remove(ctx context.Context, obj model.Obj) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *Local) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error {
|
func (d *Local) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error {
|
||||||
fullPath := filepath.Join(dstDir.GetID(), stream.GetName())
|
fullPath := filepath.Join(dstDir.GetPath(), stream.GetName())
|
||||||
out, err := os.Create(fullPath)
|
out, err := os.Create(fullPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/alist-org/alist/v3/internal/driver"
|
"github.com/alist-org/alist/v3/internal/driver"
|
||||||
"github.com/alist-org/alist/v3/internal/errs"
|
"github.com/alist-org/alist/v3/internal/errs"
|
||||||
"github.com/alist-org/alist/v3/internal/model"
|
"github.com/alist-org/alist/v3/internal/model"
|
||||||
|
"github.com/alist-org/alist/v3/internal/op"
|
||||||
"github.com/alist-org/alist/v3/pkg/utils"
|
"github.com/alist-org/alist/v3/pkg/utils"
|
||||||
"github.com/go-resty/resty/v2"
|
"github.com/go-resty/resty/v2"
|
||||||
)
|
)
|
||||||
@ -41,7 +42,7 @@ func (d *Onedrive) Drop(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *Onedrive) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
|
func (d *Onedrive) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
|
||||||
files, err := d.GetFiles(dir.GetID())
|
files, err := d.GetFiles(dir.GetPath())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -53,7 +54,7 @@ func (d *Onedrive) List(ctx context.Context, dir model.Obj, args model.ListArgs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *Onedrive) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
func (d *Onedrive) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||||
f, err := d.GetFile(file.GetID())
|
f, err := d.GetFile(file.GetPath())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -66,7 +67,7 @@ func (d *Onedrive) Link(ctx context.Context, file model.Obj, args model.LinkArgs
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *Onedrive) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error {
|
func (d *Onedrive) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error {
|
||||||
url := d.GetMetaUrl(false, parentDir.GetID()) + "/children"
|
url := d.GetMetaUrl(false, parentDir.GetPath()) + "/children"
|
||||||
data := base.Json{
|
data := base.Json{
|
||||||
"name": dirName,
|
"name": dirName,
|
||||||
"folder": base.Json{},
|
"folder": base.Json{},
|
||||||
@ -79,35 +80,31 @@ func (d *Onedrive) MakeDir(ctx context.Context, parentDir model.Obj, dirName str
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *Onedrive) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
|
func (d *Onedrive) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||||
dst, err := d.GetFile(dstDir.GetID())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
data := base.Json{
|
data := base.Json{
|
||||||
"parentReference": base.Json{
|
"parentReference": base.Json{
|
||||||
"id": dst.Id,
|
"id": dstDir.GetID(),
|
||||||
},
|
},
|
||||||
"name": srcObj.GetName(),
|
"name": srcObj.GetName(),
|
||||||
}
|
}
|
||||||
url := d.GetMetaUrl(false, srcObj.GetID())
|
url := d.GetMetaUrl(false, srcObj.GetPath())
|
||||||
_, err = d.Request(url, http.MethodPatch, func(req *resty.Request) {
|
_, err := d.Request(url, http.MethodPatch, func(req *resty.Request) {
|
||||||
req.SetBody(data)
|
req.SetBody(data)
|
||||||
}, nil)
|
}, nil)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Onedrive) Rename(ctx context.Context, srcObj model.Obj, newName string) error {
|
func (d *Onedrive) Rename(ctx context.Context, srcObj model.Obj, newName string) error {
|
||||||
dstDir, err := d.GetFile(stdpath.Dir(srcObj.GetID()))
|
dstDir, err := op.Get(ctx, d, stdpath.Dir(srcObj.GetPath()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
data := base.Json{
|
data := base.Json{
|
||||||
"parentReference": base.Json{
|
"parentReference": base.Json{
|
||||||
"id": dstDir.Id,
|
"id": dstDir.GetID(),
|
||||||
},
|
},
|
||||||
"name": newName,
|
"name": newName,
|
||||||
}
|
}
|
||||||
url := d.GetMetaUrl(false, srcObj.GetID())
|
url := d.GetMetaUrl(false, srcObj.GetPath())
|
||||||
_, err = d.Request(url, http.MethodPatch, func(req *resty.Request) {
|
_, err = d.Request(url, http.MethodPatch, func(req *resty.Request) {
|
||||||
req.SetBody(data)
|
req.SetBody(data)
|
||||||
}, nil)
|
}, nil)
|
||||||
@ -115,7 +112,7 @@ func (d *Onedrive) Rename(ctx context.Context, srcObj model.Obj, newName string)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *Onedrive) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
|
func (d *Onedrive) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||||
dst, err := d.GetFile(dstDir.GetID())
|
dst, err := d.GetFile(dstDir.GetPath())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -126,7 +123,7 @@ func (d *Onedrive) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
|
|||||||
},
|
},
|
||||||
"name": srcObj.GetName(),
|
"name": srcObj.GetName(),
|
||||||
}
|
}
|
||||||
url := d.GetMetaUrl(false, srcObj.GetID()) + "/copy"
|
url := d.GetMetaUrl(false, srcObj.GetPath()) + "/copy"
|
||||||
_, err = d.Request(url, http.MethodPost, func(req *resty.Request) {
|
_, err = d.Request(url, http.MethodPost, func(req *resty.Request) {
|
||||||
req.SetBody(data)
|
req.SetBody(data)
|
||||||
}, nil)
|
}, nil)
|
||||||
@ -134,7 +131,7 @@ func (d *Onedrive) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *Onedrive) Remove(ctx context.Context, obj model.Obj) error {
|
func (d *Onedrive) Remove(ctx context.Context, obj model.Obj) error {
|
||||||
url := d.GetMetaUrl(false, obj.GetID())
|
url := d.GetMetaUrl(false, obj.GetPath())
|
||||||
_, err := d.Request(url, http.MethodDelete, nil, nil)
|
_, err := d.Request(url, http.MethodDelete, nil, nil)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ type Addition struct {
|
|||||||
driver.RootFolderPath
|
driver.RootFolderPath
|
||||||
Region string `json:"region" type:"select" required:"true" options:"global,cn,us,de"`
|
Region string `json:"region" type:"select" required:"true" options:"global,cn,us,de"`
|
||||||
IsSharepoint bool `json:"is_sharepoint"`
|
IsSharepoint bool `json:"is_sharepoint"`
|
||||||
ClientId string `json:"client_id" required:"true"`
|
ClientID string `json:"client_id" required:"true"`
|
||||||
ClientSecret string `json:"client_secret" required:"true"`
|
ClientSecret string `json:"client_secret" required:"true"`
|
||||||
RedirectUri string `json:"redirect_uri" required:"true" default:"https://tool.nn.ci/onedrive/callback"`
|
RedirectUri string `json:"redirect_uri" required:"true" default:"https://tool.nn.ci/onedrive/callback"`
|
||||||
RefreshToken string `json:"refresh_token" required:"true"`
|
RefreshToken string `json:"refresh_token" required:"true"`
|
||||||
|
@ -49,7 +49,7 @@ func fileToObj(f File) *model.ObjThumbURL {
|
|||||||
}
|
}
|
||||||
return &model.ObjThumbURL{
|
return &model.ObjThumbURL{
|
||||||
Object: model.Object{
|
Object: model.Object{
|
||||||
//ID: f.Id,
|
ID: f.Id,
|
||||||
Name: f.Name,
|
Name: f.Name,
|
||||||
Size: f.Size,
|
Size: f.Size,
|
||||||
Modified: f.LastModifiedDateTime,
|
Modified: f.LastModifiedDateTime,
|
||||||
|
@ -77,7 +77,7 @@ func (d *Onedrive) _refreshToken() error {
|
|||||||
var e TokenErr
|
var e TokenErr
|
||||||
_, err := base.RestyClient.R().SetResult(&resp).SetError(&e).SetFormData(map[string]string{
|
_, err := base.RestyClient.R().SetResult(&resp).SetError(&e).SetFormData(map[string]string{
|
||||||
"grant_type": "refresh_token",
|
"grant_type": "refresh_token",
|
||||||
"client_id": d.ClientId,
|
"client_id": d.ClientID,
|
||||||
"client_secret": d.ClientSecret,
|
"client_secret": d.ClientSecret,
|
||||||
"redirect_uri": d.RedirectUri,
|
"redirect_uri": d.RedirectUri,
|
||||||
"refresh_token": d.RefreshToken,
|
"refresh_token": d.RefreshToken,
|
||||||
@ -96,7 +96,7 @@ func (d *Onedrive) _refreshToken() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Onedrive) Request(url string, method string, callback func(*resty.Request), resp interface{}) ([]byte, error) {
|
func (d *Onedrive) Request(url string, method string, callback base.ReqCallback, resp interface{}) ([]byte, error) {
|
||||||
req := base.RestyClient.R()
|
req := base.RestyClient.R()
|
||||||
req.SetHeader("Authorization", "Bearer "+d.AccessToken)
|
req.SetHeader("Authorization", "Bearer "+d.AccessToken)
|
||||||
if callback != nil {
|
if callback != nil {
|
||||||
@ -147,7 +147,7 @@ func (d *Onedrive) GetFile(path string) (*File, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *Onedrive) upSmall(dstDir model.Obj, stream model.FileStreamer) error {
|
func (d *Onedrive) upSmall(dstDir model.Obj, stream model.FileStreamer) error {
|
||||||
url := d.GetMetaUrl(false, stdpath.Join(dstDir.GetID(), stream.GetName())) + "/content"
|
url := d.GetMetaUrl(false, stdpath.Join(dstDir.GetPath(), stream.GetName())) + "/content"
|
||||||
data, err := io.ReadAll(stream)
|
data, err := io.ReadAll(stream)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -159,7 +159,7 @@ func (d *Onedrive) upSmall(dstDir model.Obj, stream model.FileStreamer) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *Onedrive) upBig(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error {
|
func (d *Onedrive) upBig(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error {
|
||||||
url := d.GetMetaUrl(false, stdpath.Join(dstDir.GetID(), stream.GetName())) + "/createUploadSession"
|
url := d.GetMetaUrl(false, stdpath.Join(dstDir.GetPath(), stream.GetName())) + "/createUploadSession"
|
||||||
res, err := d.Request(url, http.MethodPost, nil, nil)
|
res, err := d.Request(url, http.MethodPost, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -66,7 +66,7 @@ func (d *PikPak) refreshToken() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *PikPak) request(url string, method string, callback func(*resty.Request), resp interface{}) ([]byte, error) {
|
func (d *PikPak) request(url string, method string, callback base.ReqCallback, resp interface{}) ([]byte, error) {
|
||||||
req := base.RestyClient.R()
|
req := base.RestyClient.R()
|
||||||
req.SetHeader("Authorization", "Bearer "+d.AccessToken)
|
req.SetHeader("Authorization", "Bearer "+d.AccessToken)
|
||||||
if callback != nil {
|
if callback != nil {
|
||||||
|
@ -21,7 +21,7 @@ import (
|
|||||||
|
|
||||||
// do others that not defined in Driver interface
|
// do others that not defined in Driver interface
|
||||||
|
|
||||||
func (d *Quark) request(pathname string, method string, callback func(req *resty.Request), resp interface{}) ([]byte, error) {
|
func (d *Quark) request(pathname string, method string, callback base.ReqCallback, resp interface{}) ([]byte, error) {
|
||||||
u := "https://drive.quark.cn/1/clouddrive" + pathname
|
u := "https://drive.quark.cn/1/clouddrive" + pathname
|
||||||
req := base.RestyClient.R()
|
req := base.RestyClient.R()
|
||||||
req.SetHeaders(map[string]string{
|
req.SetHeaders(map[string]string{
|
||||||
|
@ -22,7 +22,7 @@ func (d *Teambition) isInternational() bool {
|
|||||||
return d.Region == "international"
|
return d.Region == "international"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Teambition) request(pathname string, method string, callback func(req *resty.Request), resp interface{}) ([]byte, error) {
|
func (d *Teambition) request(pathname string, method string, callback base.ReqCallback, resp interface{}) ([]byte, error) {
|
||||||
url := "https://www.teambition.com" + pathname
|
url := "https://www.teambition.com" + pathname
|
||||||
if d.isInternational() {
|
if d.isInternational() {
|
||||||
url = "https://us.teambition.com" + pathname
|
url = "https://us.teambition.com" + pathname
|
||||||
|
@ -13,6 +13,7 @@ type Obj interface {
|
|||||||
ModTime() time.Time
|
ModTime() time.Time
|
||||||
IsDir() bool
|
IsDir() bool
|
||||||
GetID() string
|
GetID() string
|
||||||
|
GetPath() string
|
||||||
}
|
}
|
||||||
|
|
||||||
type FileStreamer interface {
|
type FileStreamer interface {
|
||||||
@ -32,8 +33,8 @@ type Thumb interface {
|
|||||||
Thumb() string
|
Thumb() string
|
||||||
}
|
}
|
||||||
|
|
||||||
type SetID interface {
|
type SetPath interface {
|
||||||
SetID(id string)
|
SetPath(path string)
|
||||||
}
|
}
|
||||||
|
|
||||||
func SortFiles(objs []Obj, orderBy, orderDirection string) {
|
func SortFiles(objs []Obj, orderBy, orderDirection string) {
|
||||||
|
@ -4,6 +4,7 @@ import "time"
|
|||||||
|
|
||||||
type Object struct {
|
type Object struct {
|
||||||
ID string
|
ID string
|
||||||
|
Path string
|
||||||
Name string
|
Name string
|
||||||
Size int64
|
Size int64
|
||||||
Modified time.Time
|
Modified time.Time
|
||||||
@ -30,8 +31,12 @@ func (o *Object) GetID() string {
|
|||||||
return o.ID
|
return o.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Object) SetID(id string) {
|
func (o *Object) GetPath() string {
|
||||||
o.ID = id
|
return o.Path
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Object) SetPath(id string) {
|
||||||
|
o.Path = id
|
||||||
}
|
}
|
||||||
|
|
||||||
type Thumbnail struct {
|
type Thumbnail struct {
|
||||||
|
@ -35,6 +35,7 @@ func List(ctx context.Context, storage driver.Driver, path string, args model.Li
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.WithMessage(err, "failed get dir")
|
return nil, errors.WithMessage(err, "failed get dir")
|
||||||
}
|
}
|
||||||
|
log.Debugf("list dir: %+v", dir)
|
||||||
if !dir.IsDir() {
|
if !dir.IsDir() {
|
||||||
return nil, errors.WithStack(errs.NotFolder)
|
return nil, errors.WithStack(errs.NotFolder)
|
||||||
}
|
}
|
||||||
@ -94,7 +95,7 @@ func Get(ctx context.Context, storage driver.Driver, path string) (model.Obj, er
|
|||||||
}
|
}
|
||||||
if r, ok := storage.GetAddition().(driver.IRootFolderPath); ok && isRoot(path, r.GetRootFolderPath()) {
|
if r, ok := storage.GetAddition().(driver.IRootFolderPath); ok && isRoot(path, r.GetRootFolderPath()) {
|
||||||
return &model.Object{
|
return &model.Object{
|
||||||
ID: r.GetRootFolderPath(),
|
Path: r.GetRootFolderPath(),
|
||||||
Name: "root",
|
Name: "root",
|
||||||
Size: 0,
|
Size: 0,
|
||||||
Modified: storage.GetStorage().Modified,
|
Modified: storage.GetStorage().Modified,
|
||||||
@ -108,12 +109,13 @@ func Get(ctx context.Context, storage driver.Driver, path string) (model.Obj, er
|
|||||||
return nil, errors.WithMessage(err, "failed get parent list")
|
return nil, errors.WithMessage(err, "failed get parent list")
|
||||||
}
|
}
|
||||||
for _, f := range files {
|
for _, f := range files {
|
||||||
|
// TODO maybe copy obj here
|
||||||
if f.GetName() == name {
|
if f.GetName() == name {
|
||||||
// use path as id, why don't set id in List function?
|
// use path as id, why don't set id in List function?
|
||||||
// because files maybe cache, set id here can reduce memory usage
|
// because files maybe cache, set id here can reduce memory usage
|
||||||
if f.GetID() == "" {
|
if f.GetPath() == "" {
|
||||||
if s, ok := f.(model.SetID); ok {
|
if s, ok := f.(model.SetPath); ok {
|
||||||
s.SetID(path)
|
s.SetPath(path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return f, nil
|
return f, nil
|
||||||
|
Loading…
x
Reference in New Issue
Block a user