import { Status } from '$lib'; import { kvStore } from '$lib/server/db/index.js'; import { json } from '@sveltejs/kit'; interface SubscribedTo { subscribed: string[]; // any ID (including channels, dms, et cetera can be added in here, to send SSE data to any group of users) userId: string; controller: ReadableStreamDefaultController; } export const _clients = new Map(); export function _sendToSubscribers(id: string, payload: unknown) { for (const [key, client] of _clients) { if (client.subscribed.includes(id)) { try { client.controller.enqueue(`data: ${JSON.stringify(payload)}\n\n`); } catch { _clients.delete(key); } } } } export function _sendToUser(userId: string, payload: unknown) { for (const [, client] of _clients) { if (client.userId == userId) { client.controller.enqueue(`data: ${JSON.stringify(payload)}\n\n`); } } } export function _isUserConnected(userId: string): boolean { for (const client of _clients.values()) { if (client.userId === userId) return true; } return false; } export async function GET({ locals, request }) { if (!locals.user) { return json({ error: 'Unauthorized' }, { status: 401 }); } const userId = locals.user.id; //@TODO add more to subscribed eventually, server members, et cetera const subscribed = locals.user.friends.map((f) => f.id); subscribed.push(userId); // shit such as friend requests const overwrite = locals.user.statusOverwrite; const sessionId = crypto.randomUUID(); const stream = new ReadableStream({ start(controller) { _clients.set(sessionId, { subscribed, userId, controller }); console.log(`SSE Client opened. total: ${_clients.size}`); controller.enqueue(`data: ${JSON.stringify({ type: 'connected', sessionId })}\n\n`); if (overwrite === Status.DND) { kvStore.set(`user-${userId}-state`, Status.DND); _sendToSubscribers(userId, { type: 'status', id: userId, status: Status.DND, statusMessage: kvStore.get('user-' + userId + '-state') != Status.OFFLINE ? kvStore.get('user-' + userId + '-message') : '' }); } request.signal.addEventListener('abort', () => { _clients.delete(sessionId); console.log(`SSE Client aborted. total: ${_clients.size}`); if (_isUserConnected(userId)) return; if (overwrite === Status.OFFLINE) return; kvStore.set(`user-${userId}-state`, Status.OFFLINE); _sendToSubscribers(userId, { type: 'status', id: userId, status: Status.OFFLINE, statusMessage: '' }); }); }, cancel() { console.log(`SSE Client cancelled. total: ${_clients.size}`); if (_isUserConnected(userId)) return; if (overwrite === Status.OFFLINE) return; kvStore.set(`user-${userId}-state`, Status.OFFLINE); _sendToSubscribers(userId, { type: 'status', id: userId, status: Status.OFFLINE, statusMessage: '' }); } }); return new Response(stream, { headers: { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', Connection: 'keep-alive' } }); }