commit 430b4cf723a79b315eeca02e574d7bb64cd2733e Author: 微凉 <36558727+Xhofe@users.noreply.github.com> Date: Thu Dec 24 01:39:45 2020 +0800 Initial commit diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..dfe07704 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..d62ae77d --- /dev/null +++ b/.gitignore @@ -0,0 +1,23 @@ +.idea/ +.DS_Store +output/ + +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib +*.db +*.bin + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ +*.yml +bin/* \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..d2dba1c9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 微凉 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 00000000..4bad1448 --- /dev/null +++ b/README.md @@ -0,0 +1,15 @@ + + +#### TODO + +- [ ] 搜索与翻页 +- [x] 排序 +- [ ] 文件预览 + - [ ] 图片([viewerjs](https://github.com/fengyuanchen/viewerjs)) + - [ ] 视频 ([vue-dplayer](https://github.com/MoePlayer/vue-dplayer)) + - [ ] 音频([vue-aplayer](https://github.com/SevenOutman/vue-aplayer)) +- [ ] Readme渲染 +- [ ] 路径优化(不要重复请求) +- [x] 密码加密 +- [ ] 缓存 + diff --git a/alidrive/auth.go b/alidrive/auth.go new file mode 100644 index 00000000..972e6ff5 --- /dev/null +++ b/alidrive/auth.go @@ -0,0 +1,74 @@ +package alidrive + +import ( + "encoding/json" + "fmt" + "github.com/Xhofe/alist/conf" + "github.com/Xhofe/alist/utils" + log "github.com/sirupsen/logrus" +) + +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) +} + +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 +} + +func RefreshToken() bool { + log.Infof("刷新token...") + url:="https://websv.aliyundrive.com/token/refresh" + req:=RefreshTokenReq{RefreshToken:conf.Conf.AliDrive.RefreshToken} + var token TokenResp + if body, err := DoPost(url, req,false); err != nil { + log.Errorf("tokenLogin-doPost出错:%s",err.Error()) + return false + }else { + if err = json.Unmarshal(body,&token);err!=nil { + log.Errorf("解析json[%s]出错:%s",string(body),err.Error()) + log.Errorf("此处json解析失败应该是refresh_token失效") + return false + } + } + //刷新成功 更新token + conf.Conf.AliDrive.AccessToken=token.AccessToken + conf.Conf.AliDrive.RefreshToken=token.RefreshToken + conf.Authorization=token.TokenType+"\t"+token.AccessToken + return true +} diff --git a/alidrive/const.go b/alidrive/const.go new file mode 100644 index 00000000..ca6fecc1 --- /dev/null +++ b/alidrive/const.go @@ -0,0 +1,5 @@ +package alidrive + +var ( + User *UserInfo +) diff --git a/alidrive/req_bean.go b/alidrive/req_bean.go new file mode 100644 index 00000000..a899dbe1 --- /dev/null +++ b/alidrive/req_bean.go @@ -0,0 +1,46 @@ +package alidrive + +type ListReq struct { + DriveId string `json:"drive_id"` + Fields string `json:"fields"` + ImageThumbnailProcess string `json:"image_thumbnail_process"` + ImageUrlProcess string `json:"image_url_process"` + Limit int `json:"limit"` + Marker string `json:"marker"` + OrderBy string `json:"order_by"` + OrderDirection string `json:"order_direction"` + ParentFileId string `json:"parent_file_id"` + VideoThumbnailProcess string `json:"video_thumbnail_process"` +} + +type GetReq struct { + DriveId string `json:"drive_id"` + FileId string `json:"file_id"` + ImageThumbnailProcess string `json:"image_thumbnail_process"` + VideoThumbnailProcess string `json:"video_thumbnail_process"` +} + +type SearchReq struct { + DriveId string `json:"drive_id"` + ImageThumbnailProcess string `json:"image_thumbnail_process"` + ImageUrlProcess string `json:"image_url_process"` + Limit int `json:"limit"` + Marker string `json:"marker"` + OrderBy string `json:"order_by"`//"type ASC,updated_at DESC" + + Query string `json:"query"`// "name match '测试文件'" + + VideoThumbnailProcess string `json:"video_thumbnail_process"` +} + +type TokenLoginReq struct { + Token string `json:"token"` +} + +type GetTokenReq struct { + Code string `json:"code"` +} + +type RefreshTokenReq struct { + RefreshToken string `json:"refresh_token"` +} \ No newline at end of file diff --git a/alidrive/request.go b/alidrive/request.go new file mode 100644 index 00000000..91f726d4 --- /dev/null +++ b/alidrive/request.go @@ -0,0 +1,200 @@ +package alidrive + +import ( + "bytes" + "encoding/json" + "fmt" + "github.com/Xhofe/alist/conf" + log "github.com/sirupsen/logrus" + "io/ioutil" + "net/http" + "strings" + "time" +) + +func GetFile(fileId string) (*File, error) { + url:=conf.Conf.AliDrive.ApiUrl+"/file/get" + req:=GetReq{ + DriveId: User.DefaultDriveId, + FileId: fileId, + ImageThumbnailProcess: conf.ImageThumbnailProcess, + VideoThumbnailProcess: conf.VideoThumbnailProcess, + } + var file File + if body, err := DoPost(url, req,true); err != nil { + log.Errorf("doPost出错:%s",err.Error()) + return nil,err + }else { + if err = json.Unmarshal(body,&file);err !=nil { + log.Errorf("解析json[%s]出错:%s",string(body),err.Error()) + return nil,err + } + } + if file.IsAvailable() { + return &file,nil + } + if file.Code==conf.AccessTokenInvalid { + if RefreshToken() { + return GetFile(fileId) + } + } + return nil,fmt.Errorf(file.Message) +} + +func Search(key string,limit int, marker string) (*Files, error) { + url:=conf.Conf.AliDrive.ApiUrl+"/file/search" + req:=SearchReq{ + DriveId: User.DefaultDriveId, + ImageThumbnailProcess: conf.ImageThumbnailProcess, + ImageUrlProcess: conf.ImageUrlProcess, + Limit: limit, + Marker: marker, + OrderBy: conf.OrderSearch, + Query: fmt.Sprintf("name match '%s'",key), + VideoThumbnailProcess: conf.VideoThumbnailProcess, + } + var files Files + if body, err := DoPost(url, req,true); err != nil { + log.Errorf("doPost出错:%s",err.Error()) + return nil,err + }else { + if err = json.Unmarshal(body,&files);err !=nil { + log.Errorf("解析json[%s]出错:%s",string(body),err.Error()) + return nil,err + } + } + if files.IsAvailable() { + return &files,nil + } + if files.Code==conf.AccessTokenInvalid { + if RefreshToken() { + return Search(key,limit,marker) + } + } + return nil,fmt.Errorf(files.Message) +} + +func GetRoot(limit int,marker string,orderBy string,orderDirection string) (*Files,error) { + return GetList(conf.Conf.AliDrive.RootFolder,limit,marker,orderBy,orderDirection) +} + +func GetList(parent string,limit int,marker string,orderBy string,orderDirection string) (*Files,error) { + url:=conf.Conf.AliDrive.ApiUrl+"/file/list" + req:=ListReq{ + DriveId: User.DefaultDriveId, + Fields: "*", + ImageThumbnailProcess: conf.ImageThumbnailProcess, + ImageUrlProcess: conf.ImageUrlProcess, + Limit: limit, + Marker: marker, + OrderBy: orderBy, + OrderDirection: orderDirection, + ParentFileId: parent, + VideoThumbnailProcess: conf.VideoThumbnailProcess, + } + var files Files + if body, err := DoPost(url, req,true); err != nil { + log.Errorf("doPost出错:%s",err.Error()) + return nil,err + }else { + if err = json.Unmarshal(body,&files);err !=nil { + log.Errorf("解析json[%s]出错:%s",string(body),err.Error()) + return nil,err + } + } + if files.IsAvailable() { + return &files,nil + } + if files.Code==conf.AccessTokenInvalid { + if RefreshToken() { + return GetRoot(limit,marker,orderBy,orderDirection) + } + } + return nil,fmt.Errorf(files.Message) +} + +func GetUserInfo() (*UserInfo,error) { + url:=conf.Conf.AliDrive.ApiUrl+"/user/get" + var user UserInfo + if body, err := DoPost(url, map[string]interface{}{},true); err != nil { + log.Errorf("doPost出错:%s",err.Error()) + return nil,err + }else { + if err = json.Unmarshal(body,&user);err !=nil { + log.Errorf("解析json[%s]出错:%s",string(body),err.Error()) + return nil,err + } + } + if user.IsAvailable() { + return &user,nil + } + if user.Code==conf.AccessTokenInvalid { + if RefreshToken() { + return GetUserInfo() + } + } + return nil,fmt.Errorf(user.Message) +} + +func DoPost(url string,request interface{},auth bool) (body []byte, err error) { + var( + resp *http.Response + ) + requestBody := new(bytes.Buffer) + err = json.NewEncoder(requestBody).Encode(request) + if err !=nil { + log.Errorf("创建requestBody出错:%s",err.Error()) + } + req,err:=http.NewRequest("POST",url,requestBody) + log.Debugf("do_post_req:%v",req) + if err != nil { + log.Errorf("创建request出错:%s",err.Error()) + return + } + if auth { + req.Header.Set("authorization",conf.Authorization) + } + 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("origin","https://aliyundrive.com") + req.Header.Add("accept","*/*") + req.Header.Add("Accept-Language", "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3") + req.Header.Add("Connection", "keep-alive") + + for retryCount := 3; retryCount >= 0; retryCount-- { + if resp,err=conf.Client.Do(req);err!=nil&&strings.Contains(err.Error(),"timeout") { + <- time.After(time.Second) + }else { + break + } + } + if err!=nil { + log.Errorf("请求阿里云盘api时出错:%s",err.Error()) + return + } + if body, err = ioutil.ReadAll(resp.Body); err != nil { + log.Errorf("读取api返回内容失败") + } + 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 +} \ No newline at end of file diff --git a/alidrive/resp_bean.go b/alidrive/resp_bean.go new file mode 100644 index 00000000..f69a2855 --- /dev/null +++ b/alidrive/resp_bean.go @@ -0,0 +1,135 @@ +package alidrive + +import ( + log "github.com/sirupsen/logrus" + "io/ioutil" + "net/http" + "strings" + "time" +) + +type RespError struct { + Code string `json:"code"` + Message string `json:"message"` +} + +type UserInfo struct { + RespError + DomainId string `json:"domain_id"` + UserId string `json:"user_id"` + Avatar string `json:"avatar"` + CreatedAt int `json:"created_at"` + UpdatedAt int `json:"updated_at"` + Email string `json:"email"` + NickName string `json:"nick_name"` + Phone string `json:"phone"` + Role string `json:"role"` + Status string `json:"status"` + UserName string `json:"user_name"` + Description string `json:"description"` + DefaultDriveId string `json:"default_drive_id"` + UserData map[string]interface{} `json:"user_data"` +} + +type Files struct { + RespError + Items []File `json:"items"` + NextMarker string `json:"next_marker"` + Readme string `json:"readme"` + Paths []Path `json:"paths"` +} + +type Path struct { + Name string `json:"name"` + FileId string `json:"file_id"` +} + +type File struct { + RespError + DriveId string `json:"drive_id"` + CreatedAt *time.Time `json:"created_at"` + DomainId string `json:"domain_id"` + EncryptMode string `json:"encrypt_mode"` + FileExtension string `json:"file_extension"` + FileId string `json:"file_id"` + Hidden bool `json:"hidden"` + Name string `json:"name"` + ParentFileId string `json:"parent_file_id"` + Starred bool `json:"starred"` + Status string `json:"status"` + Type string `json:"type"` + UpdatedAt *time.Time `json:"updated_at"` + // 文件多出部分 + Category string `json:"category"` + ContentHash string `json:"content_hash"` + ContentHashName string `json:"content_hash_name"` + ContentType string `json:"content_type"` + Crc64Hash string `json:"crc_64_hash"` + DownloadUrl string `json:"download_url"` + PunishFlag int `json:"punish_flag"` + Size int `json:"size"` + Thumbnail string `json:"thumbnail"` + Url string `json:"url"` + ImageMediaMetadata map[string]interface{} `json:"image_media_metadata"` + + Paths []Path `json:"paths"` +} + +func (resp *RespError) IsAvailable() bool { + return resp.Code == "" +} + +type TokenLoginResp struct { + RespError + Goto string `json:"goto"` +} + +type TokenResp struct { + RespError + AccessToken string `json:"access_token"` + RefreshToken string `json:"refresh_token"` + ExpiresIn int `json:"expires_in"` + TokenType string `json:"token_type"` + + UserInfo + + DefaultSboxDriveId string `json:"default_sbox_drive_id"` + ExpireTime *time.Time `json:"expire_time"` + State string `json:"state"` + ExistLink []interface{} `json:"exist_link"` + NeedLink bool `json:"need_link"` + PinSetup bool `json:"pin_setup"` + IsFirstLogin bool `json:"is_first_login"` + NeedRpVerify bool `json:"need_rp_verify"` + DeviceId string `json:"device_id"` +} + +func HasPassword(files *Files) string { + fileList := files.Items + for _, file := range fileList { + if strings.HasPrefix(file.Name, ".password-") { + return file.Name[10:] + } + } + return "" +} + +func HasReadme(files *Files) string { + fileList := files.Items + for _, file := range fileList { + if file.Name == "Readme.md" { + resp, err := http.Get(file.Url) + if err != nil { + log.Errorf("Get Readme出错:%s", err.Error()) + return "" + } + data, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.Errorf("读取 Readme出错:%s", err.Error()) + return "" + } + return string(data) + } + } + return "" +} diff --git a/alist.go b/alist.go new file mode 100644 index 00000000..07572821 --- /dev/null +++ b/alist.go @@ -0,0 +1,7 @@ +package main + +import "github.com/Xhofe/alist/bootstrap" + +func main() { + bootstrap.Run() +} \ No newline at end of file diff --git a/bootstrap/alidrive.go b/bootstrap/alidrive.go new file mode 100644 index 00000000..36dd1edd --- /dev/null +++ b/bootstrap/alidrive.go @@ -0,0 +1,34 @@ +package bootstrap + +import ( + "github.com/Xhofe/alist/alidrive" + "github.com/Xhofe/alist/conf" + log "github.com/sirupsen/logrus" +) + +func InitAliDrive() bool { + //首先token_login + if conf.Conf.AliDrive.RefreshToken == "" { + tokenLogin,err:=alidrive.TokenLogin() + if err!=nil { + log.Errorf("登录失败:%s",err.Error()) + return false + } + //然后get_token + token,err:=alidrive.GetToken(tokenLogin) + if err!=nil { + return false + } + conf.Authorization=token.TokenType+" "+token.AccessToken + } + conf.Authorization=conf.Bearer+conf.Conf.AliDrive.AccessToken + log.Infof("token:%s",conf.Authorization) + user,err:=alidrive.GetUserInfo() + if err != nil { + log.Errorf("初始化用户失败:%s",err.Error()) + return false + } + log.Infof("当前用户信息:%v",user) + alidrive.User=user + return true +} diff --git a/bootstrap/client.go b/bootstrap/client.go new file mode 100644 index 00000000..38895fe2 --- /dev/null +++ b/bootstrap/client.go @@ -0,0 +1,10 @@ +package bootstrap + +import ( + "github.com/Xhofe/alist/conf" + "net/http" +) + +func InitClient() { + conf.Client=&http.Client{} +} \ No newline at end of file diff --git a/bootstrap/cmd.go b/bootstrap/cmd.go new file mode 100644 index 00000000..06a38db8 --- /dev/null +++ b/bootstrap/cmd.go @@ -0,0 +1,64 @@ +package bootstrap + +import ( + "flag" + "github.com/Xhofe/alist/conf" + serv "github.com/Xhofe/alist/server" + "github.com/gin-gonic/gin" + log "github.com/sirupsen/logrus" +) + +func init() { + flag.BoolVar(&conf.Debug,"debug",false,"use debug mode") + flag.BoolVar(&conf.Help,"help",false,"show usage help") + flag.StringVar(&conf.Con,"conf","conf.yml","config file") +} + +func Run() { + flag.Parse() + if conf.Help { + flag.Usage() + return + } + start() +} + +func printASC() { + log.Info(` + ________ ___ ___ ________ _________ +|\ __ \|\ \ |\ \|\ ____\|\___ ___\ +\ \ \|\ \ \ \ \ \ \ \ \___|\|___ \ \_| + \ \ __ \ \ \ \ \ \ \_____ \ \ \ \ + \ \ \ \ \ \ \____\ \ \|____|\ \ \ \ \ + \ \__\ \__\ \_______\ \__\____\_\ \ \ \__\ + \|__|\|__|\|_______|\|__|\_________\ \|__| + \|_________| +`) +} + +func start() { + InitLog() + printASC() + InitClient() + if !ReadConf(conf.Con) { + log.Errorf("读取配置文件时出现错误,启动失败.") + return + } + if !InitAliDrive() { + log.Errorf("初始化阿里云盘出现错误,启动失败.") + return + } + InitCron() + server() +} + +func server() { + baseServer:="0.0.0.0:"+conf.Conf.Server.Port + log.Infof("Starting server @ %s",baseServer) + r:=gin.Default() + serv.InitRouter(r) + err:=r.Run(baseServer) + if err!=nil { + log.Errorf("Server failed start:%s",err.Error()) + } +} \ No newline at end of file diff --git a/bootstrap/config.go b/bootstrap/config.go new file mode 100644 index 00000000..a25d5c29 --- /dev/null +++ b/bootstrap/config.go @@ -0,0 +1,28 @@ +package bootstrap + +import ( + "github.com/Xhofe/alist/conf" + "github.com/Xhofe/alist/utils" + log "github.com/sirupsen/logrus" + "gopkg.in/yaml.v2" + "io/ioutil" +) + +func ReadConf(config string) bool { + if !utils.Exists(config) { + log.Infof("找不到配置文件:%s",config) + return false + } + confFile,err:=ioutil.ReadFile(config) + if err !=nil { + log.Errorf("读取配置文件时发生错误:%s",err.Error()) + return false + } + err = yaml.Unmarshal(confFile, conf.Conf) + if err !=nil { + log.Errorf("加载配置文件时发生错误:%s",err.Error()) + return false + } + log.Debugf("config:%v",conf.Conf) + return true +} \ No newline at end of file diff --git a/bootstrap/cron.go b/bootstrap/cron.go new file mode 100644 index 00000000..0b411e14 --- /dev/null +++ b/bootstrap/cron.go @@ -0,0 +1,26 @@ +package bootstrap + +import ( + "github.com/Xhofe/alist/alidrive" + "github.com/Xhofe/alist/conf" + "github.com/Xhofe/alist/utils" + "github.com/robfig/cron/v3" + log "github.com/sirupsen/logrus" +) + +var Cron *cron.Cron + +func refreshToken() { + alidrive.RefreshToken() + utils.WriteToYml(conf.Con,conf.Conf) +} + +func InitCron() { + log.Infof("初始化定时任务:刷新token") + Cron=cron.New() + _,err:=Cron.AddFunc("@every 2h",refreshToken) + if err!=nil { + log.Errorf("添加启动任务失败:%s",err.Error()) + } + Cron.Start() +} \ No newline at end of file diff --git a/bootstrap/log.go b/bootstrap/log.go new file mode 100644 index 00000000..20885dd0 --- /dev/null +++ b/bootstrap/log.go @@ -0,0 +1,21 @@ +package bootstrap + +import ( + "github.com/Xhofe/alist/conf" + "github.com/gin-gonic/gin" + log "github.com/sirupsen/logrus" +) + +func InitLog() { + if conf.Debug { + log.SetLevel(log.DebugLevel) + }else { + gin.SetMode(gin.ReleaseMode) + } + log.SetFormatter(&log.TextFormatter{ + ForceColors:true, + EnvironmentOverrideColors:true, + TimestampFormat:"2006-01-02 15:04:05", + FullTimestamp:true, + }) +} \ No newline at end of file diff --git a/conf.yml.example b/conf.yml.example new file mode 100644 index 00000000..743a4eca --- /dev/null +++ b/conf.yml.example @@ -0,0 +1,11 @@ +server: + site_url: http://localhost + port: 5244 + search: true +ali_drive: + api_url: https://api.aliyundrive.com/v2 + root_folder: root + token: + access_token: + refresh_token: need + max_files_count: 3000 \ No newline at end of file diff --git a/conf/config.go b/conf/config.go new file mode 100644 index 00000000..1565cd0d --- /dev/null +++ b/conf/config.go @@ -0,0 +1,18 @@ +package conf + +type Config struct { + Server struct{ + SiteUrl string `yaml:"site_url"`//网站url + Port string `yaml:"port"`//端口 + Search bool `yaml:"search"`//允许搜索 + } `yaml:"server"` + AliDrive struct{ + ApiUrl string `yaml:"api_url"`//阿里云盘api + RootFolder string `yaml:"root_folder"`//根目录id + //Authorization string `yaml:"authorization"`//授权token + LoginToken string `yaml:"login_token"` + AccessToken string `yaml:"access_token"` + RefreshToken string `yaml:"refresh_token"` + MaxFilesCount int `yaml:"max_files_count"` + } `yaml:"ali_drive"` +} \ No newline at end of file diff --git a/conf/const.go b/conf/const.go new file mode 100644 index 00000000..f2b6335d --- /dev/null +++ b/conf/const.go @@ -0,0 +1,30 @@ +package conf + +import ( + "net/http" +) + +var( + Debug bool + Help bool + Con string + Client *http.Client + Authorization string +) + +var Conf = new(Config) + +const ( + ImageThumbnailProcess="image/resize,w_50" + VideoThumbnailProcess="video/snapshot,t_0,f_jpg,w_50" + ImageUrlProcess="image/resize,w_1920/format,jpeg" + ASC="ASC" + DESC="DESC" + OrderUpdatedAt="updated_at" + OrderCreatedAt="created_at" + OrderSize="size" + OrderName="name" + OrderSearch="type ASC,updated_at DESC" + AccessTokenInvalid="AccessTokenInvalid" + Bearer="Bearer\t" +) \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 00000000..5f730fdd --- /dev/null +++ b/go.mod @@ -0,0 +1,20 @@ +module github.com/Xhofe/alist + +go 1.15 + +require ( + github.com/gin-gonic/gin v1.6.3 + github.com/go-playground/validator/v10 v10.4.1 // indirect + github.com/golang/protobuf v1.4.3 // indirect + github.com/json-iterator/go v1.1.10 // indirect + github.com/leodido/go-urn v1.2.1 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.1 // indirect + github.com/robfig/cron/v3 v3.0.0 + github.com/sirupsen/logrus v1.7.0 + github.com/ugorji/go v1.2.2 // indirect + golang.org/x/crypto v0.0.0-20201217014255-9d1352758620 // indirect + golang.org/x/sys v0.0.0-20201218084310-7d0127a74742 // indirect + google.golang.org/protobuf v1.25.0 // indirect + gopkg.in/yaml.v2 v2.4.0 +) diff --git a/go.sum b/go.sum new file mode 100644 index 00000000..258a2b34 --- /dev/null +++ b/go.sum @@ -0,0 +1,142 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14= +github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= +github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= +github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= +github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= +github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY= +github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= +github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE= +github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= +github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= +github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= +github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/robfig/cron/v3 v3.0.0 h1:kQ6Cb7aHOHTSzNVNEhmp8EcWKLb4CbiMW9h9VyIhO4E= +github.com/robfig/cron/v3 v3.0.0/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= +github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= +github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= +github.com/ugorji/go v1.2.2 h1:60ZHIOcsJlo3bJm9CbTVu7OSqT2mxaEmyQbK2NwCkn0= +github.com/ugorji/go v1.2.2/go.mod h1:bitgyERdV7L7Db/Z5gfd5v2NQMNhhiFiZwpgMw2SP7k= +github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= +github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/ugorji/go/codec v1.2.2 h1:08Gah8d+dXj4cZNUHhtuD/S4PXD5WpVbj5B8/ClELAQ= +github.com/ugorji/go/codec v1.2.2/go.mod h1:OM8g7OAy52uYl3Yk+RE/3AS1nXFn1Wh4PPLtupCxbuU= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201217014255-9d1352758620 h1:3wPMTskHO3+O6jqTEXyFcsnuxMQOqYSaHsDxcbUXpqA= +golang.org/x/crypto v0.0.0-20201217014255-9d1352758620/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201218084310-7d0127a74742 h1:+CBz4km/0KPU3RGTwARGh/noP3bEwtHcq+0YcBQM2JQ= +golang.org/x/sys v0.0.0-20201218084310-7d0127a74742/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/server/common.go b/server/common.go new file mode 100644 index 00000000..0b9d773d --- /dev/null +++ b/server/common.go @@ -0,0 +1,22 @@ +package server + +import "github.com/gin-gonic/gin" + +func metaResponse(code int, msg string) gin.H { + return gin.H{ + "meta":gin.H{ + "code":code, + "msg":msg, + }, + } +} + +func dataResponse(data interface{}) gin.H { + return gin.H{ + "meta":gin.H{ + "code":200, + "msg":"success", + }, + "data":data, + } +} \ No newline at end of file diff --git a/server/controllers.go b/server/controllers.go new file mode 100644 index 00000000..99d1920f --- /dev/null +++ b/server/controllers.go @@ -0,0 +1,102 @@ +package server + +import ( + "github.com/Xhofe/alist/alidrive" + "github.com/Xhofe/alist/conf" + "github.com/gin-gonic/gin" + log "github.com/sirupsen/logrus" +) + +// TODO:添加前置路由信息 + +func Get(c *gin.Context) { + var get alidrive.GetReq + if err := c.ShouldBindJSON(&get); err != nil { + c.JSON(200,metaResponse(400,"Bad Request")) + return + } + log.Debugf("get:%v",get) + file,err:=alidrive.GetFile(get.FileId) + if err !=nil { + c.JSON(200,metaResponse(500,err.Error())) + return + } + paths,err:=alidrive.GetPaths(get.FileId) + if err!=nil { + c.JSON(200,metaResponse(500,err.Error())) + return + } + file.Paths=*paths + c.JSON(200,dataResponse(file)) +} + +func List(c *gin.Context) { + var list ListReq + if err := c.ShouldBindJSON(&list);err!=nil { + c.JSON(200,metaResponse(400,"Bad Request")) + return + } + log.Debugf("list:%v",list) + var ( + files *alidrive.Files + err error + ) + if list.Limit == 0 { + list.Limit=50 + } + if conf.Conf.AliDrive.MaxFilesCount!=0 { + list.Limit=conf.Conf.AliDrive.MaxFilesCount + } + if list.ParentFileId == "root" { + files,err=alidrive.GetRoot(list.Limit,list.Marker,list.OrderBy,list.OrderDirection) + }else { + files,err=alidrive.GetList(list.ParentFileId,list.Limit,list.Marker,list.OrderBy,list.OrderDirection) + } + if err!=nil { + c.JSON(200,metaResponse(500,err.Error())) + return + } + password:=alidrive.HasPassword(files) + if password!="" && password!=list.Password { + if list.Password=="" { + c.JSON(200,metaResponse(401,"need password.")) + return + } + c.JSON(200,metaResponse(401,"wrong password.")) + return + } + paths,err:=alidrive.GetPaths(list.ParentFileId) + if err!=nil { + c.JSON(200,metaResponse(500,err.Error())) + return + } + files.Paths=*paths + files.Readme=alidrive.HasReadme(files) + c.JSON(200,dataResponse(files)) +} + +func Search(c *gin.Context) { + if !conf.Conf.Server.Search { + c.JSON(200,metaResponse(403,"Not allow search.")) + return + } + var search alidrive.SearchReq + if err := c.ShouldBindJSON(&search); err != nil { + c.JSON(200,metaResponse(400,"Bad Request")) + return + } + log.Debugf("search:%v",search) + if search.Limit == 0 { + search.Limit=50 + } + // Search只支持0-100 + //if conf.Conf.AliDrive.MaxFilesCount!=0 { + // search.Limit=conf.Conf.AliDrive.MaxFilesCount + //} + files,err:=alidrive.Search(search.Query,search.Limit,search.OrderBy) + if err != nil { + c.JSON(200,metaResponse(500,err.Error())) + return + } + c.JSON(200,dataResponse(files)) +} \ No newline at end of file diff --git a/server/middlewares.go b/server/middlewares.go new file mode 100644 index 00000000..84c55c21 --- /dev/null +++ b/server/middlewares.go @@ -0,0 +1,27 @@ +package server + +import ( + "github.com/gin-gonic/gin" + "net/http" +) + +func CrosHandler() gin.HandlerFunc { + return func(context *gin.Context) { + method := context.Request.Method + context.Writer.Header().Set("Access-Control-Allow-Origin", "*") + context.Header("Access-Control-Allow-Origin", "*") // 设置允许访问所有域 + context.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE,UPDATE") + context.Header("Access-Control-Allow-Headers", "Authorization, Content-Length, X-CSRF-Token, Token,session,X_Requested_With,Accept, Origin, Host, Connection, Accept-Encoding, Accept-Language,DNT, X-CustomHeader, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Pragma,token,openid,opentoken") + context.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers,Cache-Control,Content-Language,Content-Type,Expires,Last-Modified,Pragma,FooBar") + context.Header("Access-Control-Max-Age", "172800") + context.Header("Access-Control-Allow-Credentials", "false") + context.Set("content-type", "application/json") //设置返回格式是json + + if method == "OPTIONS" { + context.JSON(http.StatusOK, metaResponse(200,"Options Request!")) + } + + //处理请求 + context.Next() + } +} \ No newline at end of file diff --git a/server/req_bean.go b/server/req_bean.go new file mode 100644 index 00000000..2c335b4d --- /dev/null +++ b/server/req_bean.go @@ -0,0 +1,8 @@ +package server + +import "github.com/Xhofe/alist/alidrive" + +type ListReq struct { + Password string `json:"password"` + alidrive.ListReq +} \ No newline at end of file diff --git a/server/router.go b/server/router.go new file mode 100644 index 00000000..f71660f3 --- /dev/null +++ b/server/router.go @@ -0,0 +1,17 @@ +package server + +import "github.com/gin-gonic/gin" + +func InitRouter(engine *gin.Engine) { + engine.Use(CrosHandler()) + InitApiRouter(engine) +} + +func InitApiRouter(engine *gin.Engine) { + v2:=engine.Group("/api/v2") + { + v2.POST("/get",Get) + v2.POST("/list",List) + v2.POST("/search",Search) + } +} \ No newline at end of file diff --git a/test/alidrive_test.go b/test/alidrive_test.go new file mode 100644 index 00000000..3c2b0ef8 --- /dev/null +++ b/test/alidrive_test.go @@ -0,0 +1,40 @@ +package test + +import ( + "fmt" + "github.com/Xhofe/alist/alidrive" + "github.com/Xhofe/alist/bootstrap" + "github.com/Xhofe/alist/conf" + "testing" +) + +func init() { + bootstrap.InitLog() + bootstrap.ReadConf("../conf.yml") + bootstrap.InitClient() + bootstrap.InitAliDrive() +} + +func TestGetUserInfo(t *testing.T) { + user,err:= alidrive.GetUserInfo() + fmt.Println(err) + fmt.Println(user) +} + +func TestGetRoot(t *testing.T) { + files,err:=alidrive.GetRoot(50,"",conf.OrderUpdatedAt,conf.DESC) + fmt.Println(err) + fmt.Println(files) +} + +func TestSearch(t *testing.T) { + files,err:=alidrive.Search("测试文件",50,"") + fmt.Println(err) + fmt.Println(files) +} + +func TestGet(t *testing.T) { + file,err:=alidrive.GetFile("5fb7c80e85e4f335cd344008be1b1b5349f74414") + fmt.Println(err) + fmt.Println(file) +} \ No newline at end of file diff --git a/test/utils_test.go b/test/utils_test.go new file mode 100644 index 00000000..45eef8c7 --- /dev/null +++ b/test/utils_test.go @@ -0,0 +1,18 @@ +package test + +import ( + "fmt" + "github.com/Xhofe/alist/alidrive" + "github.com/Xhofe/alist/conf" + "github.com/Xhofe/alist/utils" + "testing" +) + +func TestStr(t *testing.T) { + fmt.Println(".password-"[10:]) +} + +func TestWriteYml(t *testing.T) { + alidrive.RefreshToken() + utils.WriteToYml("../conf.yml",conf.Conf) +} \ No newline at end of file diff --git a/utils/check.go b/utils/check.go new file mode 100644 index 00000000..f6db06f1 --- /dev/null +++ b/utils/check.go @@ -0,0 +1,16 @@ +package utils + +import ( + log "github.com/sirupsen/logrus" + "net/url" +) + +func GetCode(rawUrl string) string { + u,err:=url.Parse(rawUrl) + if err!=nil { + log.Errorf("解析url出错:%s",err.Error()) + return "" + } + code:=u.Query().Get("code") + return code +} \ No newline at end of file diff --git a/utils/file.go b/utils/file.go new file mode 100644 index 00000000..846a7f90 --- /dev/null +++ b/utils/file.go @@ -0,0 +1,41 @@ +package utils + +import ( + log "github.com/sirupsen/logrus" + "gopkg.in/yaml.v2" + "io/ioutil" + "os" + "path/filepath" +) + +func Exists(name string) bool { + if _, err := os.Stat(name); err != nil { + if os.IsNotExist(err) { + return false + } + } + return true +} + +func CreatNestedFile(path string) (*os.File, error) { + basePath := filepath.Dir(path) + if !Exists(basePath) { + err := os.MkdirAll(basePath, 0700) + if err != nil { + log.Errorf("无法创建目录,%s", err) + return nil, err + } + } + return os.Create(path) +} + +func WriteToYml(src string,conf interface{}){ + data,err := yaml.Marshal(conf) + if err!=nil { + log.Errorf("Conf转[]byte失败:%s",err.Error()) + } + err = ioutil.WriteFile(src,data,0777) + if err!=nil { + log.Errorf("写yml文件失败",err.Error()) + } +} \ No newline at end of file