-
-
Notifications
You must be signed in to change notification settings - Fork 6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add aliyundrive share driver (close #1215)
- Loading branch information
Showing
5 changed files
with
330 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
package aliyundrive_share | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"net/http" | ||
"time" | ||
|
||
"github.com/alist-org/alist/v3/drivers/base" | ||
"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/pkg/cron" | ||
"github.com/alist-org/alist/v3/pkg/utils" | ||
log "github.com/sirupsen/logrus" | ||
) | ||
|
||
type AliyundriveShare struct { | ||
model.Storage | ||
Addition | ||
AccessToken string | ||
ShareToken string | ||
DriveId string | ||
cron *cron.Cron | ||
} | ||
|
||
func (d *AliyundriveShare) Config() driver.Config { | ||
return config | ||
} | ||
|
||
func (d *AliyundriveShare) GetAddition() driver.Additional { | ||
return d.Addition | ||
} | ||
|
||
func (d *AliyundriveShare) Init(ctx context.Context, storage model.Storage) error { | ||
d.Storage = storage | ||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition) | ||
if err != nil { | ||
return err | ||
} | ||
err = d.refreshToken() | ||
if err != nil { | ||
return err | ||
} | ||
err = d.getShareToken() | ||
if err != nil { | ||
return err | ||
} | ||
d.cron = cron.NewCron(time.Hour * 2) | ||
d.cron.Do(func() { | ||
err := d.refreshToken() | ||
if err != nil { | ||
log.Errorf("%+v", err) | ||
} | ||
}) | ||
return nil | ||
} | ||
|
||
func (d *AliyundriveShare) Drop(ctx context.Context) error { | ||
if d.cron != nil { | ||
d.cron.Stop() | ||
} | ||
return nil | ||
} | ||
|
||
func (d *AliyundriveShare) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) { | ||
files, err := d.getFiles(dir.GetID()) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return utils.SliceConvert(files, func(src File) (model.Obj, error) { | ||
return fileToObj(src), nil | ||
}) | ||
} | ||
|
||
//func (d *AliyundriveShare) Get(ctx context.Context, path string) (model.Obj, error) { | ||
// // this is optional | ||
// return nil, errs.NotImplement | ||
//} | ||
|
||
func (d *AliyundriveShare) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) { | ||
data := base.Json{ | ||
"drive_id": d.DriveId, | ||
"file_id": file.GetID(), | ||
"expire_sec": 14400, | ||
} | ||
var e ErrorResp | ||
res, err := base.RestyClient.R(). | ||
SetError(&e).SetBody(data). | ||
SetHeader("content-type", "application/json"). | ||
SetHeader("Authorization", "Bearer\t"+d.AccessToken). | ||
Post("https://api.aliyundrive.com/v2/file/get_download_url") | ||
if err != nil { | ||
return nil, err | ||
} | ||
if e.Code != "" { | ||
if e.Code == "AccessTokenInvalid" { | ||
err = d.refreshToken() | ||
if err != nil { | ||
return nil, err | ||
} | ||
return d.Link(ctx, file, args) | ||
} | ||
return nil, errors.New(e.Message) | ||
} | ||
return &model.Link{ | ||
Header: http.Header{ | ||
"Referer": []string{"https://www.aliyundrive.com/"}, | ||
}, | ||
URL: utils.Json.Get(res.Body(), "url").ToString(), | ||
}, nil | ||
} | ||
|
||
func (d *AliyundriveShare) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error { | ||
// TODO create folder | ||
return errs.NotSupport | ||
} | ||
|
||
func (d *AliyundriveShare) Move(ctx context.Context, srcObj, dstDir model.Obj) error { | ||
// TODO move obj | ||
return errs.NotSupport | ||
} | ||
|
||
func (d *AliyundriveShare) Rename(ctx context.Context, srcObj model.Obj, newName string) error { | ||
// TODO rename obj | ||
return errs.NotSupport | ||
} | ||
|
||
func (d *AliyundriveShare) Copy(ctx context.Context, srcObj, dstDir model.Obj) error { | ||
// TODO copy obj | ||
return errs.NotSupport | ||
} | ||
|
||
func (d *AliyundriveShare) Remove(ctx context.Context, obj model.Obj) error { | ||
// TODO remove obj | ||
return errs.NotSupport | ||
} | ||
|
||
func (d *AliyundriveShare) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error { | ||
// TODO upload file | ||
return errs.NotSupport | ||
} | ||
|
||
var _ driver.Driver = (*AliyundriveShare)(nil) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package aliyundrive_share | ||
|
||
import ( | ||
"github.com/alist-org/alist/v3/internal/driver" | ||
"github.com/alist-org/alist/v3/internal/op" | ||
) | ||
|
||
type Addition struct { | ||
RefreshToken string `json:"refresh_token" required:"true"` | ||
ShareId string `json:"share_id" required:"true"` | ||
SharePwd string `json:"share_pwd"` | ||
driver.RootID | ||
OrderBy string `json:"order_by" type:"select" options:"name,size,updated_at,created_at"` | ||
OrderDirection string `json:"order_direction" type:"select" options:"ASC,DESC"` | ||
} | ||
|
||
var config = driver.Config{ | ||
Name: "AliyundriveShare", | ||
LocalSort: false, | ||
OnlyProxy: false, | ||
NoUpload: true, | ||
DefaultRoot: "root", | ||
} | ||
|
||
func init() { | ||
op.RegisterDriver(config, func() driver.Driver { | ||
return &AliyundriveShare{} | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package aliyundrive_share | ||
|
||
import ( | ||
"time" | ||
|
||
"github.com/alist-org/alist/v3/internal/model" | ||
) | ||
|
||
type ErrorResp struct { | ||
Code string `json:"code"` | ||
Message string `json:"message"` | ||
} | ||
|
||
type ShareTokenResp struct { | ||
ShareToken string `json:"share_token"` | ||
ExpireTime time.Time `json:"expire_time"` | ||
ExpiresIn int `json:"expires_in"` | ||
} | ||
|
||
type ListResp struct { | ||
Items []File `json:"items"` | ||
NextMarker string `json:"next_marker"` | ||
PunishedFileCount int `json:"punished_file_count"` | ||
} | ||
|
||
type File struct { | ||
DriveId string `json:"drive_id"` | ||
DomainId string `json:"domain_id"` | ||
FileId string `json:"file_id"` | ||
ShareId string `json:"share_id"` | ||
Name string `json:"name"` | ||
Type string `json:"type"` | ||
CreatedAt time.Time `json:"created_at"` | ||
UpdatedAt time.Time `json:"updated_at"` | ||
ParentFileId string `json:"parent_file_id"` | ||
Size int64 `json:"size"` | ||
Thumbnail string `json:"thumbnail"` | ||
} | ||
|
||
func fileToObj(f File) *model.ObjThumb { | ||
return &model.ObjThumb{ | ||
Object: model.Object{ | ||
ID: f.FileId, | ||
Name: f.Name, | ||
Size: f.Size, | ||
Modified: f.UpdatedAt, | ||
IsFolder: f.Type == "folder", | ||
}, | ||
Thumbnail: model.Thumbnail{Thumbnail: f.Thumbnail}, | ||
} | ||
} | ||
|
||
//type ShareLinkResp struct { | ||
// DownloadUrl string `json:"download_url"` | ||
// Url string `json:"url"` | ||
// Thumbnail string `json:"thumbnail"` | ||
//} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
package aliyundrive_share | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
|
||
"github.com/alist-org/alist/v3/drivers/base" | ||
"github.com/alist-org/alist/v3/internal/op" | ||
log "github.com/sirupsen/logrus" | ||
) | ||
|
||
func (d *AliyundriveShare) refreshToken() error { | ||
url := "https://auth.aliyundrive.com/v2/account/token" | ||
var resp base.TokenResp | ||
var e ErrorResp | ||
_, err := base.RestyClient.R(). | ||
SetBody(base.Json{"refresh_token": d.RefreshToken, "grant_type": "refresh_token"}). | ||
SetResult(&resp). | ||
SetError(&e). | ||
Post(url) | ||
if err != nil { | ||
return err | ||
} | ||
if e.Code != "" { | ||
return fmt.Errorf("failed to refresh token: %s", e.Message) | ||
} | ||
d.RefreshToken, d.AccessToken = resp.RefreshToken, resp.AccessToken | ||
op.MustSaveDriverStorage(d) | ||
return nil | ||
} | ||
|
||
// do others that not defined in Driver interface | ||
func (d *AliyundriveShare) getShareToken() error { | ||
data := base.Json{ | ||
"share_id": d.ShareId, | ||
} | ||
if d.SharePwd != "" { | ||
data["share_pwd"] = d.SharePwd | ||
} | ||
var e ErrorResp | ||
var resp ShareTokenResp | ||
_, err := base.RestyClient.R(). | ||
SetResult(&resp).SetError(&e).SetBody(data). | ||
Post("https://api.aliyundrive.com/v2/share_link/get_share_token") | ||
if err != nil { | ||
return err | ||
} | ||
if e.Code != "" { | ||
return errors.New(e.Message) | ||
} | ||
d.ShareToken = resp.ShareToken | ||
return nil | ||
} | ||
|
||
func (d *AliyundriveShare) getFiles(fileId string) ([]File, error) { | ||
files := make([]File, 0) | ||
data := base.Json{ | ||
"image_thumbnail_process": "image/resize,w_160/format,jpeg", | ||
"image_url_process": "image/resize,w_1920/format,jpeg", | ||
"limit": 100, | ||
"order_by": d.OrderBy, | ||
"order_direction": d.OrderDirection, | ||
"parent_file_id": fileId, | ||
"share_id": d.ShareId, | ||
"video_thumbnail_process": "video/snapshot,t_1000,f_jpg,ar_auto,w_300", | ||
"marker": "first", | ||
} | ||
for data["marker"] != "" { | ||
if data["marker"] == "first" { | ||
data["marker"] = "" | ||
} | ||
var e ErrorResp | ||
var resp ListResp | ||
res, err := base.RestyClient.R(). | ||
SetHeader("x-share-token", d.ShareToken). | ||
SetResult(&resp).SetError(&e).SetBody(data). | ||
Post("https://api.aliyundrive.com/adrive/v3/file/list") | ||
if err != nil { | ||
return nil, err | ||
} | ||
log.Debugf("aliyundrive share get files: %s", res.String()) | ||
if e.Code != "" { | ||
if e.Code == "AccessTokenInvalid" { | ||
err = d.getShareToken() | ||
if err != nil { | ||
return nil, err | ||
} | ||
return d.getFiles(fileId) | ||
} | ||
return nil, errors.New(e.Message) | ||
} | ||
data["marker"] = resp.NextMarker | ||
files = append(files, resp.Items...) | ||
} | ||
if len(files) > 0 && d.DriveId == "" { | ||
d.DriveId = files[0].DriveId | ||
} | ||
return files, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3537153
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well-done!