62 lines
2.0 KiB
Go
62 lines
2.0 KiB
Go
package service
|
||
|
||
import (
|
||
"context"
|
||
|
||
roomv1 "hyapp.local/api/proto/room/v1"
|
||
"hyapp/pkg/appcode"
|
||
"hyapp/pkg/roomid"
|
||
"hyapp/pkg/xerr"
|
||
"hyapp/services/room-service/internal/room/state"
|
||
)
|
||
|
||
// GetRoomSnapshot 返回房间页主动同步所需的完整 Room Cell 快照。
|
||
// 该查询只读,不刷新 presence、不写 command log,也不隐式 JoinRoom。
|
||
func (s *Service) GetRoomSnapshot(ctx context.Context, req *roomv1.GetRoomSnapshotRequest) (*roomv1.GetRoomSnapshotResponse, error) {
|
||
ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode())
|
||
roomID := req.GetRoomId()
|
||
viewerUserID := req.GetViewerUserId()
|
||
if !roomid.ValidStringID(roomID) {
|
||
// 快照查询同样受腾讯 IM GroupID 和 RTC strRoomId 格式约束,避免脏 room_id 进入恢复路径。
|
||
return nil, xerr.New(xerr.InvalidArgument, "room_id is invalid")
|
||
}
|
||
if viewerUserID <= 0 {
|
||
// viewer_user_id 必须来自 gateway 鉴权,room-service 不接受匿名读取完整 presence。
|
||
return nil, xerr.New(xerr.InvalidArgument, "viewer_user_id is required")
|
||
}
|
||
|
||
closed, err := s.isRoomClosed(ctx, roomID)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
if closed {
|
||
return nil, xerr.New(xerr.RoomClosed, "room closed")
|
||
}
|
||
|
||
snapshot, err := s.currentSnapshot(ctx, roomID)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
if snapshot == nil || snapshot.GetRoomId() == "" {
|
||
return nil, xerr.New(xerr.NotFound, "room not found")
|
||
}
|
||
if snapshot.GetStatus() != state.RoomStatusActive {
|
||
return nil, xerr.New(xerr.RoomClosed, "room closed")
|
||
}
|
||
if snapshotUserBanned(snapshot, viewerUserID, s.clock.Now().UnixMilli()) || findProtoUser(snapshot, viewerUserID) == nil {
|
||
// 完整快照包含在线用户、麦位和房管集合,必须要求 viewer 仍在业务 presence 内。
|
||
return nil, xerr.New(xerr.PermissionDenied, "viewer is not in room")
|
||
}
|
||
|
||
followed, err := s.repository.IsRoomFollowed(ctx, viewerUserID, roomID)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
return &roomv1.GetRoomSnapshotResponse{
|
||
Room: snapshot,
|
||
ServerTimeMs: s.clock.Now().UnixMilli(),
|
||
IsFollowed: followed,
|
||
}, nil
|
||
}
|