package service import ( "carrotskin/internal/model" "carrotskin/internal/repository" "context" "encoding/base64" "time" "go.uber.org/zap" ) // SerializationService 序列化服务接口 type SerializationService interface { // SerializeProfile 序列化档案为Yggdrasil格式 SerializeProfile(ctx context.Context, profile model.Profile) map[string]interface{} // SerializeUser 序列化用户为Yggdrasil格式 SerializeUser(ctx context.Context, user *model.User, uuid string) map[string]interface{} } // Property Yggdrasil属性 type Property struct { Name string `json:"name"` Value string `json:"value"` Signature string `json:"signature,omitempty"` } // yggdrasilSerializationService 序列化服务实现 type yggdrasilSerializationService struct { textureRepo repository.TextureRepository signatureService *signatureService logger *zap.Logger } // NewSerializationService 创建序列化服务实例 func NewSerializationService( textureRepo repository.TextureRepository, signatureService *signatureService, logger *zap.Logger, ) SerializationService { return &yggdrasilSerializationService{ textureRepo: textureRepo, signatureService: signatureService, logger: logger, } } // SerializeProfile 序列化档案为Yggdrasil格式 func (s *yggdrasilSerializationService) SerializeProfile(ctx context.Context, profile model.Profile) map[string]interface{} { // 创建基本材质数据 texturesMap := make(map[string]interface{}) textures := map[string]interface{}{ "timestamp": time.Now().UnixMilli(), "profileId": profile.UUID, "profileName": profile.Name, "textures": texturesMap, } // 处理皮肤 if profile.SkinID != nil { skin, err := s.textureRepo.FindByID(*profile.SkinID) if err != nil { s.logger.Error("获取皮肤失败", zap.Error(err), zap.Int64("skinID", *profile.SkinID), ) } else if skin != nil { texturesMap["SKIN"] = map[string]interface{}{ "url": skin.URL, "metadata": skin.Size, } } } // 处理披风 if profile.CapeID != nil { cape, err := s.textureRepo.FindByID(*profile.CapeID) if err != nil { s.logger.Error("获取披风失败", zap.Error(err), zap.Int64("capeID", *profile.CapeID), ) } else if cape != nil { texturesMap["CAPE"] = map[string]interface{}{ "url": cape.URL, "metadata": cape.Size, } } } // 将textures编码为base64 bytes, err := json.Marshal(textures) if err != nil { s.logger.Error("序列化textures失败", zap.Error(err), zap.String("profileUUID", profile.UUID), ) return nil } textureData := base64.StdEncoding.EncodeToString(bytes) signature, err := s.signatureService.SignStringWithSHA1withRSA(textureData) if err != nil { s.logger.Error("签名textures失败", zap.Error(err), zap.String("profileUUID", profile.UUID), ) return nil } // 构建结果 data := map[string]interface{}{ "id": profile.UUID, "name": profile.Name, "properties": []Property{ { Name: "textures", Value: textureData, Signature: signature, }, }, } return data } // SerializeUser 序列化用户为Yggdrasil格式 func (s *yggdrasilSerializationService) SerializeUser(ctx context.Context, user *model.User, uuid string) map[string]interface{} { if user == nil { s.logger.Error("尝试序列化空用户") return nil } data := map[string]interface{}{ "id": uuid, } // 正确处理 *datatypes.JSON 指针类型 // 如果 Properties 为 nil,则设置为 nil;否则解引用并解析为 JSON 值 if user.Properties == nil { data["properties"] = nil } else { // datatypes.JSON 是 []byte 类型,需要解析为实际的 JSON 值 var propertiesValue interface{} if err := json.Unmarshal(*user.Properties, &propertiesValue); err != nil { s.logger.Warn("解析用户Properties失败,使用空值", zap.Error(err), zap.Int64("userID", user.ID), ) data["properties"] = nil } else { data["properties"] = propertiesValue } } return data }