mirror of https://github.com/Xhofe/alist
🎇 teambition support
parent
ef5cad1bf0
commit
6ff2cdab98
|
@ -204,12 +204,13 @@ func InitSettings() {
|
||||||
Group: model.BACK,
|
Group: model.BACK,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: "load type",
|
Key: "load type",
|
||||||
Value: "all",
|
Value: "all",
|
||||||
Type: "select",
|
Type: "select",
|
||||||
Values: "all,load more,auto load more,pagination",
|
Values: "all,load more,auto load more,pagination",
|
||||||
Access: model.PUBLIC,
|
Description: "Not recommended to choose to auto load more, it has bugs now",
|
||||||
Group: model.FRONT,
|
Access: model.PUBLIC,
|
||||||
|
Group: model.FRONT,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: "default page size",
|
Key: "default page size",
|
||||||
|
|
|
@ -14,6 +14,7 @@ import (
|
||||||
_ "github.com/Xhofe/alist/drivers/pikpak"
|
_ "github.com/Xhofe/alist/drivers/pikpak"
|
||||||
_ "github.com/Xhofe/alist/drivers/s3"
|
_ "github.com/Xhofe/alist/drivers/s3"
|
||||||
_ "github.com/Xhofe/alist/drivers/shandian"
|
_ "github.com/Xhofe/alist/drivers/shandian"
|
||||||
|
_ "github.com/Xhofe/alist/drivers/teambition"
|
||||||
_ "github.com/Xhofe/alist/drivers/webdav"
|
_ "github.com/Xhofe/alist/drivers/webdav"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
|
@ -0,0 +1,252 @@
|
||||||
|
package teambition
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/Xhofe/alist/conf"
|
||||||
|
"github.com/Xhofe/alist/drivers/base"
|
||||||
|
"github.com/Xhofe/alist/model"
|
||||||
|
"github.com/Xhofe/alist/utils"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Teambition struct{}
|
||||||
|
|
||||||
|
func (driver Teambition) Config() base.DriverConfig {
|
||||||
|
return base.DriverConfig{
|
||||||
|
Name: "Teambition",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (driver Teambition) Items() []base.Item {
|
||||||
|
return []base.Item{
|
||||||
|
{
|
||||||
|
Name: "internal_type",
|
||||||
|
Label: "Teambition type",
|
||||||
|
Type: base.TypeSelect,
|
||||||
|
Required: true,
|
||||||
|
Values: "China,International",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "access_token",
|
||||||
|
Label: "Cookie",
|
||||||
|
Type: base.TypeString,
|
||||||
|
Description: "Unknown expiration time",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "zone",
|
||||||
|
Label: "Project id",
|
||||||
|
Type: base.TypeString,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "root_folder",
|
||||||
|
Label: "root folder file_id",
|
||||||
|
Type: base.TypeString,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "order_by",
|
||||||
|
Label: "order_by",
|
||||||
|
Type: base.TypeSelect,
|
||||||
|
Values: "fileName,fileSize,updated,created",
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "order_direction",
|
||||||
|
Label: "order_direction",
|
||||||
|
Type: base.TypeSelect,
|
||||||
|
Values: "Asc,Desc",
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (driver Teambition) Save(account *model.Account, old *model.Account) error {
|
||||||
|
_, err := driver.Request("/api/v2/roles", base.Get, nil, nil, nil, nil, nil, account)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (driver Teambition) File(path string, account *model.Account) (*model.File, error) {
|
||||||
|
path = utils.ParsePath(path)
|
||||||
|
if path == "/" {
|
||||||
|
return &model.File{
|
||||||
|
Id: account.RootFolder,
|
||||||
|
Name: account.Name,
|
||||||
|
Size: 0,
|
||||||
|
Type: conf.FOLDER,
|
||||||
|
Driver: driver.Config().Name,
|
||||||
|
UpdatedAt: account.UpdatedAt,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
dir, name := filepath.Split(path)
|
||||||
|
files, err := driver.Files(dir, account)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, file := range files {
|
||||||
|
if file.Name == name {
|
||||||
|
return &file, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, base.ErrPathNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
func (driver Teambition) Files(path string, account *model.Account) ([]model.File, error) {
|
||||||
|
path = utils.ParsePath(path)
|
||||||
|
var files []model.File
|
||||||
|
cache, err := base.GetCache(path, account)
|
||||||
|
if err == nil {
|
||||||
|
files, _ = cache.([]model.File)
|
||||||
|
} else {
|
||||||
|
file, err := driver.File(path, account)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
files, err = driver.GetFiles(file.Id, account)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(files) > 0 {
|
||||||
|
_ = base.SetCache(path, files, account)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return files, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (driver Teambition) Link(args base.Args, account *model.Account) (*base.Link, error) {
|
||||||
|
path := args.Path
|
||||||
|
file, err := driver.File(path, account)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
url := file.Url
|
||||||
|
res, err := base.NoRedirectClient.R().Get(url)
|
||||||
|
if res.StatusCode() == 302 {
|
||||||
|
url = res.Header().Get("location")
|
||||||
|
}
|
||||||
|
return &base.Link{Url: url}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (driver Teambition) Path(path string, account *model.Account) (*model.File, []model.File, error) {
|
||||||
|
path = utils.ParsePath(path)
|
||||||
|
log.Debugf("teambition path: %s", path)
|
||||||
|
file, err := driver.File(path, account)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if !file.IsDir() {
|
||||||
|
return file, nil, nil
|
||||||
|
}
|
||||||
|
files, err := driver.Files(path, account)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
return nil, files, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (driver Teambition) Proxy(c *gin.Context, account *model.Account) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (driver Teambition) Preview(path string, account *model.Account) (interface{}, error) {
|
||||||
|
return nil, base.ErrNotSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
func (driver Teambition) MakeDir(path string, account *model.Account) error {
|
||||||
|
parentFile, err := driver.File(utils.Dir(path), account)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
data := base.Json{
|
||||||
|
"objectType": "collection",
|
||||||
|
"_projectId": account.Zone,
|
||||||
|
"_creatorId": "",
|
||||||
|
"created": "",
|
||||||
|
"updated": "",
|
||||||
|
"title": utils.Base(path),
|
||||||
|
"color": "blue",
|
||||||
|
"description": "",
|
||||||
|
"workCount": 0,
|
||||||
|
"collectionType": "",
|
||||||
|
"recentWorks": []interface{}{},
|
||||||
|
"_parentId": parentFile.Id,
|
||||||
|
"subCount": nil,
|
||||||
|
}
|
||||||
|
_, err = driver.Request("/api/collections", base.Post, nil, nil, nil, &data, nil, account)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (driver Teambition) Move(src string, dst string, account *model.Account) error {
|
||||||
|
srcFile, err := driver.File(src, account)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
dstParentFile, err := driver.File(utils.Dir(dst), account)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
pre := "/api/works/"
|
||||||
|
if srcFile.IsDir() {
|
||||||
|
pre = "/api/collections/"
|
||||||
|
}
|
||||||
|
_, err = driver.Request(pre+srcFile.Id+"/move", base.Put, nil, nil, nil, &base.Json{
|
||||||
|
"_parentId": dstParentFile.Id,
|
||||||
|
}, nil, account)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (driver Teambition) Rename(src string, dst string, account *model.Account) error {
|
||||||
|
srcFile, err := driver.File(src, account)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
pre := "/api/works/"
|
||||||
|
data := base.Json{
|
||||||
|
"fileName": utils.Base(dst),
|
||||||
|
}
|
||||||
|
if srcFile.IsDir() {
|
||||||
|
pre = "/api/collections/"
|
||||||
|
data = base.Json{
|
||||||
|
"title": utils.Base(dst),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, err = driver.Request(pre+srcFile.Id, base.Put, nil, nil, nil, &data, nil, account)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (driver Teambition) Copy(src string, dst string, account *model.Account) error {
|
||||||
|
srcFile, err := driver.File(src, account)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
dstParentFile, err := driver.File(utils.Dir(dst), account)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
pre := "/api/works/"
|
||||||
|
if srcFile.IsDir() {
|
||||||
|
pre = "/api/collections/"
|
||||||
|
}
|
||||||
|
_, err = driver.Request(pre+srcFile.Id+"/fork", base.Put, nil, nil, nil, &base.Json{
|
||||||
|
"_parentId": dstParentFile.Id,
|
||||||
|
}, nil, account)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (driver Teambition) Delete(path string, account *model.Account) error {
|
||||||
|
srcFile, err := driver.File(path, account)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
pre := "/api/works/"
|
||||||
|
if srcFile.IsDir() {
|
||||||
|
pre = "/api/collections/"
|
||||||
|
}
|
||||||
|
_, err = driver.Request(pre+srcFile.Id+"/archive", base.Post, nil, nil, nil, nil, nil, account)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (driver Teambition) Upload(file *model.FileStream, account *model.Account) error {
|
||||||
|
return base.ErrNotImplement
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ base.Driver = (*Teambition)(nil)
|
|
@ -0,0 +1,153 @@
|
||||||
|
package teambition
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"github.com/Xhofe/alist/conf"
|
||||||
|
"github.com/Xhofe/alist/drivers/base"
|
||||||
|
"github.com/Xhofe/alist/model"
|
||||||
|
"github.com/Xhofe/alist/utils"
|
||||||
|
"github.com/go-resty/resty/v2"
|
||||||
|
"path"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ErrResp struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (driver Teambition) Request(pathname string, method int, headers, query, form map[string]string, data interface{}, resp interface{}, account *model.Account) ([]byte, error) {
|
||||||
|
url := "https://www.teambition.com" + pathname
|
||||||
|
if account.InternalType == "International" {
|
||||||
|
url = "https://us.teambition.com" + pathname
|
||||||
|
}
|
||||||
|
req := base.RestyClient.R()
|
||||||
|
req.SetHeader("Cookie", account.AccessToken)
|
||||||
|
if headers != nil {
|
||||||
|
req.SetHeaders(headers)
|
||||||
|
}
|
||||||
|
if query != nil {
|
||||||
|
req.SetQueryParams(query)
|
||||||
|
}
|
||||||
|
if form != nil {
|
||||||
|
req.SetFormData(form)
|
||||||
|
}
|
||||||
|
if data != nil {
|
||||||
|
req.SetBody(data)
|
||||||
|
}
|
||||||
|
if resp != nil {
|
||||||
|
req.SetResult(resp)
|
||||||
|
}
|
||||||
|
var e ErrResp
|
||||||
|
var err error
|
||||||
|
var res *resty.Response
|
||||||
|
req.SetError(&e)
|
||||||
|
switch method {
|
||||||
|
case base.Get:
|
||||||
|
res, err = req.Get(url)
|
||||||
|
case base.Post:
|
||||||
|
res, err = req.Post(url)
|
||||||
|
case base.Delete:
|
||||||
|
res, err = req.Delete(url)
|
||||||
|
case base.Patch:
|
||||||
|
res, err = req.Patch(url)
|
||||||
|
case base.Put:
|
||||||
|
res, err = req.Put(url)
|
||||||
|
default:
|
||||||
|
return nil, base.ErrNotSupport
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if e.Name != "" {
|
||||||
|
return nil, errors.New(e.Message)
|
||||||
|
}
|
||||||
|
return res.Body(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type Collection struct {
|
||||||
|
ID string `json:"_id"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Updated time.Time `json:"updated"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Work struct {
|
||||||
|
ID string `json:"_id"`
|
||||||
|
FileName string `json:"fileName"`
|
||||||
|
FileSize int64 `json:"fileSize"`
|
||||||
|
FileKey string `json:"fileKey"`
|
||||||
|
FileCategory string `json:"fileCategory"`
|
||||||
|
DownloadURL string `json:"downloadUrl"`
|
||||||
|
ThumbnailURL string `json:"thumbnailUrl"`
|
||||||
|
Thumbnail string `json:"thumbnail"`
|
||||||
|
Updated time.Time `json:"updated"`
|
||||||
|
PreviewURL string `json:"previewUrl"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (driver Teambition) GetFiles(parentId string, account *model.Account) ([]model.File, error) {
|
||||||
|
files := make([]model.File, 0)
|
||||||
|
page := 1
|
||||||
|
for {
|
||||||
|
var collections []Collection
|
||||||
|
_, err := driver.Request("/api/collections", base.Get, nil, map[string]string{
|
||||||
|
"_parentId": parentId,
|
||||||
|
"_projectId": account.Zone,
|
||||||
|
"order": account.OrderBy + account.OrderDirection,
|
||||||
|
"count": "50",
|
||||||
|
"page": strconv.Itoa(page),
|
||||||
|
}, nil, nil, &collections, account)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(collections) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
page++
|
||||||
|
for _, collection := range collections {
|
||||||
|
files = append(files, model.File{
|
||||||
|
Id: collection.ID,
|
||||||
|
Name: collection.Title,
|
||||||
|
Size: 0,
|
||||||
|
Type: conf.FOLDER,
|
||||||
|
Driver: driver.Config().Name,
|
||||||
|
UpdatedAt: &collection.Updated,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
page = 1
|
||||||
|
for {
|
||||||
|
var works []Work
|
||||||
|
_, err := driver.Request("/api/works", base.Get, nil, map[string]string{
|
||||||
|
"_parentId": parentId,
|
||||||
|
"_projectId": account.Zone,
|
||||||
|
"order": account.OrderBy + account.OrderDirection,
|
||||||
|
"count": "50",
|
||||||
|
"page": strconv.Itoa(page),
|
||||||
|
}, nil, nil, &works, account)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(works) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
page++
|
||||||
|
for _, work := range works {
|
||||||
|
files = append(files, model.File{
|
||||||
|
Id: work.ID,
|
||||||
|
Name: work.FileName,
|
||||||
|
Size: work.FileSize,
|
||||||
|
Type: utils.GetFileType(path.Ext(work.FileName)),
|
||||||
|
Driver: driver.Config().Name,
|
||||||
|
UpdatedAt: &work.Updated,
|
||||||
|
Thumbnail: work.Thumbnail,
|
||||||
|
Url: work.DownloadURL,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return files, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
base.RegisterDriver(&Teambition{})
|
||||||
|
}
|
Loading…
Reference in New Issue