2026-05-29 11:59:57 +08:00

120 lines
3.4 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 (
"context"
"sort"
roomv1 "hyapp.local/api/proto/room/v1"
"hyapp/pkg/appcode"
"hyapp/pkg/roomid"
"hyapp/pkg/xerr"
"hyapp/services/room-service/internal/room/state"
)
const (
// defaultRoomBannedUsersPageSize 是房间黑名单面板默认页大小。
defaultRoomBannedUsersPageSize = 20
// maxRoomBannedUsersPageSize 限制单次查询量,避免管理面板一次拉完整治理状态。
maxRoomBannedUsersPageSize = 100
)
// ListRoomBannedUsers 分页读取房间当前仍有效的黑名单。
// 黑名单状态属于 Room Cell用户头像、昵称、国家等展示资料由 gateway 批量查询 user-service。
func (s *Service) ListRoomBannedUsers(ctx context.Context, req *roomv1.ListRoomBannedUsersRequest) (*roomv1.ListRoomBannedUsersResponse, error) {
ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode())
roomID := req.GetRoomId()
viewerUserID := req.GetViewerUserId()
if !roomid.ValidStringID(roomID) {
return nil, xerr.New(xerr.InvalidArgument, "room_id is invalid")
}
if viewerUserID <= 0 {
return nil, xerr.New(xerr.InvalidArgument, "viewer_user_id is required")
}
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")
}
current := state.FromProto(snapshot)
if err := requireManagerPresent(current, viewerUserID); err != nil {
// 黑名单是房间治理数据,只允许当前仍在房间内的 owner/admin 查看。
return nil, err
}
nowMS := s.clock.Now().UnixMilli()
items := activeBannedUsersFromState(current, nowMS)
page, pageSize := normalizeRoomBannedUsersPage(req.GetPage(), req.GetPageSize())
total := int64(len(items))
start := (page - 1) * pageSize
if start >= len(items) {
items = nil
} else {
end := start + pageSize
if end > len(items) {
end = len(items)
}
items = items[start:end]
}
return &roomv1.ListRoomBannedUsersResponse{
Items: items,
Total: total,
Page: int32(page),
PageSize: int32(pageSize),
ServerTimeMs: nowMS,
}, nil
}
func activeBannedUsersFromState(current *state.RoomState, nowMS int64) []*roomv1.RoomBannedUser {
if current == nil || len(current.BanUsers) == 0 {
return nil
}
items := make([]*roomv1.RoomBannedUser, 0, len(current.BanUsers))
for _, ban := range current.BanUsers {
if !ban.ActiveAt(nowMS) {
continue
}
remainingMS := int64(0)
if ban.ExpiresAtMS > 0 {
remainingMS = ban.ExpiresAtMS - nowMS
}
items = append(items, &roomv1.RoomBannedUser{
UserId: ban.UserID,
ActorUserId: ban.ActorUserID,
CreatedAtMs: ban.CreatedAtMS,
UnbanAtMs: ban.ExpiresAtMS,
RemainingMs: remainingMS,
Permanent: ban.ExpiresAtMS == 0,
})
}
sort.Slice(items, func(i, j int) bool {
if items[i].GetCreatedAtMs() != items[j].GetCreatedAtMs() {
return items[i].GetCreatedAtMs() > items[j].GetCreatedAtMs()
}
return items[i].GetUserId() < items[j].GetUserId()
})
return items
}
func normalizeRoomBannedUsersPage(rawPage int32, rawPageSize int32) (int, int) {
page := int(rawPage)
if page <= 0 {
page = 1
}
pageSize := int(rawPageSize)
if pageSize <= 0 {
pageSize = defaultRoomBannedUsersPageSize
}
if pageSize > maxRoomBannedUsersPageSize {
pageSize = maxRoomBannedUsersPageSize
}
return page, pageSize
}