Files
chad/server/plugins/socket/webrtc/index.ts
2026-05-22 05:08:02 +06:00

97 lines
2.9 KiB
TypeScript

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)
})
}
}