2026-06-29 10:41:24 +08:00

78 lines
3.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package service
import (
"fmt"
"strings"
"time"
roomeventsv1 "hyapp.local/api/proto/events/room/v1"
"hyapp/services/room-service/internal/room/command"
"hyapp/services/room-service/internal/room/outbox"
"hyapp/services/room-service/internal/room/state"
)
// roomMicChangedEvent 建立 RoomMicChanged 事实;展示快照只来自命令入口,
// room-service 不反查 user-service保证 Room Cell 主链路仍只维护房态。
func roomMicChangedEvent(event *roomeventsv1.RoomMicChanged, profile command.UserDisplayProfile) *roomeventsv1.RoomMicChanged {
if event == nil {
event = &roomeventsv1.RoomMicChanged{}
}
event.TargetNickname = strings.TrimSpace(profile.Nickname)
event.TargetAvatar = strings.TrimSpace(profile.Avatar)
event.TargetDisplayUserId = strings.TrimSpace(profile.DisplayUserID)
event.TargetPrettyDisplayUserId = strings.TrimSpace(profile.PrettyDisplayUserID)
return event
}
// roomMicChangedIMAttributes 是 direct IM 和 outbox 补偿的唯一麦位 attributes 映射。
// 目标用户展示字段同时写 target_*actor 与 target 相同时再写旧客户端已认识的 nickname/avatar。
func roomMicChangedIMAttributes(event *roomeventsv1.RoomMicChanged) map[string]string {
if event == nil {
return map[string]string{}
}
values := map[string]string{
"action": strings.TrimSpace(event.GetAction()),
"mic_session_id": strings.TrimSpace(event.GetMicSessionId()),
"publish_state": strings.TrimSpace(event.GetPublishState()),
"reason": strings.TrimSpace(event.GetReason()),
"publish_deadline_ms": fmt.Sprintf("%d", event.GetPublishDeadlineMs()),
"publish_event_time_ms": fmt.Sprintf("%d", event.GetPublishEventTimeMs()),
"mic_muted": fmt.Sprintf("%t", event.GetMicMuted()),
"seat_status": strings.TrimSpace(event.GetSeatStatus()),
"target_gift_value": fmt.Sprintf("%d", event.GetTargetGiftValue()),
"target_nickname": strings.TrimSpace(event.GetTargetNickname()),
"target_avatar": strings.TrimSpace(event.GetTargetAvatar()),
"target_display_user_id": strings.TrimSpace(event.GetTargetDisplayUserId()),
"target_pretty_display_user_id": strings.TrimSpace(event.GetTargetPrettyDisplayUserId()),
}
if event.GetActorUserId() == event.GetTargetUserId() {
values["nickname"] = values["target_nickname"]
values["avatar"] = values["target_avatar"]
values["display_user_id"] = values["target_display_user_id"]
values["pretty_display_user_id"] = values["target_pretty_display_user_id"]
}
for key, value := range values {
if value == "" {
delete(values, key)
}
}
return values
}
// buildMicDownEventForSeat records every non-MicDown release path as the same
// RoomMicChanged/down fact, so downstream duration consumers never need to infer
// mic closure from leave/kick/close side effects.
func buildMicDownEventForSeat(roomID string, roomVersion int64, now time.Time, actorUserID int64, targetUserID int64, seatNo int32, micSessionID string, reason string) (outbox.Record, error) {
return outbox.Build(roomID, "RoomMicChanged", roomVersion, now, roomMicChangedEvent(&roomeventsv1.RoomMicChanged{
ActorUserId: actorUserID,
TargetUserId: targetUserID,
FromSeat: seatNo,
ToSeat: 0,
Action: "down",
MicSessionId: micSessionID,
PublishState: state.MicPublishIdle,
Reason: reason,
SeatStatus: state.MicSeatStatusEmpty,
}, command.UserDisplayProfile{}))
}