- Introduced new API endpoints for rendering textures, avatars, capes, and previews, enhancing the texture handling capabilities. - Implemented corresponding service methods in the TextureHandler to process rendering requests and return appropriate responses. - Updated the TextureRenderService interface to include methods for rendering textures, avatars, and capes, along with their respective parameters. - Enhanced error handling for invalid texture IDs and added support for different rendering types and formats. - Updated go.mod to include the webp library for image processing.
225 lines
8.7 KiB
Go
225 lines
8.7 KiB
Go
// Package service 定义业务逻辑层接口
|
||
package service
|
||
|
||
import (
|
||
"carrotskin/internal/model"
|
||
"carrotskin/pkg/storage"
|
||
"context"
|
||
"time"
|
||
|
||
"go.uber.org/zap"
|
||
)
|
||
|
||
// UserService 用户服务接口
|
||
type UserService interface {
|
||
// 用户认证
|
||
Register(ctx context.Context, username, password, email, avatar string) (*model.User, string, error)
|
||
Login(ctx context.Context, usernameOrEmail, password, ipAddress, userAgent string) (*model.User, string, error)
|
||
|
||
// 用户查询
|
||
GetByID(ctx context.Context, id int64) (*model.User, error)
|
||
GetByEmail(ctx context.Context, email string) (*model.User, error)
|
||
|
||
// 用户更新
|
||
UpdateInfo(ctx context.Context, user *model.User) error
|
||
UpdateAvatar(ctx context.Context, userID int64, avatarURL string) error
|
||
ChangePassword(ctx context.Context, userID int64, oldPassword, newPassword string) error
|
||
ResetPassword(ctx context.Context, email, newPassword string) error
|
||
ChangeEmail(ctx context.Context, userID int64, newEmail string) error
|
||
|
||
// URL验证
|
||
ValidateAvatarURL(ctx context.Context, avatarURL string) error
|
||
|
||
// 配置获取
|
||
GetMaxProfilesPerUser() int
|
||
GetMaxTexturesPerUser() int
|
||
}
|
||
|
||
// ProfileService 档案服务接口
|
||
type ProfileService interface {
|
||
// 档案CRUD
|
||
Create(ctx context.Context, userID int64, name string) (*model.Profile, error)
|
||
GetByUUID(ctx context.Context, uuid string) (*model.Profile, error)
|
||
GetByUserID(ctx context.Context, userID int64) ([]*model.Profile, error)
|
||
Update(ctx context.Context, uuid string, userID int64, name *string, skinID, capeID *int64) (*model.Profile, error)
|
||
Delete(ctx context.Context, uuid string, userID int64) error
|
||
|
||
// 档案状态
|
||
SetActive(ctx context.Context, uuid string, userID int64) error
|
||
CheckLimit(ctx context.Context, userID int64, maxProfiles int) error
|
||
|
||
// 批量查询
|
||
GetByNames(ctx context.Context, names []string) ([]*model.Profile, error)
|
||
GetByProfileName(ctx context.Context, name string) (*model.Profile, error)
|
||
}
|
||
|
||
// TextureService 材质服务接口
|
||
type TextureService interface {
|
||
// 材质CRUD
|
||
Create(ctx context.Context, uploaderID int64, name, description, textureType, url, hash string, size int, isPublic, isSlim bool) (*model.Texture, error)
|
||
UploadTexture(ctx context.Context, uploaderID int64, name, description, textureType string, fileData []byte, fileName string, isPublic, isSlim bool) (*model.Texture, error) // 直接上传材质文件
|
||
GetByID(ctx context.Context, id int64) (*model.Texture, error)
|
||
GetByHash(ctx context.Context, hash string) (*model.Texture, error)
|
||
GetByUserID(ctx context.Context, uploaderID int64, page, pageSize int) ([]*model.Texture, int64, error)
|
||
Search(ctx context.Context, keyword string, textureType model.TextureType, publicOnly bool, page, pageSize int) ([]*model.Texture, int64, error)
|
||
Update(ctx context.Context, textureID, uploaderID int64, name, description string, isPublic *bool) (*model.Texture, error)
|
||
Delete(ctx context.Context, textureID, uploaderID int64) error
|
||
|
||
// 收藏
|
||
ToggleFavorite(ctx context.Context, userID, textureID int64) (bool, error)
|
||
GetUserFavorites(ctx context.Context, userID int64, page, pageSize int) ([]*model.Texture, int64, error)
|
||
|
||
// 限制检查
|
||
CheckUploadLimit(ctx context.Context, uploaderID int64, maxTextures int) error
|
||
}
|
||
|
||
// TokenService 令牌服务接口
|
||
type TokenService interface {
|
||
// 令牌管理
|
||
Create(ctx context.Context, userID int64, uuid, clientToken string) (*model.Profile, []*model.Profile, string, string, error)
|
||
Validate(ctx context.Context, accessToken, clientToken string) bool
|
||
Refresh(ctx context.Context, accessToken, clientToken, selectedProfileID string) (string, string, error)
|
||
Invalidate(ctx context.Context, accessToken string)
|
||
InvalidateUserTokens(ctx context.Context, userID int64)
|
||
|
||
// 令牌查询
|
||
GetUUIDByAccessToken(ctx context.Context, accessToken string) (string, error)
|
||
GetUserIDByAccessToken(ctx context.Context, accessToken string) (int64, error)
|
||
}
|
||
|
||
// VerificationService 验证码服务接口
|
||
type VerificationService interface {
|
||
SendCode(ctx context.Context, email, codeType string) error
|
||
VerifyCode(ctx context.Context, email, code, codeType string) error
|
||
}
|
||
|
||
// CaptchaService 滑动验证码服务接口
|
||
type CaptchaService interface {
|
||
Generate(ctx context.Context) (masterImg, tileImg, captchaID string, y int, err error)
|
||
Verify(ctx context.Context, dx int, captchaID string) (bool, error)
|
||
}
|
||
|
||
// UploadService 上传服务接口
|
||
type UploadService interface {
|
||
GenerateAvatarUploadURL(ctx context.Context, userID int64, fileName string) (*storage.PresignedPostPolicyResult, error)
|
||
GenerateTextureUploadURL(ctx context.Context, userID int64, fileName, textureType string) (*storage.PresignedPostPolicyResult, error)
|
||
}
|
||
|
||
// YggdrasilService Yggdrasil服务接口
|
||
type YggdrasilService interface {
|
||
// 用户认证
|
||
GetUserIDByEmail(ctx context.Context, email string) (int64, error)
|
||
VerifyPassword(ctx context.Context, password string, userID int64) error
|
||
|
||
// 会话管理
|
||
JoinServer(ctx context.Context, serverID, accessToken, selectedProfile, ip string) error
|
||
HasJoinedServer(ctx context.Context, serverID, username, ip string) error
|
||
|
||
// 密码管理
|
||
ResetYggdrasilPassword(ctx context.Context, userID int64) (string, error)
|
||
|
||
// 序列化
|
||
SerializeProfile(ctx context.Context, profile model.Profile) map[string]interface{}
|
||
SerializeUser(ctx context.Context, user *model.User, uuid string) map[string]interface{}
|
||
|
||
// 证书
|
||
GeneratePlayerCertificate(ctx context.Context, uuid string) (map[string]interface{}, error)
|
||
GetPublicKey(ctx context.Context) (string, error)
|
||
}
|
||
|
||
// SecurityService 安全服务接口
|
||
type SecurityService interface {
|
||
// 登录安全
|
||
CheckLoginLocked(ctx context.Context, identifier string) (bool, time.Duration, error)
|
||
RecordLoginFailure(ctx context.Context, identifier string) (int, error)
|
||
ClearLoginAttempts(ctx context.Context, identifier string) error
|
||
GetRemainingLoginAttempts(ctx context.Context, identifier string) (int, error)
|
||
|
||
// 验证码安全
|
||
CheckVerifyLocked(ctx context.Context, email, codeType string) (bool, time.Duration, error)
|
||
RecordVerifyFailure(ctx context.Context, email, codeType string) (int, error)
|
||
ClearVerifyAttempts(ctx context.Context, email, codeType string) error
|
||
}
|
||
|
||
// TextureRenderService 纹理渲染服务接口
|
||
type TextureRenderService interface {
|
||
// RenderTexture 渲染纹理为预览图
|
||
RenderTexture(ctx context.Context, textureID int64, renderType RenderType, size int, format ImageFormat) (*RenderResult, error)
|
||
// RenderTextureFromData 从原始数据渲染纹理
|
||
RenderTextureFromData(ctx context.Context, textureData []byte, renderType RenderType, size int, format ImageFormat, isSlim bool) ([]byte, string, error)
|
||
// GetRenderURL 获取渲染图的URL
|
||
GetRenderURL(textureID int64, renderType RenderType, size int, format ImageFormat) string
|
||
// DeleteRenderCache 删除渲染缓存
|
||
DeleteRenderCache(ctx context.Context, textureID int64) error
|
||
// RenderAvatar 渲染头像(支持2D/3D模式)
|
||
RenderAvatar(ctx context.Context, textureID int64, size int, mode AvatarMode, format ImageFormat) (*RenderResult, error)
|
||
// RenderCape 渲染披风
|
||
RenderCape(ctx context.Context, textureID int64, size int, format ImageFormat) (*RenderResult, error)
|
||
// RenderPreview 渲染预览图(类似Blessing Skin的preview功能)
|
||
RenderPreview(ctx context.Context, textureID int64, size int, format ImageFormat) (*RenderResult, error)
|
||
}
|
||
|
||
// RenderType 渲染类型
|
||
type RenderType string
|
||
|
||
const (
|
||
RenderTypeFront RenderType = "front" // 正面
|
||
RenderTypeBack RenderType = "back" // 背面
|
||
RenderTypeFull RenderType = "full" // 全身
|
||
RenderTypeHead RenderType = "head" // 头像
|
||
RenderTypeIsometric RenderType = "isometric" // 等距视图
|
||
)
|
||
|
||
// ImageFormat 输出格式
|
||
type ImageFormat string
|
||
|
||
const (
|
||
ImageFormatPNG ImageFormat = "png"
|
||
ImageFormatWEBP ImageFormat = "webp"
|
||
)
|
||
|
||
// AvatarMode 头像模式
|
||
type AvatarMode string
|
||
|
||
const (
|
||
AvatarMode2D AvatarMode = "2d" // 2D头像
|
||
AvatarMode3D AvatarMode = "3d" // 3D头像
|
||
)
|
||
|
||
// TextureType 纹理类型
|
||
type TextureType string
|
||
|
||
const (
|
||
TextureTypeSteve TextureType = "steve" // Steve皮肤
|
||
TextureTypeAlex TextureType = "alex" // Alex皮肤
|
||
TextureTypeCape TextureType = "cape" // 披风
|
||
)
|
||
|
||
// RenderResult 渲染结果(附带缓存/HTTP头信息)
|
||
type RenderResult struct {
|
||
URL string
|
||
ContentType string
|
||
ETag string
|
||
LastModified time.Time
|
||
Size int64
|
||
}
|
||
|
||
// Services 服务集合
|
||
type Services struct {
|
||
User UserService
|
||
Profile ProfileService
|
||
Texture TextureService
|
||
Token TokenService
|
||
Verification VerificationService
|
||
Captcha CaptchaService
|
||
Upload UploadService
|
||
Yggdrasil YggdrasilService
|
||
Security SecurityService
|
||
}
|
||
|
||
// ServiceDeps 服务依赖
|
||
type ServiceDeps struct {
|
||
Logger *zap.Logger
|
||
Storage *storage.StorageClient
|
||
}
|