fix(gateway): expose mic seat animation appearance

This commit is contained in:
zhx 2026-06-15 15:02:28 +08:00
parent 152bdf232e
commit 55770ce23b
5 changed files with 157 additions and 39 deletions

View File

@ -62,6 +62,18 @@ GET /api/v1/users/me/appearance
"entitlement_id": "ent-vehicle", "entitlement_id": "ent-vehicle",
"expires_at_ms": 1999999999999 "expires_at_ms": 1999999999999
}, },
"mic_seat_animation": {
"resource_id": 8106,
"resource_code": "mic_seat_wave_gold",
"resource_type": "mic_seat_animation",
"name": "Gold Mic Wave",
"asset_url": "https://cdn.example/mic-seat.png",
"preview_url": "",
"animation_url": "https://cdn.example/mic-seat.svga",
"metadata_json": "{}",
"entitlement_id": "ent-mic-seat-wave",
"expires_at_ms": 1999999999999
},
"equipped_badges": [], "equipped_badges": [],
"badges": [ "badges": [
{ {
@ -94,7 +106,20 @@ GET /api/v1/users/me/appearance
"honor_badges": [], "honor_badges": [],
"server_time_ms": 1778256000000 "server_time_ms": 1778256000000
}, },
"resources": [], "resources": [
{
"resource_id": 8106,
"resource_code": "mic_seat_wave_gold",
"resource_type": "mic_seat_animation",
"name": "Gold Mic Wave",
"asset_url": "https://cdn.example/mic-seat.png",
"preview_url": "",
"animation_url": "https://cdn.example/mic-seat.svga",
"metadata_json": "{}",
"entitlement_id": "ent-mic-seat-wave",
"expires_at_ms": 1999999999999
}
],
"server_time_ms": 1778256000000 "server_time_ms": 1778256000000
} }
``` ```
@ -107,6 +132,7 @@ GET /api/v1/users/me/appearance
| avatar_frame | 当前佩戴头像框,未佩戴时为 `{}` | | avatar_frame | 当前佩戴头像框,未佩戴时为 `{}` |
| profile_card | 当前佩戴背景卡,未佩戴时为 `{}` | | profile_card | 当前佩戴背景卡,未佩戴时为 `{}` |
| vehicle | 当前佩戴入场座驾,未佩戴时为 `{}` | | vehicle | 当前佩戴入场座驾,未佩戴时为 `{}` |
| mic_seat_animation | 当前佩戴麦位声波,未佩戴时为 `{}` |
| equipped_badges | wallet 当前佩戴的 badge 权益 | | equipped_badges | wallet 当前佩戴的 badge 权益 |
| badges | 房间、公屏等高频展示用徽章,取 `strip_badges` | | badges | 房间、公屏等高频展示用徽章,取 `strip_badges` |
| badge_profile | 完整徽章展示配置 | | badge_profile | 完整徽章展示配置 |
@ -116,7 +142,7 @@ GET /api/v1/users/me/appearance
说明: 说明:
- 过期佩戴不会返回。 - 过期佩戴不会返回。
- 头像框、背景卡、入场座驾来自 wallet 当前佩戴。 - 头像框、背景卡、入场座驾、麦位声波来自 wallet 当前佩戴。
- 徽章展示配置来自 activity。 - 徽章展示配置来自 activity。
- 客户端渲染动画优先使用 `animation_url`,没有动画时用 `asset_url``preview_url` 兜底。 - 客户端渲染动画优先使用 `animation_url`,没有动画时用 `asset_url``preview_url` 兜底。
@ -345,6 +371,18 @@ GET /api/v1/users/room-display-profiles:batch?user_ids=42,43
"entitlement_id": "ent-vehicle", "entitlement_id": "ent-vehicle",
"expires_at_ms": 1999999999999 "expires_at_ms": 1999999999999
}, },
"mic_seat_animation": {
"resource_id": 8106,
"resource_code": "mic_seat_wave_gold",
"resource_type": "mic_seat_animation",
"name": "Gold Mic Wave",
"asset_url": "https://cdn.example/mic-seat.png",
"preview_url": "",
"animation_url": "https://cdn.example/mic-seat.svga",
"metadata_json": "{}",
"entitlement_id": "ent-mic-seat-wave",
"expires_at_ms": 1999999999999
},
"charm": 0 "charm": 0
} }
] ]
@ -356,6 +394,7 @@ GET /api/v1/users/room-display-profiles:batch?user_ids=42,43
- 房间、公屏、在线列表展示头像框用 `avatar_frame` - 房间、公屏、在线列表展示头像框用 `avatar_frame`
- 房间资料卡展示用 `profile_card`,从 `metadata_json.profile_card_layout` 解析 `content_top``content_height` - 房间资料卡展示用 `profile_card`,从 `metadata_json.profile_card_layout` 解析 `content_top``content_height`
- 入场座驾展示用 `vehicle` - 入场座驾展示用 `vehicle`
- 麦位声波展示用 `mic_seat_animation`
- 徽章条展示用 `badges` - 徽章条展示用 `badges`
- 过期佩戴不会返回。 - 过期佩戴不会返回。

View File

@ -2440,6 +2440,17 @@ func TestJoinRoomReturnsInitialDataWithIMGroupRTCTokenAndProfiles(t *testing.T)
GrantStrategy: "extend_expiry", GrantStrategy: "extend_expiry",
Status: "active", Status: "active",
} }
micSeatResource := &walletv1.Resource{
ResourceId: 8106,
ResourceCode: "mic_seat_wave_gold",
ResourceType: "mic_seat_animation",
Name: "Gold Mic Wave",
AssetUrl: "https://cdn.example/mic-seat.png",
AnimationUrl: "https://cdn.example/mic-seat.svga",
MetadataJson: `{"usage":"mic_seat"}`,
GrantStrategy: "set_active_flag",
Status: "active",
}
shortBadgeResource := &walletv1.Resource{ shortBadgeResource := &walletv1.Resource{
ResourceId: 8105, ResourceId: 8105,
ResourceCode: "badge_tile_gold", ResourceCode: "badge_tile_gold",
@ -2471,6 +2482,14 @@ func TestJoinRoomReturnsInitialDataWithIMGroupRTCTokenAndProfiles(t *testing.T)
Equipped: true, Equipped: true,
ExpiresAtMs: 1999999999999, ExpiresAtMs: 1999999999999,
}, },
{
UserId: 42,
EntitlementId: "ent-mic-seat-wave",
ResourceId: 8106,
Resource: micSeatResource,
Equipped: true,
ExpiresAtMs: 1999999999999,
},
}, },
}}, }},
}, },
@ -2531,13 +2550,13 @@ func TestJoinRoomReturnsInitialDataWithIMGroupRTCTokenAndProfiles(t *testing.T)
} }
hasRoomDisplayResourceQuery := false hasRoomDisplayResourceQuery := false
for _, req := range walletClient.batchEquippedRequests { for _, req := range walletClient.batchEquippedRequests {
if strings.Join(req.GetResourceTypes(), ",") == "avatar_frame,profile_card,vehicle,badge" { if strings.Join(req.GetResourceTypes(), ",") == "avatar_frame,profile_card,vehicle,badge,mic_seat_animation" {
hasRoomDisplayResourceQuery = true hasRoomDisplayResourceQuery = true
break break
} }
} }
if !hasRoomDisplayResourceQuery { if !hasRoomDisplayResourceQuery {
t.Fatalf("join response must batch room wearable resources including profile_card: %+v", walletClient.batchEquippedRequests) t.Fatalf("join response must batch room wearable resources including mic_seat_animation: %+v", walletClient.batchEquippedRequests)
} }
profiles, profilesOK := data["profiles"].([]any) profiles, profilesOK := data["profiles"].([]any)
if !profilesOK || len(profiles) == 0 { if !profilesOK || len(profiles) == 0 {
@ -2557,6 +2576,10 @@ func TestJoinRoomReturnsInitialDataWithIMGroupRTCTokenAndProfiles(t *testing.T)
if !profileCardOK || profileCard["resource_id"] != float64(8104) || !strings.Contains(metadataJSON, `"content_top":143`) { if !profileCardOK || profileCard["resource_id"] != float64(8104) || !strings.Contains(metadataJSON, `"content_top":143`) {
t.Fatalf("join profile must include profile_card metadata_json: %+v", currentProfile) t.Fatalf("join profile must include profile_card metadata_json: %+v", currentProfile)
} }
micSeatAnimation, micSeatAnimationOK := currentProfile["mic_seat_animation"].(map[string]any)
if !micSeatAnimationOK || micSeatAnimation["resource_id"] != float64(8106) || micSeatAnimation["animation_url"] != "https://cdn.example/mic-seat.svga" {
t.Fatalf("join profile must include mic_seat_animation resource: %+v", currentProfile)
}
badges, badgesOK := currentProfile["badges"].([]any) badges, badgesOK := currentProfile["badges"].([]any)
if !badgesOK || len(badges) != 1 { if !badgesOK || len(badges) != 1 {
t.Fatalf("join profile must include equipped badge list: %+v", currentProfile["badges"]) t.Fatalf("join profile must include equipped badge list: %+v", currentProfile["badges"])
@ -5928,6 +5951,17 @@ func TestAppearanceAggregatesEquippedResourcesAndBadges(t *testing.T) {
GrantStrategy: "set_active_flag", GrantStrategy: "set_active_flag",
Status: "active", Status: "active",
} }
micSeatResource := &walletv1.Resource{
ResourceId: 8106,
ResourceCode: "mic_seat_wave_gold",
ResourceType: "mic_seat_animation",
Name: "Gold Mic Wave",
AssetUrl: "https://cdn.example/mic-seat.png",
AnimationUrl: "https://cdn.example/mic-seat.svga",
MetadataJson: `{"usage":"mic_seat"}`,
GrantStrategy: "set_active_flag",
Status: "active",
}
walletClient := &fakeWalletClient{ walletClient := &fakeWalletClient{
batchEquippedResp: &walletv1.BatchGetUserEquippedResourcesResponse{ batchEquippedResp: &walletv1.BatchGetUserEquippedResourcesResponse{
Users: []*walletv1.UserEquippedResources{{ Users: []*walletv1.UserEquippedResources{{
@ -5937,6 +5971,7 @@ func TestAppearanceAggregatesEquippedResourcesAndBadges(t *testing.T) {
{UserId: 42, EntitlementId: "ent-vehicle", ResourceId: 8102, Resource: vehicleResource, Equipped: true, ExpiresAtMs: 1999999999999}, {UserId: 42, EntitlementId: "ent-vehicle", ResourceId: 8102, Resource: vehicleResource, Equipped: true, ExpiresAtMs: 1999999999999},
{UserId: 42, EntitlementId: "ent-profile-card", ResourceId: 8104, Resource: profileCardResource, Equipped: true, ExpiresAtMs: 1999999999999}, {UserId: 42, EntitlementId: "ent-profile-card", ResourceId: 8104, Resource: profileCardResource, Equipped: true, ExpiresAtMs: 1999999999999},
{UserId: 42, EntitlementId: "ent-badge", ResourceId: 8103, Resource: badgeResource, Equipped: true, ExpiresAtMs: 1999999999999}, {UserId: 42, EntitlementId: "ent-badge", ResourceId: 8103, Resource: badgeResource, Equipped: true, ExpiresAtMs: 1999999999999},
{UserId: 42, EntitlementId: "ent-mic-seat-wave", ResourceId: 8106, Resource: micSeatResource, Equipped: true, ExpiresAtMs: 1999999999999},
}, },
}}, }},
}, },
@ -5986,6 +6021,11 @@ func TestAppearanceAggregatesEquippedResourcesAndBadges(t *testing.T) {
ResourceID int64 `json:"resource_id"` ResourceID int64 `json:"resource_id"`
MetadataJSON string `json:"metadata_json"` MetadataJSON string `json:"metadata_json"`
} `json:"profile_card"` } `json:"profile_card"`
MicSeatAnimation struct {
ResourceID int64 `json:"resource_id"`
AnimationURL string `json:"animation_url"`
EntitlementID string `json:"entitlement_id"`
} `json:"mic_seat_animation"`
EquippedBadges []struct { EquippedBadges []struct {
ResourceID int64 `json:"resource_id"` ResourceID int64 `json:"resource_id"`
} `json:"equipped_badges"` } `json:"equipped_badges"`
@ -5995,6 +6035,10 @@ func TestAppearanceAggregatesEquippedResourcesAndBadges(t *testing.T) {
AssetURL string `json:"asset_url"` AssetURL string `json:"asset_url"`
} `json:"resource"` } `json:"resource"`
} `json:"badges"` } `json:"badges"`
Resources []struct {
ResourceID int64 `json:"resource_id"`
ResourceType string `json:"resource_type"`
} `json:"resources"`
} `json:"data"` } `json:"data"`
} }
if err := json.NewDecoder(recorder.Body).Decode(&envelope); err != nil { if err := json.NewDecoder(recorder.Body).Decode(&envelope); err != nil {
@ -6003,12 +6047,25 @@ func TestAppearanceAggregatesEquippedResourcesAndBadges(t *testing.T) {
if walletClient.lastBatchEquipped == nil || walletClient.lastBatchEquipped.GetUserIds()[0] != 42 { if walletClient.lastBatchEquipped == nil || walletClient.lastBatchEquipped.GetUserIds()[0] != 42 {
t.Fatalf("appearance should batch query equipped resources: %+v", walletClient.lastBatchEquipped) t.Fatalf("appearance should batch query equipped resources: %+v", walletClient.lastBatchEquipped)
} }
if strings.Join(walletClient.lastBatchEquipped.GetResourceTypes(), ",") != "avatar_frame,profile_card,vehicle,badge,mic_seat_animation" {
t.Fatalf("appearance should query mic_seat_animation with wearable resources: %+v", walletClient.lastBatchEquipped.GetResourceTypes())
}
if achievementClient.lastBadges == nil || achievementClient.lastBadges.GetUserId() != 42 { if achievementClient.lastBadges == nil || achievementClient.lastBadges.GetUserId() != 42 {
t.Fatalf("appearance should query displayed badges: %+v", achievementClient.lastBadges) t.Fatalf("appearance should query displayed badges: %+v", achievementClient.lastBadges)
} }
if envelope.Code != httpkit.CodeOK || envelope.Data.UserID != "42" || envelope.Data.AvatarFrame.AnimationURL != "https://cdn.example/frame.svga" || envelope.Data.Vehicle.ResourceID != 8102 || envelope.Data.ProfileCard.ResourceID != 8104 || !strings.Contains(envelope.Data.ProfileCard.MetadataJSON, `"content_top":117`) || len(envelope.Data.EquippedBadges) != 1 || len(envelope.Data.Badges) != 1 || envelope.Data.Badges[0].Resource.AssetURL != "https://cdn.example/badge.png" { if envelope.Code != httpkit.CodeOK || envelope.Data.UserID != "42" || envelope.Data.AvatarFrame.AnimationURL != "https://cdn.example/frame.svga" || envelope.Data.Vehicle.ResourceID != 8102 || envelope.Data.ProfileCard.ResourceID != 8104 || !strings.Contains(envelope.Data.ProfileCard.MetadataJSON, `"content_top":117`) || envelope.Data.MicSeatAnimation.ResourceID != 8106 || envelope.Data.MicSeatAnimation.AnimationURL != "https://cdn.example/mic-seat.svga" || envelope.Data.MicSeatAnimation.EntitlementID != "ent-mic-seat-wave" || len(envelope.Data.EquippedBadges) != 1 || len(envelope.Data.Badges) != 1 || envelope.Data.Badges[0].Resource.AssetURL != "https://cdn.example/badge.png" {
t.Fatalf("appearance response mismatch: %+v", envelope) t.Fatalf("appearance response mismatch: %+v", envelope)
} }
hasMicSeatResource := false
for _, resource := range envelope.Data.Resources {
if resource.ResourceID == 8106 && resource.ResourceType == "mic_seat_animation" {
hasMicSeatResource = true
break
}
}
if !hasMicSeatResource {
t.Fatalf("appearance resources must include equipped mic_seat_animation: %+v", envelope.Data.Resources)
}
} }
func TestListEmojiPacksFiltersRegionAndReturnsAssets(t *testing.T) { func TestListEmojiPacksFiltersRegionAndReturnsAssets(t *testing.T) {

View File

@ -24,6 +24,13 @@ import (
const ( const (
defaultRoomFeedRelationPageSize = 100 defaultRoomFeedRelationPageSize = 100
maxRoomFeedRelationScanCount = 500 maxRoomFeedRelationScanCount = 500
// 房间展示资料只读取客户端能在首屏、公屏或资料卡直接渲染的当前佩戴资源。
roomAppearanceResourceAvatarFrame = "avatar_frame"
roomAppearanceResourceProfileCard = "profile_card"
roomAppearanceResourceVehicle = "vehicle"
roomAppearanceResourceBadge = "badge"
roomAppearanceResourceMicSeatAnimation = "mic_seat_animation"
) )
type flexibleInt64 int64 type flexibleInt64 int64
@ -1649,6 +1656,7 @@ func (h *Handler) roomDisplayProfileMap(request *http.Request, userIDs []int64)
AvatarFrame: appearance.AvatarFrame, AvatarFrame: appearance.AvatarFrame,
ProfileCard: appearance.ProfileCard, ProfileCard: appearance.ProfileCard,
Vehicle: appearance.Vehicle, Vehicle: appearance.Vehicle,
MicSeatAnimation: appearance.MicSeatAnimation,
Charm: 0, Charm: 0,
} }
// 显式补空对象/空数组,避免客户端在房间资料中同时处理 null 和空值。 // 显式补空对象/空数组,避免客户端在房间资料中同时处理 null 和空值。
@ -1677,6 +1685,11 @@ func (h *Handler) roomDisplayProfileMap(request *http.Request, userIDs []int64)
profile.Vehicle = map[string]any{} profile.Vehicle = map[string]any{}
profiles[userID] = profile profiles[userID] = profile
} }
if profiles[userID].MicSeatAnimation == nil {
profile := profiles[userID]
profile.MicSeatAnimation = map[string]any{}
profiles[userID] = profile
}
if profiles[userID].ProfileCard == nil { if profiles[userID].ProfileCard == nil {
profile := profiles[userID] profile := profiles[userID]
profile.ProfileCard = map[string]any{} profile.ProfileCard = map[string]any{}
@ -1687,10 +1700,11 @@ func (h *Handler) roomDisplayProfileMap(request *http.Request, userIDs []int64)
} }
type roomAppearanceResources struct { type roomAppearanceResources struct {
AvatarFrame map[string]any AvatarFrame map[string]any
ProfileCard map[string]any ProfileCard map[string]any
Vehicle map[string]any Vehicle map[string]any
Badges []map[string]any MicSeatAnimation map[string]any
Badges []map[string]any
} }
func (h *Handler) roomAppearanceResourceMap(request *http.Request, userIDs []int64) map[int64]roomAppearanceResources { func (h *Handler) roomAppearanceResourceMap(request *http.Request, userIDs []int64) map[int64]roomAppearanceResources {
@ -1703,7 +1717,7 @@ func (h *Handler) roomAppearanceResourceMap(request *http.Request, userIDs []int
RequestId: httpkit.RequestIDFromContext(request.Context()), RequestId: httpkit.RequestIDFromContext(request.Context()),
AppCode: appcode.FromContext(request.Context()), AppCode: appcode.FromContext(request.Context()),
UserIds: userIDs, UserIds: userIDs,
ResourceTypes: []string{"avatar_frame", "profile_card", "vehicle", "badge"}, ResourceTypes: []string{roomAppearanceResourceAvatarFrame, roomAppearanceResourceProfileCard, roomAppearanceResourceVehicle, roomAppearanceResourceBadge, roomAppearanceResourceMicSeatAnimation},
}) })
if err != nil { if err != nil {
// 装扮是展示增强,失败不影响房间主数据返回。 // 装扮是展示增强,失败不影响房间主数据返回。
@ -1718,14 +1732,16 @@ func (h *Handler) roomAppearanceResourceMap(request *http.Request, userIDs []int
// 同一资源类型只保留当前佩戴的一个权益wallet equipment 主键保证唯一性。 // 同一资源类型只保留当前佩戴的一个权益wallet equipment 主键保证唯一性。
resource := roomAppearanceResourceFromEntitlement(item) resource := roomAppearanceResourceFromEntitlement(item)
switch item.GetResource().GetResourceType() { switch item.GetResource().GetResourceType() {
case "avatar_frame": case roomAppearanceResourceAvatarFrame:
current.AvatarFrame = resource current.AvatarFrame = resource
case "profile_card": case roomAppearanceResourceProfileCard:
current.ProfileCard = resource current.ProfileCard = resource
case "vehicle": case roomAppearanceResourceVehicle:
current.Vehicle = resource current.Vehicle = resource
case "badge": case roomAppearanceResourceBadge:
current.Badges = append(current.Badges, roomBadgeItemFromEquippedResource(resource)) current.Badges = append(current.Badges, roomBadgeItemFromEquippedResource(resource))
case roomAppearanceResourceMicSeatAnimation:
current.MicSeatAnimation = resource
} }
} }
result[user.GetUserId()] = current result[user.GetUserId()] = current

View File

@ -172,6 +172,7 @@ type roomDisplayProfileData struct {
AvatarFrame map[string]any `json:"avatar_frame"` AvatarFrame map[string]any `json:"avatar_frame"`
ProfileCard map[string]any `json:"profile_card"` ProfileCard map[string]any `json:"profile_card"`
Vehicle map[string]any `json:"vehicle"` Vehicle map[string]any `json:"vehicle"`
MicSeatAnimation map[string]any `json:"mic_seat_animation"`
Charm int64 `json:"charm"` Charm int64 `json:"charm"`
} }

View File

@ -17,26 +17,28 @@ import (
const ( const (
// /appearance 只暴露客户端能直接佩戴或展示的装扮维度;类型值保持和 wallet resource_type 一致。 // /appearance 只暴露客户端能直接佩戴或展示的装扮维度;类型值保持和 wallet resource_type 一致。
appearanceResourceAvatarFrame = "avatar_frame" appearanceResourceAvatarFrame = "avatar_frame"
appearanceResourceProfileCard = "profile_card" appearanceResourceProfileCard = "profile_card"
appearanceResourceVehicle = "vehicle" appearanceResourceVehicle = "vehicle"
appearanceResourceBadge = "badge" appearanceResourceBadge = "badge"
appearanceResourceMicSeatAnimation = "mic_seat_animation"
) )
var errAppearanceUpstream = errors.New("upstream service error") var errAppearanceUpstream = errors.New("upstream service error")
type appearanceData struct { type appearanceData struct {
UserID string `json:"user_id"` UserID string `json:"user_id"`
AvatarFrame map[string]any `json:"avatar_frame"` AvatarFrame map[string]any `json:"avatar_frame"`
ProfileCard map[string]any `json:"profile_card"` ProfileCard map[string]any `json:"profile_card"`
Vehicle map[string]any `json:"vehicle"` Vehicle map[string]any `json:"vehicle"`
Level map[string]any `json:"level"` MicSeatAnimation map[string]any `json:"mic_seat_animation"`
LevelBadges map[string]any `json:"level_badges"` Level map[string]any `json:"level"`
EquippedBadges []map[string]any `json:"equipped_badges"` LevelBadges map[string]any `json:"level_badges"`
Badges []map[string]any `json:"badges"` EquippedBadges []map[string]any `json:"equipped_badges"`
BadgeProfile appearanceBadgeData `json:"badge_profile"` Badges []map[string]any `json:"badges"`
Resources []map[string]any `json:"resources"` BadgeProfile appearanceBadgeData `json:"badge_profile"`
ServerTimeMS int64 `json:"server_time_ms"` Resources []map[string]any `json:"resources"`
ServerTimeMS int64 `json:"server_time_ms"`
} }
type appearanceBadgeData struct { type appearanceBadgeData struct {
@ -80,15 +82,16 @@ func (h *Handler) writeAppearance(writer http.ResponseWriter, request *http.Requ
func (h *Handler) appearanceForUser(request *http.Request, userID int64) (appearanceData, error) { func (h *Handler) appearanceForUser(request *http.Request, userID int64) (appearanceData, error) {
// 先初始化为空对象/数组,保证客户端不需要处理 null 和字段缺失两套形态。 // 先初始化为空对象/数组,保证客户端不需要处理 null 和字段缺失两套形态。
data := appearanceData{ data := appearanceData{
UserID: strconv.FormatInt(userID, 10), UserID: strconv.FormatInt(userID, 10),
AvatarFrame: map[string]any{}, AvatarFrame: map[string]any{},
ProfileCard: map[string]any{}, ProfileCard: map[string]any{},
Vehicle: map[string]any{}, Vehicle: map[string]any{},
Level: defaultAppearanceLevelDisplay(), MicSeatAnimation: map[string]any{},
LevelBadges: map[string]any{}, Level: defaultAppearanceLevelDisplay(),
EquippedBadges: []map[string]any{}, LevelBadges: map[string]any{},
Badges: []map[string]any{}, EquippedBadges: []map[string]any{},
Resources: []map[string]any{}, Badges: []map[string]any{},
Resources: []map[string]any{},
} }
// 当前佩戴只走 BatchGetUserEquippedResources // 当前佩戴只走 BatchGetUserEquippedResources
// 1. wallet 内部会过滤过期佩戴; // 1. wallet 内部会过滤过期佩戴;
@ -97,7 +100,7 @@ func (h *Handler) appearanceForUser(request *http.Request, userID int64) (appear
RequestId: httpkit.RequestIDFromContext(request.Context()), RequestId: httpkit.RequestIDFromContext(request.Context()),
AppCode: appcode.FromContext(request.Context()), AppCode: appcode.FromContext(request.Context()),
UserIds: []int64{userID}, UserIds: []int64{userID},
ResourceTypes: []string{appearanceResourceAvatarFrame, appearanceResourceProfileCard, appearanceResourceVehicle, appearanceResourceBadge}, ResourceTypes: []string{appearanceResourceAvatarFrame, appearanceResourceProfileCard, appearanceResourceVehicle, appearanceResourceBadge, appearanceResourceMicSeatAnimation},
}) })
if err != nil { if err != nil {
return data, err return data, err
@ -120,6 +123,8 @@ func (h *Handler) appearanceForUser(request *http.Request, userID int64) (appear
data.Vehicle = resource data.Vehicle = resource
case appearanceResourceBadge: case appearanceResourceBadge:
data.EquippedBadges = append(data.EquippedBadges, resource) data.EquippedBadges = append(data.EquippedBadges, resource)
case appearanceResourceMicSeatAnimation:
data.MicSeatAnimation = resource
} }
} }
} }