diff --git a/bootstrap/model.go b/bootstrap/model.go index 376a526c..b329811b 100644 --- a/bootstrap/model.go +++ b/bootstrap/model.go @@ -12,24 +12,28 @@ import ( func InitModel() bool { log.Infof("初始化数据库...") switch conf.Conf.Database.Type { - case "sqlite3":{ - needMigrate := !utils.Exists(conf.Conf.Database.DBFile) - db, err := gorm.Open(sqlite.Open(conf.Conf.Database.DBFile), &gorm.Config{}) - if err!=nil { - log.Errorf("连接数据库出现错误:%s", err.Error()) - return false - } - conf.DB = db - if needMigrate { - log.Infof("迁移数据库...") - err = conf.DB.AutoMigrate(&models.File{}) - if err !=nil { - log.Errorf("数据库迁移失败:%s",err.Error()) + case "sqlite3": + { + needMigrate := !utils.Exists(conf.Conf.Database.DBFile) + db, err := gorm.Open(sqlite.Open(conf.Conf.Database.DBFile), &gorm.Config{}) + if err != nil { + log.Errorf("连接数据库出现错误:%s", err.Error()) return false } + conf.DB = db + if needMigrate { + log.Infof("迁移数据库...") + err = conf.DB.AutoMigrate(&models.File{}) + if err != nil { + log.Errorf("数据库迁移失败:%s", err.Error()) + return false + } + if err := models.BuildTree(); err != nil { + log.Errorf("构建目录树失败:%s", err.Error()) + } + } + return true } - return true - } default: log.Errorf("不支持的数据库类型:%s", conf.Conf.Database.Type) return false diff --git a/server/controllers/utils.go b/server/controllers/utils.go index 59ae1784..a757c987 100644 --- a/server/controllers/utils.go +++ b/server/controllers/utils.go @@ -2,6 +2,7 @@ package controllers import ( "github.com/Xhofe/alist/conf" + "github.com/Xhofe/alist/server/models" "github.com/gin-gonic/gin" ) @@ -24,4 +25,18 @@ func RefreshCache(c *gin.Context) { } c.JSON(200, MetaResponse(400,"disabled cache.")) return +} + +// rebuild tree +func RebuildTree(c *gin.Context) { + if err:=models.Clear();err!=nil{ + c.JSON(200,MetaResponse(500,err.Error())) + return + } + if err:=models.BuildTree();err!=nil { + c.JSON(200,MetaResponse(500,err.Error())) + return + } + c.JSON(200,MetaResponse(200,"success.")) + return } \ No newline at end of file diff --git a/server/controllers/get.go b/server/controllers/v1/get.go similarity index 80% rename from server/controllers/get.go rename to server/controllers/v1/get.go index 167b669e..7caa40eb 100644 --- a/server/controllers/get.go +++ b/server/controllers/v1/get.go @@ -1,7 +1,8 @@ -package controllers +package v1 import ( "github.com/Xhofe/alist/alidrive" + "github.com/Xhofe/alist/server/controllers" "github.com/gin-gonic/gin" log "github.com/sirupsen/logrus" "strings" @@ -12,7 +13,7 @@ import ( func Get(c *gin.Context) { var get alidrive.GetReq if err := c.ShouldBindJSON(&get); err != nil { - c.JSON(200, MetaResponse(400,"Bad Request")) + c.JSON(200, controllers.MetaResponse(400,"Bad Request")) return } log.Debugf("get:%+v",get) @@ -28,25 +29,25 @@ func Get(c *gin.Context) { //} file,err:=alidrive.GetFile(get.FileId) if err !=nil { - c.JSON(200, MetaResponse(500,err.Error())) + c.JSON(200, controllers.MetaResponse(500,err.Error())) return } paths,err:=alidrive.GetPaths(get.FileId) if err!=nil { - c.JSON(200, MetaResponse(500,err.Error())) + c.JSON(200, controllers.MetaResponse(500,err.Error())) return } file.Paths=*paths download,err:=alidrive.GetDownLoadUrl(get.FileId) if err!=nil { - c.JSON(200, MetaResponse(500,err.Error())) + c.JSON(200, controllers.MetaResponse(500,err.Error())) return } file.DownloadUrl=download.Url //if conf.Conf.Cache.Enable { // conf.Cache.Set(cacheKey,file,cache.DefaultExpiration) //} - c.JSON(200, DataResponse(file)) + c.JSON(200, controllers.DataResponse(file)) } func Down(c *gin.Context) { @@ -64,7 +65,7 @@ func Down(c *gin.Context) { //} file,err:=alidrive.GetDownLoadUrl(fileId) if err != nil { - c.JSON(200, MetaResponse(500,err.Error())) + c.JSON(200, controllers.MetaResponse(500,err.Error())) return } //if conf.Conf.Cache.Enable { diff --git a/server/controllers/list.go b/server/controllers/v1/list.go similarity index 76% rename from server/controllers/list.go rename to server/controllers/v1/list.go index 0282d8a7..1fad61f7 100644 --- a/server/controllers/list.go +++ b/server/controllers/v1/list.go @@ -1,9 +1,10 @@ -package controllers +package v1 import ( "fmt" "github.com/Xhofe/alist/alidrive" "github.com/Xhofe/alist/conf" + "github.com/Xhofe/alist/server/controllers" "github.com/gin-gonic/gin" "github.com/patrickmn/go-cache" log "github.com/sirupsen/logrus" @@ -19,7 +20,7 @@ type ListReq struct { func List(c *gin.Context) { var list ListReq if err := c.ShouldBindJSON(&list);err!=nil { - c.JSON(200, MetaResponse(400,"Bad Request")) + c.JSON(200, controllers.MetaResponse(400,"Bad Request")) return } log.Debugf("list:%+v",list) @@ -29,7 +30,7 @@ func List(c *gin.Context) { files,exist:=conf.Cache.Get(cacheKey) if exist { log.Debugf("使用了缓存:%s",cacheKey) - c.JSON(200, DataResponse(files)) + c.JSON(200, controllers.DataResponse(files)) return } } @@ -49,21 +50,21 @@ func List(c *gin.Context) { files,err=alidrive.GetList(list.ParentFileId,list.Limit,list.Marker,list.OrderBy,list.OrderDirection) } if err!=nil { - c.JSON(200, MetaResponse(500,err.Error())) + c.JSON(200, controllers.MetaResponse(500,err.Error())) return } password:=alidrive.HasPassword(files) if password!="" && password!=list.Password { if list.Password=="" { - c.JSON(200, MetaResponse(401,"need password.")) + c.JSON(200, controllers.MetaResponse(401,"need password.")) return } - c.JSON(200, MetaResponse(401,"wrong password.")) + c.JSON(200, controllers.MetaResponse(401,"wrong password.")) return } paths,err:=alidrive.GetPaths(list.ParentFileId) if err!=nil { - c.JSON(200, MetaResponse(500,err.Error())) + c.JSON(200, controllers.MetaResponse(500,err.Error())) return } files.Paths=*paths @@ -71,5 +72,5 @@ func List(c *gin.Context) { if conf.Conf.Cache.Enable { conf.Cache.Set(cacheKey,files,cache.DefaultExpiration) } - c.JSON(200, DataResponse(files)) + c.JSON(200, controllers.DataResponse(files)) } \ No newline at end of file diff --git a/server/controllers/offie_preview.go b/server/controllers/v1/offie_preview.go similarity index 64% rename from server/controllers/offie_preview.go rename to server/controllers/v1/offie_preview.go index 303aad65..1b0f3821 100644 --- a/server/controllers/offie_preview.go +++ b/server/controllers/v1/offie_preview.go @@ -1,7 +1,8 @@ -package controllers +package v1 import ( "github.com/Xhofe/alist/alidrive" + "github.com/Xhofe/alist/server/controllers" "github.com/gin-gonic/gin" log "github.com/sirupsen/logrus" ) @@ -10,14 +11,14 @@ import ( func OfficePreview(c *gin.Context) { var req alidrive.OfficePreviewUrlReq if err := c.ShouldBindJSON(&req); err != nil { - c.JSON(200, MetaResponse(400,"Bad Request")) + c.JSON(200, controllers.MetaResponse(400,"Bad Request")) return } log.Debugf("preview_req:%+v",req) preview,err:=alidrive.GetOfficePreviewUrl(req.FileId) if err!=nil { - c.JSON(200, MetaResponse(500,err.Error())) + c.JSON(200, controllers.MetaResponse(500,err.Error())) return } - c.JSON(200, DataResponse(preview)) + c.JSON(200, controllers.DataResponse(preview)) } \ No newline at end of file diff --git a/server/controllers/search.go b/server/controllers/v1/search.go similarity index 74% rename from server/controllers/search.go rename to server/controllers/v1/search.go index c9999cd0..f48bcd69 100644 --- a/server/controllers/search.go +++ b/server/controllers/v1/search.go @@ -1,9 +1,10 @@ -package controllers +package v1 import ( "fmt" "github.com/Xhofe/alist/alidrive" "github.com/Xhofe/alist/conf" + "github.com/Xhofe/alist/server/controllers" "github.com/gin-gonic/gin" "github.com/patrickmn/go-cache" log "github.com/sirupsen/logrus" @@ -12,12 +13,12 @@ import ( // handle search request func Search(c *gin.Context) { if !conf.Conf.Server.Search { - c.JSON(200, MetaResponse(403,"Not allow search.")) + c.JSON(200, controllers.MetaResponse(403,"Not allow search.")) return } var search alidrive.SearchReq if err := c.ShouldBindJSON(&search); err != nil { - c.JSON(200, MetaResponse(400,"Bad Request")) + c.JSON(200, controllers.MetaResponse(400,"Bad Request")) return } log.Debugf("search:%+v",search) @@ -27,7 +28,7 @@ func Search(c *gin.Context) { files,exist:=conf.Cache.Get(cacheKey) if exist { log.Debugf("使用了缓存:%s",cacheKey) - c.JSON(200, DataResponse(files)) + c.JSON(200, controllers.DataResponse(files)) return } } @@ -40,11 +41,11 @@ func Search(c *gin.Context) { //} files,err:=alidrive.Search(search.Query,search.Limit,search.OrderBy) if err != nil { - c.JSON(200, MetaResponse(500,err.Error())) + c.JSON(200, controllers.MetaResponse(500,err.Error())) return } if conf.Conf.Cache.Enable { conf.Cache.Set(cacheKey,files,cache.DefaultExpiration) } - c.JSON(200, DataResponse(files)) + c.JSON(200, controllers.DataResponse(files)) } \ No newline at end of file diff --git a/server/controllers/v2/get.go b/server/controllers/v2/get.go new file mode 100644 index 00000000..c9c23fae --- /dev/null +++ b/server/controllers/v2/get.go @@ -0,0 +1,52 @@ +package v2 + +import ( + "github.com/Xhofe/alist/alidrive" + "github.com/Xhofe/alist/server/controllers" + "github.com/Xhofe/alist/server/models" + "github.com/gin-gonic/gin" + log "github.com/sirupsen/logrus" + "path/filepath" +) + +// get request bean +type GetReq struct { + File string `json:"file"` + Password string `json:"password"` +} + +// handle list request +func Get(c *gin.Context) { + var get GetReq + if err := c.ShouldBindJSON(&get); err != nil { + c.JSON(200, controllers.MetaResponse(400, "Bad Request.")) + return + } + log.Debugf("list:%+v", get) + path,name:=filepath.Split(get.File) + file, err := models.GetFileByParentPathAndName(path,name) + if err != nil { + c.JSON(200, controllers.MetaResponse(500, err.Error())) + return + } + c.JSON(200, controllers.DataResponse(file)) +} + +// handle download request +func Down(c *gin.Context) { + filePath:=c.Param("file") + log.Debugf("down:%s",filePath) + path,name:=filepath.Split(filePath) + fileModel, err := models.GetFileByParentPathAndName(path,name) + if err != nil { + c.JSON(200, controllers.MetaResponse(500, err.Error())) + return + } + file,err:=alidrive.GetDownLoadUrl(fileModel.FileId) + if err != nil { + c.JSON(200, controllers.MetaResponse(500,err.Error())) + return + } + c.Redirect(301,file.Url) + return +} diff --git a/server/controllers/v2/list.go b/server/controllers/v2/list.go new file mode 100644 index 00000000..b9f047a4 --- /dev/null +++ b/server/controllers/v2/list.go @@ -0,0 +1,30 @@ +package v2 + +import ( + "github.com/Xhofe/alist/server/controllers" + "github.com/Xhofe/alist/server/models" + "github.com/gin-gonic/gin" + log "github.com/sirupsen/logrus" +) + +// list request bean +type ListReq struct { + Path string `json:"path"` + Password string `json:"password"` +} + +// handle list request +func List(c *gin.Context) { + var list ListReq + if err := c.ShouldBindJSON(&list); err != nil { + c.JSON(200, controllers.MetaResponse(400, "Bad Request.")) + return + } + log.Debugf("list:%+v", list) + files, err := models.GetFilesByParentPath(list.Path) + if err != nil { + c.JSON(200, controllers.MetaResponse(500, err.Error())) + return + } + c.JSON(200, controllers.DataResponse(files)) +} diff --git a/server/models/create.go b/server/models/create.go new file mode 100644 index 00000000..bb4083b7 --- /dev/null +++ b/server/models/create.go @@ -0,0 +1,58 @@ +package models + +import ( + "fmt" + "github.com/Xhofe/alist/alidrive" + "github.com/Xhofe/alist/conf" + log "github.com/sirupsen/logrus" + "gorm.io/gorm" +) + +// build tree +func BuildTree() error { + log.Infof("开始构建目录树...") + tx := conf.DB.Begin() + defer func() { + if r := recover(); r != nil { + tx.Rollback() + } + }() + if err := tx.Error; err != nil { + return err + } + if err := BuildOne(conf.Conf.AliDrive.RootFolder, "/root/", tx); err != nil { + tx.Rollback() + return err + } + return tx.Commit().Error +} + +func BuildOne(parent string, path string, tx *gorm.DB) error { + files, err := alidrive.GetList(parent, conf.Conf.AliDrive.MaxFilesCount, "", "", "") + if err != nil { + return err + } + for _, file := range files.Items { + newFile := File{ + ParentPath: path, + FileExtension: file.FileExtension, + FileId: file.FileId, + Name: file.Name, + Type: file.Type, + UpdatedAt: file.UpdatedAt, + Category: file.Category, + ContentType: file.ContentType, + Size: file.Size, + } + log.Debugf("插入file:%+v", newFile) + if err := tx.Create(&newFile).Error; err != nil { + return err + } + if file.Type == "folder" { + if err := BuildOne(file.FileId, fmt.Sprintf("%s%s/", path, file.Name), tx); err != nil { + return err + } + } + } + return nil +} diff --git a/server/models/file.go b/server/models/file.go index 7ea5a3c5..fef7f5c3 100644 --- a/server/models/file.go +++ b/server/models/file.go @@ -16,16 +16,29 @@ type File struct { Category string `json:"category"` ContentType string `json:"content_type"` Size int64 `json:"size"` + Password string `json:"password"` } func (file *File) Create() error { return conf.DB.Create(file).Error } -func GetFilesByParentPath(parentPath string) (*[]File,error) { +func Clear() error { + return conf.DB.Where("1 = 1").Delete(&File{}).Error +} + +func GetFileByParentPathAndName(parentPath, name string) (*File, error) { + var file File + if err := conf.DB.Where("parent_path = ? AND name = ?", parentPath, name).First(&file).Error; err != nil { + return nil, err + } + return &file, nil +} + +func GetFilesByParentPath(parentPath string) (*[]File, error) { var files []File if err := conf.DB.Where("parent_path = ?", parentPath).Find(&files).Error; err != nil { - return nil,err + return nil, err } return &files, nil } @@ -33,15 +46,15 @@ func GetFilesByParentPath(parentPath string) (*[]File,error) { func SearchByNameGlobal(keyword string) (*[]File, error) { var files []File if err := conf.DB.Where("name LIKE ?", fmt.Sprintf("%%%s%%", keyword)).Find(&files).Error; err != nil { - return nil,err + return nil, err } return &files, nil } func SearchByNameInPath(keyword string, parentPath string) (*[]File, error) { var files []File - if err := conf.DB.Where("parent_path LIKE ? AND name LIKE ?",fmt.Sprintf("%s%%", parentPath), fmt.Sprintf("%%%s%%", keyword)).Find(&files).Error; err != nil { - return nil,err + if err := conf.DB.Where("parent_path LIKE ? AND name LIKE ?", fmt.Sprintf("%s%%", parentPath), fmt.Sprintf("%%%s%%", keyword)).Find(&files).Error; err != nil { + return nil, err } return &files, nil -} \ No newline at end of file +} diff --git a/server/router.go b/server/router.go index 57261c2b..8c34804b 100644 --- a/server/router.go +++ b/server/router.go @@ -3,6 +3,8 @@ package server import ( "github.com/Xhofe/alist/conf" "github.com/Xhofe/alist/server/controllers" + "github.com/Xhofe/alist/server/controllers/v1" + v2 "github.com/Xhofe/alist/server/controllers/v2" "github.com/gin-contrib/static" "github.com/gin-gonic/gin" log "github.com/sirupsen/logrus" @@ -21,14 +23,21 @@ func InitRouter(engine *gin.Engine) { // init api router func InitApiRouter(engine *gin.Engine) { - v2:=engine.Group("/api") + apiV1 :=engine.Group("/api/v1") { - v2.GET("/info",controllers.Info) - v2.POST("/get",controllers.Get) - v2.POST("/list",controllers.List) - v2.POST("/search",controllers.Search) - v2.POST("/office_preview",controllers.OfficePreview) + apiV1.GET("/info",controllers.Info) + apiV1.POST("/get", v1.Get) + apiV1.POST("/list", v1.List) + apiV1.POST("/search", v1.Search) + apiV1.POST("/office_preview", v1.OfficePreview) + apiV1.GET("/d/*file_id", v1.Down) } - engine.GET("/d/*file_id",controllers.Down) + apiV2:=engine.Group("/api") + { + apiV2.POST("/list",v2.List) + apiV2.POST("/get",v2.Get) + } + engine.GET("/d/*file",v2.Down) engine.GET("/cache/:password",controllers.RefreshCache) + engine.GET("/rebuild",controllers.RebuildTree) } \ No newline at end of file