mirror of
				https://github.com/songquanpeng/one-api.git
				synced 2025-11-04 07:43:41 +08:00 
			
		
		
		
	Channel API done without verification
This commit is contained in:
		@@ -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
 | 
			
		||||
)
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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"))
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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) {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user