package app import ( "fmt" "io" "net/http" "strconv" "git.echol.cn/loser/st/server/global" "git.echol.cn/loser/st/server/middleware" "git.echol.cn/loser/st/server/model/app/request" "git.echol.cn/loser/st/server/model/app/response" sysResponse "git.echol.cn/loser/st/server/model/common/response" "git.echol.cn/loser/st/server/service" "github.com/gin-gonic/gin" "go.uber.org/zap" ) type ExtensionApi struct{} var extensionService = service.ServiceGroupApp.AppServiceGroup.ExtensionService // CreateExtension 创建/安装扩展 // @Summary 创建/安装扩展 // @Description 创建一个新的扩展或安装扩展 // @Tags 扩展管理 // @Accept json // @Produce json // @Param data body request.CreateExtensionRequest true "扩展信息" // @Success 200 {object} response.Response{data=response.ExtensionResponse} // @Router /app/extension [post] func (a *ExtensionApi) CreateExtension(c *gin.Context) { userID := middleware.GetAppUserID(c) var req request.CreateExtensionRequest if err := c.ShouldBindJSON(&req); err != nil { sysResponse.FailWithMessage(err.Error(), c) return } extension, err := extensionService.CreateExtension(userID, &req) if err != nil { global.GVA_LOG.Error("创建扩展失败", zap.Error(err)) sysResponse.FailWithMessage("创建失败: "+err.Error(), c) return } sysResponse.OkWithData(response.ToExtensionResponse(extension), c) } // UpdateExtension 更新扩展 // @Summary 更新扩展 // @Description 更新扩展信息 // @Tags 扩展管理 // @Accept json // @Produce json // @Param id path int true "扩展ID" // @Param data body request.UpdateExtensionRequest true "扩展信息" // @Success 200 {object} response.Response // @Router /app/extension/:id [put] func (a *ExtensionApi) UpdateExtension(c *gin.Context) { userID := middleware.GetAppUserID(c) // 从路径参数获取 ID idStr := c.Param("id") id, err := strconv.ParseUint(idStr, 10, 32) if err != nil { sysResponse.FailWithMessage("无效的扩展ID", c) return } extensionID := uint(id) var req request.UpdateExtensionRequest if err := c.ShouldBindJSON(&req); err != nil { sysResponse.FailWithMessage(err.Error(), c) return } if err := extensionService.UpdateExtension(userID, extensionID, &req); err != nil { global.GVA_LOG.Error("更新扩展失败", zap.Error(err)) sysResponse.FailWithMessage("更新失败: "+err.Error(), c) return } sysResponse.OkWithMessage("更新成功", c) } // DeleteExtension 删除/卸载扩展 // @Summary 删除/卸载扩展 // @Description 删除扩展 // @Tags 扩展管理 // @Accept json // @Produce json // @Param id path int true "扩展ID" // @Param deleteFiles query bool false "是否删除文件" // @Success 200 {object} response.Response // @Router /app/extension/:id [delete] func (a *ExtensionApi) DeleteExtension(c *gin.Context) { userID := middleware.GetAppUserID(c) // 从路径参数获取 ID idStr := c.Param("id") id, err := strconv.ParseUint(idStr, 10, 32) if err != nil { sysResponse.FailWithMessage("无效的扩展ID", c) return } extensionID := uint(id) deleteFiles := c.Query("deleteFiles") == "true" if err := extensionService.DeleteExtension(userID, extensionID, deleteFiles); err != nil { global.GVA_LOG.Error("删除扩展失败", zap.Error(err)) sysResponse.FailWithMessage("删除失败: "+err.Error(), c) return } sysResponse.OkWithMessage("删除成功", c) } // GetExtension 获取扩展详情 // @Summary 获取扩展详情 // @Description 获取扩展详细信息 // @Tags 扩展管理 // @Accept json // @Produce json // @Param id path int true "扩展ID" // @Success 200 {object} response.Response{data=response.ExtensionResponse} // @Router /app/extension/:id [get] func (a *ExtensionApi) GetExtension(c *gin.Context) { userID := middleware.GetAppUserID(c) // 从路径参数获取 ID idStr := c.Param("id") id, err := strconv.ParseUint(idStr, 10, 32) if err != nil { sysResponse.FailWithMessage("无效的扩展ID", c) return } extensionID := uint(id) extension, err := extensionService.GetExtension(userID, extensionID) if err != nil { global.GVA_LOG.Error("获取扩展失败", zap.Error(err)) sysResponse.FailWithMessage("获取失败: "+err.Error(), c) return } sysResponse.OkWithData(response.ToExtensionResponse(extension), c) } // GetExtensionList 获取扩展列表 // @Summary 获取扩展列表 // @Description 获取扩展列表 // @Tags 扩展管理 // @Accept json // @Produce json // @Param data query request.ExtensionListRequest true "查询参数" // @Success 200 {object} response.Response{data=response.ExtensionListResponse} // @Router /app/extension/list [get] func (a *ExtensionApi) GetExtensionList(c *gin.Context) { userID := middleware.GetAppUserID(c) var req request.ExtensionListRequest if err := c.ShouldBindQuery(&req); err != nil { sysResponse.FailWithMessage(err.Error(), c) return } // 默认分页 if req.Page < 1 { req.Page = 1 } if req.PageSize < 1 { req.PageSize = 20 } result, err := extensionService.GetExtensionList(userID, &req) if err != nil { global.GVA_LOG.Error("获取扩展列表失败", zap.Error(err)) sysResponse.FailWithMessage("获取失败: "+err.Error(), c) return } sysResponse.OkWithData(result, c) } // ToggleExtension 启用/禁用扩展 // @Summary 启用/禁用扩展 // @Description 切换扩展的启用状态 // @Tags 扩展管理 // @Accept json // @Produce json // @Param id path int true "扩展ID" // @Param data body request.ToggleExtensionRequest true "启用状态" // @Success 200 {object} response.Response // @Router /app/extension/:id/toggle [post] func (a *ExtensionApi) ToggleExtension(c *gin.Context) { userID := middleware.GetAppUserID(c) // 从路径参数获取 ID idStr := c.Param("id") id, err := strconv.ParseUint(idStr, 10, 32) if err != nil { sysResponse.FailWithMessage("无效的扩展ID", c) return } extensionID := uint(id) var req request.ToggleExtensionRequest if err := c.ShouldBindJSON(&req); err != nil { sysResponse.FailWithMessage("请求参数错误", c) return } if req.IsEnabled == nil { sysResponse.FailWithMessage("isEnabled 参数不能为空", c) return } if err := extensionService.ToggleExtension(userID, extensionID, *req.IsEnabled); err != nil { global.GVA_LOG.Error("切换扩展状态失败", zap.Error(err)) sysResponse.FailWithMessage("操作失败: "+err.Error(), c) return } sysResponse.OkWithMessage("操作成功", c) } // UpdateExtensionSettings 更新扩展配置 // @Summary 更新扩展配置 // @Description 更新扩展的用户配置 // @Tags 扩展管理 // @Accept json // @Produce json // @Param id path int true "扩展ID" // @Param data body request.UpdateExtensionSettingsRequest true "配置信息" // @Success 200 {object} response.Response // @Router /app/extension/:id/settings [put] func (a *ExtensionApi) UpdateExtensionSettings(c *gin.Context) { userID := middleware.GetAppUserID(c) // 从路径参数获取 ID idStr := c.Param("id") id, err := strconv.ParseUint(idStr, 10, 32) if err != nil { sysResponse.FailWithMessage("无效的扩展ID", c) return } extensionID := uint(id) var req request.UpdateExtensionSettingsRequest if err := c.ShouldBindJSON(&req); err != nil { sysResponse.FailWithMessage(err.Error(), c) return } if err := extensionService.UpdateExtensionSettings(userID, extensionID, req.Settings); err != nil { global.GVA_LOG.Error("更新扩展配置失败", zap.Error(err)) sysResponse.FailWithMessage("更新失败: "+err.Error(), c) return } sysResponse.OkWithMessage("更新成功", c) } // GetExtensionSettings 获取扩展配置 // @Summary 获取扩展配置 // @Description 获取扩展的用户配置 // @Tags 扩展管理 // @Accept json // @Produce json // @Param id path int true "扩展ID" // @Success 200 {object} response.Response{data=map[string]interface{}} // @Router /app/extension/:id/settings [get] func (a *ExtensionApi) GetExtensionSettings(c *gin.Context) { userID := middleware.GetAppUserID(c) // 从路径参数获取 ID idStr := c.Param("id") id, err := strconv.ParseUint(idStr, 10, 32) if err != nil { sysResponse.FailWithMessage("无效的扩展ID", c) return } extensionID := uint(id) settings, err := extensionService.GetExtensionSettings(userID, extensionID) if err != nil { global.GVA_LOG.Error("获取扩展配置失败", zap.Error(err)) sysResponse.FailWithMessage("获取失败: "+err.Error(), c) return } sysResponse.OkWithData(settings, c) } // GetExtensionManifest 获取扩展 manifest // @Summary 获取扩展 manifest // @Description 获取扩展的 manifest.json // @Tags 扩展管理 // @Accept json // @Produce json // @Param id path int true "扩展ID" // @Success 200 {object} response.Response{data=response.ExtensionManifestResponse} // @Router /app/extension/:id/manifest [get] func (a *ExtensionApi) GetExtensionManifest(c *gin.Context) { userID := middleware.GetAppUserID(c) // 从路径参数获取 ID idStr := c.Param("id") id, err := strconv.ParseUint(idStr, 10, 32) if err != nil { sysResponse.FailWithMessage("无效的扩展ID", c) return } extensionID := uint(id) manifest, err := extensionService.GetExtensionManifest(userID, extensionID) if err != nil { global.GVA_LOG.Error("获取扩展 manifest 失败", zap.Error(err)) sysResponse.FailWithMessage("获取失败: "+err.Error(), c) return } sysResponse.OkWithData(manifest, c) } // ImportExtension 导入扩展 // @Summary 导入扩展 // @Description 从文件导入扩展 // @Tags 扩展管理 // @Accept multipart/form-data // @Produce json // @Param file formData file true "扩展文件(manifest.json)" // @Success 200 {object} response.Response{data=response.ExtensionResponse} // @Router /app/extension/import [post] func (a *ExtensionApi) ImportExtension(c *gin.Context) { userID := middleware.GetAppUserID(c) // 获取文件 file, err := c.FormFile("file") if err != nil { sysResponse.FailWithMessage("请上传扩展文件", c) return } // 文件大小限制(5MB) if file.Size > 5<<20 { sysResponse.FailWithMessage("文件大小不能超过 5MB", c) return } // 读取文件内容 src, err := file.Open() if err != nil { global.GVA_LOG.Error("打开文件失败", zap.Error(err)) sysResponse.FailWithMessage("文件读取失败", c) return } defer src.Close() fileData, err := io.ReadAll(src) if err != nil { global.GVA_LOG.Error("读取文件内容失败", zap.Error(err)) sysResponse.FailWithMessage("文件读取失败", c) return } // 导入扩展 extension, err := extensionService.ImportExtension(userID, fileData) if err != nil { global.GVA_LOG.Error("导入扩展失败", zap.Error(err)) sysResponse.FailWithMessage("导入失败: "+err.Error(), c) return } sysResponse.OkWithData(response.ToExtensionResponse(extension), c) } // ExportExtension 导出扩展 // @Summary 导出扩展 // @Description 导出扩展为 manifest.json 文件 // @Tags 扩展管理 // @Accept json // @Produce application/json // @Param id path int true "扩展ID" // @Success 200 {object} response.ExtensionManifestResponse // @Router /app/extension/:id/export [get] func (a *ExtensionApi) ExportExtension(c *gin.Context) { userID := middleware.GetAppUserID(c) // 从路径参数获取 ID idStr := c.Param("id") id, err := strconv.ParseUint(idStr, 10, 32) if err != nil { sysResponse.FailWithMessage("无效的扩展ID", c) return } extensionID := uint(id) exportData, err := extensionService.ExportExtension(userID, extensionID) if err != nil { global.GVA_LOG.Error("导出扩展失败", zap.Error(err)) sysResponse.FailWithMessage("导出失败: "+err.Error(), c) return } // 设置响应头 filename := fmt.Sprintf("extension_%d_manifest.json", extensionID) c.Header("Content-Type", "application/json") c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", filename)) // 直接返回 JSON 数据 c.Data(http.StatusOK, "application/json", exportData) } // UpdateExtensionStats 更新扩展统计 // @Summary 更新扩展统计 // @Description 更新扩展的使用统计 // @Tags 扩展管理 // @Accept json // @Produce json // @Param data body request.ExtensionStatsRequest true "统计信息" // @Success 200 {object} response.Response // @Router /app/extension/stats [post] func (a *ExtensionApi) UpdateExtensionStats(c *gin.Context) { userID := middleware.GetAppUserID(c) var req request.ExtensionStatsRequest if err := c.ShouldBindJSON(&req); err != nil { sysResponse.FailWithMessage(err.Error(), c) return } if err := extensionService.UpdateExtensionStats(userID, req.ExtensionID, req.Action, req.Value); err != nil { global.GVA_LOG.Error("更新扩展统计失败", zap.Error(err)) sysResponse.FailWithMessage("更新失败: "+err.Error(), c) return } sysResponse.OkWithMessage("更新成功", c) } // GetEnabledExtensions 获取启用的扩展列表 // @Summary 获取启用的扩展列表 // @Description 获取用户启用的所有扩展(用于前端加载) // @Tags 扩展管理 // @Accept json // @Produce json // @Success 200 {object} response.Response{data=[]response.ExtensionResponse} // @Router /app/extension/enabled [get] func (a *ExtensionApi) GetEnabledExtensions(c *gin.Context) { userID := middleware.GetAppUserID(c) extensions, err := extensionService.GetEnabledExtensions(userID) if err != nil { global.GVA_LOG.Error("获取启用扩展列表失败", zap.Error(err)) sysResponse.FailWithMessage("获取失败: "+err.Error(), c) return } sysResponse.OkWithData(extensions, c) } // InstallExtensionFromURL 智能安装扩展(自动识别 Git URL 或 Manifest URL) // @Summary 智能安装扩展 // @Description 自动识别 Git 仓库 URL 或 Manifest.json URL 并安装扩展(兼容 SillyTavern) // @Tags 扩展管理 // @Accept json // @Produce json // @Param data body request.InstallExtensionFromURLRequest true "安装 URL 信息" // @Success 200 {object} response.Response{data=response.ExtensionResponse} // @Router /app/extension/install/url [post] func (a *ExtensionApi) InstallExtensionFromURL(c *gin.Context) { userID := middleware.GetAppUserID(c) var req request.InstallExtensionFromURLRequest if err := c.ShouldBindJSON(&req); err != nil { sysResponse.FailWithMessage("请求参数错误: "+err.Error(), c) return } // 设置默认分支 if req.Branch == "" { req.Branch = "main" } extension, err := extensionService.InstallExtensionFromURL(userID, req.URL, req.Branch) if err != nil { global.GVA_LOG.Error("从 URL 安装扩展失败", zap.Error(err), zap.String("url", req.URL)) sysResponse.FailWithMessage("安装失败: "+err.Error(), c) return } sysResponse.OkWithData(response.ToExtensionResponse(extension), c) } // UpgradeExtension 升级扩展版本 // @Summary 升级扩展版本 // @Description 根据扩展的安装来源自动选择更新方式(Git pull 或重新下载) // @Tags 扩展管理 // @Accept json // @Produce json // @Param id path int true "扩展ID" // @Param data body request.UpdateExtensionRequest false "更新选项" // @Success 200 {object} response.Response{data=response.ExtensionResponse} // @Router /app/extension/:id/update [post] func (a *ExtensionApi) UpgradeExtension(c *gin.Context) { userID := middleware.GetAppUserID(c) // 从路径参数获取 ID idStr := c.Param("id") id, err := strconv.ParseUint(idStr, 10, 32) if err != nil { sysResponse.FailWithMessage("无效的扩展ID", c) return } extensionID := uint(id) var req request.UpdateExtensionRequest // 允许不传 body(使用默认值) _ = c.ShouldBindJSON(&req) extension, err := extensionService.UpgradeExtension(userID, extensionID, req.Force) if err != nil { global.GVA_LOG.Error("升级扩展失败", zap.Error(err), zap.Uint("extensionID", extensionID)) sysResponse.FailWithMessage("升级失败: "+err.Error(), c) return } sysResponse.OkWithData(response.ToExtensionResponse(extension), c) } // InstallExtensionFromGit 从 Git URL 安装扩展 // @Summary 从 Git URL 安装扩展 // @Description 从 Git 仓库 URL 克隆并安装扩展 // @Tags 扩展管理 // @Accept json // @Produce json // @Param data body request.InstallExtensionFromGitRequest true "Git URL 信息" // @Success 200 {object} response.Response{data=response.ExtensionResponse} // @Router /app/extension/install/git [post] func (a *ExtensionApi) InstallExtensionFromGit(c *gin.Context) { userID := middleware.GetAppUserID(c) var req request.InstallExtensionFromGitRequest if err := c.ShouldBindJSON(&req); err != nil { sysResponse.FailWithMessage(err.Error(), c) return } // 设置默认分支 if req.Branch == "" { req.Branch = "main" } extension, err := extensionService.InstallExtensionFromGit(userID, req.GitUrl, req.Branch) if err != nil { global.GVA_LOG.Error("从 Git 安装扩展失败", zap.Error(err)) sysResponse.FailWithMessage("安装失败: "+err.Error(), c) return } sysResponse.OkWithData(response.ToExtensionResponse(extension), c) }