745 lines
26 KiB
Go
745 lines
26 KiB
Go
package roomapi
|
||
|
||
import (
|
||
"strconv"
|
||
|
||
"hyapp/pkg/tencentrtc"
|
||
|
||
roomv1 "hyapp.local/api/proto/room/v1"
|
||
)
|
||
|
||
const joinRoomContributionRankLimit = 10
|
||
|
||
type roomListData struct {
|
||
Rooms []roomListItemData `json:"rooms"`
|
||
NextCursor string `json:"next_cursor,omitempty"`
|
||
}
|
||
|
||
type myRoomData struct {
|
||
HasRoom bool `json:"has_room"`
|
||
Room *roomListItemData `json:"room,omitempty"`
|
||
ServerTimeMS int64 `json:"server_time_ms"`
|
||
}
|
||
|
||
type roomListItemData struct {
|
||
RoomID string `json:"room_id"`
|
||
IMGroupID string `json:"im_group_id"`
|
||
OwnerUserID string `json:"owner_user_id,omitempty"`
|
||
Title string `json:"title,omitempty"`
|
||
CoverURL string `json:"cover_url,omitempty"`
|
||
Mode string `json:"mode,omitempty"`
|
||
Status string `json:"status,omitempty"`
|
||
Locked bool `json:"locked"`
|
||
Heat int64 `json:"heat"`
|
||
OnlineCount int32 `json:"online_count"`
|
||
SeatCount int32 `json:"seat_count"`
|
||
OccupiedSeatCount int32 `json:"occupied_seat_count"`
|
||
VisibleRegionID int64 `json:"visible_region_id,omitempty"`
|
||
AppCode string `json:"app_code,omitempty"`
|
||
RoomShortID string `json:"room_short_id,omitempty"`
|
||
}
|
||
|
||
type joinRoomData struct {
|
||
Result roomCommandResultData `json:"result"`
|
||
Room roomInitialData `json:"room"`
|
||
Viewer roomViewerData `json:"viewer"`
|
||
Seats []roomSeatData `json:"seats"`
|
||
ContributionRank []roomRankItemData `json:"contribution_rank"`
|
||
Profiles []roomUserProfileData `json:"profiles"`
|
||
IM roomIMData `json:"im"`
|
||
RTC roomRTCData `json:"rtc"`
|
||
ServerTimeMS int64 `json:"server_time_ms"`
|
||
}
|
||
|
||
type roomDetailData struct {
|
||
Room roomInitialData `json:"room"`
|
||
Viewer roomViewerData `json:"viewer"`
|
||
IsFollowed bool `json:"is_followed"`
|
||
Seats []roomSeatData `json:"seats"`
|
||
RankTop []roomRankItemData `json:"rank_top"`
|
||
OnlineCount int32 `json:"online_count"`
|
||
Permissions roomPermissionsData `json:"permissions"`
|
||
Profiles []roomDisplayProfileData `json:"profiles,omitempty"`
|
||
IM roomIMData `json:"im"`
|
||
RTC roomRTCData `json:"rtc"`
|
||
ServerTimeMS int64 `json:"server_time_ms"`
|
||
}
|
||
|
||
type roomOnlineUsersData struct {
|
||
Items []roomOnlineUserData `json:"items"`
|
||
Total int64 `json:"total"`
|
||
Page int32 `json:"page"`
|
||
PageSize int32 `json:"page_size"`
|
||
ServerTimeMS int64 `json:"server_time_ms"`
|
||
}
|
||
|
||
type roomOnlineUserData struct {
|
||
UserID string `json:"user_id"`
|
||
Role string `json:"role,omitempty"`
|
||
IsOwner bool `json:"is_owner"`
|
||
RoomRole string `json:"room_role,omitempty"`
|
||
GiftValue int64 `json:"gift_value"`
|
||
JoinedAtMS int64 `json:"joined_at_ms,omitempty"`
|
||
LastSeenAtMS int64 `json:"last_seen_at_ms,omitempty"`
|
||
Profile *roomDisplayProfileData `json:"profile,omitempty"`
|
||
}
|
||
|
||
type setRoomAdminData struct {
|
||
Result roomCommandResultData `json:"result"`
|
||
TargetUserID string `json:"target_user_id"`
|
||
RoomRole string `json:"room_role"`
|
||
ServerTimeMS int64 `json:"server_time_ms"`
|
||
}
|
||
|
||
type roomPermissionsData struct {
|
||
IsOwner bool `json:"is_owner"`
|
||
IsAdmin bool `json:"is_admin"`
|
||
IsMuted bool `json:"is_muted"`
|
||
CanSpeak bool `json:"can_speak"`
|
||
CanSendGift bool `json:"can_send_gift"`
|
||
CanMicUp bool `json:"can_mic_up"`
|
||
CanManageRoom bool `json:"can_manage_room"`
|
||
CanLeaveRoom bool `json:"can_leave_room"`
|
||
CanCloseRoom bool `json:"can_close_room"`
|
||
CanMuteMic bool `json:"can_mute_mic"`
|
||
CanOpenGiftBox bool `json:"can_open_gift_box"`
|
||
}
|
||
|
||
type roomDisplayProfileData struct {
|
||
UserID string `json:"user_id"`
|
||
Username string `json:"username"`
|
||
Avatar string `json:"avatar"`
|
||
DisplayUserID string `json:"display_user_id"`
|
||
VIP map[string]any `json:"vip"`
|
||
Level map[string]any `json:"level"`
|
||
Badges []map[string]any `json:"badges"`
|
||
AvatarFrame map[string]any `json:"avatar_frame"`
|
||
Vehicle map[string]any `json:"vehicle"`
|
||
Charm int64 `json:"charm"`
|
||
}
|
||
|
||
type roomGiftPanelData struct {
|
||
CoinBalance int64 `json:"coin_balance"`
|
||
Recipients []roomGiftRecipientData `json:"recipients"`
|
||
Tabs []roomGiftTabData `json:"tabs"`
|
||
Gifts []giftConfigData `json:"gifts"`
|
||
QuantityPresets []int32 `json:"quantity_presets"`
|
||
}
|
||
|
||
type roomTreasureData struct {
|
||
Enabled bool `json:"enabled"`
|
||
Levels []roomTreasureLevelData `json:"levels"`
|
||
State roomTreasureStateData `json:"state"`
|
||
BroadcastScope string `json:"broadcast_scope"`
|
||
OpenDelayMS int64 `json:"open_delay_ms"`
|
||
BroadcastDelayMS int64 `json:"broadcast_delay_ms"`
|
||
RewardStackPolicy string `json:"reward_stack_policy"`
|
||
ServerTimeMS int64 `json:"server_time_ms"`
|
||
}
|
||
|
||
type roomTreasureLevelData struct {
|
||
Level int32 `json:"level"`
|
||
EnergyThreshold int64 `json:"energy_threshold"`
|
||
CoverURL string `json:"cover_url,omitempty"`
|
||
AnimationURL string `json:"animation_url,omitempty"`
|
||
OpeningAnimationURL string `json:"opening_animation_url,omitempty"`
|
||
OpenedImageURL string `json:"opened_image_url,omitempty"`
|
||
InRoomRewards []roomTreasureRewardData `json:"in_room_rewards"`
|
||
Top1Rewards []roomTreasureRewardData `json:"top1_rewards"`
|
||
IgniterRewards []roomTreasureRewardData `json:"igniter_rewards"`
|
||
}
|
||
|
||
type roomTreasureRewardData struct {
|
||
RewardItemID string `json:"reward_item_id"`
|
||
ResourceGroupID int64 `json:"resource_group_id"`
|
||
Weight int64 `json:"weight,omitempty"`
|
||
DisplayName string `json:"display_name,omitempty"`
|
||
IconURL string `json:"icon_url,omitempty"`
|
||
}
|
||
|
||
type roomTreasureStateData struct {
|
||
CurrentLevel int32 `json:"current_level"`
|
||
CurrentProgress int64 `json:"current_progress"`
|
||
EnergyThreshold int64 `json:"energy_threshold"`
|
||
Status string `json:"status"`
|
||
CountdownStartedAtMS int64 `json:"countdown_started_at_ms,omitempty"`
|
||
OpenAtMS int64 `json:"open_at_ms,omitempty"`
|
||
OpenedAtMS int64 `json:"opened_at_ms,omitempty"`
|
||
ResetAtMS int64 `json:"reset_at_ms"`
|
||
Top1UserID string `json:"top1_user_id,omitempty"`
|
||
IgniterUserID string `json:"igniter_user_id,omitempty"`
|
||
BoxID string `json:"box_id,omitempty"`
|
||
ConfigVersion int64 `json:"config_version,omitempty"`
|
||
LastRewards []roomTreasureRewardGrantData `json:"last_rewards,omitempty"`
|
||
}
|
||
|
||
type roomTreasureRewardGrantData struct {
|
||
RewardRole string `json:"reward_role"`
|
||
UserID string `json:"user_id"`
|
||
RewardItemID string `json:"reward_item_id"`
|
||
ResourceGroupID int64 `json:"resource_group_id"`
|
||
DisplayName string `json:"display_name,omitempty"`
|
||
IconURL string `json:"icon_url,omitempty"`
|
||
GrantID string `json:"grant_id,omitempty"`
|
||
Status string `json:"status,omitempty"`
|
||
}
|
||
|
||
type roomGiftRecipientData struct {
|
||
TargetType string `json:"target_type"`
|
||
UserID string `json:"user_id,omitempty"`
|
||
SeatNo int32 `json:"seat_no,omitempty"`
|
||
Label string `json:"label,omitempty"`
|
||
Profile *roomDisplayProfileData `json:"profile,omitempty"`
|
||
}
|
||
|
||
type roomGiftTabData struct {
|
||
Key string `json:"key"`
|
||
GiftTypeCode string `json:"gift_type_code,omitempty"`
|
||
Label string `json:"label,omitempty"`
|
||
Order int32 `json:"order"`
|
||
}
|
||
|
||
type updateRoomProfileData struct {
|
||
Result roomCommandResultData `json:"result"`
|
||
Room roomInitialData `json:"room"`
|
||
Seats []roomSeatData `json:"seats"`
|
||
ServerTimeMS int64 `json:"server_time_ms"`
|
||
}
|
||
|
||
type roomSnapshotData struct {
|
||
Room roomInitialData `json:"room"`
|
||
Seats []roomSeatData `json:"seats"`
|
||
ContributionRank []roomRankItemData `json:"contribution_rank"`
|
||
IsFollowed bool `json:"is_followed"`
|
||
ServerTimeMS int64 `json:"server_time_ms"`
|
||
}
|
||
|
||
type roomFollowData struct {
|
||
RoomID string `json:"room_id"`
|
||
IsFollowed bool `json:"is_followed"`
|
||
FollowedAtMS int64 `json:"followed_at_ms,omitempty"`
|
||
ServerTimeMS int64 `json:"server_time_ms"`
|
||
}
|
||
|
||
type roomCommandResultData struct {
|
||
Applied bool `json:"applied"`
|
||
RoomVersion int64 `json:"room_version"`
|
||
ServerTimeMS int64 `json:"server_time_ms"`
|
||
}
|
||
|
||
type roomInitialData struct {
|
||
RoomID string `json:"room_id"`
|
||
IMGroupID string `json:"im_group_id"`
|
||
RoomShortID string `json:"room_short_id,omitempty"`
|
||
Title string `json:"title,omitempty"`
|
||
CoverURL string `json:"cover_url,omitempty"`
|
||
Description string `json:"description,omitempty"`
|
||
OwnerUserID string `json:"owner_user_id,omitempty"`
|
||
Mode string `json:"mode,omitempty"`
|
||
Status string `json:"status,omitempty"`
|
||
ChatEnabled bool `json:"chat_enabled"`
|
||
Locked bool `json:"locked"`
|
||
Heat int64 `json:"heat"`
|
||
OnlineCount int32 `json:"online_count"`
|
||
SeatCount int32 `json:"seat_count"`
|
||
OccupiedSeatCount int32 `json:"occupied_seat_count"`
|
||
VisibleRegionID int64 `json:"visible_region_id,omitempty"`
|
||
Version int64 `json:"version"`
|
||
}
|
||
|
||
type roomViewerData struct {
|
||
UserID string `json:"user_id"`
|
||
Role string `json:"role,omitempty"`
|
||
JoinedAtMS int64 `json:"joined_at_ms,omitempty"`
|
||
LastSeenAtMS int64 `json:"last_seen_at_ms,omitempty"`
|
||
}
|
||
|
||
type roomSeatData struct {
|
||
SeatNo int32 `json:"seat_no"`
|
||
UserID string `json:"user_id,omitempty"`
|
||
Locked bool `json:"locked"`
|
||
PublishState string `json:"publish_state,omitempty"`
|
||
MicSessionID string `json:"mic_session_id,omitempty"`
|
||
PublishDeadlineMS int64 `json:"publish_deadline_ms,omitempty"`
|
||
MicMuted bool `json:"mic_muted"`
|
||
SeatStatus string `json:"seat_status,omitempty"`
|
||
}
|
||
|
||
type roomRankItemData struct {
|
||
UserID string `json:"user_id"`
|
||
Score int64 `json:"score"`
|
||
GiftValue int64 `json:"gift_value"`
|
||
UpdatedAtMS int64 `json:"updated_at_ms,omitempty"`
|
||
}
|
||
|
||
type roomUserProfileData struct {
|
||
UserID string `json:"user_id"`
|
||
DisplayUserID string `json:"display_user_id,omitempty"`
|
||
Username string `json:"username,omitempty"`
|
||
Avatar string `json:"avatar,omitempty"`
|
||
}
|
||
|
||
type roomIMData struct {
|
||
GroupID string `json:"group_id"`
|
||
NeedJoinGroup bool `json:"need_join_group"`
|
||
}
|
||
|
||
type roomRTCData struct {
|
||
NeedToken bool `json:"need_token"`
|
||
Available bool `json:"available"`
|
||
Token *tencentrtc.TokenResult `json:"token,omitempty"`
|
||
Reason string `json:"reason,omitempty"`
|
||
}
|
||
|
||
func roomListDataFromProto(resp *roomv1.ListRoomsResponse) roomListData {
|
||
if resp == nil {
|
||
return roomListData{}
|
||
}
|
||
items := make([]roomListItemData, 0, len(resp.GetRooms()))
|
||
for _, room := range resp.GetRooms() {
|
||
items = append(items, roomListItemDataFromProto(room))
|
||
}
|
||
return roomListData{Rooms: items, NextCursor: resp.GetNextCursor()}
|
||
}
|
||
|
||
func myRoomDataFromProto(resp *roomv1.GetMyRoomResponse) myRoomData {
|
||
if resp == nil {
|
||
return myRoomData{}
|
||
}
|
||
data := myRoomData{HasRoom: resp.GetHasRoom(), ServerTimeMS: resp.GetServerTimeMs()}
|
||
if resp.GetHasRoom() && resp.GetRoom() != nil {
|
||
room := roomListItemDataFromProto(resp.GetRoom())
|
||
data.Room = &room
|
||
}
|
||
return data
|
||
}
|
||
|
||
func roomTreasureDataFromProto(resp *roomv1.GetRoomTreasureResponse) roomTreasureData {
|
||
if resp == nil || resp.GetTreasure() == nil {
|
||
return roomTreasureData{}
|
||
}
|
||
treasure := resp.GetTreasure()
|
||
return roomTreasureData{
|
||
Enabled: treasure.GetEnabled(),
|
||
Levels: roomTreasureLevelsFromProto(treasure.GetLevels()),
|
||
State: roomTreasureStateFromProto(treasure.GetState()),
|
||
BroadcastScope: treasure.GetBroadcastScope(),
|
||
OpenDelayMS: treasure.GetOpenDelayMs(),
|
||
BroadcastDelayMS: treasure.GetBroadcastDelayMs(),
|
||
RewardStackPolicy: treasure.GetRewardStackPolicy(),
|
||
ServerTimeMS: resp.GetServerTimeMs(),
|
||
}
|
||
}
|
||
|
||
func roomTreasureLevelsFromProto(levels []*roomv1.RoomTreasureLevel) []roomTreasureLevelData {
|
||
out := make([]roomTreasureLevelData, 0, len(levels))
|
||
for _, level := range levels {
|
||
out = append(out, roomTreasureLevelData{
|
||
Level: level.GetLevel(),
|
||
EnergyThreshold: level.GetEnergyThreshold(),
|
||
CoverURL: level.GetCoverUrl(),
|
||
AnimationURL: level.GetAnimationUrl(),
|
||
OpeningAnimationURL: level.GetOpeningAnimationUrl(),
|
||
OpenedImageURL: level.GetOpenedImageUrl(),
|
||
InRoomRewards: roomTreasureRewardsFromProto(level.GetInRoomRewards()),
|
||
Top1Rewards: roomTreasureRewardsFromProto(level.GetTop1Rewards()),
|
||
IgniterRewards: roomTreasureRewardsFromProto(level.GetIgniterRewards()),
|
||
})
|
||
}
|
||
return out
|
||
}
|
||
|
||
func roomTreasureRewardsFromProto(rewards []*roomv1.RoomTreasureRewardItem) []roomTreasureRewardData {
|
||
out := make([]roomTreasureRewardData, 0, len(rewards))
|
||
for _, reward := range rewards {
|
||
out = append(out, roomTreasureRewardData{
|
||
RewardItemID: reward.GetRewardItemId(),
|
||
ResourceGroupID: reward.GetResourceGroupId(),
|
||
Weight: reward.GetWeight(),
|
||
DisplayName: reward.GetDisplayName(),
|
||
IconURL: reward.GetIconUrl(),
|
||
})
|
||
}
|
||
return out
|
||
}
|
||
|
||
func roomTreasureStateFromProto(state *roomv1.RoomTreasureState) roomTreasureStateData {
|
||
if state == nil {
|
||
return roomTreasureStateData{}
|
||
}
|
||
return roomTreasureStateData{
|
||
CurrentLevel: state.GetCurrentLevel(),
|
||
CurrentProgress: state.GetCurrentProgress(),
|
||
EnergyThreshold: state.GetEnergyThreshold(),
|
||
Status: state.GetStatus(),
|
||
CountdownStartedAtMS: state.GetCountdownStartedAtMs(),
|
||
OpenAtMS: state.GetOpenAtMs(),
|
||
OpenedAtMS: state.GetOpenedAtMs(),
|
||
ResetAtMS: state.GetResetAtMs(),
|
||
Top1UserID: formatOptionalUserID(state.GetTop1UserId()),
|
||
IgniterUserID: formatOptionalUserID(state.GetIgniterUserId()),
|
||
BoxID: state.GetBoxId(),
|
||
ConfigVersion: state.GetConfigVersion(),
|
||
LastRewards: roomTreasureRewardGrantsFromProto(state.GetLastRewards()),
|
||
}
|
||
}
|
||
|
||
func roomTreasureRewardGrantsFromProto(rewards []*roomv1.RoomTreasureRewardGrant) []roomTreasureRewardGrantData {
|
||
out := make([]roomTreasureRewardGrantData, 0, len(rewards))
|
||
for _, reward := range rewards {
|
||
out = append(out, roomTreasureRewardGrantData{
|
||
RewardRole: reward.GetRewardRole(),
|
||
UserID: formatOptionalUserID(reward.GetUserId()),
|
||
RewardItemID: reward.GetRewardItemId(),
|
||
ResourceGroupID: reward.GetResourceGroupId(),
|
||
DisplayName: reward.GetDisplayName(),
|
||
IconURL: reward.GetIconUrl(),
|
||
GrantID: reward.GetGrantId(),
|
||
Status: reward.GetStatus(),
|
||
})
|
||
}
|
||
return out
|
||
}
|
||
|
||
func roomListItemDataFromProto(room *roomv1.RoomListItem) roomListItemData {
|
||
if room == nil {
|
||
return roomListItemData{}
|
||
}
|
||
roomID := room.GetRoomId()
|
||
return roomListItemData{
|
||
RoomID: roomID,
|
||
IMGroupID: roomIMGroupID(roomID),
|
||
OwnerUserID: formatOptionalUserID(room.GetOwnerUserId()),
|
||
Title: room.GetTitle(),
|
||
CoverURL: room.GetCoverUrl(),
|
||
Mode: room.GetMode(),
|
||
Status: room.GetStatus(),
|
||
Locked: room.GetLocked(),
|
||
Heat: room.GetHeat(),
|
||
OnlineCount: room.GetOnlineCount(),
|
||
SeatCount: room.GetSeatCount(),
|
||
OccupiedSeatCount: room.GetOccupiedSeatCount(),
|
||
VisibleRegionID: room.GetVisibleRegionId(),
|
||
AppCode: room.GetAppCode(),
|
||
RoomShortID: room.GetRoomShortId(),
|
||
}
|
||
}
|
||
|
||
func commandResultDataFromProto(result *roomv1.CommandResult) roomCommandResultData {
|
||
if result == nil {
|
||
return roomCommandResultData{}
|
||
}
|
||
return roomCommandResultData{
|
||
Applied: result.GetApplied(),
|
||
RoomVersion: result.GetRoomVersion(),
|
||
ServerTimeMS: result.GetServerTimeMs(),
|
||
}
|
||
}
|
||
|
||
func updateRoomProfileDataFromProto(resp *roomv1.UpdateRoomProfileResponse) updateRoomProfileData {
|
||
if resp == nil {
|
||
return updateRoomProfileData{}
|
||
}
|
||
snapshot := resp.GetRoom()
|
||
return updateRoomProfileData{
|
||
Result: commandResultDataFromProto(resp.GetResult()),
|
||
Room: roomInitialRoomDataFromSnapshot(snapshot, snapshot.GetRoomId()),
|
||
Seats: roomSeatDataFromSnapshot(snapshot),
|
||
ServerTimeMS: resp.GetResult().GetServerTimeMs(),
|
||
}
|
||
}
|
||
|
||
func roomSnapshotDataFromProto(resp *roomv1.GetRoomSnapshotResponse) roomSnapshotData {
|
||
if resp == nil {
|
||
return roomSnapshotData{}
|
||
}
|
||
snapshot := resp.GetRoom()
|
||
return roomSnapshotData{
|
||
Room: roomInitialRoomDataFromSnapshot(snapshot, snapshot.GetRoomId()),
|
||
Seats: roomSeatDataFromSnapshot(snapshot),
|
||
ContributionRank: roomRankDataFromSnapshot(snapshot, 0),
|
||
IsFollowed: resp.GetIsFollowed(),
|
||
ServerTimeMS: resp.GetServerTimeMs(),
|
||
}
|
||
}
|
||
|
||
func roomInitialRoomDataFromSnapshot(snapshot *roomv1.RoomSnapshot, roomID string) roomInitialData {
|
||
if snapshot == nil {
|
||
return roomInitialData{RoomID: roomID, IMGroupID: roomIMGroupID(roomID)}
|
||
}
|
||
ext := snapshot.GetRoomExt()
|
||
if roomID == "" {
|
||
roomID = snapshot.GetRoomId()
|
||
}
|
||
roomShortID := snapshot.GetRoomShortId()
|
||
if roomShortID == "" {
|
||
roomShortID = ext["room_short_id"]
|
||
}
|
||
seatCount, occupiedSeatCount := roomSeatCounts(snapshot)
|
||
return roomInitialData{
|
||
RoomID: roomID,
|
||
IMGroupID: roomIMGroupID(roomID),
|
||
RoomShortID: roomShortID,
|
||
Title: ext["title"],
|
||
CoverURL: ext["cover_url"],
|
||
Description: ext["description"],
|
||
OwnerUserID: formatOptionalUserID(snapshot.GetOwnerUserId()),
|
||
Mode: snapshot.GetMode(),
|
||
Status: snapshot.GetStatus(),
|
||
ChatEnabled: snapshot.GetChatEnabled(),
|
||
Locked: snapshot.GetLocked(),
|
||
Heat: snapshot.GetHeat(),
|
||
OnlineCount: int32(len(snapshot.GetOnlineUsers())),
|
||
SeatCount: seatCount,
|
||
OccupiedSeatCount: occupiedSeatCount,
|
||
VisibleRegionID: snapshot.GetVisibleRegionId(),
|
||
Version: snapshot.GetVersion(),
|
||
}
|
||
}
|
||
|
||
func roomViewerDataFromProto(user *roomv1.RoomUser, fallbackUserID int64) roomViewerData {
|
||
userID := fallbackUserID
|
||
if user.GetUserId() > 0 {
|
||
userID = user.GetUserId()
|
||
}
|
||
return roomViewerData{
|
||
UserID: formatOptionalUserID(userID),
|
||
Role: user.GetRole(),
|
||
JoinedAtMS: user.GetJoinedAtMs(),
|
||
LastSeenAtMS: user.GetLastSeenAtMs(),
|
||
}
|
||
}
|
||
|
||
func roomSeatDataFromSnapshot(snapshot *roomv1.RoomSnapshot) []roomSeatData {
|
||
seats := snapshot.GetMicSeats()
|
||
items := make([]roomSeatData, 0, len(seats))
|
||
for _, seat := range seats {
|
||
items = append(items, roomSeatData{
|
||
SeatNo: seat.GetSeatNo(),
|
||
UserID: formatOptionalUserID(seat.GetUserId()),
|
||
Locked: seat.GetLocked(),
|
||
PublishState: seat.GetPublishState(),
|
||
MicSessionID: seat.GetMicSessionId(),
|
||
PublishDeadlineMS: seat.GetPublishDeadlineMs(),
|
||
MicMuted: seat.GetMicMuted(),
|
||
SeatStatus: seat.GetSeatStatus(),
|
||
})
|
||
}
|
||
return items
|
||
}
|
||
|
||
func roomDetailDataFromSnapshot(resp *roomv1.GetRoomSnapshotResponse, viewerUserID int64, rtc roomRTCData, profiles []roomDisplayProfileData) roomDetailData {
|
||
if resp == nil {
|
||
return roomDetailData{}
|
||
}
|
||
snapshot := resp.GetRoom()
|
||
roomID := snapshot.GetRoomId()
|
||
viewer := protoRoomUserByID(snapshot, viewerUserID)
|
||
return roomDetailData{
|
||
Room: roomInitialRoomDataFromSnapshot(snapshot, roomID),
|
||
Viewer: roomViewerDataFromProto(viewer, viewerUserID),
|
||
IsFollowed: resp.GetIsFollowed(),
|
||
Seats: roomSeatDataFromSnapshot(snapshot),
|
||
RankTop: roomRankDataFromSnapshot(snapshot, joinRoomContributionRankLimit),
|
||
OnlineCount: int32(len(snapshot.GetOnlineUsers())),
|
||
Permissions: roomPermissionsFromSnapshot(snapshot, viewerUserID),
|
||
Profiles: profiles,
|
||
IM: roomIMData{GroupID: roomIMGroupID(roomID), NeedJoinGroup: true},
|
||
RTC: rtc,
|
||
ServerTimeMS: resp.GetServerTimeMs(),
|
||
}
|
||
}
|
||
|
||
func roomFollowDataFromProto(resp *roomv1.FollowRoomResponse) roomFollowData {
|
||
if resp == nil {
|
||
return roomFollowData{}
|
||
}
|
||
return roomFollowData{
|
||
RoomID: resp.GetRoomId(),
|
||
IsFollowed: resp.GetFollowed(),
|
||
FollowedAtMS: resp.GetFollowedAtMs(),
|
||
ServerTimeMS: resp.GetServerTimeMs(),
|
||
}
|
||
}
|
||
|
||
func roomUnfollowDataFromProto(resp *roomv1.UnfollowRoomResponse) roomFollowData {
|
||
if resp == nil {
|
||
return roomFollowData{}
|
||
}
|
||
return roomFollowData{
|
||
RoomID: resp.GetRoomId(),
|
||
IsFollowed: resp.GetFollowed(),
|
||
ServerTimeMS: resp.GetServerTimeMs(),
|
||
}
|
||
}
|
||
|
||
func roomPermissionsFromSnapshot(snapshot *roomv1.RoomSnapshot, viewerUserID int64) roomPermissionsData {
|
||
if snapshot == nil || viewerUserID <= 0 {
|
||
return roomPermissionsData{}
|
||
}
|
||
isOwner := snapshot.GetOwnerUserId() == viewerUserID
|
||
isAdmin := !isOwner && containsInt64(snapshot.GetAdminUserIds(), viewerUserID)
|
||
isMuted := containsInt64(snapshot.GetMuteUserIds(), viewerUserID)
|
||
inRoom := protoRoomUserByID(snapshot, viewerUserID) != nil
|
||
return roomPermissionsData{
|
||
IsOwner: isOwner,
|
||
IsAdmin: isAdmin,
|
||
IsMuted: isMuted,
|
||
CanSpeak: inRoom && snapshot.GetChatEnabled() && !isMuted,
|
||
CanSendGift: inRoom && snapshot.GetStatus() == "active",
|
||
CanMicUp: inRoom && snapshot.GetStatus() == "active" && protoSeatByUserID(snapshot, viewerUserID) == nil,
|
||
CanManageRoom: inRoom && (isOwner || isAdmin),
|
||
CanLeaveRoom: inRoom,
|
||
CanCloseRoom: inRoom,
|
||
CanMuteMic: inRoom && protoSeatByUserID(snapshot, viewerUserID) != nil,
|
||
CanOpenGiftBox: inRoom && snapshot.GetStatus() == "active",
|
||
}
|
||
}
|
||
|
||
func roomRankDataFromSnapshot(snapshot *roomv1.RoomSnapshot, limit int) []roomRankItemData {
|
||
rank := snapshot.GetGiftRank()
|
||
if limit > 0 && len(rank) > limit {
|
||
rank = rank[:limit]
|
||
}
|
||
items := make([]roomRankItemData, 0, len(rank))
|
||
for _, item := range rank {
|
||
items = append(items, roomRankItemData{
|
||
UserID: formatOptionalUserID(item.GetUserId()),
|
||
Score: item.GetScore(),
|
||
GiftValue: item.GetGiftValue(),
|
||
UpdatedAtMS: item.GetUpdatedAtMs(),
|
||
})
|
||
}
|
||
return items
|
||
}
|
||
|
||
func roomInitialProfileUserIDs(snapshot *roomv1.RoomSnapshot, viewerUserID int64, rankLimit int) []int64 {
|
||
seen := map[int64]bool{}
|
||
userIDs := make([]int64, 0, 16)
|
||
add := func(userID int64) {
|
||
if userID <= 0 || seen[userID] {
|
||
return
|
||
}
|
||
seen[userID] = true
|
||
userIDs = append(userIDs, userID)
|
||
}
|
||
|
||
add(snapshot.GetOwnerUserId())
|
||
add(viewerUserID)
|
||
for _, seat := range snapshot.GetMicSeats() {
|
||
add(seat.GetUserId())
|
||
}
|
||
rank := snapshot.GetGiftRank()
|
||
if rankLimit > 0 && len(rank) > rankLimit {
|
||
rank = rank[:rankLimit]
|
||
}
|
||
for _, item := range rank {
|
||
add(item.GetUserId())
|
||
}
|
||
return userIDs
|
||
}
|
||
|
||
func roomOnlineUserDataFromProto(resp *roomv1.ListRoomOnlineUsersResponse, profiles map[int64]roomDisplayProfileData) roomOnlineUsersData {
|
||
if resp == nil {
|
||
return roomOnlineUsersData{}
|
||
}
|
||
source := resp.GetItems()
|
||
if len(source) == 0 {
|
||
source = roomOnlineUsersFromLegacyUsers(resp.GetUsers())
|
||
}
|
||
items := make([]roomOnlineUserData, 0, len(source))
|
||
for _, user := range source {
|
||
item := roomOnlineUserData{
|
||
UserID: formatOptionalUserID(user.GetUserId()),
|
||
Role: user.GetRole(),
|
||
IsOwner: user.GetIsOwner(),
|
||
RoomRole: user.GetRoomRole(),
|
||
GiftValue: user.GetGiftValue(),
|
||
JoinedAtMS: user.GetJoinedAtMs(),
|
||
LastSeenAtMS: user.GetLastSeenAtMs(),
|
||
}
|
||
if profile, ok := profiles[user.GetUserId()]; ok {
|
||
copied := profile
|
||
item.Profile = &copied
|
||
}
|
||
items = append(items, item)
|
||
}
|
||
return roomOnlineUsersData{
|
||
Items: items,
|
||
Total: resp.GetTotal(),
|
||
Page: resp.GetPage(),
|
||
PageSize: resp.GetPageSize(),
|
||
ServerTimeMS: resp.GetServerTimeMs(),
|
||
}
|
||
}
|
||
|
||
func roomOnlineUsersFromLegacyUsers(users []*roomv1.RoomUser) []*roomv1.RoomOnlineUser {
|
||
items := make([]*roomv1.RoomOnlineUser, 0, len(users))
|
||
for _, user := range users {
|
||
items = append(items, &roomv1.RoomOnlineUser{
|
||
UserId: user.GetUserId(),
|
||
Role: user.GetRole(),
|
||
JoinedAtMs: user.GetJoinedAtMs(),
|
||
LastSeenAtMs: user.GetLastSeenAtMs(),
|
||
RoomRole: "normal",
|
||
})
|
||
}
|
||
return items
|
||
}
|
||
|
||
func protoRoomUserByID(snapshot *roomv1.RoomSnapshot, userID int64) *roomv1.RoomUser {
|
||
if snapshot == nil || userID <= 0 {
|
||
return nil
|
||
}
|
||
for _, user := range snapshot.GetOnlineUsers() {
|
||
if user.GetUserId() == userID {
|
||
return user
|
||
}
|
||
}
|
||
return nil
|
||
}
|
||
|
||
func protoSeatByUserID(snapshot *roomv1.RoomSnapshot, userID int64) *roomv1.SeatState {
|
||
if snapshot == nil || userID <= 0 {
|
||
return nil
|
||
}
|
||
for _, seat := range snapshot.GetMicSeats() {
|
||
if seat.GetUserId() == userID {
|
||
return seat
|
||
}
|
||
}
|
||
return nil
|
||
}
|
||
|
||
func containsInt64(values []int64, target int64) bool {
|
||
for _, value := range values {
|
||
if value == target {
|
||
return true
|
||
}
|
||
}
|
||
return false
|
||
}
|
||
|
||
func roomSeatCounts(snapshot *roomv1.RoomSnapshot) (int32, int32) {
|
||
seatCount := int32(len(snapshot.GetMicSeats()))
|
||
occupiedSeatCount := int32(0)
|
||
for _, seat := range snapshot.GetMicSeats() {
|
||
if seat.GetUserId() > 0 {
|
||
occupiedSeatCount++
|
||
}
|
||
}
|
||
return seatCount, occupiedSeatCount
|
||
}
|
||
|
||
func roomIMGroupID(roomID string) string {
|
||
// 当前房间群规则固定为腾讯云 IM GroupID 等于内部 room_id;显式下发给客户端,避免端侧硬编码规则。
|
||
return roomID
|
||
}
|
||
|
||
func formatOptionalUserID(userID int64) string {
|
||
if userID <= 0 {
|
||
return ""
|
||
}
|
||
return strconv.FormatInt(userID, 10)
|
||
}
|