Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 130 additions & 0 deletions drivers/123_open/driver.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package _123_open

import (
"context"
"strconv"

"github.com/alist-org/alist/v3/internal/driver"
"github.com/alist-org/alist/v3/internal/errs"
"github.com/alist-org/alist/v3/internal/model"
"github.com/alist-org/alist/v3/internal/op"
"github.com/alist-org/alist/v3/internal/stream"
"github.com/alist-org/alist/v3/pkg/utils"
)

type Open123 struct {
model.Storage
Addition
}

func (d *Open123) Config() driver.Config {
return config
}

func (d *Open123) GetAddition() driver.Additional {
return &d.Addition
}

func (d *Open123) Init(ctx context.Context) error {
if d.UploadThread < 1 || d.UploadThread > 32 {
d.UploadThread = 3
}

return nil
}

func (d *Open123) Drop(ctx context.Context) error {
op.MustSaveDriverStorage(d)
return nil
}

func (d *Open123) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
fileLastId := int64(0)
parentFileId, err := strconv.ParseInt(dir.GetID(), 10, 64)
if err != nil {
return nil, err
}
res := make([]File, 0)

for fileLastId != -1 {
files, err := d.getFiles(parentFileId, 100, fileLastId)
if err != nil {
return nil, err
}
// 目前123panAPI请求,trashed失效,只能通过遍历过滤
for i := range files.Data.FileList {
if files.Data.FileList[i].Trashed == 0 {
res = append(res, files.Data.FileList[i])
}
}
fileLastId = files.Data.LastFileId
}
return utils.SliceConvert(res, func(src File) (model.Obj, error) {
return src, nil
})
}

func (d *Open123) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
fileId, _ := strconv.ParseInt(file.GetID(), 10, 64)

res, err := d.getDownloadInfo(fileId)
if err != nil {
return nil, err
}

link := model.Link{URL: res.Data.DownloadUrl}
return &link, nil
}

func (d *Open123) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error {
parentFileId, _ := strconv.ParseInt(parentDir.GetID(), 10, 64)

return d.mkdir(parentFileId, dirName)
}

func (d *Open123) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
toParentFileID, _ := strconv.ParseInt(dstDir.GetID(), 10, 64)

return d.move(srcObj.(File).FileId, toParentFileID)
}

func (d *Open123) Rename(ctx context.Context, srcObj model.Obj, newName string) error {
fileId, _ := strconv.ParseInt(srcObj.GetID(), 10, 64)

return d.rename(fileId, newName)
}

func (d *Open123) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
return errs.NotSupport
}

func (d *Open123) Remove(ctx context.Context, obj model.Obj) error {
fileId, _ := strconv.ParseInt(obj.GetID(), 10, 64)

return d.trash(fileId)
}

func (d *Open123) Put(ctx context.Context, dstDir model.Obj, file model.FileStreamer, up driver.UpdateProgress) error {
parentFileId, err := strconv.ParseInt(dstDir.GetID(), 10, 64)
etag := file.GetHash().GetHash(utils.MD5)

if len(etag) < utils.MD5.Width {
cacheFileProgress := model.UpdateProgressWithRange(up, 0, 50)
up = model.UpdateProgressWithRange(up, 50, 100)
_, etag, err = stream.CacheFullInTempFileAndHash(file, cacheFileProgress, utils.MD5)
if err != nil {
return err
}
}
createResp, err := d.create(parentFileId, file.GetName(), etag, file.GetSize(), 2, false)
if err != nil {
return err
}
if createResp.Data.Reuse {
return nil
}

return d.Upload(ctx, file, createResp, up)
}

var _ driver.Driver = (*Open123)(nil)
27 changes: 27 additions & 0 deletions drivers/123_open/meta.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package _123_open

import (
"github.com/alist-org/alist/v3/internal/driver"
"github.com/alist-org/alist/v3/internal/op"
)

type Addition struct {
driver.RootID
RefreshToken string `json:"RefreshToken" required:"false"`
ClientID string `json:"ClientID" required:"false"`
ClientSecret string `json:"ClientSecret" required:"false"`
AccessToken string `json:"AccessToken" required:"false"`
UploadThread int `json:"UploadThread" type:"number" default:"3" help:"the threads of upload"`
}

var config = driver.Config{
Name: "123 Open",
DefaultRoot: "0",
LocalSort: true,
}

func init() {
op.RegisterDriver(func() driver.Driver {
return &Open123{}
})
}
205 changes: 205 additions & 0 deletions drivers/123_open/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
package _123_open

import (
"strconv"
"time"

"github.com/alist-org/alist/v3/internal/model"
"github.com/alist-org/alist/v3/pkg/utils"
)

type ApiInfo struct {
url string
qps int
token chan struct{}
}

func (a *ApiInfo) Require() {
if a.qps > 0 {
a.token <- struct{}{}
}
}
func (a *ApiInfo) Release() {
if a.qps > 0 {
time.AfterFunc(time.Second, func() {
<-a.token
})
}
}
func (a *ApiInfo) SetQPS(qps int) {
a.qps = qps
a.token = make(chan struct{}, qps)
}
func (a *ApiInfo) NowLen() int {
return len(a.token)
}
func InitApiInfo(url string, qps int) *ApiInfo {
return &ApiInfo{
url: url,
qps: qps,
token: make(chan struct{}, qps),
}
}

type File struct {
FileName string `json:"filename"`
Size int64 `json:"size"`
CreateAt string `json:"createAt"`
UpdateAt string `json:"updateAt"`
FileId int64 `json:"fileId"`
Type int `json:"type"`
Etag string `json:"etag"`
S3KeyFlag string `json:"s3KeyFlag"`
ParentFileId int `json:"parentFileId"`
Category int `json:"category"`
Status int `json:"status"`
Trashed int `json:"trashed"`
}

func (f File) GetHash() utils.HashInfo {
return utils.NewHashInfo(utils.MD5, f.Etag)
}

func (f File) GetPath() string {
return ""
}

func (f File) GetSize() int64 {
return f.Size
}

func (f File) GetName() string {
return f.FileName
}

func (f File) CreateTime() time.Time {
parsedTime, err := time.Parse("2006-01-02 15:04:05", f.CreateAt)
if err != nil {
return time.Now()
}
return parsedTime
}

func (f File) ModTime() time.Time {
parsedTime, err := time.Parse("2006-01-02 15:04:05", f.UpdateAt)
if err != nil {
return time.Now()
}
return parsedTime
}

func (f File) IsDir() bool {
return f.Type == 1
}

func (f File) GetID() string {
return strconv.FormatInt(f.FileId, 10)
}

var _ model.Obj = (*File)(nil)

type BaseResp struct {
Code int `json:"code"`
Message string `json:"message"`
XTraceID string `json:"x-traceID"`
}

type AccessTokenResp struct {
BaseResp
Data struct {
AccessToken string `json:"accessToken"`
ExpiredAt string `json:"expiredAt"`
} `json:"data"`
}

type RefreshTokenResp struct {
AccessToken string `json:"access_token"`
ExpiresIn int `json:"expires_in"`
RefreshToken string `json:"refresh_token"`
Scope string `json:"scope"`
TokenType string `json:"token_type"`
}

type UserInfoResp struct {
BaseResp
Data struct {
UID int64 `json:"uid"`
Username string `json:"username"`
DisplayName string `json:"displayName"`
HeadImage string `json:"headImage"`
Passport string `json:"passport"`
Mail string `json:"mail"`
SpaceUsed int64 `json:"spaceUsed"`
SpacePermanent int64 `json:"spacePermanent"`
SpaceTemp int64 `json:"spaceTemp"`
SpaceTempExpr string `json:"spaceTempExpr"`
Vip bool `json:"vip"`
DirectTraffic int64 `json:"directTraffic"`
IsHideUID bool `json:"isHideUID"`
} `json:"data"`
}

type FileListResp struct {
BaseResp
Data struct {
LastFileId int64 `json:"lastFileId"`
FileList []File `json:"fileList"`
} `json:"data"`
}

type DownloadInfoResp struct {
BaseResp
Data struct {
DownloadUrl string `json:"downloadUrl"`
} `json:"data"`
}

type UploadCreateResp struct {
BaseResp
Data struct {
FileID int64 `json:"fileID"`
PreuploadID string `json:"preuploadID"`
Reuse bool `json:"reuse"`
SliceSize int64 `json:"sliceSize"`
} `json:"data"`
}

type UploadUrlResp struct {
BaseResp
Data struct {
PresignedURL string `json:"presignedURL"`
}
}

type UploadCompleteResp struct {
BaseResp
Data struct {
Async bool `json:"async"`
Completed bool `json:"completed"`
FileID int64 `json:"fileID"`
} `json:"data"`
}

type UploadAsyncResp struct {
BaseResp
Data struct {
Completed bool `json:"completed"`
FileID int64 `json:"fileID"`
} `json:"data"`
}

type UploadResp struct {
BaseResp
Data struct {
AccessKeyId string `json:"AccessKeyId"`
Bucket string `json:"Bucket"`
Key string `json:"Key"`
SecretAccessKey string `json:"SecretAccessKey"`
SessionToken string `json:"SessionToken"`
FileId int64 `json:"FileId"`
Reuse bool `json:"Reuse"`
EndPoint string `json:"EndPoint"`
StorageNode string `json:"StorageNode"`
UploadId string `json:"UploadId"`
} `json:"data"`
}
Loading
Loading