diff --git a/common/constants.go b/common/constants.go index f3294a42..7895203f 100644 --- a/common/constants.go +++ b/common/constants.go @@ -83,3 +83,15 @@ const ( UserStatusEnabled = 1 // don't use 0, 0 is the default value! UserStatusDisabled = 2 // also don't use 0 ) + +const ( + ChannelStatusUnknown = 0 + ChannelStatusEnabled = 1 // don't use 0, 0 is the default value! + ChannelStatusDisabled = 2 // also don't use 0 +) + +const ( + ChannelTypeUnknown = 0 + ChannelTypeOpenAI = 1 + ChannelTypeAPI2D = 2 +) diff --git a/controller/channel.go b/controller/channel.go index 1e85e970..6dd81b56 100644 --- a/controller/channel.go +++ b/controller/channel.go @@ -1,15 +1,11 @@ package controller import ( - "fmt" "github.com/gin-gonic/gin" "net/http" "one-api/common" "one-api/model" - "path/filepath" "strconv" - "strings" - "time" ) func GetAllChannels(c *gin.Context) { @@ -17,7 +13,7 @@ func GetAllChannels(c *gin.Context) { if p < 0 { p = 0 } - files, err := model.GetAllChannels(p*common.ItemsPerPage, common.ItemsPerPage) + channels, err := model.GetAllChannels(p*common.ItemsPerPage, common.ItemsPerPage) if err != nil { c.JSON(http.StatusOK, gin.H{ "success": false, @@ -28,14 +24,14 @@ func GetAllChannels(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "success": true, "message": "", - "data": files, + "data": channels, }) return } func SearchChannels(c *gin.Context) { keyword := c.Query("keyword") - files, err := model.SearchChannels(keyword) + channels, err := model.SearchChannels(keyword) if err != nil { c.JSON(http.StatusOK, gin.H{ "success": false, @@ -46,13 +42,13 @@ func SearchChannels(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "success": true, "message": "", - "data": files, + "data": channels, }) return } -func UploadFile(c *gin.Context) { - form, err := c.MultipartForm() +func GetChannel(c *gin.Context) { + id, err := strconv.Atoi(c.Param("id")) if err != nil { c.JSON(http.StatusOK, gin.H{ "success": false, @@ -60,43 +56,39 @@ func UploadFile(c *gin.Context) { }) return } - uploadPath := common.UploadPath - description := c.PostForm("description") - if description == "" { - description = "无描述信息" + channel, err := model.GetChannelById(id) + if err != nil { + c.JSON(http.StatusOK, gin.H{ + "success": false, + "message": err.Error(), + }) + return } - uploader := c.GetString("username") - if uploader == "" { - uploader = "访客用户" + c.JSON(http.StatusOK, gin.H{ + "success": true, + "message": "", + "data": channel, + }) + return +} + +func AddChannel(c *gin.Context) { + channel := model.Channel{} + err := c.ShouldBindJSON(&channel) + if err != nil { + c.JSON(http.StatusOK, gin.H{ + "success": false, + "message": err.Error(), + }) + return } - uploaderId := c.GetInt("id") - currentTime := time.Now().Format("2006-01-02 15:04:05") - files := form.File["file"] - for _, file := range files { - filename := filepath.Base(file.Filename) - ext := filepath.Ext(filename) - link := common.GetUUID() + ext - savePath := filepath.Join(uploadPath, link) // both parts are checked, so this path should be safe to use - if err := c.SaveUploadedFile(file, savePath); err != nil { - c.JSON(http.StatusOK, gin.H{ - "success": false, - "message": err.Error(), - }) - return - } - // save to database - fileObj := &model.Channel{ - Description: description, - Uploader: uploader, - UploadTime: currentTime, - UploaderId: uploaderId, - Link: link, - Filename: filename, - } - err = fileObj.Insert() - if err != nil { - _ = fmt.Errorf(err.Error()) - } + err = channel.Insert() + if err != nil { + c.JSON(http.StatusOK, gin.H{ + "success": false, + "message": err.Error(), + }) + return } c.JSON(http.StatusOK, gin.H{ "success": true, @@ -105,56 +97,45 @@ func UploadFile(c *gin.Context) { return } -func DeleteFile(c *gin.Context) { - fileIdStr := c.Param("id") - fileId, err := strconv.Atoi(fileIdStr) - if err != nil || fileId == 0 { - c.JSON(http.StatusBadRequest, gin.H{ - "success": false, - "message": "无效的参数", - }) - return - } - - fileObj := &model.Channel{ - Id: fileId, - } - model.DB.Where("id = ?", fileId).First(&fileObj) - if fileObj.Link == "" { - c.JSON(http.StatusOK, gin.H{ - "success": false, - "message": "文件不存在!", - }) - return - } - err = fileObj.Delete() +func DeleteChannel(c *gin.Context) { + id, _ := strconv.Atoi(c.Param("id")) + channel := model.Channel{Id: id} + err := channel.Delete() if err != nil { c.JSON(http.StatusOK, gin.H{ - "success": true, + "success": false, "message": err.Error(), }) return - } else { - message := "文件删除成功" - c.JSON(http.StatusOK, gin.H{ - "success": true, - "message": message, - }) } - + c.JSON(http.StatusOK, gin.H{ + "success": true, + "message": "", + }) + return } -func DownloadFile(c *gin.Context) { - path := c.Param("file") - fullPath := filepath.Join(common.UploadPath, path) - if !strings.HasPrefix(fullPath, common.UploadPath) { - // We may being attacked! - c.Status(403) +func UpdateChannel(c *gin.Context) { + channel := model.Channel{} + err := c.ShouldBindJSON(&channel) + if err != nil { + c.JSON(http.StatusOK, gin.H{ + "success": false, + "message": err.Error(), + }) return } - c.File(fullPath) - // Update download counter - go func() { - model.UpdateDownloadCounter(path) - }() + err = channel.Update() + if err != nil { + c.JSON(http.StatusOK, gin.H{ + "success": false, + "message": err.Error(), + }) + return + } + c.JSON(http.StatusOK, gin.H{ + "success": true, + "message": "", + }) + return } diff --git a/model/channel.go b/model/channel.go index eaaba0e8..4badd53c 100644 --- a/model/channel.go +++ b/model/channel.go @@ -2,50 +2,49 @@ package model import ( _ "gorm.io/driver/sqlite" - "gorm.io/gorm" - "one-api/common" - "os" - "path" ) type Channel struct { - Id int `json:"id"` - Filename string `json:"filename" gorm:"index"` - Description string `json:"description"` - Uploader string `json:"uploader" gorm:"index"` - UploaderId int `json:"uploader_id" gorm:"index"` - Link string `json:"link" gorm:"unique;index"` - UploadTime string `json:"upload_time"` - DownloadCounter int `json:"download_counter"` + Id int `json:"id"` + Type int `json:"type" gorm:"default:0"` + Key string `json:"key"` + Status int `json:"status" gorm:"default:1"` } func GetAllChannels(startIdx int, num int) ([]*Channel, error) { - var files []*Channel + var channels []*Channel var err error - err = DB.Order("id desc").Limit(num).Offset(startIdx).Find(&files).Error - return files, err + err = DB.Order("id desc").Limit(num).Offset(startIdx).Find(&channels).Error + return channels, err } -func SearchChannels(keyword string) (files []*Channel, err error) { - err = DB.Select([]string{"id", "filename", "description", "uploader", "uploader_id", "link", "upload_time", "download_counter"}).Where( - "filename LIKE ? or uploader LIKE ? or uploader_id = ?", keyword+"%", keyword+"%", keyword).Find(&files).Error - return files, err +func SearchChannels(keyword string) (channels []*Channel, err error) { + err = DB.Select([]string{"id", "key"}, keyword, keyword).Find(&channels).Error + return channels, err } -func (file *Channel) Insert() error { +func GetChannelById(id int) (*Channel, error) { + channel := Channel{Id: id} + var err error = nil + err = DB.Select([]string{"id", "type"}).First(&channel, "id = ?", id).Error + return &channel, err +} + +func (channel *Channel) Insert() error { var err error - err = DB.Create(file).Error + err = DB.Create(channel).Error + return err +} + +func (channel *Channel) Update() error { + var err error + err = DB.Model(channel).Updates(channel).Error return err } // Delete Make sure link is valid! Because we will use os.Remove to delete it! -func (file *Channel) Delete() error { +func (channel *Channel) Delete() error { var err error - err = DB.Delete(file).Error - err = os.Remove(path.Join(common.UploadPath, file.Link)) + err = DB.Delete(channel).Error return err } - -func UpdateDownloadCounter(link string) { - DB.Model(&Channel{}).Where("link = ?", link).UpdateColumn("download_counter", gorm.Expr("download_counter + 1")) -} diff --git a/router/api-router.go b/router/api-router.go index cc319075..27efe79c 100644 --- a/router/api-router.go +++ b/router/api-router.go @@ -54,13 +54,15 @@ func SetApiRouter(router *gin.Engine) { optionRoute.GET("/", controller.GetOptions) optionRoute.PUT("/", controller.UpdateOption) } - fileRoute := apiRouter.Group("/file") - fileRoute.Use(middleware.AdminAuth()) + channelRoute := apiRouter.Group("/channel") + channelRoute.Use(middleware.AdminAuth()) { - fileRoute.GET("/", controller.GetAllChannels) - fileRoute.GET("/search", controller.SearchChannels) - fileRoute.POST("/", middleware.UploadRateLimit(), controller.UploadFile) - fileRoute.DELETE("/:id", controller.DeleteFile) + channelRoute.GET("/", controller.GetAllChannels) + channelRoute.GET("/search", controller.SearchChannels) + channelRoute.GET("/:id", controller.GetChannel) + channelRoute.POST("/", controller.AddChannel) + channelRoute.PUT("/", controller.UpdateChannel) + channelRoute.DELETE("/:id", controller.DeleteChannel) } } } diff --git a/router/web-router.go b/router/web-router.go index 8201b09e..6b9b3dcf 100644 --- a/router/web-router.go +++ b/router/web-router.go @@ -6,14 +6,11 @@ import ( "github.com/gin-gonic/gin" "net/http" "one-api/common" - "one-api/controller" "one-api/middleware" ) func setWebRouter(router *gin.Engine, buildFS embed.FS, indexPage []byte) { router.Use(middleware.GlobalWebRateLimit()) - fileDownloadRoute := router.Group("/") - fileDownloadRoute.GET("/upload/:file", middleware.DownloadRateLimit(), controller.DownloadFile) router.Use(middleware.Cache()) router.Use(static.Serve("/", common.EmbedFolder(buildFS, "web/build"))) router.NoRoute(func(c *gin.Context) {