mirror of https://github.com/Xhofe/alist
🚧 MediaTrack support
parent
36b533cb16
commit
10f06fde5c
|
@ -9,6 +9,7 @@ import (
|
|||
_ "github.com/Xhofe/alist/drivers/ftp"
|
||||
_ "github.com/Xhofe/alist/drivers/google"
|
||||
_ "github.com/Xhofe/alist/drivers/lanzou"
|
||||
_ "github.com/Xhofe/alist/drivers/mediatrack"
|
||||
_ "github.com/Xhofe/alist/drivers/native"
|
||||
_ "github.com/Xhofe/alist/drivers/onedrive"
|
||||
_ "github.com/Xhofe/alist/drivers/pikpak"
|
||||
|
|
|
@ -0,0 +1,276 @@
|
|||
package mediatrack
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/Xhofe/alist/conf"
|
||||
"github.com/Xhofe/alist/drivers/base"
|
||||
"github.com/Xhofe/alist/model"
|
||||
"github.com/Xhofe/alist/utils"
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
"github.com/aws/aws-sdk-go/service/s3/s3manager"
|
||||
"github.com/gin-gonic/gin"
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
type MediaTrack struct{}
|
||||
|
||||
func (driver MediaTrack) Config() base.DriverConfig {
|
||||
return base.DriverConfig{
|
||||
Name: "MediaTrack",
|
||||
}
|
||||
}
|
||||
|
||||
func (driver MediaTrack) Items() []base.Item {
|
||||
return []base.Item{
|
||||
{
|
||||
Name: "access_token",
|
||||
Label: "Token",
|
||||
Type: base.TypeString,
|
||||
Description: "Unknown expiration time",
|
||||
},
|
||||
{
|
||||
Name: "root_folder",
|
||||
Label: "root folder file_id",
|
||||
Type: base.TypeString,
|
||||
},
|
||||
{
|
||||
Name: "order_by",
|
||||
Label: "order_by",
|
||||
Type: base.TypeSelect,
|
||||
Values: "updated_at,title,size",
|
||||
Required: true,
|
||||
},
|
||||
{
|
||||
Name: "order_direction",
|
||||
Label: "desc",
|
||||
Type: base.TypeSelect,
|
||||
Values: "true,false",
|
||||
Required: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (driver MediaTrack) Save(account *model.Account, old *model.Account) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (driver MediaTrack) 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 MediaTrack) 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 MediaTrack) Link(args base.Args, account *model.Account) (*base.Link, error) {
|
||||
file, err := driver.File(args.Path, account)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pre := "https://jayce.api.mediatrack.cn/v3/assets/" + file.Id
|
||||
body, err := driver.Request(pre+"/token", base.Get, nil, nil, nil, nil, nil, account)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
url := pre + "/raw"
|
||||
res, err := base.NoRedirectClient.R().SetQueryParam("token", jsoniter.Get(body, "data").ToString()).Get(url)
|
||||
return &base.Link{Url: res.Header().Get("location")}, nil
|
||||
}
|
||||
|
||||
func (driver MediaTrack) Path(path string, account *model.Account) (*model.File, []model.File, error) {
|
||||
path = utils.ParsePath(path)
|
||||
log.Debugf("MediaTrack 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 MediaTrack) Proxy(c *gin.Context, account *model.Account) {
|
||||
|
||||
}
|
||||
|
||||
func (driver MediaTrack) Preview(path string, account *model.Account) (interface{}, error) {
|
||||
return nil, base.ErrNotImplement
|
||||
}
|
||||
|
||||
func (driver MediaTrack) MakeDir(path string, account *model.Account) error {
|
||||
parentFile, err := driver.File(utils.Dir(path), account)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
url := fmt.Sprintf("https://jayce.api.mediatrack.cn/v4/assets/%s/children", parentFile.Id)
|
||||
_, err = driver.Request(url, base.Post, nil, nil, nil, base.Json{
|
||||
"type": 1,
|
||||
"title": utils.Base(path),
|
||||
}, nil, account)
|
||||
return err
|
||||
}
|
||||
|
||||
func (driver MediaTrack) 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
|
||||
}
|
||||
data := base.Json{
|
||||
"parent_id": dstParentFile.Id,
|
||||
"ids": []string{srcFile.Id},
|
||||
}
|
||||
url := "https://jayce.api.mediatrack.cn/v4/assets/batch/move"
|
||||
_, err = driver.Request(url, base.Post, nil, nil, nil, data, nil, account)
|
||||
return err
|
||||
}
|
||||
|
||||
func (driver MediaTrack) Rename(src string, dst string, account *model.Account) error {
|
||||
srcFile, err := driver.File(src, account)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
url := "https://jayce.api.mediatrack.cn/v3/assets/" + srcFile.Id
|
||||
data := base.Json{
|
||||
"title": utils.Base(dst),
|
||||
}
|
||||
_, err = driver.Request(url, base.Put, nil, nil, nil, data, nil, account)
|
||||
return err
|
||||
}
|
||||
|
||||
func (driver MediaTrack) 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
|
||||
}
|
||||
data := base.Json{
|
||||
"parent_id": dstParentFile.Id,
|
||||
"ids": []string{srcFile.Id},
|
||||
}
|
||||
url := "https://jayce.api.mediatrack.cn/v4/assets/batch/clone"
|
||||
_, err = driver.Request(url, base.Post, nil, nil, nil, data, nil, account)
|
||||
return err
|
||||
}
|
||||
|
||||
func (driver MediaTrack) Delete(path string, account *model.Account) error {
|
||||
parentFile, err := driver.File(utils.Dir(path), account)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
file, err := driver.File(path, account)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data := base.Json{
|
||||
"origin_id": parentFile.Id,
|
||||
"ids": []string{file.Id},
|
||||
}
|
||||
url := "https://jayce.api.mediatrack.cn/v4/assets/batch/delete"
|
||||
_, err = driver.Request(url, base.Delete, nil, nil, nil, data, nil, account)
|
||||
return err
|
||||
}
|
||||
|
||||
func (driver MediaTrack) Upload(file *model.FileStream, account *model.Account) error {
|
||||
parentFile, err := driver.File(file.ParentPath, account)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
src := "assets/56461b45-6d08-40a0-bfbf-0a47689bffaa" // random?
|
||||
var resp UploadResp
|
||||
_, err = driver.Request("https://jayce.api.mediatrack.cn/v3/storage/tokens/asset", base.Get, nil, map[string]string{
|
||||
"src": src,
|
||||
}, nil, nil, &resp, account)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
credential := resp.Data.Credentials
|
||||
cfg := &aws.Config{
|
||||
Credentials: credentials.NewStaticCredentials(credential.TmpSecretID, credential.TmpSecretKey, credential.Token),
|
||||
Region: &resp.Data.Region,
|
||||
Endpoint: aws.String("cos.accelerate.myqcloud.com"),
|
||||
}
|
||||
s, err := session.NewSession(cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
uploader := s3manager.NewUploader(s)
|
||||
input := &s3manager.UploadInput{
|
||||
Bucket: &resp.Data.Bucket,
|
||||
Key: &resp.Data.Object,
|
||||
Body: file,
|
||||
}
|
||||
_, err = uploader.Upload(input)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
url := fmt.Sprintf("https://jayce.api.mediatrack.cn/v3/assets/%s/children", parentFile.Id)
|
||||
data := base.Json{
|
||||
"category": 10,
|
||||
"description": file.GetFileName(),
|
||||
"hash": "c459fda4d79554d692555932a5d5e6c1",
|
||||
"mime": file.MIMEType,
|
||||
"size": file.GetSize(),
|
||||
"src": src,
|
||||
"title": file.GetFileName(),
|
||||
"type": 0,
|
||||
}
|
||||
_, err = driver.Request(url, base.Post, nil, nil, nil, data, nil, account)
|
||||
return err
|
||||
}
|
||||
|
||||
var _ base.Driver = (*MediaTrack)(nil)
|
|
@ -0,0 +1,181 @@
|
|||
package mediatrack
|
||||
|
||||
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"
|
||||
"path"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
type BaseResp struct {
|
||||
Status string `json:"status"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
type T struct {
|
||||
BaseResp
|
||||
}
|
||||
|
||||
func (driver MediaTrack) Request(url string, method int, headers, query, form map[string]string, data interface{}, resp interface{}, account *model.Account) ([]byte, error) {
|
||||
req := base.RestyClient.R()
|
||||
req.SetHeader("Authorization", "Bearer "+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)
|
||||
}
|
||||
var e BaseResp
|
||||
req.SetResult(&e)
|
||||
var err error
|
||||
var res *resty.Response
|
||||
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.Status != "SUCCESS" {
|
||||
return nil, errors.New(e.Message)
|
||||
}
|
||||
if resp != nil {
|
||||
err = utils.Json.Unmarshal(res.Body(), resp)
|
||||
}
|
||||
return res.Body(), err
|
||||
}
|
||||
|
||||
type File struct {
|
||||
Category int `json:"category"`
|
||||
ChildAssets []interface{} `json:"childAssets"`
|
||||
CommentCount int `json:"comment_count"`
|
||||
CoverAsset interface{} `json:"cover_asset"`
|
||||
CoverAssetID string `json:"cover_asset_id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
DeletedAt string `json:"deleted_at"`
|
||||
Description string `json:"description"`
|
||||
File struct {
|
||||
Cover string `json:"cover"`
|
||||
Src string `json:"src"`
|
||||
} `json:"file"`
|
||||
//FileID string `json:"file_id"`
|
||||
ID string `json:"id"`
|
||||
|
||||
Size string `json:"size"`
|
||||
Thumbnails []interface{} `json:"thumbnails"`
|
||||
Title string `json:"title"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
func (driver MediaTrack) formatFile(file *File) *model.File {
|
||||
f := model.File{
|
||||
Id: file.ID,
|
||||
Name: file.Title,
|
||||
Size: 0,
|
||||
Driver: driver.Config().Name,
|
||||
UpdatedAt: &file.UpdatedAt,
|
||||
}
|
||||
if file.Category == 0 {
|
||||
// folder
|
||||
f.Type = conf.FOLDER
|
||||
} else {
|
||||
size, _ := strconv.ParseInt(file.Size, 10, 64)
|
||||
f.Size = size
|
||||
f.Type = utils.GetFileType(path.Ext(file.Title))
|
||||
if file.File.Cover != "" {
|
||||
f.Thumbnail = "https://nano.mtres.cn/" + file.File.Cover
|
||||
}
|
||||
}
|
||||
return &f
|
||||
}
|
||||
|
||||
type ChildrenResp struct {
|
||||
Status string `json:"status"`
|
||||
Data struct {
|
||||
Total int `json:"total"`
|
||||
Assets []File `json:"assets"`
|
||||
} `json:"data"`
|
||||
Path string `json:"path"`
|
||||
TraceID string `json:"trace_id"`
|
||||
RequestID string `json:"requestId"`
|
||||
}
|
||||
|
||||
func (driver MediaTrack) GetFiles(parentId string, account *model.Account) ([]model.File, error) {
|
||||
files := make([]model.File, 0)
|
||||
url := fmt.Sprintf("https://jayce.api.mediatrack.cn/v4/assets/%s/children", parentId)
|
||||
sort := ""
|
||||
if account.OrderBy != "" {
|
||||
if account.OrderDirection == "true" {
|
||||
sort = "-"
|
||||
}
|
||||
sort += account.OrderBy
|
||||
}
|
||||
page := 1
|
||||
for {
|
||||
var resp ChildrenResp
|
||||
_, err := driver.Request(url, base.Get, nil, map[string]string{
|
||||
"page": strconv.Itoa(page),
|
||||
"size": "50",
|
||||
"sort": sort,
|
||||
}, nil, nil, &resp, account)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(resp.Data.Assets) == 0 {
|
||||
break
|
||||
}
|
||||
page++
|
||||
for _, file := range resp.Data.Assets {
|
||||
files = append(files, *driver.formatFile(&file))
|
||||
}
|
||||
}
|
||||
return files, nil
|
||||
}
|
||||
|
||||
type UploadResp struct {
|
||||
Status string `json:"status"`
|
||||
Data struct {
|
||||
Credentials struct {
|
||||
TmpSecretID string `json:"TmpSecretId"`
|
||||
TmpSecretKey string `json:"TmpSecretKey"`
|
||||
Token string `json:"Token"`
|
||||
ExpiredTime int `json:"ExpiredTime"`
|
||||
Expiration time.Time `json:"Expiration"`
|
||||
StartTime int `json:"StartTime"`
|
||||
} `json:"credentials"`
|
||||
Object string `json:"object"`
|
||||
Bucket string `json:"bucket"`
|
||||
Region string `json:"region"`
|
||||
URL string `json:"url"`
|
||||
Size string `json:"size"`
|
||||
} `json:"data"`
|
||||
Path string `json:"path"`
|
||||
TraceID string `json:"trace_id"`
|
||||
RequestID string `json:"requestId"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
base.RegisterDriver(&MediaTrack{})
|
||||
}
|
Loading…
Reference in New Issue