2026-05-11 19:26:01 +08:00

327 lines
10 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 http
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"`
HostUserID string `json:"host_user_id,omitempty"`
Title string `json:"title,omitempty"`
CoverURL string `json:"cover_url,omitempty"`
Mode string `json:"mode,omitempty"`
Status string `json:"status,omitempty"`
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 updateRoomProfileData struct {
Result roomCommandResultData `json:"result"`
Room roomInitialData `json:"room"`
Seats []roomSeatData `json:"seats"`
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"`
HostUserID string `json:"host_user_id,omitempty"`
Mode string `json:"mode,omitempty"`
Status string `json:"status,omitempty"`
ChatEnabled bool `json:"chat_enabled"`
Heat int64 `json:"heat"`
OnlineCount int32 `json:"online_count"`
SeatCount int32 `json:"seat_count"`
OccupiedSeatCount int32 `json:"occupied_seat_count"`
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"`
}
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 roomListItemDataFromProto(room *roomv1.RoomListItem) roomListItemData {
if room == nil {
return roomListItemData{}
}
roomID := room.GetRoomId()
return roomListItemData{
RoomID: roomID,
IMGroupID: roomIMGroupID(roomID),
OwnerUserID: formatOptionalUserID(room.GetOwnerUserId()),
HostUserID: formatOptionalUserID(room.GetHostUserId()),
Title: room.GetTitle(),
CoverURL: room.GetCoverUrl(),
Mode: room.GetMode(),
Status: room.GetStatus(),
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 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()),
HostUserID: formatOptionalUserID(snapshot.GetHostUserId()),
Mode: snapshot.GetMode(),
Status: snapshot.GetStatus(),
ChatEnabled: snapshot.GetChatEnabled(),
Heat: snapshot.GetHeat(),
OnlineCount: int32(len(snapshot.GetOnlineUsers())),
SeatCount: seatCount,
OccupiedSeatCount: occupiedSeatCount,
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(),
})
}
return items
}
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(snapshot.GetHostUserId())
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 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)
}