🎇 多盘支持
This commit is contained in:
@ -2,77 +2,44 @@ package alidrive
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
|
||||||
"github.com/Xhofe/alist/conf"
|
"github.com/Xhofe/alist/conf"
|
||||||
"github.com/Xhofe/alist/utils"
|
"github.com/Xhofe/alist/utils"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
// use token login
|
|
||||||
func TokenLogin() (*TokenLoginResp, error) {
|
|
||||||
log.Infof("尝试使用token登录...")
|
|
||||||
url := "https://auth.aliyundrive.com/v2/oauth/token_login"
|
|
||||||
req := TokenLoginReq{Token: conf.Conf.AliDrive.LoginToken}
|
|
||||||
log.Debugf("token_login_req:%+v", req)
|
|
||||||
var tokenLogin TokenLoginResp
|
|
||||||
if body, err := DoPost(url, req, false); err != nil {
|
|
||||||
log.Errorf("tokenLogin-doPost出错:%s", err.Error())
|
|
||||||
return nil, err
|
|
||||||
} else {
|
|
||||||
if err = json.Unmarshal(body, &tokenLogin); err != nil {
|
|
||||||
log.Errorf("解析json[%s]出错:%s", string(body), err.Error())
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if tokenLogin.IsAvailable() {
|
|
||||||
return &tokenLogin, nil
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("登录token失效,请更换:%s", tokenLogin.Message)
|
|
||||||
}
|
|
||||||
|
|
||||||
// get access token
|
|
||||||
func GetToken(tokenLogin *TokenLoginResp) (*TokenResp, error) {
|
|
||||||
log.Infof("获取API token...")
|
|
||||||
url := "https://websv.aliyundrive.com/token/get"
|
|
||||||
code := utils.GetCode(tokenLogin.Goto)
|
|
||||||
if code == "" {
|
|
||||||
return nil, fmt.Errorf("获取code出错")
|
|
||||||
}
|
|
||||||
req := GetTokenReq{Code: code}
|
|
||||||
var token TokenResp
|
|
||||||
if body, err := DoPost(url, req, false); err != nil {
|
|
||||||
log.Errorf("tokenLogin-doPost出错:%s", err.Error())
|
|
||||||
return nil, err
|
|
||||||
} else {
|
|
||||||
if err = json.Unmarshal(body, &token); err != nil {
|
|
||||||
log.Errorf("解析json[%s]出错:%s", string(body), err.Error())
|
|
||||||
log.Errorf("此处json解析失败应该是code失效")
|
|
||||||
return nil, fmt.Errorf("code失效")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &token, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// refresh access_token token by refresh_token
|
// refresh access_token token by refresh_token
|
||||||
func RefreshToken() bool {
|
func RefreshToken(drive *conf.Drive) bool {
|
||||||
log.Infof("刷新token...")
|
log.Infof("刷新[%s]token...", drive.Name)
|
||||||
url := "https://websv.aliyundrive.com/token/refresh"
|
url := "https://websv.aliyundrive.com/token/refresh"
|
||||||
req := RefreshTokenReq{RefreshToken: conf.Conf.AliDrive.RefreshToken}
|
req := RefreshTokenReq{RefreshToken: drive.RefreshToken}
|
||||||
var token TokenResp
|
var token TokenResp
|
||||||
if body, err := DoPost(url, req, false); err != nil {
|
if body, err := DoPost(url, req, ""); err != nil {
|
||||||
log.Errorf("tokenLogin-doPost出错:%s", err.Error())
|
log.Errorf("tokenLogin-doPost出错:%s", err.Error())
|
||||||
return false
|
return false
|
||||||
} else {
|
} else {
|
||||||
if err = json.Unmarshal(body, &token); err != nil {
|
if err = json.Unmarshal(body, &token); err != nil {
|
||||||
log.Errorf("解析json[%s]出错:%s", string(body), err.Error())
|
log.Errorf("解析json[%s]出错:%s", string(body), err.Error())
|
||||||
log.Errorf("此处json解析失败应该是refresh_token失效")
|
log.Errorf("此处json解析失败应该是[%s]refresh_token失效", drive.Name)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//刷新成功 更新token并写入文件
|
//刷新成功 更新token
|
||||||
conf.Conf.AliDrive.AccessToken = token.AccessToken
|
drive.AccessToken = token.AccessToken
|
||||||
conf.Conf.AliDrive.RefreshToken = token.RefreshToken
|
drive.RefreshToken = token.RefreshToken
|
||||||
conf.Authorization = token.TokenType + "\t" + token.AccessToken
|
|
||||||
utils.WriteToYml(conf.Con, conf.Conf)
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func RefreshTokenAll() string {
|
||||||
|
log.Infof("刷新所有token...")
|
||||||
|
res := ""
|
||||||
|
for i, drive := range conf.Conf.AliDrive.Drives {
|
||||||
|
if !RefreshToken(&conf.Conf.AliDrive.Drives[i]) {
|
||||||
|
res = res + drive.Name + ","
|
||||||
|
}
|
||||||
|
}
|
||||||
|
utils.WriteToYml(conf.ConfigFile, conf.Conf)
|
||||||
|
if res != "" {
|
||||||
|
return res[:len(res)-1]
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
@ -1,5 +0,0 @@
|
|||||||
package alidrive
|
|
||||||
|
|
||||||
var (
|
|
||||||
User *UserInfo
|
|
||||||
)
|
|
@ -13,41 +13,41 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// get file
|
// get file
|
||||||
func GetFile(fileId string) (*File, error) {
|
func GetFile(fileId string, drive *conf.Drive) (*File, error) {
|
||||||
url := conf.Conf.AliDrive.ApiUrl + "/file/get"
|
url := conf.Conf.AliDrive.ApiUrl + "/file/get"
|
||||||
req := GetReq{
|
req := GetReq{
|
||||||
DriveId: User.DefaultDriveId,
|
DriveId: drive.DefaultDriveId,
|
||||||
FileId: fileId,
|
FileId: fileId,
|
||||||
ImageThumbnailProcess: conf.ImageThumbnailProcess,
|
ImageThumbnailProcess: conf.ImageThumbnailProcess,
|
||||||
VideoThumbnailProcess: conf.VideoThumbnailProcess,
|
VideoThumbnailProcess: conf.VideoThumbnailProcess,
|
||||||
}
|
}
|
||||||
var resp File
|
var resp File
|
||||||
if err := BodyToJson(url, req, &resp, true); err != nil {
|
if err := BodyToJson(url, req, &resp, drive); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &resp, nil
|
return &resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// get download_url
|
// get download_url
|
||||||
func GetDownLoadUrl(fileId string) (*DownloadResp, error) {
|
func GetDownLoadUrl(fileId string, drive *conf.Drive) (*DownloadResp, error) {
|
||||||
url := conf.Conf.AliDrive.ApiUrl + "/file/get_download_url"
|
url := conf.Conf.AliDrive.ApiUrl + "/file/get_download_url"
|
||||||
req := DownloadReq{
|
req := DownloadReq{
|
||||||
DriveId: User.DefaultDriveId,
|
DriveId: drive.DefaultDriveId,
|
||||||
FileId: fileId,
|
FileId: fileId,
|
||||||
ExpireSec: 14400,
|
ExpireSec: 14400,
|
||||||
}
|
}
|
||||||
var resp DownloadResp
|
var resp DownloadResp
|
||||||
if err := BodyToJson(url, req, &resp, true); err != nil {
|
if err := BodyToJson(url, req, &resp, drive); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &resp, nil
|
return &resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// search by keyword
|
// search by keyword
|
||||||
func Search(key string, limit int, marker string) (*Files, error) {
|
func Search(key string, limit int, marker string, drive *conf.Drive) (*Files, error) {
|
||||||
url := conf.Conf.AliDrive.ApiUrl + "/file/search"
|
url := conf.Conf.AliDrive.ApiUrl + "/file/search"
|
||||||
req := SearchReq{
|
req := SearchReq{
|
||||||
DriveId: User.DefaultDriveId,
|
DriveId: drive.DefaultDriveId,
|
||||||
ImageThumbnailProcess: conf.ImageThumbnailProcess,
|
ImageThumbnailProcess: conf.ImageThumbnailProcess,
|
||||||
ImageUrlProcess: conf.ImageUrlProcess,
|
ImageUrlProcess: conf.ImageUrlProcess,
|
||||||
Limit: limit,
|
Limit: limit,
|
||||||
@ -57,22 +57,22 @@ func Search(key string, limit int, marker string) (*Files, error) {
|
|||||||
VideoThumbnailProcess: conf.VideoThumbnailProcess,
|
VideoThumbnailProcess: conf.VideoThumbnailProcess,
|
||||||
}
|
}
|
||||||
var resp Files
|
var resp Files
|
||||||
if err := BodyToJson(url, req, &resp, true); err != nil {
|
if err := BodyToJson(url, req, &resp, drive); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &resp, nil
|
return &resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// get root folder
|
// get root folder
|
||||||
func GetRoot(limit int, marker string, orderBy string, orderDirection string) (*Files, error) {
|
func GetRoot(limit int, marker string, orderBy string, orderDirection string, drive *conf.Drive) (*Files, error) {
|
||||||
return GetList(conf.Conf.AliDrive.RootFolder, limit, marker, orderBy, orderDirection)
|
return GetList(drive.RootFolder, limit, marker, orderBy, orderDirection, drive)
|
||||||
}
|
}
|
||||||
|
|
||||||
// get folder list by file_id
|
// get folder list by file_id
|
||||||
func GetList(parent string, limit int, marker string, orderBy string, orderDirection string) (*Files, error) {
|
func GetList(parent string, limit int, marker string, orderBy string, orderDirection string, drive *conf.Drive) (*Files, error) {
|
||||||
url := conf.Conf.AliDrive.ApiUrl + "/file/list"
|
url := conf.Conf.AliDrive.ApiUrl + "/file/list"
|
||||||
req := ListReq{
|
req := ListReq{
|
||||||
DriveId: User.DefaultDriveId,
|
DriveId: drive.DefaultDriveId,
|
||||||
Fields: "*",
|
Fields: "*",
|
||||||
ImageThumbnailProcess: conf.ImageThumbnailProcess,
|
ImageThumbnailProcess: conf.ImageThumbnailProcess,
|
||||||
ImageUrlProcess: conf.ImageUrlProcess,
|
ImageUrlProcess: conf.ImageUrlProcess,
|
||||||
@ -84,40 +84,40 @@ func GetList(parent string, limit int, marker string, orderBy string, orderDirec
|
|||||||
VideoThumbnailProcess: conf.VideoThumbnailProcess,
|
VideoThumbnailProcess: conf.VideoThumbnailProcess,
|
||||||
}
|
}
|
||||||
var resp Files
|
var resp Files
|
||||||
if err := BodyToJson(url, req, &resp, true); err != nil {
|
if err := BodyToJson(url, req, &resp, drive); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &resp, nil
|
return &resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// get user info
|
// get user info
|
||||||
func GetUserInfo() (*UserInfo, error) {
|
func GetUserInfo(drive *conf.Drive) (*UserInfo, error) {
|
||||||
url := conf.Conf.AliDrive.ApiUrl + "/user/get"
|
url := conf.Conf.AliDrive.ApiUrl + "/user/get"
|
||||||
var resp UserInfo
|
var resp UserInfo
|
||||||
if err := BodyToJson(url, map[string]interface{}{}, &resp, true); err != nil {
|
if err := BodyToJson(url, map[string]interface{}{}, &resp, drive); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &resp, nil
|
return &resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// get office preview url and token
|
// get office preview url and token
|
||||||
func GetOfficePreviewUrl(fileId string) (*OfficePreviewUrlResp, error) {
|
func GetOfficePreviewUrl(fileId string, drive *conf.Drive) (*OfficePreviewUrlResp, error) {
|
||||||
url := conf.Conf.AliDrive.ApiUrl + "/file/get_office_preview_url"
|
url := conf.Conf.AliDrive.ApiUrl + "/file/get_office_preview_url"
|
||||||
req := OfficePreviewUrlReq{
|
req := OfficePreviewUrlReq{
|
||||||
AccessToken: conf.Conf.AliDrive.AccessToken,
|
AccessToken: drive.AccessToken,
|
||||||
DriveId: User.DefaultDriveId,
|
DriveId: drive.DefaultDriveId,
|
||||||
FileId: fileId,
|
FileId: fileId,
|
||||||
}
|
}
|
||||||
var resp OfficePreviewUrlResp
|
var resp OfficePreviewUrlResp
|
||||||
if err := BodyToJson(url, req, &resp, true); err != nil {
|
if err := BodyToJson(url, req, &resp, drive); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &resp, nil
|
return &resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert body to json
|
// convert body to json
|
||||||
func BodyToJson(url string, req interface{}, resp RespHandle, auth bool) error {
|
func BodyToJson(url string, req interface{}, resp RespHandle, drive *conf.Drive) error {
|
||||||
if body, err := DoPost(url, req, auth); err != nil {
|
if body, err := DoPost(url, req, drive.AccessToken); err != nil {
|
||||||
log.Errorf("doPost出错:%s", err.Error())
|
log.Errorf("doPost出错:%s", err.Error())
|
||||||
return err
|
return err
|
||||||
} else {
|
} else {
|
||||||
@ -131,15 +131,15 @@ func BodyToJson(url string, req interface{}, resp RespHandle, auth bool) error {
|
|||||||
}
|
}
|
||||||
if resp.GetCode() == conf.AccessTokenInvalid {
|
if resp.GetCode() == conf.AccessTokenInvalid {
|
||||||
resp.SetCode("")
|
resp.SetCode("")
|
||||||
if RefreshToken() {
|
if RefreshToken(drive) {
|
||||||
return BodyToJson(url, req, resp, auth)
|
return BodyToJson(url, req, resp, drive)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return fmt.Errorf(resp.GetMessage())
|
return fmt.Errorf(resp.GetMessage())
|
||||||
}
|
}
|
||||||
|
|
||||||
// do post request
|
// do post request
|
||||||
func DoPost(url string, request interface{}, auth bool) (body []byte, err error) {
|
func DoPost(url string, request interface{}, auth string) (body []byte, err error) {
|
||||||
var (
|
var (
|
||||||
resp *http.Response
|
resp *http.Response
|
||||||
)
|
)
|
||||||
@ -154,8 +154,8 @@ func DoPost(url string, request interface{}, auth bool) (body []byte, err error)
|
|||||||
log.Errorf("创建request出错:%s", err.Error())
|
log.Errorf("创建request出错:%s", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if auth {
|
if auth != "" {
|
||||||
req.Header.Set("authorization", conf.Authorization)
|
req.Header.Set("authorization", conf.Bearer + auth)
|
||||||
}
|
}
|
||||||
req.Header.Add("content-type", "application/json")
|
req.Header.Add("content-type", "application/json")
|
||||||
req.Header.Add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36")
|
req.Header.Add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36")
|
||||||
@ -181,24 +181,3 @@ func DoPost(url string, request interface{}, auth bool) (body []byte, err error)
|
|||||||
log.Debugf("请求返回信息:%s", string(body))
|
log.Debugf("请求返回信息:%s", string(body))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetPaths(fileId string) (*[]Path, error) {
|
|
||||||
paths := make([]Path, 0)
|
|
||||||
for fileId != conf.Conf.AliDrive.RootFolder && fileId != "root" {
|
|
||||||
file, err := GetFile(fileId)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("获取path出错:%s", err.Error())
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
paths = append(paths, Path{
|
|
||||||
Name: file.Name,
|
|
||||||
FileId: file.FileId,
|
|
||||||
})
|
|
||||||
fileId = file.ParentFileId
|
|
||||||
}
|
|
||||||
paths = append(paths, Path{
|
|
||||||
Name: "Root",
|
|
||||||
FileId: "root",
|
|
||||||
})
|
|
||||||
return &paths, nil
|
|
||||||
}
|
|
||||||
|
@ -10,28 +10,24 @@ import (
|
|||||||
func InitAliDrive() bool {
|
func InitAliDrive() bool {
|
||||||
log.Infof("初始化阿里云盘...")
|
log.Infof("初始化阿里云盘...")
|
||||||
//首先token_login
|
//首先token_login
|
||||||
if conf.Conf.AliDrive.RefreshToken == "" {
|
res := alidrive.RefreshTokenAll()
|
||||||
tokenLogin, err := alidrive.TokenLogin()
|
if res != "" {
|
||||||
if err != nil {
|
log.Errorf("盘[%s]refresh_token失效,请检查", res)
|
||||||
log.Errorf("登录失败:%s", err.Error())
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
//然后get_token
|
|
||||||
token, err := alidrive.GetToken(tokenLogin)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
conf.Authorization = token.TokenType + "\t" + token.AccessToken
|
|
||||||
} else {
|
|
||||||
conf.Authorization = conf.Bearer + conf.Conf.AliDrive.AccessToken
|
|
||||||
}
|
}
|
||||||
log.Debugf("token:%s", conf.Authorization)
|
log.Debugf("config:%+v", conf.Conf)
|
||||||
user, err := alidrive.GetUserInfo()
|
for i, _ := range conf.Conf.AliDrive.Drives {
|
||||||
if err != nil {
|
InitDriveId(&conf.Conf.AliDrive.Drives[i])
|
||||||
log.Errorf("初始化用户失败:%s", err.Error())
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
log.Infof("当前用户信息:%+v", user)
|
return true
|
||||||
alidrive.User = user
|
}
|
||||||
|
|
||||||
|
func InitDriveId(drive *conf.Drive) bool {
|
||||||
|
user, err := alidrive.GetUserInfo(drive)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("初始化盘[%s]失败:%s", drive.Name, err.Error())
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
drive.DefaultDriveId = user.DefaultDriveId
|
||||||
|
log.Infof("初始化盘[%s]成功:%+v", drive.Name, user)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ func init() {
|
|||||||
flag.BoolVar(&conf.Debug, "debug", false, "use debug mode")
|
flag.BoolVar(&conf.Debug, "debug", false, "use debug mode")
|
||||||
flag.BoolVar(&conf.Help, "help", false, "show usage help")
|
flag.BoolVar(&conf.Help, "help", false, "show usage help")
|
||||||
flag.BoolVar(&conf.Version, "version", false, "show version info")
|
flag.BoolVar(&conf.Version, "version", false, "show version info")
|
||||||
flag.StringVar(&conf.Con, "conf", "conf.yml", "config file")
|
flag.StringVar(&conf.ConfigFile, "conf", "conf.yml", "config file")
|
||||||
flag.BoolVar(&conf.SkipUpdate, "skip-update", false, "skip update")
|
flag.BoolVar(&conf.SkipUpdate, "skip-update", false, "skip update")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ func start() {
|
|||||||
if !conf.SkipUpdate {
|
if !conf.SkipUpdate {
|
||||||
CheckUpdate()
|
CheckUpdate()
|
||||||
}
|
}
|
||||||
if !ReadConf(conf.Con) {
|
if !ReadConf(conf.ConfigFile) {
|
||||||
log.Errorf("读取配置文件时出现错误,启动失败.")
|
log.Errorf("读取配置文件时出现错误,启动失败.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ func ReadConf(config string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
log.Debugf("config:%+v", conf.Conf)
|
log.Debugf("config:%+v", conf.Conf)
|
||||||
|
conf.Conf.Info.Roots = utils.GetNames()
|
||||||
conf.Origins = strings.Split(conf.Conf.Server.SiteUrl, ",")
|
conf.Origins = strings.Split(conf.Conf.Server.SiteUrl, ",")
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ var Cron *cron.Cron
|
|||||||
|
|
||||||
// refresh token func for cron
|
// refresh token func for cron
|
||||||
func refreshToken() {
|
func refreshToken() {
|
||||||
alidrive.RefreshToken()
|
alidrive.RefreshTokenAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
// init cron jobs
|
// init cron jobs
|
||||||
|
@ -33,9 +33,7 @@ func InitModel() bool {
|
|||||||
log.Errorf("数据库迁移失败:%s", err.Error())
|
log.Errorf("数据库迁移失败:%s", err.Error())
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if err := models.BuildTree(); err != nil {
|
models.BuildTreeAll()
|
||||||
log.Errorf("构建目录树失败:%s", err.Error())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,27 @@
|
|||||||
package conf
|
package conf
|
||||||
|
|
||||||
|
type Drive struct {
|
||||||
|
AccessToken string `yaml:"-"`
|
||||||
|
RefreshToken string `yaml:"refresh_token"`
|
||||||
|
RootFolder string `yaml:"root_folder"` //根目录id
|
||||||
|
Name string `yaml:"name"`
|
||||||
|
Password string `yaml:"password"`
|
||||||
|
Hide bool `yaml:"hide"`
|
||||||
|
DefaultDriveId string `yaml:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
// config struct
|
// config struct
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Info struct {
|
Info struct {
|
||||||
Title string `yaml:"title" json:"title"`
|
Title string `yaml:"title" json:"title"`
|
||||||
Logo string `yaml:"logo" json:"logo"`
|
Roots []string `yaml:"-" json:"roots"`
|
||||||
FooterText string `yaml:"footer_text" json:"footer_text"`
|
Logo string `yaml:"logo" json:"logo"`
|
||||||
FooterUrl string `yaml:"footer_url" json:"footer_url"`
|
FooterText string `yaml:"footer_text" json:"footer_text"`
|
||||||
MusicImg string `yaml:"music_img" json:"music_img"`
|
FooterUrl string `yaml:"footer_url" json:"footer_url"`
|
||||||
CheckUpdate bool `yaml:"check_update" json:"check_update"`
|
MusicImg string `yaml:"music_img" json:"music_img"`
|
||||||
Script string `yaml:"script" json:"script"`
|
CheckUpdate bool `yaml:"check_update" json:"check_update"`
|
||||||
Autoplay bool `yaml:"autoplay" json:"autoplay"`
|
Script string `yaml:"script" json:"script"`
|
||||||
|
Autoplay bool `yaml:"autoplay" json:"autoplay"`
|
||||||
Preview struct {
|
Preview struct {
|
||||||
Url string `yaml:"url" json:"url"`
|
Url string `yaml:"url" json:"url"`
|
||||||
PreProcess []string `yaml:"pre_process" json:"pre_process"`
|
PreProcess []string `yaml:"pre_process" json:"pre_process"`
|
||||||
@ -27,13 +38,9 @@ type Config struct {
|
|||||||
Password string `yaml:"password"`
|
Password string `yaml:"password"`
|
||||||
} `yaml:"server"`
|
} `yaml:"server"`
|
||||||
AliDrive struct {
|
AliDrive struct {
|
||||||
ApiUrl string `yaml:"api_url"` //阿里云盘api
|
ApiUrl string `yaml:"api_url"` //阿里云盘api
|
||||||
RootFolder string `yaml:"root_folder"` //根目录id
|
MaxFilesCount int `yaml:"max_files_count"`
|
||||||
//Authorization string `yaml:"authorization"`//授权token
|
Drives []Drive `yaml:"drives"`
|
||||||
LoginToken string `yaml:"login_token"`
|
|
||||||
AccessToken string `yaml:"access_token"`
|
|
||||||
RefreshToken string `yaml:"refresh_token"`
|
|
||||||
MaxFilesCount int `yaml:"max_files_count"`
|
|
||||||
} `yaml:"ali_drive"`
|
} `yaml:"ali_drive"`
|
||||||
Database struct {
|
Database struct {
|
||||||
Type string `yaml:"type"`
|
Type string `yaml:"type"`
|
||||||
|
@ -9,11 +9,10 @@ var (
|
|||||||
Debug bool // is debug command
|
Debug bool // is debug command
|
||||||
Help bool // is help command
|
Help bool // is help command
|
||||||
Version bool // is print version command
|
Version bool // is print version command
|
||||||
Con string // config file
|
ConfigFile string // config file
|
||||||
SkipUpdate bool // skip update
|
SkipUpdate bool // skip update
|
||||||
|
|
||||||
Client *http.Client // request client
|
Client *http.Client // request client
|
||||||
Authorization string // authorization string
|
|
||||||
|
|
||||||
DB *gorm.DB
|
DB *gorm.DB
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DownReq struct {
|
type DownReq struct {
|
||||||
@ -44,7 +45,12 @@ func Down(c *gin.Context) {
|
|||||||
c.JSON(200, MetaResponse(406, "无法下载目录."))
|
c.JSON(200, MetaResponse(406, "无法下载目录."))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
file, err := alidrive.GetDownLoadUrl(fileModel.FileId)
|
drive := utils.GetDriveByName(strings.Split(dir,"/")[0])
|
||||||
|
if drive == nil {
|
||||||
|
c.JSON(200, MetaResponse(500, "找不到drive."))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
file, err := alidrive.GetDownLoadUrl(fileModel.FileId, drive)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(200, MetaResponse(500, err.Error()))
|
c.JSON(200, MetaResponse(500, err.Error()))
|
||||||
return
|
return
|
||||||
|
@ -3,9 +3,11 @@ package controllers
|
|||||||
import (
|
import (
|
||||||
"github.com/Xhofe/alist/alidrive"
|
"github.com/Xhofe/alist/alidrive"
|
||||||
"github.com/Xhofe/alist/server/models"
|
"github.com/Xhofe/alist/server/models"
|
||||||
|
"github.com/Xhofe/alist/utils"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// get request bean
|
// get request bean
|
||||||
@ -40,7 +42,12 @@ func Get(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
down, err := alidrive.GetDownLoadUrl(file.FileId)
|
drive := utils.GetDriveByName(strings.Split(dir,"/")[0])
|
||||||
|
if drive == nil {
|
||||||
|
c.JSON(200, MetaResponse(500, "找不到drive."))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
down, err := alidrive.GetDownLoadUrl(file.FileId, drive)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(200, MetaResponse(500, err.Error()))
|
c.JSON(200, MetaResponse(500, err.Error()))
|
||||||
return
|
return
|
||||||
|
@ -2,6 +2,7 @@ package controllers
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/Xhofe/alist/alidrive"
|
"github.com/Xhofe/alist/alidrive"
|
||||||
|
"github.com/Xhofe/alist/utils"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
@ -12,13 +13,18 @@ type OfficePreviewReq struct {
|
|||||||
|
|
||||||
// handle office_preview request
|
// handle office_preview request
|
||||||
func OfficePreview(c *gin.Context) {
|
func OfficePreview(c *gin.Context) {
|
||||||
|
drive := utils.GetDriveByName(c.Param("drive"))
|
||||||
|
if drive == nil {
|
||||||
|
c.JSON(200, MetaResponse(400, "drive isn't exist."))
|
||||||
|
return
|
||||||
|
}
|
||||||
var req OfficePreviewReq
|
var req OfficePreviewReq
|
||||||
if err := c.ShouldBindJSON(&req); err != nil {
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
c.JSON(200, MetaResponse(400, "Bad Request:"+err.Error()))
|
c.JSON(200, MetaResponse(400, "Bad Request:"+err.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Debugf("preview_req:%+v", req)
|
log.Debugf("preview_req:%+v", req)
|
||||||
preview, err := alidrive.GetOfficePreviewUrl(req.FileId)
|
preview, err := alidrive.GetOfficePreviewUrl(req.FileId, drive)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(200, MetaResponse(500, err.Error()))
|
c.JSON(200, MetaResponse(500, err.Error()))
|
||||||
return
|
return
|
||||||
|
@ -55,7 +55,11 @@ func Path(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
// delete password
|
// delete password
|
||||||
for i, _ := range *files {
|
for i, _ := range *files {
|
||||||
(*files)[i].Password = ""
|
if (*files)[i].Password == "" {
|
||||||
|
(*files)[i].Password = "n"
|
||||||
|
}else {
|
||||||
|
(*files)[i].Password = "y"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
c.JSON(200, DataResponse(files))
|
c.JSON(200, DataResponse(files))
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package controllers
|
|||||||
import (
|
import (
|
||||||
"github.com/Xhofe/alist/conf"
|
"github.com/Xhofe/alist/conf"
|
||||||
"github.com/Xhofe/alist/server/models"
|
"github.com/Xhofe/alist/server/models"
|
||||||
|
"github.com/Xhofe/alist/utils"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -13,7 +14,12 @@ func Info(c *gin.Context) {
|
|||||||
|
|
||||||
// rebuild tree
|
// rebuild tree
|
||||||
func RebuildTree(c *gin.Context) {
|
func RebuildTree(c *gin.Context) {
|
||||||
password := c.Param("password")[1:]
|
drive := utils.GetDriveByName(c.Param("drive"))
|
||||||
|
if drive == nil {
|
||||||
|
c.JSON(200, MetaResponse(400, "drive isn't exist."))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
password := c.Param("password")
|
||||||
if password != conf.Conf.Server.Password {
|
if password != conf.Conf.Server.Password {
|
||||||
if password == "" {
|
if password == "" {
|
||||||
c.JSON(200, MetaResponse(401, "need password."))
|
c.JSON(200, MetaResponse(401, "need password."))
|
||||||
@ -22,11 +28,11 @@ func RebuildTree(c *gin.Context) {
|
|||||||
c.JSON(200, MetaResponse(401, "wrong password."))
|
c.JSON(200, MetaResponse(401, "wrong password."))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := models.Clear(); err != nil {
|
if err := models.Clear(drive); err != nil {
|
||||||
c.JSON(200, MetaResponse(500, err.Error()))
|
c.JSON(200, MetaResponse(500, err.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := models.BuildTree(); err != nil {
|
if err := models.BuildTree(drive); err != nil {
|
||||||
c.JSON(200, MetaResponse(500, err.Error()))
|
c.JSON(200, MetaResponse(500, err.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -9,8 +9,18 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func BuildTreeAll() {
|
||||||
|
for i, _ := range conf.Conf.AliDrive.Drives {
|
||||||
|
if err := BuildTree(&conf.Conf.AliDrive.Drives[i]); err != nil {
|
||||||
|
log.Errorf("盘[%s]构建目录树失败:%s", err.Error())
|
||||||
|
}else {
|
||||||
|
log.Infof("盘[%s]构建目录树成功")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// build tree
|
// build tree
|
||||||
func BuildTree() error {
|
func BuildTree(drive *conf.Drive) error {
|
||||||
log.Infof("开始构建目录树...")
|
log.Infof("开始构建目录树...")
|
||||||
tx := conf.DB.Begin()
|
tx := conf.DB.Begin()
|
||||||
defer func() {
|
defer func() {
|
||||||
@ -22,24 +32,25 @@ func BuildTree() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
rootFile := File{
|
rootFile := File{
|
||||||
Dir: "",
|
Dir: "",
|
||||||
FileId: conf.Conf.AliDrive.RootFolder,
|
FileId: drive.RootFolder,
|
||||||
Name: "root",
|
Name: drive.Name,
|
||||||
Type: "folder",
|
Type: "folder",
|
||||||
|
Password: drive.Password,
|
||||||
}
|
}
|
||||||
if err := tx.Create(&rootFile).Error; err != nil {
|
if err := tx.Create(&rootFile).Error; err != nil {
|
||||||
tx.Rollback()
|
tx.Rollback()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := BuildOne(conf.Conf.AliDrive.RootFolder, "root/", tx, ""); err != nil {
|
if err := BuildOne(drive.RootFolder, drive.Name+"/", tx, drive.Password, drive); err != nil {
|
||||||
tx.Rollback()
|
tx.Rollback()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return tx.Commit().Error
|
return tx.Commit().Error
|
||||||
}
|
}
|
||||||
|
|
||||||
func BuildOne(parent string, path string, tx *gorm.DB, parentPassword string) error {
|
func BuildOne(parent string, path string, tx *gorm.DB, parentPassword string, drive *conf.Drive) error {
|
||||||
files, err := alidrive.GetList(parent, conf.Conf.AliDrive.MaxFilesCount, "", "", "")
|
files, err := alidrive.GetList(parent, conf.Conf.AliDrive.MaxFilesCount, "", "", "", drive)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -71,7 +82,7 @@ func BuildOne(parent string, path string, tx *gorm.DB, parentPassword string) er
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if file.Type == "folder" {
|
if file.Type == "folder" {
|
||||||
if err := BuildOne(file.FileId, fmt.Sprintf("%s%s/", path, name), tx, password); err != nil {
|
if err := BuildOne(file.FileId, fmt.Sprintf("%s%s/", path, name), tx, password, drive); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,8 +24,8 @@ func (file *File) Create() error {
|
|||||||
return conf.DB.Create(file).Error
|
return conf.DB.Create(file).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
func Clear() error {
|
func Clear(drive *conf.Drive) error {
|
||||||
return conf.DB.Where("1 = 1").Delete(&File{}).Error
|
return conf.DB.Where("dir like ?", fmt.Sprintf("%s%%", drive.Name)).Delete(&File{}).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetFileByDirAndName(dir, name string) (*File, error) {
|
func GetFileByDirAndName(dir, name string) (*File, error) {
|
||||||
|
@ -26,10 +26,10 @@ func InitApiRouter(engine *gin.Engine) {
|
|||||||
apiV2.GET("/info", controllers.Info)
|
apiV2.GET("/info", controllers.Info)
|
||||||
apiV2.POST("/get", controllers.Get)
|
apiV2.POST("/get", controllers.Get)
|
||||||
apiV2.POST("/path", controllers.Path)
|
apiV2.POST("/path", controllers.Path)
|
||||||
apiV2.POST("/office_preview", controllers.OfficePreview)
|
apiV2.POST("/office_preview/:drive", controllers.OfficePreview)
|
||||||
apiV2.POST("/local_search", controllers.LocalSearch)
|
apiV2.POST("/local_search", controllers.LocalSearch)
|
||||||
apiV2.POST("/global_search", controllers.GlobalSearch)
|
apiV2.POST("/global_search", controllers.GlobalSearch)
|
||||||
apiV2.GET("/rebuild/*password", controllers.RebuildTree)
|
apiV2.GET("/rebuild/:drive/:password", controllers.RebuildTree)
|
||||||
}
|
}
|
||||||
engine.GET("/d/*path", controllers.Down)
|
engine.GET("/d/*path", controllers.Down)
|
||||||
}
|
}
|
||||||
|
22
utils/config.go
Normal file
22
utils/config.go
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import "github.com/Xhofe/alist/conf"
|
||||||
|
|
||||||
|
func GetDriveByName(name string) *conf.Drive {
|
||||||
|
for i, drive := range conf.Conf.AliDrive.Drives{
|
||||||
|
if drive.Name == name {
|
||||||
|
return &conf.Conf.AliDrive.Drives[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetNames() []string {
|
||||||
|
res := make([]string, 0)
|
||||||
|
for _, drive := range conf.Conf.AliDrive.Drives{
|
||||||
|
if !drive.Hide {
|
||||||
|
res = append(res, drive.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
Reference in New Issue
Block a user