- Updated main.go to initialize email service and include it in the dependency injection container. - Refactored handlers to utilize context in service method calls, improving consistency and error handling. - Introduced new service options for upload, security, and captcha services, enhancing modularity and testability. - Removed unused repository implementations to streamline the codebase. This commit continues the effort to improve the architecture by ensuring all services are properly injected and utilized across the application.
283 lines
7.1 KiB
Go
283 lines
7.1 KiB
Go
package handler
|
|
|
|
import (
|
|
"carrotskin/internal/container"
|
|
"carrotskin/internal/model"
|
|
"carrotskin/internal/types"
|
|
"strconv"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
// TextureHandler 材质处理器(依赖注入版本)
|
|
type TextureHandler struct {
|
|
container *container.Container
|
|
logger *zap.Logger
|
|
}
|
|
|
|
// NewTextureHandler 创建TextureHandler实例
|
|
func NewTextureHandler(c *container.Container) *TextureHandler {
|
|
return &TextureHandler{
|
|
container: c,
|
|
logger: c.Logger,
|
|
}
|
|
}
|
|
|
|
// GenerateUploadURL 生成材质上传URL
|
|
func (h *TextureHandler) GenerateUploadURL(c *gin.Context) {
|
|
userID, ok := GetUserIDFromContext(c)
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
var req types.GenerateTextureUploadURLRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
RespondBadRequest(c, "请求参数错误", err)
|
|
return
|
|
}
|
|
|
|
if h.container.Storage == nil {
|
|
RespondServerError(c, "存储服务不可用", nil)
|
|
return
|
|
}
|
|
|
|
result, err := h.container.UploadService.GenerateTextureUploadURL(
|
|
c.Request.Context(),
|
|
userID,
|
|
req.FileName,
|
|
string(req.TextureType),
|
|
)
|
|
if err != nil {
|
|
h.logger.Error("生成材质上传URL失败",
|
|
zap.Int64("user_id", userID),
|
|
zap.String("file_name", req.FileName),
|
|
zap.String("texture_type", string(req.TextureType)),
|
|
zap.Error(err),
|
|
)
|
|
RespondBadRequest(c, err.Error(), nil)
|
|
return
|
|
}
|
|
|
|
RespondSuccess(c, &types.GenerateTextureUploadURLResponse{
|
|
PostURL: result.PostURL,
|
|
FormData: result.FormData,
|
|
TextureURL: result.FileURL,
|
|
ExpiresIn: 900,
|
|
})
|
|
}
|
|
|
|
// Create 创建材质记录
|
|
func (h *TextureHandler) Create(c *gin.Context) {
|
|
userID, ok := GetUserIDFromContext(c)
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
var req types.CreateTextureRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
RespondBadRequest(c, "请求参数错误", err)
|
|
return
|
|
}
|
|
|
|
maxTextures := h.container.UserService.GetMaxTexturesPerUser()
|
|
if err := h.container.TextureService.CheckUploadLimit(c.Request.Context(), userID, maxTextures); err != nil {
|
|
RespondBadRequest(c, err.Error(), nil)
|
|
return
|
|
}
|
|
|
|
texture, err := h.container.TextureService.Create(
|
|
c.Request.Context(),
|
|
userID,
|
|
req.Name,
|
|
req.Description,
|
|
string(req.Type),
|
|
req.URL,
|
|
req.Hash,
|
|
req.Size,
|
|
req.IsPublic,
|
|
req.IsSlim,
|
|
)
|
|
if err != nil {
|
|
h.logger.Error("创建材质失败",
|
|
zap.Int64("user_id", userID),
|
|
zap.String("name", req.Name),
|
|
zap.Error(err),
|
|
)
|
|
RespondBadRequest(c, err.Error(), nil)
|
|
return
|
|
}
|
|
|
|
RespondSuccess(c, TextureToTextureInfo(texture))
|
|
}
|
|
|
|
// Get 获取材质详情
|
|
func (h *TextureHandler) Get(c *gin.Context) {
|
|
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
|
if err != nil {
|
|
RespondBadRequest(c, "无效的材质ID", err)
|
|
return
|
|
}
|
|
|
|
texture, err := h.container.TextureService.GetByID(c.Request.Context(), id)
|
|
if err != nil {
|
|
RespondNotFound(c, err.Error())
|
|
return
|
|
}
|
|
|
|
RespondSuccess(c, TextureToTextureInfo(texture))
|
|
}
|
|
|
|
// Search 搜索材质
|
|
func (h *TextureHandler) Search(c *gin.Context) {
|
|
keyword := c.Query("keyword")
|
|
textureTypeStr := c.Query("type")
|
|
publicOnly := c.Query("public_only") == "true"
|
|
|
|
page := parseIntWithDefault(c.DefaultQuery("page", "1"), 1)
|
|
pageSize := parseIntWithDefault(c.DefaultQuery("page_size", "20"), 20)
|
|
|
|
var textureType model.TextureType
|
|
switch textureTypeStr {
|
|
case "SKIN":
|
|
textureType = model.TextureTypeSkin
|
|
case "CAPE":
|
|
textureType = model.TextureTypeCape
|
|
}
|
|
|
|
textures, total, err := h.container.TextureService.Search(c.Request.Context(), keyword, textureType, publicOnly, page, pageSize)
|
|
if err != nil {
|
|
h.logger.Error("搜索材质失败", zap.String("keyword", keyword), zap.Error(err))
|
|
RespondServerError(c, "搜索材质失败", err)
|
|
return
|
|
}
|
|
|
|
c.JSON(200, model.NewPaginationResponse(TexturesToTextureInfos(textures), total, page, pageSize))
|
|
}
|
|
|
|
// Update 更新材质
|
|
func (h *TextureHandler) Update(c *gin.Context) {
|
|
userID, ok := GetUserIDFromContext(c)
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
textureID, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
|
if err != nil {
|
|
RespondBadRequest(c, "无效的材质ID", err)
|
|
return
|
|
}
|
|
|
|
var req types.UpdateTextureRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
RespondBadRequest(c, "请求参数错误", err)
|
|
return
|
|
}
|
|
|
|
texture, err := h.container.TextureService.Update(c.Request.Context(), textureID, userID, req.Name, req.Description, req.IsPublic)
|
|
if err != nil {
|
|
h.logger.Error("更新材质失败",
|
|
zap.Int64("user_id", userID),
|
|
zap.Int64("texture_id", textureID),
|
|
zap.Error(err),
|
|
)
|
|
RespondForbidden(c, err.Error())
|
|
return
|
|
}
|
|
|
|
RespondSuccess(c, TextureToTextureInfo(texture))
|
|
}
|
|
|
|
// Delete 删除材质
|
|
func (h *TextureHandler) Delete(c *gin.Context) {
|
|
userID, ok := GetUserIDFromContext(c)
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
textureID, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
|
if err != nil {
|
|
RespondBadRequest(c, "无效的材质ID", err)
|
|
return
|
|
}
|
|
|
|
if err := h.container.TextureService.Delete(c.Request.Context(), textureID, userID); err != nil {
|
|
h.logger.Error("删除材质失败",
|
|
zap.Int64("user_id", userID),
|
|
zap.Int64("texture_id", textureID),
|
|
zap.Error(err),
|
|
)
|
|
RespondForbidden(c, err.Error())
|
|
return
|
|
}
|
|
|
|
RespondSuccess(c, nil)
|
|
}
|
|
|
|
// ToggleFavorite 切换收藏状态
|
|
func (h *TextureHandler) ToggleFavorite(c *gin.Context) {
|
|
userID, ok := GetUserIDFromContext(c)
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
textureID, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
|
if err != nil {
|
|
RespondBadRequest(c, "无效的材质ID", err)
|
|
return
|
|
}
|
|
|
|
isFavorited, err := h.container.TextureService.ToggleFavorite(c.Request.Context(), userID, textureID)
|
|
if err != nil {
|
|
h.logger.Error("切换收藏状态失败",
|
|
zap.Int64("user_id", userID),
|
|
zap.Int64("texture_id", textureID),
|
|
zap.Error(err),
|
|
)
|
|
RespondBadRequest(c, err.Error(), nil)
|
|
return
|
|
}
|
|
|
|
RespondSuccess(c, map[string]bool{"is_favorited": isFavorited})
|
|
}
|
|
|
|
// GetUserTextures 获取用户上传的材质列表
|
|
func (h *TextureHandler) GetUserTextures(c *gin.Context) {
|
|
userID, ok := GetUserIDFromContext(c)
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
page := parseIntWithDefault(c.DefaultQuery("page", "1"), 1)
|
|
pageSize := parseIntWithDefault(c.DefaultQuery("page_size", "20"), 20)
|
|
|
|
textures, total, err := h.container.TextureService.GetByUserID(c.Request.Context(), userID, page, pageSize)
|
|
if err != nil {
|
|
h.logger.Error("获取用户材质列表失败", zap.Int64("user_id", userID), zap.Error(err))
|
|
RespondServerError(c, "获取材质列表失败", err)
|
|
return
|
|
}
|
|
|
|
c.JSON(200, model.NewPaginationResponse(TexturesToTextureInfos(textures), total, page, pageSize))
|
|
}
|
|
|
|
// GetUserFavorites 获取用户收藏的材质列表
|
|
func (h *TextureHandler) GetUserFavorites(c *gin.Context) {
|
|
userID, ok := GetUserIDFromContext(c)
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
page := parseIntWithDefault(c.DefaultQuery("page", "1"), 1)
|
|
pageSize := parseIntWithDefault(c.DefaultQuery("page_size", "20"), 20)
|
|
|
|
textures, total, err := h.container.TextureService.GetUserFavorites(c.Request.Context(), userID, page, pageSize)
|
|
if err != nil {
|
|
h.logger.Error("获取用户收藏列表失败", zap.Int64("user_id", userID), zap.Error(err))
|
|
RespondServerError(c, "获取收藏列表失败", err)
|
|
return
|
|
}
|
|
|
|
c.JSON(200, model.NewPaginationResponse(TexturesToTextureInfos(textures), total, page, pageSize))
|
|
}
|