Channel API done without verification

This commit is contained in:
JustSong 2023-04-22 22:02:59 +08:00
parent af96007025
commit 6164829239
5 changed files with 115 additions and 124 deletions

View File

@ -83,3 +83,15 @@ const (
UserStatusEnabled = 1 // don't use 0, 0 is the default value! UserStatusEnabled = 1 // don't use 0, 0 is the default value!
UserStatusDisabled = 2 // also don't use 0 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
)

View File

@ -1,15 +1,11 @@
package controller package controller
import ( import (
"fmt"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"net/http" "net/http"
"one-api/common" "one-api/common"
"one-api/model" "one-api/model"
"path/filepath"
"strconv" "strconv"
"strings"
"time"
) )
func GetAllChannels(c *gin.Context) { func GetAllChannels(c *gin.Context) {
@ -17,7 +13,7 @@ func GetAllChannels(c *gin.Context) {
if p < 0 { if p < 0 {
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 { if err != nil {
c.JSON(http.StatusOK, gin.H{ c.JSON(http.StatusOK, gin.H{
"success": false, "success": false,
@ -28,14 +24,14 @@ func GetAllChannels(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{ c.JSON(http.StatusOK, gin.H{
"success": true, "success": true,
"message": "", "message": "",
"data": files, "data": channels,
}) })
return return
} }
func SearchChannels(c *gin.Context) { func SearchChannels(c *gin.Context) {
keyword := c.Query("keyword") keyword := c.Query("keyword")
files, err := model.SearchChannels(keyword) channels, err := model.SearchChannels(keyword)
if err != nil { if err != nil {
c.JSON(http.StatusOK, gin.H{ c.JSON(http.StatusOK, gin.H{
"success": false, "success": false,
@ -46,13 +42,13 @@ func SearchChannels(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{ c.JSON(http.StatusOK, gin.H{
"success": true, "success": true,
"message": "", "message": "",
"data": files, "data": channels,
}) })
return return
} }
func UploadFile(c *gin.Context) { func GetChannel(c *gin.Context) {
form, err := c.MultipartForm() id, err := strconv.Atoi(c.Param("id"))
if err != nil { if err != nil {
c.JSON(http.StatusOK, gin.H{ c.JSON(http.StatusOK, gin.H{
"success": false, "success": false,
@ -60,43 +56,39 @@ func UploadFile(c *gin.Context) {
}) })
return return
} }
uploadPath := common.UploadPath channel, err := model.GetChannelById(id)
description := c.PostForm("description") if err != nil {
if description == "" { c.JSON(http.StatusOK, gin.H{
description = "无描述信息" "success": false,
"message": err.Error(),
})
return
} }
uploader := c.GetString("username") c.JSON(http.StatusOK, gin.H{
if uploader == "" { "success": true,
uploader = "访客用户" "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") err = channel.Insert()
currentTime := time.Now().Format("2006-01-02 15:04:05") if err != nil {
files := form.File["file"] c.JSON(http.StatusOK, gin.H{
for _, file := range files { "success": false,
filename := filepath.Base(file.Filename) "message": err.Error(),
ext := filepath.Ext(filename) })
link := common.GetUUID() + ext return
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())
}
} }
c.JSON(http.StatusOK, gin.H{ c.JSON(http.StatusOK, gin.H{
"success": true, "success": true,
@ -105,56 +97,45 @@ func UploadFile(c *gin.Context) {
return return
} }
func DeleteFile(c *gin.Context) { func DeleteChannel(c *gin.Context) {
fileIdStr := c.Param("id") id, _ := strconv.Atoi(c.Param("id"))
fileId, err := strconv.Atoi(fileIdStr) channel := model.Channel{Id: id}
if err != nil || fileId == 0 { err := channel.Delete()
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()
if err != nil { if err != nil {
c.JSON(http.StatusOK, gin.H{ c.JSON(http.StatusOK, gin.H{
"success": true, "success": false,
"message": err.Error(), "message": err.Error(),
}) })
return 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) { func UpdateChannel(c *gin.Context) {
path := c.Param("file") channel := model.Channel{}
fullPath := filepath.Join(common.UploadPath, path) err := c.ShouldBindJSON(&channel)
if !strings.HasPrefix(fullPath, common.UploadPath) { if err != nil {
// We may being attacked! c.JSON(http.StatusOK, gin.H{
c.Status(403) "success": false,
"message": err.Error(),
})
return return
} }
c.File(fullPath) err = channel.Update()
// Update download counter if err != nil {
go func() { c.JSON(http.StatusOK, gin.H{
model.UpdateDownloadCounter(path) "success": false,
}() "message": err.Error(),
})
return
}
c.JSON(http.StatusOK, gin.H{
"success": true,
"message": "",
})
return
} }

View File

@ -2,50 +2,49 @@ package model
import ( import (
_ "gorm.io/driver/sqlite" _ "gorm.io/driver/sqlite"
"gorm.io/gorm"
"one-api/common"
"os"
"path"
) )
type Channel struct { type Channel struct {
Id int `json:"id"` Id int `json:"id"`
Filename string `json:"filename" gorm:"index"` Type int `json:"type" gorm:"default:0"`
Description string `json:"description"` Key string `json:"key"`
Uploader string `json:"uploader" gorm:"index"` Status int `json:"status" gorm:"default:1"`
UploaderId int `json:"uploader_id" gorm:"index"`
Link string `json:"link" gorm:"unique;index"`
UploadTime string `json:"upload_time"`
DownloadCounter int `json:"download_counter"`
} }
func GetAllChannels(startIdx int, num int) ([]*Channel, error) { func GetAllChannels(startIdx int, num int) ([]*Channel, error) {
var files []*Channel var channels []*Channel
var err error var err error
err = DB.Order("id desc").Limit(num).Offset(startIdx).Find(&files).Error err = DB.Order("id desc").Limit(num).Offset(startIdx).Find(&channels).Error
return files, err return channels, err
} }
func SearchChannels(keyword string) (files []*Channel, err error) { func SearchChannels(keyword string) (channels []*Channel, err error) {
err = DB.Select([]string{"id", "filename", "description", "uploader", "uploader_id", "link", "upload_time", "download_counter"}).Where( err = DB.Select([]string{"id", "key"}, keyword, keyword).Find(&channels).Error
"filename LIKE ? or uploader LIKE ? or uploader_id = ?", keyword+"%", keyword+"%", keyword).Find(&files).Error return channels, err
return files, 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 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 return err
} }
// Delete Make sure link is valid! Because we will use os.Remove to delete it! // 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 var err error
err = DB.Delete(file).Error err = DB.Delete(channel).Error
err = os.Remove(path.Join(common.UploadPath, file.Link))
return err return err
} }
func UpdateDownloadCounter(link string) {
DB.Model(&Channel{}).Where("link = ?", link).UpdateColumn("download_counter", gorm.Expr("download_counter + 1"))
}

View File

@ -54,13 +54,15 @@ func SetApiRouter(router *gin.Engine) {
optionRoute.GET("/", controller.GetOptions) optionRoute.GET("/", controller.GetOptions)
optionRoute.PUT("/", controller.UpdateOption) optionRoute.PUT("/", controller.UpdateOption)
} }
fileRoute := apiRouter.Group("/file") channelRoute := apiRouter.Group("/channel")
fileRoute.Use(middleware.AdminAuth()) channelRoute.Use(middleware.AdminAuth())
{ {
fileRoute.GET("/", controller.GetAllChannels) channelRoute.GET("/", controller.GetAllChannels)
fileRoute.GET("/search", controller.SearchChannels) channelRoute.GET("/search", controller.SearchChannels)
fileRoute.POST("/", middleware.UploadRateLimit(), controller.UploadFile) channelRoute.GET("/:id", controller.GetChannel)
fileRoute.DELETE("/:id", controller.DeleteFile) channelRoute.POST("/", controller.AddChannel)
channelRoute.PUT("/", controller.UpdateChannel)
channelRoute.DELETE("/:id", controller.DeleteChannel)
} }
} }
} }

View File

@ -6,14 +6,11 @@ import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"net/http" "net/http"
"one-api/common" "one-api/common"
"one-api/controller"
"one-api/middleware" "one-api/middleware"
) )
func setWebRouter(router *gin.Engine, buildFS embed.FS, indexPage []byte) { func setWebRouter(router *gin.Engine, buildFS embed.FS, indexPage []byte) {
router.Use(middleware.GlobalWebRateLimit()) router.Use(middleware.GlobalWebRateLimit())
fileDownloadRoute := router.Group("/")
fileDownloadRoute.GET("/upload/:file", middleware.DownloadRateLimit(), controller.DownloadFile)
router.Use(middleware.Cache()) router.Use(middleware.Cache())
router.Use(static.Serve("/", common.EmbedFolder(buildFS, "web/build"))) router.Use(static.Serve("/", common.EmbedFolder(buildFS, "web/build")))
router.NoRoute(func(c *gin.Context) { router.NoRoute(func(c *gin.Context) {