mirror of https://github.com/Xhofe/alist
✨ teambition upload (<= 20 MB)
parent
2a9598f4c6
commit
df513b7dc0
|
@ -19,6 +19,7 @@ func InitAccounts() {
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Errorf("no [%s] driver", account.Type)
|
log.Errorf("no [%s] driver", account.Type)
|
||||||
} else {
|
} else {
|
||||||
|
log.Infof("start init account: [%s], type: [%s]", account.Name, account.Type)
|
||||||
err := driver.Save(&accounts[i], nil)
|
err := driver.Save(&accounts[i], nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("init account [%s] error:[%s]", account.Name, err.Error())
|
log.Errorf("init account [%s] error:[%s]", account.Name, err.Error())
|
||||||
|
@ -27,4 +28,4 @@ func InitAccounts() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -252,7 +252,34 @@ func (driver Teambition) Delete(path string, account *model.Account) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (driver Teambition) Upload(file *model.FileStream, account *model.Account) error {
|
func (driver Teambition) Upload(file *model.FileStream, account *model.Account) error {
|
||||||
return base.ErrNotImplement
|
if file == nil {
|
||||||
|
return base.ErrEmptyFile
|
||||||
|
}
|
||||||
|
parentFile, err := driver.File(file.ParentPath, account)
|
||||||
|
if !parentFile.IsDir() {
|
||||||
|
return base.ErrNotFolder
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
res, err := driver.Request("/projects", base.Get, nil, nil, nil, nil, nil, account)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
token := GetBetweenStr(string(res), "strikerAuth":"", "","phoneForLogin")
|
||||||
|
var newFile *FileUpload
|
||||||
|
if file.Size <= 20971520 {
|
||||||
|
// post upload
|
||||||
|
newFile, err = driver.upload(file, token, account)
|
||||||
|
} else {
|
||||||
|
// chunk upload
|
||||||
|
err = base.ErrNotImplement
|
||||||
|
//newFile, err = driver.chunkUpload(file, token, account)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return driver.finishUpload(newFile, parentFile.Id, account)
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ base.Driver = (*Teambition)(nil)
|
var _ base.Driver = (*Teambition)(nil)
|
||||||
|
|
|
@ -2,11 +2,14 @@ package teambition
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"github.com/Xhofe/alist/conf"
|
"github.com/Xhofe/alist/conf"
|
||||||
"github.com/Xhofe/alist/drivers/base"
|
"github.com/Xhofe/alist/drivers/base"
|
||||||
"github.com/Xhofe/alist/model"
|
"github.com/Xhofe/alist/model"
|
||||||
"github.com/Xhofe/alist/utils"
|
"github.com/Xhofe/alist/utils"
|
||||||
"github.com/go-resty/resty/v2"
|
"github.com/go-resty/resty/v2"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"io"
|
||||||
"path"
|
"path"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
@ -66,25 +69,6 @@ func (driver Teambition) Request(pathname string, method int, headers, query, fo
|
||||||
return res.Body(), nil
|
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) {
|
func (driver Teambition) GetFiles(parentId string, account *model.Account) ([]model.File, error) {
|
||||||
files := make([]model.File, 0)
|
files := make([]model.File, 0)
|
||||||
page := 1
|
page := 1
|
||||||
|
@ -151,6 +135,94 @@ func (driver Teambition) GetFiles(parentId string, account *model.Account) ([]mo
|
||||||
return files, nil
|
return files, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (driver Teambition) upload(file *model.FileStream, token string, account *model.Account) (*FileUpload, error) {
|
||||||
|
prefix := "tcs"
|
||||||
|
if account.InternalType == "International" {
|
||||||
|
prefix = "us-tcs"
|
||||||
|
}
|
||||||
|
var newFile FileUpload
|
||||||
|
_, err := base.RestyClient.R().SetResult(&newFile).SetHeader("Authorization", token).
|
||||||
|
SetMultipartFormData(map[string]string{
|
||||||
|
"name": file.GetFileName(),
|
||||||
|
"type": file.GetMIMEType(),
|
||||||
|
"size": strconv.FormatUint(file.GetSize(), 10),
|
||||||
|
//"lastModifiedDate": "",
|
||||||
|
}).SetMultipartField("file", file.GetFileName(), file.GetMIMEType(), file).
|
||||||
|
Post(fmt.Sprintf("https://%s.teambition.net/upload", prefix))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &newFile, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (driver Teambition) chunkUpload(file *model.FileStream, token string, account *model.Account) (*FileUpload, error) {
|
||||||
|
prefix := "tcs"
|
||||||
|
if account.InternalType == "International" {
|
||||||
|
prefix = "us-tcs"
|
||||||
|
}
|
||||||
|
var newChunk ChunkUpload
|
||||||
|
_, err := base.RestyClient.R().SetResult(&newChunk).SetHeader("Authorization", token).
|
||||||
|
SetBody(base.Json{
|
||||||
|
"fileName": file.GetFileName(),
|
||||||
|
"fileSize": file.GetSize(),
|
||||||
|
"lastUpdated": time.Now(),
|
||||||
|
}).Post(fmt.Sprintf("https://%s.teambition.net/upload/chunk", prefix))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for i := 0; i < newChunk.Chunks; i++ {
|
||||||
|
chunkSize := newChunk.ChunkSize
|
||||||
|
if i == newChunk.Chunks-1 {
|
||||||
|
chunkSize = int(file.GetSize()) - i*chunkSize
|
||||||
|
}
|
||||||
|
log.Debugf("%d : %d", i, chunkSize)
|
||||||
|
chunkData := make([]byte, chunkSize)
|
||||||
|
_, err = io.ReadFull(file, chunkData)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
u := fmt.Sprintf("https://%s.teambition.net/upload/chunk/%s?chunk=%d&chunks=%d",
|
||||||
|
prefix, newChunk.FileKey, i+1, newChunk.Chunks)
|
||||||
|
log.Debugf("url: %s", u)
|
||||||
|
res, err := base.RestyClient.R().SetHeaders(map[string]string{
|
||||||
|
"Authorization": token,
|
||||||
|
"Content-Type": "application/octet-stream",
|
||||||
|
"Referer": "https://www.teambition.com/",
|
||||||
|
}).SetBody(chunkData).Post(u)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
log.Debug(res.Status(), res.String())
|
||||||
|
//req, err := http.NewRequest("POST",
|
||||||
|
// u,
|
||||||
|
// bytes.NewBuffer(chunkData))
|
||||||
|
//if err != nil {
|
||||||
|
// return nil, err
|
||||||
|
//}
|
||||||
|
//req.Header.Set("Authorization", token)
|
||||||
|
//req.Header.Set("Content-Type", "application/octet-stream")
|
||||||
|
//req.Header.Set("Referer", "https://www.teambition.com/")
|
||||||
|
//resp, err := base.HttpClient.Do(req)
|
||||||
|
//res, _ := ioutil.ReadAll(resp.Body)
|
||||||
|
//log.Debugf("chunk upload status: %s, res: %s", resp.Status, string(res))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &newChunk.FileUpload, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (driver Teambition) finishUpload(file *FileUpload, parentId string, account *model.Account) error {
|
||||||
|
file.InvolveMembers = []interface{}{}
|
||||||
|
file.Visible = "members"
|
||||||
|
file.ParentId = parentId
|
||||||
|
_, err := driver.Request("/api/works", base.Post, nil, nil, nil, base.Json{
|
||||||
|
"works": []FileUpload{*file},
|
||||||
|
"_parentId": parentId,
|
||||||
|
}, nil, account)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
base.RegisterDriver(&Teambition{})
|
base.RegisterDriver(&Teambition{})
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
package teambition
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
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"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FileUpload struct {
|
||||||
|
FileKey string `json:"fileKey"`
|
||||||
|
FileName string `json:"fileName"`
|
||||||
|
FileType string `json:"fileType"`
|
||||||
|
FileSize int `json:"fileSize"`
|
||||||
|
FileCategory string `json:"fileCategory"`
|
||||||
|
ImageWidth int `json:"imageWidth"`
|
||||||
|
ImageHeight int `json:"imageHeight"`
|
||||||
|
InvolveMembers []interface{} `json:"involveMembers"`
|
||||||
|
Source string `json:"source"`
|
||||||
|
Visible string `json:"visible"`
|
||||||
|
ParentId string `json:"_parentId"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ChunkUpload struct {
|
||||||
|
FileUpload
|
||||||
|
Storage string `json:"storage"`
|
||||||
|
MimeType string `json:"mimeType"`
|
||||||
|
Chunks int `json:"chunks"`
|
||||||
|
ChunkSize int `json:"chunkSize"`
|
||||||
|
Created time.Time `json:"created"`
|
||||||
|
FileMD5 string `json:"fileMD5"`
|
||||||
|
LastUpdated time.Time `json:"lastUpdated"`
|
||||||
|
UploadedChunks []interface{} `json:"uploadedChunks"`
|
||||||
|
Token struct {
|
||||||
|
AppID string `json:"AppID"`
|
||||||
|
OrganizationID string `json:"OrganizationID"`
|
||||||
|
UserID string `json:"UserID"`
|
||||||
|
Exp time.Time `json:"Exp"`
|
||||||
|
Storage string `json:"Storage"`
|
||||||
|
Resource string `json:"Resource"`
|
||||||
|
Speed int `json:"Speed"`
|
||||||
|
} `json:"token"`
|
||||||
|
DownloadUrl string `json:"downloadUrl"`
|
||||||
|
ThumbnailUrl string `json:"thumbnailUrl"`
|
||||||
|
PreviewUrl string `json:"previewUrl"`
|
||||||
|
ImmPreviewUrl string `json:"immPreviewUrl"`
|
||||||
|
PreviewExt string `json:"previewExt"`
|
||||||
|
LastUploadTime interface{} `json:"lastUploadTime"`
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package teambition
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
|
func GetBetweenStr(str, start, end string) string {
|
||||||
|
n := strings.Index(str, start)
|
||||||
|
if n == -1 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
n = n + len(start)
|
||||||
|
str = string([]byte(str)[n:])
|
||||||
|
m := strings.Index(str, end)
|
||||||
|
if m == -1 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
str = string([]byte(str)[:m])
|
||||||
|
return str
|
||||||
|
}
|
Loading…
Reference in New Issue