import type { FastifyInstance } from 'fastify' import { consola } from 'consola' import { Channel } from './Channel.ts' import { ChannelManager } from './ChannelManager.ts' import { Client } from './Client.ts' import { WebRtcGateway } from './Gateway.ts' export default async function (fastify: FastifyInstance) { const { io, bus, mediasoupRouter, prisma } = fastify const channels = new ChannelManager(mediasoupRouter) const dbChannels = await prisma.channel.findMany() for (const dbChannel of dbChannels) { const channel = await Channel.create(dbChannel.id, dbChannel.persistent, mediasoupRouter) channels.create(channel) setupChannelEvents(channel) } const defaultChannel = channels.get('default')! io.on('connection', async (socket) => { consola.info('[WebRtc]', 'Client connected', socket.id) const client = new Client(socket.id, socket.data.user.username, mediasoupRouter) defaultChannel.addClient(client) socket.join(defaultChannel.id) const _gateway = new WebRtcGateway(io, socket, client, channels) socket.emit('initialized', { rtpCapabilities: mediasoupRouter.rtpCapabilities, channelId: client.channelId, clients: channels.all.flatMap(c => c.clients).map(c => c.serialize()), }) socket.broadcast.emit('new-client', client.serialize()) }) bus.on('channel:created', async (dbChannel) => { io.emit('channel-created', dbChannel) const channel = await Channel.create(dbChannel.id, dbChannel.persistent, mediasoupRouter) channels.create(channel) setupChannelEvents(channel) }) bus.on('channel:removed', async (dbChannel) => { io.emit('channel-removed', dbChannel.id) const channel = channels.get(dbChannel.id) if (!channel) return for (const client of channel.clients) { channel.unwireClient(client) client.clearConsumers() const socket = io.sockets.sockets.get(client.socketId) if (socket) { socket.leave(dbChannel.id) defaultChannel.addClient(client) socket.join(defaultChannel.id) await defaultChannel.wireClient(client) io.emit('client-switched-channel', client.serialize()) } } channels.delete(dbChannel.id) }) function setupChannelEvents(channel: Channel): void { channel.on('speaking-peers', peers => io.to(channel.id).emit('speaking-clients', peers)) channel.on('silence', () => { io.to(channel.id).emit('speaking-clients', []) io.to(channel.id).emit('active-speaker', undefined) }) channel.on('active-speaker', socketId => io.to(channel.id).emit('active-speaker', socketId)) channel.on('empty', async () => { if (channel.persistent) return channels.delete(channel.id) await prisma.channel.delete({ where: { id: channel.id } }) consola.info('[WebRtc]', `Non-persistent channel "${channel.id}" deleted`) io.emit('channel-removed', channel.id) }) } }