Skip to content

Commit

Permalink
feat: add baidu_photo driver
Browse files Browse the repository at this point in the history
  • Loading branch information
foxxorcat committed Sep 12, 2022
1 parent 78e34f0 commit 6b5236f
Show file tree
Hide file tree
Showing 9 changed files with 994 additions and 2 deletions.
4 changes: 3 additions & 1 deletion drivers/189pc/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -533,7 +533,9 @@ func (y *Yun189PC) FastUpload(ctx context.Context, dstDir model.Obj, file model.
silceMd5Hexs = append(silceMd5Hexs, strings.ToUpper(hex.EncodeToString(md5Byte)))
silceMd5Base64s = append(silceMd5Base64s, fmt.Sprint(i, "-", base64.StdEncoding.EncodeToString(md5Byte)))
}
file.GetReadCloser().(*os.File).Seek(0, io.SeekStart)
if _, err = tempFile.Seek(0, io.SeekStart); err != nil {
return err
}

fileMd5Hex := strings.ToUpper(hex.EncodeToString(fileMd5.Sum(nil)))
sliceMd5Hex := fileMd5Hex
Expand Down
1 change: 1 addition & 0 deletions drivers/all.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
_ "github.com/alist-org/alist/v3/drivers/189pc"
_ "github.com/alist-org/alist/v3/drivers/aliyundrive"
_ "github.com/alist-org/alist/v3/drivers/baidu_netdisk"
_ "github.com/alist-org/alist/v3/drivers/baidu_photo"
_ "github.com/alist-org/alist/v3/drivers/ftp"
_ "github.com/alist-org/alist/v3/drivers/google_drive"
_ "github.com/alist-org/alist/v3/drivers/local"
Expand Down
277 changes: 277 additions & 0 deletions drivers/baidu_photo/driver.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,277 @@
package baiduphoto

import (
"context"
"crypto/md5"
"encoding/hex"
"fmt"
"io"
"math"
"os"
"regexp"

"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"
"github.com/go-resty/resty/v2"
)

type BaiduPhoto struct {
model.Storage
Addition

AccessToken string
}

func (d *BaiduPhoto) Config() driver.Config {
return config
}

func (d *BaiduPhoto) GetAddition() driver.Additional {
return d.Addition
}

func (d *BaiduPhoto) 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 *BaiduPhoto) Drop(ctx context.Context) error {
return nil
}

func (d *BaiduPhoto) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
var objs []model.Obj
var err error
if IsRoot(dir) {
var albums []Album
if d.ShowType != "root_only_file" {
albums, err = d.GetAllAlbum(ctx)
if err != nil {
return nil, err
}
}

var files []File
if d.ShowType != "root_only_album" {
files, err = d.GetAllFile(ctx)
if err != nil {
return nil, err
}
}

objs = make([]model.Obj, 0, len(files)+len(albums))
for i := 0; i < len(albums); i++ {
objs = append(objs, &albums[i])
}
for i := 0; i < len(files); i++ {
objs = append(objs, &files[i])
}
} else if IsAlbum(dir) || IsAlbumRoot(dir) {
var files []AlbumFile
files, err = d.GetAllAlbumFile(ctx, splitID(dir.GetID())[0], "")
if err != nil {
return nil, err
}
objs = make([]model.Obj, 0, len(files))
for i := 0; i < len(files); i++ {
objs = append(objs, &files[i])
}
}
return objs, nil
}

func (d *BaiduPhoto) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
if IsAlbumFile(file) {
return d.linkAlbum(ctx, file, args)
} else if IsFile(file) {
return d.linkFile(ctx, file, args)
}
return nil, errs.NotFile
}

func (d *BaiduPhoto) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error {
if IsRoot(parentDir) {
code := regexp.MustCompile(`(?i)join:([\S]*)`).FindStringSubmatch(dirName)
if len(code) > 1 {
return d.JoinAlbum(ctx, code[1])
}
return d.CreateAlbum(ctx, dirName)
}
return errs.NotSupport
}

func (d *BaiduPhoto) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
if IsFile(srcObj) {
if IsAlbum(dstDir) {
//rootfile -> album
e := splitID(dstDir.GetID())
return d.AddAlbumFile(ctx, e[0], e[1], srcObj.GetID())
}
} else if IsAlbumFile(srcObj) {
if IsRoot(dstDir) {
//albumfile -> root
e := splitID(srcObj.GetID())
_, err := d.CopyAlbumFile(ctx, e[1], e[2], e[3], srcObj.GetID())
return err
} else if IsAlbum(dstDir) {
// albumfile -> root -> album
e := splitID(srcObj.GetID())
file, err := d.CopyAlbumFile(ctx, e[1], e[2], e[3], srcObj.GetID())
if err != nil {
return err
}
e = splitID(dstDir.GetID())
return d.AddAlbumFile(ctx, e[0], e[1], fmt.Sprint(file.Fsid))
}
}
return errs.NotSupport
}

func (d *BaiduPhoto) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
// 仅支持相册之间移动
if IsAlbumFile(srcObj) && IsAlbum(dstDir) {
err := d.Copy(ctx, srcObj, dstDir)
if err != nil {
return err
}
e := splitID(srcObj.GetID())
return d.DeleteAlbumFile(ctx, e[1], e[2], srcObj.GetID())
}
return errs.NotSupport
}

func (d *BaiduPhoto) Rename(ctx context.Context, srcObj model.Obj, newName string) error {
// 仅支持相册改名
if IsAlbum(srcObj) {
e := splitID(srcObj.GetID())
return d.SetAlbumName(ctx, e[0], e[1], newName)
}
return errs.NotSupport
}

func (d *BaiduPhoto) Remove(ctx context.Context, obj model.Obj) error {
e := splitID(obj.GetID())
if IsFile(obj) {
return d.DeleteFile(ctx, e[0])
} else if IsAlbum(obj) {
return d.DeleteAlbum(ctx, e[0], e[1])
} else if IsAlbumFile(obj) {
return d.DeleteAlbumFile(ctx, e[1], e[2], obj.GetID())
}
return errs.NotSupport
}

func (d *BaiduPhoto) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error {
// 需要获取完整文件md5,必须支持 io.Seek
tempFile, err := utils.CreateTempFile(stream.GetReadCloser())
if err != nil {
return err
}
defer func() {
_ = tempFile.Close()
_ = os.Remove(tempFile.Name())
}()
stream.SetReadCloser(tempFile)

// 计算需要的数据
const DEFAULT = 1 << 22
const SliceSize = 1 << 18
count := int(math.Ceil(float64(stream.GetSize()) / float64(DEFAULT)))

sliceMD5List := make([]string, 0, count)
fileMd5 := md5.New()
sliceMd5 := md5.New()
sliceMd52 := md5.New()
slicemd52Write := utils.LimitWriter(sliceMd52, SliceSize)
for i := 1; i <= count; i++ {
select {
case <-ctx.Done():
return ctx.Err()
default:
}
_, err := io.CopyN(io.MultiWriter(fileMd5, sliceMd5, slicemd52Write), stream, DEFAULT)
if err != nil && err != io.EOF && err != io.ErrUnexpectedEOF {
return err
}
sliceMD5List = append(sliceMD5List, hex.EncodeToString(sliceMd5.Sum(nil)))
sliceMd5.Reset()
}
if _, err = tempFile.Seek(0, io.SeekStart); err != nil {
return err
}
content_md5 := hex.EncodeToString(fileMd5.Sum(nil))
slice_md5 := hex.EncodeToString(sliceMd52.Sum(nil))

// 开始执行上传
params := map[string]string{
"autoinit": "1",
"isdir": "0",
"rtype": "1",
"ctype": "11",
"path": stream.GetName(),
"size": fmt.Sprint(stream.GetSize()),
"slice-md5": slice_md5,
"content-md5": content_md5,
"block_list": MustString(utils.Json.MarshalToString(sliceMD5List)),
}

// 预上传
var precreateResp PrecreateResp
_, err = d.Post(FILE_API_URL_V1+"/precreate", func(r *resty.Request) {
r.SetContext(ctx)
r.SetFormData(params)
}, &precreateResp)
if err != nil {
return err
}

switch precreateResp.ReturnType {
case 1: // 上传文件
uploadParams := map[string]string{
"method": "upload",
"path": params["path"],
"uploadid": precreateResp.UploadID,
}

for i := 0; i < count; i++ {
uploadParams["partseq"] = fmt.Sprint(i)
_, err = d.Post("https://c3.pcs.baidu.com/rest/2.0/pcs/superfile2", func(r *resty.Request) {
r.SetContext(ctx)
r.SetQueryParams(uploadParams)
r.SetFileReader("file", stream.GetName(), io.LimitReader(tempFile, DEFAULT))
}, nil)
if err != nil {
return err
}
up(i * 100 / count)
}
fallthrough
case 2: // 创建文件
params["uploadid"] = precreateResp.UploadID
_, err = d.Post(FILE_API_URL_V1+"/create", func(r *resty.Request) {
r.SetContext(ctx)
r.SetFormData(params)
}, &precreateResp)
if err != nil {
return err
}
fallthrough
case 3: // 增加到相册
if IsAlbum(dstDir) || IsAlbumRoot(dstDir) {
e := splitID(dstDir.GetID())
err = d.AddAlbumFile(ctx, e[0], e[1], fmt.Sprint(precreateResp.Data.FsID))
if err != nil {
return err
}
}
}
return nil
}

var _ driver.Driver = (*BaiduPhoto)(nil)
Loading

0 comments on commit 6b5236f

Please sign in to comment.