mirror of https://github.com/Xhofe/alist
feat: add `upyun-uss` driver
parent
ffba5e0aec
commit
a4a8739748
|
@ -13,6 +13,7 @@ import (
|
||||||
_ "github.com/alist-org/alist/v3/drivers/s3"
|
_ "github.com/alist-org/alist/v3/drivers/s3"
|
||||||
_ "github.com/alist-org/alist/v3/drivers/sftp"
|
_ "github.com/alist-org/alist/v3/drivers/sftp"
|
||||||
_ "github.com/alist-org/alist/v3/drivers/teambition"
|
_ "github.com/alist-org/alist/v3/drivers/teambition"
|
||||||
|
_ "github.com/alist-org/alist/v3/drivers/uss"
|
||||||
_ "github.com/alist-org/alist/v3/drivers/virtual"
|
_ "github.com/alist-org/alist/v3/drivers/virtual"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -20,8 +20,9 @@ type Addition struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
var config = driver.Config{
|
var config = driver.Config{
|
||||||
Name: "S3",
|
Name: "S3",
|
||||||
LocalSort: true,
|
LocalSort: true,
|
||||||
|
CheckStatus: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
func New() driver.Driver {
|
func New() driver.Driver {
|
||||||
|
|
|
@ -0,0 +1,147 @@
|
||||||
|
package uss
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"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/upyun/go-sdk/v3/upyun"
|
||||||
|
)
|
||||||
|
|
||||||
|
type USS struct {
|
||||||
|
model.Storage
|
||||||
|
Addition
|
||||||
|
client *upyun.UpYun
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *USS) Config() driver.Config {
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *USS) GetAddition() driver.Additional {
|
||||||
|
return d.Addition
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *USS) 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
|
||||||
|
}
|
||||||
|
d.client = upyun.NewUpYun(&upyun.UpYunConfig{
|
||||||
|
Bucket: d.Bucket,
|
||||||
|
Operator: d.OperatorName,
|
||||||
|
Password: d.OperatorPassword,
|
||||||
|
})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *USS) Drop(ctx context.Context) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *USS) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
|
||||||
|
prefix := getKey(dir.GetPath(), true)
|
||||||
|
objsChan := make(chan *upyun.FileInfo, 10)
|
||||||
|
var err error
|
||||||
|
defer close(objsChan)
|
||||||
|
go func() {
|
||||||
|
err = d.client.List(&upyun.GetObjectsConfig{
|
||||||
|
Path: prefix,
|
||||||
|
ObjectsChan: objsChan,
|
||||||
|
MaxListObjects: 0,
|
||||||
|
MaxListLevel: 1,
|
||||||
|
})
|
||||||
|
}()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
res := make([]model.Obj, 0)
|
||||||
|
for obj := range objsChan {
|
||||||
|
t := obj.Time
|
||||||
|
f := model.Object{
|
||||||
|
Name: obj.Name,
|
||||||
|
Size: obj.Size,
|
||||||
|
Modified: t,
|
||||||
|
IsFolder: obj.IsDir,
|
||||||
|
}
|
||||||
|
res = append(res, &f)
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
//func (d *USS) Get(ctx context.Context, path string) (model.Obj, error) {
|
||||||
|
// // this is optional
|
||||||
|
// return nil, errs.NotImplement
|
||||||
|
//}
|
||||||
|
|
||||||
|
func (d *USS) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||||
|
key := getKey(file.GetPath(), false)
|
||||||
|
host := d.CustomHost
|
||||||
|
if host == "" {
|
||||||
|
host = d.Endpoint
|
||||||
|
}
|
||||||
|
if strings.Contains(host, "://") {
|
||||||
|
host = "https://" + host
|
||||||
|
}
|
||||||
|
u := fmt.Sprintf("%s/%s", host, key)
|
||||||
|
downExp := time.Hour * time.Duration(d.SignURLExpire)
|
||||||
|
expireAt := time.Now().Add(downExp).Unix()
|
||||||
|
upd := url.QueryEscape(path.Base(file.GetPath()))
|
||||||
|
signStr := strings.Join([]string{d.OperatorPassword, fmt.Sprint(expireAt), fmt.Sprintf("/%s", key)}, "&")
|
||||||
|
upt := utils.GetMD5Encode(signStr)[12:20] + fmt.Sprint(expireAt)
|
||||||
|
link := fmt.Sprintf("%s?_upd=%s&_upt=%s", u, upd, upt)
|
||||||
|
return &model.Link{URL: link}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *USS) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error {
|
||||||
|
return d.client.Mkdir(getKey(path.Join(parentDir.GetPath(), dirName), true))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *USS) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||||
|
return d.client.Move(&upyun.MoveObjectConfig{
|
||||||
|
SrcPath: getKey(srcObj.GetPath(), srcObj.IsDir()),
|
||||||
|
DestPath: getKey(path.Join(dstDir.GetPath(), srcObj.GetName()), srcObj.IsDir()),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *USS) Rename(ctx context.Context, srcObj model.Obj, newName string) error {
|
||||||
|
return d.client.Move(&upyun.MoveObjectConfig{
|
||||||
|
SrcPath: getKey(srcObj.GetPath(), srcObj.IsDir()),
|
||||||
|
DestPath: getKey(path.Join(path.Dir(srcObj.GetPath()), newName), srcObj.IsDir()),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *USS) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||||
|
return d.client.Copy(&upyun.CopyObjectConfig{
|
||||||
|
SrcPath: getKey(srcObj.GetPath(), srcObj.IsDir()),
|
||||||
|
DestPath: getKey(path.Join(dstDir.GetPath(), srcObj.GetName()), srcObj.IsDir()),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *USS) Remove(ctx context.Context, obj model.Obj) error {
|
||||||
|
return d.client.Delete(&upyun.DeleteObjectConfig{
|
||||||
|
Path: getKey(obj.GetPath(), obj.IsDir()),
|
||||||
|
Async: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *USS) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error {
|
||||||
|
return d.client.Put(&upyun.PutObjectConfig{
|
||||||
|
Path: getKey(path.Join(dstDir.GetPath(), stream.GetName()), false),
|
||||||
|
Reader: stream,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *USS) Other(ctx context.Context, args model.OtherArgs) (interface{}, error) {
|
||||||
|
return nil, errs.NotSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ driver.Driver = (*USS)(nil)
|
|
@ -0,0 +1,29 @@
|
||||||
|
package uss
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/alist-org/alist/v3/internal/driver"
|
||||||
|
"github.com/alist-org/alist/v3/internal/op"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Addition struct {
|
||||||
|
driver.RootFolderPath
|
||||||
|
Bucket string `json:"bucket" required:"true"`
|
||||||
|
Endpoint string `json:"endpoint" required:"true"`
|
||||||
|
OperatorName string `json:"operator_name" required:"true"`
|
||||||
|
OperatorPassword string `json:"operator_password" required:"true"`
|
||||||
|
CustomHost string `json:"custom_host"`
|
||||||
|
SignURLExpire int `json:"sign_url_expire" type:"number" default:"4"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var config = driver.Config{
|
||||||
|
Name: "USS",
|
||||||
|
LocalSort: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
func New() driver.Driver {
|
||||||
|
return &USS{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
op.RegisterDriver(config, New)
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
package uss
|
|
@ -0,0 +1,13 @@
|
||||||
|
package uss
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
|
// do others that not defined in Driver interface
|
||||||
|
|
||||||
|
func getKey(path string, dir bool) string {
|
||||||
|
path = strings.TrimPrefix(path, "/")
|
||||||
|
if dir {
|
||||||
|
path += "/"
|
||||||
|
}
|
||||||
|
return path
|
||||||
|
}
|
1
go.mod
1
go.mod
|
@ -59,6 +59,7 @@ require (
|
||||||
github.com/pkg/sftp v1.13.5 // indirect
|
github.com/pkg/sftp v1.13.5 // indirect
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
github.com/ugorji/go/codec v1.2.7 // indirect
|
github.com/ugorji/go/codec v1.2.7 // indirect
|
||||||
|
github.com/upyun/go-sdk/v3 v3.0.3 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 // indirect
|
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 // indirect
|
||||||
golang.org/x/image v0.0.0-20220722155232-062f8c9fd539 // indirect
|
golang.org/x/image v0.0.0-20220722155232-062f8c9fd539 // indirect
|
||||||
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b // indirect
|
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b // indirect
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -219,6 +219,8 @@ github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6
|
||||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||||
github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=
|
github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=
|
||||||
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
|
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
|
||||||
|
github.com/upyun/go-sdk/v3 v3.0.3 h1:2wUkNk2fyJReMYHMvJyav050D83rYwSjN7mEPR0Pp8Q=
|
||||||
|
github.com/upyun/go-sdk/v3 v3.0.3/go.mod h1:P/SnuuwhrIgAVRd/ZpzDWqCsBAf/oHg7UggbAxyZa0E=
|
||||||
github.com/winfsp/cgofuse v1.5.0 h1:MsBP7Mi/LiJf/7/F3O/7HjjR009ds6KCdqXzKpZSWxI=
|
github.com/winfsp/cgofuse v1.5.0 h1:MsBP7Mi/LiJf/7/F3O/7HjjR009ds6KCdqXzKpZSWxI=
|
||||||
github.com/winfsp/cgofuse v1.5.0/go.mod h1:h3awhoUOcn2VYVKCwDaYxSLlZwnyK+A8KaDoLUp2lbU=
|
github.com/winfsp/cgofuse v1.5.0/go.mod h1:h3awhoUOcn2VYVKCwDaYxSLlZwnyK+A8KaDoLUp2lbU=
|
||||||
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
|
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
|
||||||
|
|
Loading…
Reference in New Issue