mirror of https://github.com/Xhofe/alist
✨ teambition upload (<= 20 MB)
parent
2a9598f4c6
commit
df513b7dc0
|
@ -19,6 +19,7 @@ func InitAccounts() {
|
|||
if !ok {
|
||||
log.Errorf("no [%s] driver", account.Type)
|
||||
} else {
|
||||
log.Infof("start init account: [%s], type: [%s]", account.Name, account.Type)
|
||||
err := driver.Save(&accounts[i], nil)
|
||||
if err != nil {
|
||||
log.Errorf("init account [%s] error:[%s]", account.Name, err.Error())
|
||||
|
|
|
@ -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 {
|
||||
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)
|
||||
|
|
|
@ -2,11 +2,14 @@ package teambition
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"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"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"io"
|
||||
"path"
|
||||
"strconv"
|
||||
"time"
|
||||
|
@ -66,25 +69,6 @@ func (driver Teambition) Request(pathname string, method int, headers, query, fo
|
|||
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
|
||||
|
@ -151,6 +135,94 @@ func (driver Teambition) GetFiles(parentId string, account *model.Account) ([]mo
|
|||
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() {
|
||||
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