2021-12-06 07:55:05 +00:00
|
|
|
package onedrive
|
2021-11-27 12:20:14 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"github.com/Xhofe/alist/conf"
|
2021-12-06 07:55:05 +00:00
|
|
|
"github.com/Xhofe/alist/drivers/base"
|
2021-11-27 12:20:14 +00:00
|
|
|
"github.com/Xhofe/alist/model"
|
|
|
|
"github.com/Xhofe/alist/utils"
|
|
|
|
"github.com/go-resty/resty/v2"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
"path/filepath"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
var oneClient = resty.New()
|
|
|
|
|
|
|
|
type Host struct {
|
|
|
|
Oauth string
|
|
|
|
Api string
|
|
|
|
}
|
|
|
|
|
|
|
|
var onedriveHostMap = map[string]Host{
|
|
|
|
"global": {
|
|
|
|
Oauth: "https://login.microsoftonline.com",
|
|
|
|
Api: "https://graph.microsoft.com",
|
|
|
|
},
|
|
|
|
"cn": {
|
|
|
|
Oauth: "https://login.chinacloudapi.cn",
|
|
|
|
Api: "https://microsoftgraph.chinacloudapi.cn",
|
|
|
|
},
|
|
|
|
"us": {
|
|
|
|
Oauth: "https://login.microsoftonline.us",
|
|
|
|
Api: "https://graph.microsoft.us",
|
|
|
|
},
|
|
|
|
"de": {
|
|
|
|
Oauth: "https://login.microsoftonline.de",
|
|
|
|
Api: "https://graph.microsoft.de",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
func (driver Onedrive) GetMetaUrl(account *model.Account, auth bool, path string) string {
|
|
|
|
path = filepath.Join(account.RootFolder, path)
|
|
|
|
log.Debugf(path)
|
|
|
|
host, _ := onedriveHostMap[account.Zone]
|
|
|
|
if auth {
|
|
|
|
return host.Oauth
|
|
|
|
}
|
|
|
|
switch account.OnedriveType {
|
|
|
|
case "onedrive":
|
|
|
|
{
|
|
|
|
if path == "/" || path == "\\" {
|
|
|
|
return fmt.Sprintf("%s/v1.0/me/drive/root", host.Api)
|
|
|
|
} else {
|
|
|
|
return fmt.Sprintf("%s/v1.0/me/drive/root:%s:", host.Api, path)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case "sharepoint":
|
|
|
|
{
|
2021-11-30 08:45:08 +00:00
|
|
|
if path == "/" || path == "\\" {
|
2021-11-27 12:20:14 +00:00
|
|
|
return fmt.Sprintf("%s/v1.0/sites/%s/drive/root", host.Api, account.SiteId)
|
|
|
|
} else {
|
|
|
|
return fmt.Sprintf("%s/v1.0/sites/%s/drive/root:%s:", host.Api, account.SiteId, path)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type OneTokenErr struct {
|
|
|
|
Error string `json:"error"`
|
|
|
|
ErrorDescription string `json:"error_description"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func (driver Onedrive) RefreshToken(account *model.Account) error {
|
|
|
|
url := driver.GetMetaUrl(account, true, "") + "/common/oauth2/v2.0/token"
|
2021-12-06 07:55:05 +00:00
|
|
|
var resp base.TokenResp
|
2021-11-27 12:20:14 +00:00
|
|
|
var e OneTokenErr
|
|
|
|
_, err := oneClient.R().SetResult(&resp).SetError(&e).SetFormData(map[string]string{
|
|
|
|
"grant_type": "refresh_token",
|
|
|
|
"client_id": account.ClientId,
|
|
|
|
"client_secret": account.ClientSecret,
|
|
|
|
"redirect_uri": account.RedirectUri,
|
|
|
|
"refresh_token": account.RefreshToken,
|
|
|
|
}).Post(url)
|
|
|
|
if err != nil {
|
|
|
|
account.Status = err.Error()
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if e.Error != "" {
|
|
|
|
account.Status = e.ErrorDescription
|
|
|
|
return fmt.Errorf("%s", e.ErrorDescription)
|
|
|
|
} else {
|
|
|
|
account.Status = "work"
|
|
|
|
}
|
|
|
|
account.RefreshToken, account.AccessToken = resp.RefreshToken, resp.AccessToken
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type OneFile struct {
|
|
|
|
Name string `json:"name"`
|
|
|
|
Size int64 `json:"size"`
|
|
|
|
LastModifiedDateTime *time.Time `json:"lastModifiedDateTime"`
|
|
|
|
Url string `json:"@microsoft.graph.downloadUrl"`
|
|
|
|
File struct {
|
|
|
|
MimeType string `json:"mimeType"`
|
|
|
|
} `json:"file"`
|
2021-11-30 08:27:23 +00:00
|
|
|
Thumbnails []struct{
|
|
|
|
Medium struct{
|
|
|
|
Url string `json:"url"`
|
|
|
|
} `json:"medium"`
|
|
|
|
} `json:"thumbnails"`
|
2021-11-27 12:20:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type OneFiles struct {
|
|
|
|
Value []OneFile `json:"value"`
|
|
|
|
NextLink string `json:"@odata.nextLink"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type OneRespErr struct {
|
|
|
|
Error struct {
|
|
|
|
Code string `json:"code"`
|
|
|
|
Message string `json:"message"`
|
|
|
|
} `json:"error"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func (driver Onedrive) FormatFile(file *OneFile) *model.File {
|
|
|
|
f := &model.File{
|
|
|
|
Name: file.Name,
|
|
|
|
Size: file.Size,
|
|
|
|
UpdatedAt: file.LastModifiedDateTime,
|
2021-11-30 01:37:51 +00:00
|
|
|
Driver: driver.Config().Name,
|
2021-11-27 12:20:14 +00:00
|
|
|
Url: file.Url,
|
|
|
|
}
|
2021-11-30 08:27:23 +00:00
|
|
|
if len(file.Thumbnails) > 0 {
|
|
|
|
f.Thumbnail = file.Thumbnails[0].Medium.Url
|
|
|
|
}
|
2021-11-27 12:20:14 +00:00
|
|
|
if file.File.MimeType == "" {
|
|
|
|
f.Type = conf.FOLDER
|
|
|
|
} else {
|
|
|
|
f.Type = utils.GetFileType(filepath.Ext(file.Name))
|
|
|
|
}
|
|
|
|
return f
|
|
|
|
}
|
|
|
|
|
|
|
|
func (driver Onedrive) GetFiles(account *model.Account, path string) ([]OneFile, error) {
|
|
|
|
var res []OneFile
|
2021-11-30 08:27:23 +00:00
|
|
|
nextLink := driver.GetMetaUrl(account, false, path) + "/children?$expand=thumbnails"
|
2021-11-27 12:20:14 +00:00
|
|
|
if account.OrderBy != "" {
|
2021-11-30 08:27:23 +00:00
|
|
|
nextLink += fmt.Sprintf("&orderby=%s", account.OrderBy)
|
2021-11-27 12:20:14 +00:00
|
|
|
if account.OrderDirection != "" {
|
2021-12-01 03:25:04 +00:00
|
|
|
nextLink += fmt.Sprintf("%%20%s", account.OrderDirection)
|
2021-11-27 12:20:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
for nextLink != "" {
|
|
|
|
var files OneFiles
|
|
|
|
var e OneRespErr
|
|
|
|
_, err := oneClient.R().SetResult(&files).SetError(&e).
|
|
|
|
SetHeader("Authorization", "Bearer "+account.AccessToken).
|
|
|
|
Get(nextLink)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if e.Error.Code != "" {
|
|
|
|
return nil, fmt.Errorf("%s", e.Error.Message)
|
|
|
|
}
|
|
|
|
res = append(res, files.Value...)
|
|
|
|
nextLink = files.NextLink
|
|
|
|
}
|
|
|
|
return res, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (driver Onedrive) GetFile(account *model.Account, path string) (*OneFile, error) {
|
|
|
|
var file OneFile
|
|
|
|
var e OneRespErr
|
|
|
|
_, err := oneClient.R().SetResult(&file).SetError(&e).
|
|
|
|
SetHeader("Authorization", "Bearer "+account.AccessToken).
|
|
|
|
Get(driver.GetMetaUrl(account, false, path))
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if e.Error.Code != "" {
|
|
|
|
return nil, fmt.Errorf("%s", e.Error.Message)
|
|
|
|
}
|
|
|
|
return &file, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func init() {
|
2021-12-06 07:55:05 +00:00
|
|
|
base.RegisterDriver(&Onedrive{})
|
2021-11-27 12:20:14 +00:00
|
|
|
oneClient.SetRetryCount(3)
|
|
|
|
}
|