import { Injectable } from '@nestjs/common'; import { RedisService } from '../infra/redis.service'; import { FamilyService } from './family.service'; const ONLINE_KEY_PREFIX = 'ws:user:'; const LAST_SEEN_KEY_PREFIX = 'ws:last_seen:'; @Injectable() export class PresenceService { constructor( private readonly redis: RedisService, private readonly family: FamilyService ) {} async isUserOnline(userId: string) { const value = await this.redis.client.get(`${ONLINE_KEY_PREFIX}${userId}`); return value === 'online'; } async getUserLastSeen(userId: string) { return this.redis.client.get(`${LAST_SEEN_KEY_PREFIX}${userId}`); } async getFamilyPresence(requesterId: string, groupId: string) { const group = await this.family.assertFamilyMember(groupId, requesterId); const members = await Promise.all( group.members.map(async (member) => { const online = await this.isUserOnline(member.userId); const lastSeenRaw = online ? null : await this.getUserLastSeen(member.userId); return { userId: member.userId, displayName: member.user.displayName, online, lastSeenAt: online ? new Date().toISOString() : lastSeenRaw ?? undefined }; }) ); return { members, onlineCount: members.filter((member) => member.online).length }; } }