78 lines
3.5 KiB
Go
78 lines
3.5 KiB
Go
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{}))
|
||
}
|