2026-05-14 13:46:53 +08:00

69 lines
1.8 KiB
Go

package voiceroomrocket
import (
"context"
"fmt"
"sort"
"strconv"
"strings"
"time"
)
type roomAudienceUser struct {
UserID int64
LastSeenTime time.Time
}
func (s *Service) listOnlineRoomUsers(ctx context.Context, sysOrigin string, roomID int64, now time.Time) ([]roomAudienceUser, error) {
if s.repo.Redis == nil {
return nil, nil
}
members, err := s.repo.Redis.SMembers(ctx, onlineRoomKey(sysOrigin, roomID)).Result()
if err != nil {
return nil, err
}
users := make([]roomAudienceUser, 0, len(members))
seen := make(map[int64]struct{}, len(members))
for _, raw := range members {
userID, err := strconv.ParseInt(strings.TrimSpace(raw), 10, 64)
if err != nil || userID <= 0 {
continue
}
if _, exists := seen[userID]; exists {
continue
}
seen[userID] = struct{}{}
users = append(users, roomAudienceUser{
UserID: userID,
LastSeenTime: s.loadUserSeenTime(ctx, sysOrigin, userID, now),
})
}
sort.Slice(users, func(i, j int) bool {
return users[i].UserID < users[j].UserID
})
return users, nil
}
func (s *Service) loadUserSeenTime(ctx context.Context, sysOrigin string, userID int64, fallback time.Time) time.Time {
if s.repo.Redis == nil {
return fallback
}
raw, err := s.repo.Redis.Get(ctx, userSeenKey(sysOrigin, userID)).Result()
if err != nil {
return fallback
}
millis, err := strconv.ParseInt(strings.TrimSpace(raw), 10, 64)
if err != nil || millis <= 0 {
return fallback
}
return resolveMillisTime(millis, fallback)
}
func onlineRoomKey(sysOrigin string, roomID int64) string {
return fmt.Sprintf("voice_room:online:%s:%d", strings.ToUpper(strings.TrimSpace(sysOrigin)), roomID)
}
func userSeenKey(sysOrigin string, userID int64) string {
return fmt.Sprintf("voice_room:user_seen:%s:%d", strings.ToUpper(strings.TrimSpace(sysOrigin)), userID)
}