45 lines
1.3 KiB
TypeScript
45 lines
1.3 KiB
TypeScript
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
|
|
};
|
|
}
|
|
}
|