mirror of https://github.com/Xhofe/alist
257 lines
6.3 KiB
Go
257 lines
6.3 KiB
Go
![]() |
package misskey
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"context"
|
||
|
"errors"
|
||
|
"io"
|
||
|
"time"
|
||
|
|
||
|
"github.com/go-resty/resty/v2"
|
||
|
|
||
|
"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/utils"
|
||
|
)
|
||
|
|
||
|
// Base layer methods
|
||
|
|
||
|
func (d *Misskey) request(path, method string, callback base.ReqCallback, resp interface{}) error {
|
||
|
url := d.Endpoint + "/api/drive" + path
|
||
|
req := base.RestyClient.R()
|
||
|
|
||
|
req.SetAuthToken(d.AccessToken).SetHeader("Content-Type", "application/json")
|
||
|
|
||
|
if callback != nil {
|
||
|
callback(req)
|
||
|
} else {
|
||
|
req.SetBody("{}")
|
||
|
}
|
||
|
|
||
|
req.SetResult(resp)
|
||
|
|
||
|
// 启用调试模式
|
||
|
req.EnableTrace()
|
||
|
|
||
|
response, err := req.Execute(method, url)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
if !response.IsSuccess() {
|
||
|
return errors.New(response.String())
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (d *Misskey) getThumb(ctx context.Context, obj model.Obj) (io.Reader, error) {
|
||
|
// TODO return the thumb of obj, optional
|
||
|
return nil, errs.NotImplement
|
||
|
}
|
||
|
|
||
|
func setBody(body interface{}) base.ReqCallback {
|
||
|
return func(req *resty.Request) {
|
||
|
req.SetBody(body)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func handleFolderId(dir model.Obj) interface{} {
|
||
|
if dir.GetID() == "" {
|
||
|
return nil
|
||
|
}
|
||
|
return dir.GetID()
|
||
|
}
|
||
|
|
||
|
// API layer methods
|
||
|
|
||
|
func (d *Misskey) getFiles(dir model.Obj) ([]model.Obj, error) {
|
||
|
var files []MFile
|
||
|
var body map[string]string
|
||
|
if dir.GetPath() != "/" {
|
||
|
body = map[string]string{"folderId": dir.GetID()}
|
||
|
} else {
|
||
|
body = map[string]string{}
|
||
|
}
|
||
|
err := d.request("/files", "POST", setBody(body), &files)
|
||
|
if err != nil {
|
||
|
return []model.Obj{}, err
|
||
|
}
|
||
|
return utils.SliceConvert(files, func(src MFile) (model.Obj, error) {
|
||
|
return mFile2Object(src), nil
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func (d *Misskey) getFolders(dir model.Obj) ([]model.Obj, error) {
|
||
|
var folders []MFolder
|
||
|
var body map[string]string
|
||
|
if dir.GetPath() != "/" {
|
||
|
body = map[string]string{"folderId": dir.GetID()}
|
||
|
} else {
|
||
|
body = map[string]string{}
|
||
|
}
|
||
|
err := d.request("/folders", "POST", setBody(body), &folders)
|
||
|
if err != nil {
|
||
|
return []model.Obj{}, err
|
||
|
}
|
||
|
return utils.SliceConvert(folders, func(src MFolder) (model.Obj, error) {
|
||
|
return mFolder2Object(src), nil
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func (d *Misskey) list(dir model.Obj) ([]model.Obj, error) {
|
||
|
files, _ := d.getFiles(dir)
|
||
|
folders, _ := d.getFolders(dir)
|
||
|
return append(files, folders...), nil
|
||
|
}
|
||
|
|
||
|
func (d *Misskey) link(file model.Obj) (*model.Link, error) {
|
||
|
var mFile MFile
|
||
|
err := d.request("/files/show", "POST", setBody(map[string]string{"fileId": file.GetID()}), &mFile)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
return &model.Link{
|
||
|
URL: mFile.URL,
|
||
|
}, nil
|
||
|
}
|
||
|
|
||
|
func (d *Misskey) makeDir(parentDir model.Obj, dirName string) (model.Obj, error) {
|
||
|
var folder MFolder
|
||
|
err := d.request("/folders/create", "POST", setBody(map[string]interface{}{"parentId": handleFolderId(parentDir), "name": dirName}), &folder)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
return mFolder2Object(folder), nil
|
||
|
}
|
||
|
|
||
|
func (d *Misskey) move(srcObj, dstDir model.Obj) (model.Obj, error) {
|
||
|
if srcObj.IsDir() {
|
||
|
var folder MFolder
|
||
|
err := d.request("/folders/update", "POST", setBody(map[string]interface{}{"folderId": srcObj.GetID(), "parentId": handleFolderId(dstDir)}), &folder)
|
||
|
return mFolder2Object(folder), err
|
||
|
} else {
|
||
|
var file MFile
|
||
|
err := d.request("/files/update", "POST", setBody(map[string]interface{}{"fileId": srcObj.GetID(), "folderId": handleFolderId(dstDir)}), &file)
|
||
|
return mFile2Object(file), err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (d *Misskey) rename(srcObj model.Obj, newName string) (model.Obj, error) {
|
||
|
if srcObj.IsDir() {
|
||
|
var folder MFolder
|
||
|
err := d.request("/folders/update", "POST", setBody(map[string]string{"folderId": srcObj.GetID(), "name": newName}), &folder)
|
||
|
return mFolder2Object(folder), err
|
||
|
} else {
|
||
|
var file MFile
|
||
|
err := d.request("/files/update", "POST", setBody(map[string]string{"fileId": srcObj.GetID(), "name": newName}), &file)
|
||
|
return mFile2Object(file), err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (d *Misskey) copy(srcObj, dstDir model.Obj) (model.Obj, error) {
|
||
|
if srcObj.IsDir() {
|
||
|
folder, err := d.makeDir(dstDir, srcObj.GetName())
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
list, err := d.list(srcObj)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
for _, obj := range list {
|
||
|
_, err := d.copy(obj, folder)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
}
|
||
|
return folder, nil
|
||
|
} else {
|
||
|
var file MFile
|
||
|
url, err := d.link(srcObj)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
err = d.request("/files/upload-from-url", "POST", setBody(map[string]interface{}{"url": url.URL, "folderId": handleFolderId(dstDir)}), &file)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
return mFile2Object(file), nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (d *Misskey) remove(obj model.Obj) error {
|
||
|
if obj.IsDir() {
|
||
|
err := d.request("/folders/delete", "POST", setBody(map[string]string{"folderId": obj.GetID()}), nil)
|
||
|
return err
|
||
|
} else {
|
||
|
err := d.request("/files/delete", "POST", setBody(map[string]string{"fileId": obj.GetID()}), nil)
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (d *Misskey) put(dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) (model.Obj, error) {
|
||
|
var file MFile
|
||
|
|
||
|
fileContent, err := io.ReadAll(stream)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
req := base.RestyClient.R().
|
||
|
SetFileReader("file", stream.GetName(), io.NopCloser(bytes.NewReader(fileContent))).
|
||
|
SetFormData(map[string]string{
|
||
|
"folderId": handleFolderId(dstDir).(string),
|
||
|
"name": stream.GetName(),
|
||
|
"comment": "",
|
||
|
"isSensitive": "false",
|
||
|
"force": "false",
|
||
|
}).
|
||
|
SetResult(&file).SetAuthToken(d.AccessToken)
|
||
|
|
||
|
resp, err := req.Post(d.Endpoint + "/api/drive/files/create")
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
if !resp.IsSuccess() {
|
||
|
return nil, errors.New(resp.String())
|
||
|
}
|
||
|
|
||
|
return mFile2Object(file), nil
|
||
|
}
|
||
|
|
||
|
func mFile2Object(file MFile) *model.ObjThumbURL {
|
||
|
ctime, err := time.Parse(time.RFC3339, file.CreatedAt)
|
||
|
if err != nil {
|
||
|
ctime = time.Time{}
|
||
|
}
|
||
|
return &model.ObjThumbURL{
|
||
|
Object: model.Object{
|
||
|
ID: file.ID,
|
||
|
Name: file.Name,
|
||
|
Ctime: ctime,
|
||
|
IsFolder: false,
|
||
|
Size: file.Size,
|
||
|
},
|
||
|
Thumbnail: model.Thumbnail{
|
||
|
Thumbnail: file.ThumbnailURL,
|
||
|
},
|
||
|
Url: model.Url{
|
||
|
Url: file.URL,
|
||
|
},
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func mFolder2Object(folder MFolder) *model.Object {
|
||
|
ctime, err := time.Parse(time.RFC3339, folder.CreatedAt)
|
||
|
if err != nil {
|
||
|
ctime = time.Time{}
|
||
|
}
|
||
|
return &model.Object{
|
||
|
ID: folder.ID,
|
||
|
Name: folder.Name,
|
||
|
Ctime: ctime,
|
||
|
IsFolder: true,
|
||
|
}
|
||
|
}
|