alist/drivers/seafile/driver.go

227 lines
5.6 KiB
Go

package seafile
import (
"context"
"fmt"
"net/http"
"strings"
"time"
"github.com/alist-org/alist/v3/internal/driver"
"github.com/alist-org/alist/v3/internal/model"
"github.com/alist-org/alist/v3/pkg/utils"
"github.com/go-resty/resty/v2"
)
type Seafile struct {
model.Storage
Addition
authorization string
libraryMap map[string]*LibraryInfo
}
func (d *Seafile) Config() driver.Config {
return config
}
func (d *Seafile) GetAddition() driver.Additional {
return &d.Addition
}
func (d *Seafile) Init(ctx context.Context) error {
d.Address = strings.TrimSuffix(d.Address, "/")
d.RootFolderPath = utils.FixAndCleanPath(d.RootFolderPath)
d.libraryMap = make(map[string]*LibraryInfo)
return d.getToken()
}
func (d *Seafile) Drop(ctx context.Context) error {
return nil
}
func (d *Seafile) List(ctx context.Context, dir model.Obj, args model.ListArgs) (result []model.Obj, err error) {
path := dir.GetPath()
if path == d.RootFolderPath {
libraries, err := d.listLibraries()
if err != nil {
return nil, err
}
if path == "/" && d.RepoId == "" {
return utils.SliceConvert(libraries, func(f LibraryItemResp) (model.Obj, error) {
return &model.Object{
Name: f.Name,
Modified: time.Unix(f.Modified, 0),
Size: f.Size,
IsFolder: true,
}, nil
})
}
}
var repo *LibraryInfo
repo, path, err = d.getRepoAndPath(path)
if err != nil {
return nil, err
}
if repo.Encrypted {
err = d.decryptLibrary(repo)
if err != nil {
return nil, err
}
}
var resp []RepoDirItemResp
_, err = d.request(http.MethodGet, fmt.Sprintf("/api2/repos/%s/dir/", repo.Id), func(req *resty.Request) {
req.SetResult(&resp).SetQueryParams(map[string]string{
"p": path,
})
})
if err != nil {
return nil, err
}
return utils.SliceConvert(resp, func(f RepoDirItemResp) (model.Obj, error) {
return &model.ObjThumb{
Object: model.Object{
Name: f.Name,
Modified: time.Unix(f.Modified, 0),
Size: f.Size,
IsFolder: f.Type == "dir",
},
// Thumbnail: model.Thumbnail{Thumbnail: f.Thumb},
}, nil
})
}
func (d *Seafile) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
repo, path, err := d.getRepoAndPath(file.GetPath())
if err != nil {
return nil, err
}
res, err := d.request(http.MethodGet, fmt.Sprintf("/api2/repos/%s/file/", repo.Id), func(req *resty.Request) {
req.SetQueryParams(map[string]string{
"p": path,
"reuse": "1",
})
})
if err != nil {
return nil, err
}
u := string(res)
u = u[1 : len(u)-1] // remove quotes
return &model.Link{URL: u}, nil
}
func (d *Seafile) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error {
repo, path, err := d.getRepoAndPath(parentDir.GetPath())
if err != nil {
return err
}
path, _ = utils.JoinBasePath(path, dirName)
_, err = d.request(http.MethodPost, fmt.Sprintf("/api2/repos/%s/dir/", repo.Id), func(req *resty.Request) {
req.SetQueryParams(map[string]string{
"p": path,
}).SetFormData(map[string]string{
"operation": "mkdir",
})
})
return err
}
func (d *Seafile) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
repo, path, err := d.getRepoAndPath(srcObj.GetPath())
if err != nil {
return err
}
dstRepo, dstPath, err := d.getRepoAndPath(dstDir.GetPath())
if err != nil {
return err
}
_, err = d.request(http.MethodPost, fmt.Sprintf("/api2/repos/%s/file/", repo.Id), func(req *resty.Request) {
req.SetQueryParams(map[string]string{
"p": path,
}).SetFormData(map[string]string{
"operation": "move",
"dst_repo": dstRepo.Id,
"dst_dir": dstPath,
})
}, true)
return err
}
func (d *Seafile) Rename(ctx context.Context, srcObj model.Obj, newName string) error {
repo, path, err := d.getRepoAndPath(srcObj.GetPath())
if err != nil {
return err
}
_, err = d.request(http.MethodPost, fmt.Sprintf("/api2/repos/%s/file/", repo.Id), func(req *resty.Request) {
req.SetQueryParams(map[string]string{
"p": path,
}).SetFormData(map[string]string{
"operation": "rename",
"newname": newName,
})
}, true)
return err
}
func (d *Seafile) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
repo, path, err := d.getRepoAndPath(srcObj.GetPath())
if err != nil {
return err
}
dstRepo, dstPath, err := d.getRepoAndPath(dstDir.GetPath())
if err != nil {
return err
}
_, err = d.request(http.MethodPost, fmt.Sprintf("/api2/repos/%s/file/", repo.Id), func(req *resty.Request) {
req.SetQueryParams(map[string]string{
"p": path,
}).SetFormData(map[string]string{
"operation": "copy",
"dst_repo": dstRepo.Id,
"dst_dir": dstPath,
})
})
return err
}
func (d *Seafile) Remove(ctx context.Context, obj model.Obj) error {
repo, path, err := d.getRepoAndPath(obj.GetPath())
if err != nil {
return err
}
_, err = d.request(http.MethodDelete, fmt.Sprintf("/api2/repos/%s/file/", repo.Id), func(req *resty.Request) {
req.SetQueryParams(map[string]string{
"p": path,
})
})
return err
}
func (d *Seafile) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error {
repo, path, err := d.getRepoAndPath(dstDir.GetPath())
if err != nil {
return err
}
res, err := d.request(http.MethodGet, fmt.Sprintf("/api2/repos/%s/upload-link/", repo.Id), func(req *resty.Request) {
req.SetQueryParams(map[string]string{
"p": path,
})
})
if err != nil {
return err
}
u := string(res)
u = u[1 : len(u)-1] // remove quotes
_, err = d.request(http.MethodPost, u, func(req *resty.Request) {
req.SetFileReader("file", stream.GetName(), stream).
SetFormData(map[string]string{
"parent_dir": path,
"replace": "1",
})
})
return err
}
var _ driver.Driver = (*Seafile)(nil)