// Package service 定义业务逻辑层接口 package service import ( "context" "time" "carrotskin/internal/model" "carrotskin/pkg/storage" "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) GetByUsername(ctx context.Context, username 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 // 头像上传 UploadAvatar(ctx context.Context, userID int64, fileData []byte, fileName string) (string, error) // URL验证 ValidateAvatarURL(ctx context.Context, avatarURL string) error // 配置获取 GetMaxProfilesPerUser() int GetMaxTexturesPerUser() int // 管理员操作 ListUsers(ctx context.Context, page, pageSize int) ([]*model.User, int64, error) SetRole(ctx context.Context, userID int64, role string) error SetStatus(ctx context.Context, userID int64, status int16) error } // 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 // 档案状态 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) // ProfileSearchByName 按用户名批量查询档案,返回简化的 NameAndId 列表(文档 2.1) // 规范化(toLowerCase)、空名过滤、每页最多 maxBatch 个限制由本方法在服务端兜底处理。 ProfileSearchByName(ctx context.Context, names []string, maxBatch int) ([]model.NameAndId, error) // ProfileSearchByNameSingle 按单个用户名查询档案,返回简化的 NameAndId(文档 2.2) // 未找到时返回 (nil, nil),符合文档中"客户端返回 Optional.empty()"的契约。 ProfileSearchByNameSingle(ctx context.Context, name string) (*model.NameAndId, error) } // TextureService 材质服务接口 type TextureService interface { // 材质CRUD 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 // 管理员操作 ListForAdmin(ctx context.Context, page, pageSize int) ([]*model.Texture, int64, error) AdminDelete(ctx context.Context, textureID int64) error IncrementDownload(ctx context.Context, textureID int64) error } // TokenService 令牌服务接口 type TokenService interface { // 令牌管理 Create(ctx context.Context, userID int64, uuid, clientToken string) (*model.Profile, []*model.Profile, string, string, error) CreateWithProfile(ctx context.Context, userID int64, profileUUID string, 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) CheckVerified(ctx context.Context, captchaID string) (bool, error) ConsumeVerified(ctx context.Context, captchaID string) 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{} SerializeProfileWithUnsigned(ctx context.Context, profile model.Profile, unsigned bool) map[string]interface{} SerializeUser(ctx context.Context, user *model.User, uuid string) map[string]interface{} // 证书 GeneratePlayerCertificate(ctx context.Context, uuid string) (*PlayerCertificate, error) GetPublicKey(ctx context.Context) (string, error) } // FriendActionType 好友操作类型(文档 1.3.2) type FriendActionType string const ( FriendActionAdd FriendActionType = "ADD" FriendActionRemove FriendActionType = "REMOVE" ) // FriendActionRequest 好友操作请求(文档 1.3.2) type FriendActionRequest struct { Name string `json:"name,omitempty"` ProfileID string `json:"profileId,omitempty"` UpdateType FriendActionType `json:"updateType"` } // FriendDTO 好友条目(文档 1.3.1 FriendDto) type FriendDTO struct { ProfileID string `json:"profileId"` Name string `json:"name"` } // FriendsListResponse 好友列表响应(文档 1.3.1) type FriendsListResponse struct { Friends []FriendDTO `json:"friends"` IncomingRequests []FriendDTO `json:"incomingRequests"` OutgoingRequests []FriendDTO `json:"outgoingRequests"` } // PlayerAttributesRequest 玩家偏好更新请求(文档 1.2.2) type PlayerAttributesRequest struct { ProfanityFilterPreferences *ProfanityFilterPreferences `json:"profanityFilterPreferences,omitempty"` FriendsPreferences *FriendsPreferences `json:"friendsPreferences,omitempty"` } // ProfanityFilterPreferences 脏词过滤偏好 type ProfanityFilterPreferences struct { ProfanityFilterOn *bool `json:"profanityFilterOn,omitempty"` } // FriendsPreferences 好友偏好 type FriendsPreferences struct { Friends *string `json:"friends,omitempty"` // ENABLED / DISABLED AcceptInvites *string `json:"acceptInvites,omitempty"` // ENABLED / DISABLED } // PlayerAttributesResponse 玩家属性响应(文档 1.2.1) // 仅实现好友相关字段,其它(privileges/banStatus 等)不在好友系统范围 type PlayerAttributesResponse struct { ProfanityFilterPreferences ProfanityFilterPreferencesResp `json:"profanityFilterPreferences"` FriendsPreferences FriendsPreferencesResp `json:"friendsPreferences"` ChatPreferences ChatPreferencesResp `json:"chatPreferences"` } // ProfanityFilterPreferencesResp 脏词过滤偏好响应 type ProfanityFilterPreferencesResp struct { ProfanityFilterOn bool `json:"profanityFilterOn"` } // FriendsPreferencesResp 好友偏好响应 type FriendsPreferencesResp struct { Friends string `json:"friends"` AcceptInvites string `json:"acceptInvites"` } // ChatPreferencesResp 聊天偏好响应 type ChatPreferencesResp struct { TextCommunication string `json:"textCommunication"` } // PresenceRequest 在线状态上报请求(文档 1.1) type PresenceRequest struct { Status string `json:"status"` } // PresenceEntry 单个在线玩家状态(文档 1.1) type PresenceEntry struct { ProfileID string `json:"profileId"` PMID string `json:"pmid,omitempty"` Status string `json:"status"` LastUpdated string `json:"lastUpdated"` } // PresenceResponse 在线状态响应(文档 1.1) type PresenceResponse struct { Presence []PresenceEntry `json:"presence"` } // BlockListResponse 屏蔽列表响应(文档 1.6) type BlockListResponse struct { BlockedProfiles []string `json:"blockedProfiles"` } // FriendsService 好友系统服务接口(文档 1.1 / 1.2 / 1.3 / 1.6) type FriendsService interface { // 好友列表与操作 ListFriends(ctx context.Context, requesterUUID string) (*FriendsListResponse, error) PerformFriendAction(ctx context.Context, requesterUUID string, req FriendActionRequest) (*FriendsListResponse, error) // 玩家偏好属性 GetAttributes(ctx context.Context, profileUUID string) (*PlayerAttributesResponse, error) UpdateAttributes(ctx context.Context, profileUUID string, req PlayerAttributesRequest) error // 在线状态 UpdatePresence(ctx context.Context, requesterUUID string, status string) (*PresenceResponse, error) // 屏蔽列表 GetBlocklist(ctx context.Context, blockerUUID string) (*BlockListResponse, 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 } // Services 服务集合 type Services struct { User UserService Profile ProfileService Texture TextureService Token TokenService Verification VerificationService Captcha CaptchaService Yggdrasil YggdrasilService Security SecurityService Friends FriendsService } // ServiceDeps 服务依赖 type ServiceDeps struct { Logger *zap.Logger Storage *storage.StorageClient }