genspark / controller /admin.go
timigogo's picture
Upload 63 files
fe3856c verified
package controller
import (
"encoding/json"
"fmt"
"genspark2api/common"
"genspark2api/common/config"
logger "genspark2api/common/loggger"
"io/ioutil"
"net/http"
"os"
"strings"
"time"
"github.com/gin-gonic/gin"
)
// 系统启动时间
var startTime = time.Now()
// GSCookie 定义cookie的结构
type GSCookie struct {
Value string // cookie值
RequestCount int // 请求次数
FailCount int // 失败请求数
LastUsedTime time.Time // 最后使用时间
Disabled bool // 是否禁用
}
// 模拟的Cookie统计
var cookieStats = make(map[string]*GSCookie)
// 模型信息
type ModelInfo struct {
ID string `json:"id"`
Name string `json:"name"`
Category string `json:"category"`
Enabled bool `json:"enabled"`
}
// ModelsListRequest 请求体
type ModelsListRequest struct {
Models []ModelInfo `json:"models"`
}
// 全局变量,存储模型列表
var modelsList []ModelInfo
var modelsListFile = "./data/models_list.json"
// 初始化模型列表
func init() {
// 加载模型列表(如果存在)
loadModelsList()
}
// AdminIndex 返回管理界面
func AdminIndex(c *gin.Context) {
c.File("./public/index.html")
}
// GetConfig 获取当前配置
func GetConfig(c *gin.Context) {
// 从环境变量获取配置
configData := map[string]string{
"GS_COOKIE": os.Getenv("GS_COOKIE"),
"API_SECRET": os.Getenv("API_SECRET"),
"AUTO_MODEL_CHAT_MAP_TYPE": os.Getenv("AUTO_MODEL_CHAT_MAP_TYPE"),
"AUTO_DEL_CHAT": os.Getenv("AUTO_DEL_CHAT"),
"MODEL_CHAT_MAP": os.Getenv("MODEL_CHAT_MAP"),
"PROXY_URL": os.Getenv("PROXY_URL"),
"RECAPTCHA_PROXY_URL": os.Getenv("RECAPTCHA_PROXY_URL"),
"REQUEST_RATE_LIMIT": os.Getenv("REQUEST_RATE_LIMIT"),
"RATE_LIMIT_COOKIE_LOCK_DURATION": os.Getenv("RATE_LIMIT_COOKIE_LOCK_DURATION"),
"ROUTE_PREFIX": os.Getenv("ROUTE_PREFIX"),
"DEBUG": os.Getenv("DEBUG"),
"REASONING_HIDE": os.Getenv("REASONING_HIDE"),
}
c.JSON(http.StatusOK, configData)
}
// SaveConfig 保存配置到.env文件
func SaveConfig(c *gin.Context) {
// 解析请求体
var configData map[string]string
if err := c.ShouldBindJSON(&configData); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"success": false,
"message": "无效的请求数据",
})
return
}
// 读取现有的.env文件(如果存在)
envFilePath := "./data/.env"
envLines := []string{}
envMap := make(map[string]string)
// 确保data目录存在
if err := os.MkdirAll("./data", 0755); err != nil {
logger.SysLog(fmt.Sprintf("创建data目录失败: %s", err.Error()))
}
if fileData, err := ioutil.ReadFile(envFilePath); err == nil {
content := string(fileData)
lines := strings.Split(content, "\n")
for _, line := range lines {
line = strings.TrimSpace(line)
if line != "" && !strings.HasPrefix(line, "#") {
parts := strings.SplitN(line, "=", 2)
if len(parts) == 2 {
key := strings.TrimSpace(parts[0])
value := strings.TrimSpace(parts[1])
envMap[key] = value
} else {
envLines = append(envLines, line) // 保留非键值对行
}
} else {
envLines = append(envLines, line) // 保留注释和空行
}
}
}
// 更新配置
for key, value := range configData {
if value != "" {
envMap[key] = value
// 同时更新环境变量
os.Setenv(key, value)
}
}
// 重建.env文件内容
var newContent strings.Builder
// 先写入非键值对的行
for _, line := range envLines {
if !strings.Contains(line, "=") {
newContent.WriteString(line)
newContent.WriteString("\n")
}
}
// 写入所有配置
for key, value := range envMap {
newContent.WriteString(fmt.Sprintf("%s=%s\n", key, value))
}
// 写入文件
if err := ioutil.WriteFile(envFilePath, []byte(newContent.String()), 0644); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"success": false,
"message": "保存配置失败: " + err.Error(),
})
return
}
// 特殊处理 - 如果更新了GS_COOKIE,则重新初始化cookie池
if _, ok := configData["GS_COOKIE"]; ok {
config.InitGSCookies()
// 更新Cookie统计信息
updateCookieStats()
}
c.JSON(http.StatusOK, gin.H{
"success": true,
"message": "配置已保存",
})
}
// updateCookieStats 更新Cookie统计信息
func updateCookieStats() {
// 获取当前所有Cookie
currentCookies := config.GetGSCookies()
// 为新的Cookie创建统计条目
for _, cookie := range currentCookies {
if _, exists := cookieStats[cookie]; !exists {
cookieStats[cookie] = &GSCookie{
Value: cookie,
RequestCount: 0,
FailCount: 0,
LastUsedTime: time.Now(),
Disabled: false,
}
}
}
// 移除不再存在的Cookie
for cookie := range cookieStats {
exists := false
for _, currentCookie := range currentCookies {
if cookie == currentCookie {
exists = true
break
}
}
if !exists {
delete(cookieStats, cookie)
}
}
}
// GetStatus 获取系统状态信息
func GetStatus(c *gin.Context) {
// 计算运行时间
uptime := time.Since(startTime).String()
// 确保Cookie统计已更新
updateCookieStats()
// Cookie池信息
cookieCount := len(config.GetGSCookies())
cookies := make([]map[string]interface{}, 0, cookieCount)
// 获取所有Cookie信息
for cookie, stats := range cookieStats {
cookieInfo := map[string]interface{}{
"value": cookie,
"active": !stats.Disabled,
"requestCount": stats.RequestCount,
"lastUsed": stats.LastUsedTime.Format("2006-01-02 15:04:05"),
}
cookies = append(cookies, cookieInfo)
}
// 计算请求统计
totalRequests := 0
successRequests := 0
failedRequests := 0
for _, stats := range cookieStats {
totalRequests += stats.RequestCount
successRequests += (stats.RequestCount - stats.FailCount)
failedRequests += stats.FailCount
}
// 返回状态信息
c.JSON(http.StatusOK, gin.H{
"version": common.Version,
"uptime": uptime,
"cookieCount": cookieCount,
"totalRequests": totalRequests,
"successRequests": successRequests,
"failedRequests": failedRequests,
"cookies": cookies,
})
}
// GetModels 获取模型列表
func GetModels(c *gin.Context) {
// 如果模型列表为空,从默认OpenAI模型列表初始化
if len(modelsList) == 0 {
initializeModelsFromDefaults()
}
c.JSON(http.StatusOK, gin.H{
"models": modelsList,
})
}
// SaveModels 保存模型列表
func SaveModels(c *gin.Context) {
var request ModelsListRequest
if err := c.ShouldBindJSON(&request); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"success": false,
"message": "无效的请求数据",
})
return
}
// 更新模型列表
modelsList = request.Models
// 保存到文件
if err := saveModelsToFile(); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"success": false,
"message": "保存模型列表失败: " + err.Error(),
})
return
}
// 更新DefaultOpenaiModelList
updateDefaultOpenaiModelList()
c.JSON(http.StatusOK, gin.H{
"success": true,
"message": "模型列表已保存",
})
}
// 从默认值初始化模型列表
func initializeModelsFromDefaults() {
// 清空现有列表
modelsList = []ModelInfo{}
// 文本模型
for _, model := range common.TextModelList {
modelsList = append(modelsList, ModelInfo{
ID: model,
Name: getModelDisplayName(model),
Category: "text",
Enabled: true,
})
}
// 图像模型
for _, model := range common.ImageModelList {
modelsList = append(modelsList, ModelInfo{
ID: model,
Name: getModelDisplayName(model),
Category: "image",
Enabled: true,
})
}
// 视频模型
for _, model := range common.VideoModelList {
modelsList = append(modelsList, ModelInfo{
ID: model,
Name: getModelDisplayName(model),
Category: "video",
Enabled: true,
})
}
// 保存到文件
saveModelsToFile()
}
// 获取模型显示名称
func getModelDisplayName(modelID string) string {
// 生成一个友好的显示名称
displayName := modelID
// 转换为首字母大写
parts := strings.Split(displayName, "-")
for i, part := range parts {
if len(part) > 0 {
// 对一些常见缩写进行特殊处理
if part == "gpt" || part == "dall" {
parts[i] = strings.ToUpper(part)
} else {
parts[i] = strings.ToUpper(part[:1]) + part[1:]
}
}
}
displayName = strings.Join(parts, " ")
displayName = strings.Replace(displayName, "/", " ", -1)
return displayName
}
// 保存模型列表到文件
func saveModelsToFile() error {
// 确保data目录存在
if err := os.MkdirAll("./data", 0755); err != nil {
return err
}
// 序列化数据
data, err := json.MarshalIndent(modelsList, "", " ")
if err != nil {
return err
}
// 写入文件
return ioutil.WriteFile(modelsListFile, data, 0644)
}
// 从文件加载模型列表
func loadModelsList() {
// 如果文件不存在,则初始化默认值
if _, err := os.Stat(modelsListFile); os.IsNotExist(err) {
initializeModelsFromDefaults()
return
}
// 读取文件
data, err := ioutil.ReadFile(modelsListFile)
if err != nil {
logger.SysLog(fmt.Sprintf("无法读取模型列表文件: %s", err.Error()))
initializeModelsFromDefaults()
return
}
// 解析JSON
if err := json.Unmarshal(data, &modelsList); err != nil {
logger.SysLog(fmt.Sprintf("解析模型列表文件失败: %s", err.Error()))
initializeModelsFromDefaults()
return
}
// 如果列表为空,初始化默认值
if len(modelsList) == 0 {
initializeModelsFromDefaults()
}
// 更新DefaultOpenaiModelList
updateDefaultOpenaiModelList()
}
// 更新DefaultOpenaiModelList
func updateDefaultOpenaiModelList() {
// 清空现有列表
common.DefaultOpenaiModelList = []string{}
// 遍历模型列表,将启用的模型添加到DefaultOpenaiModelList
for _, model := range modelsList {
if model.Enabled {
common.DefaultOpenaiModelList = append(common.DefaultOpenaiModelList, model.ID)
}
}
}