/* eslint-disable @typescript-eslint/no-unused-vars */ /* eslint-disable @typescript-eslint/no-explicit-any */ import { Worker } from 'mediasoup/node/lib/types'; import { UserDocument } from 'models/user'; import { MediasoupChannel } from 'modules/mediasoup/Channel'; import { createWorker } from 'modules/mediasoup/worker'; import { Socket } from 'socket.io'; import { User } from '@common/types/user'; import { EventEmitter } from 'stream'; import { setMemberNickname } from 'modules/bot/bot'; import PilotController from './pilot'; interface SfuClient { socket: Socket; channelId: string; user: UserDocument; } interface ISfuController { worker: Worker[]; observer: EventEmitter; clients: Map; channel: Map; init: () => void; handle: (channelId: string, socket: Socket, user: UserDocument) => void; disconnectUser: (userId: string) => void; } const SfuController: ISfuController = { clients: new Map(), channel: new Map(), observer: new EventEmitter(), worker: [], disconnectUser: async (userId: string) => { SfuController.clients.forEach((client) => { if (client.user._id.toString() === userId) { client.socket.emit('error-message', { error: 'DISCONNECTED_BY_ADMIN' }); client.socket.disconnect(); SfuController.clients.delete(client.socket.id); } }); }, init: async () => { // Setup Worker and Channel // Scalable! SfuController.worker = [ await createWorker(), await createWorker(), await createWorker(), await createWorker(), await createWorker() ]; SfuController.channel.set('1', new MediasoupChannel(SfuController.worker[0])); // LST_VAR_RD_01 SfuController.channel.set('2', new MediasoupChannel(SfuController.worker[1])); // LST_VAR_RD_02 SfuController.channel.set('3', new MediasoupChannel(SfuController.worker[2])); // LST_VAR_RD_03 SfuController.channel.set('4', new MediasoupChannel(SfuController.worker[3])); // LST_VAR_RD_04 SfuController.channel.set('x', new MediasoupChannel(SfuController.worker[4])); // LST_VAR_RESERVE // setup listends for new connections, producer-close event is handled by Channel SfuController.channel.forEach((channel, channelId) => { channel.on('producer-pausing-forced', ({ user }: { user: User.PublicUser }) => { SfuController.clients.forEach((client) => { if (client.channelId === channelId && client.user._id.toString() !== user.id) { client.socket.emit('producer-pausing-forced', { user }); } }); }); channel.on('new-producer', ({ producerId, user }) => { SfuController.clients.forEach((client) => { if (client.channelId === channelId) { client.socket.emit('new-producer', { producerId, user }); } }); }); channel.on('producer-closed', ({ producerId }) => { SfuController.clients.forEach((client) => { if (client.channelId === channelId) { client.socket.emit('producer-closed', { producerId }); } }); }); channel.on('producer-paused', ({ producerId }) => { SfuController.clients.forEach((client) => { if (client.channelId === channelId) { client.socket.emit('producer-paused', { producerId }); } }); }); channel.on('producer-resumed', ({ producerId }) => { SfuController.clients.forEach((client) => { if (client.channelId === channelId) { client.socket.emit('producer-resumed', { producerId }); } }); }); }); }, handle: (channelId, socket, user) => { const channel = SfuController.channel.get(channelId); if (!channel) { socket.emit('error-message', { error: 'invalid channel id' }); return; } // check for double connections if ( Array.from(SfuController.clients.values()).find( (client) => client.user._id.toString() === user._id.toString() ) && process.env.ALLOW_DOUBLE_CONNECTION === 'false' ) { socket.emit('error-message', { error: 'DOUBLE_CONNECTION' }); return; } SfuController.clients.set(socket.id, { socket, channelId, user }); // Update Discord username for dispatcher SfuController.observer.emit('channel-changed', channelId, user); const userInPilot = PilotController.clients.get(user._id.toString()); if (userInPilot) { userInPilot.voiceChannel = channelId; PilotController.clients.set(user._id.toString(), userInPilot); PilotController.observer.emit('stations-changed'); } channel.handleSocket(socket, user); socket.on('get-producers', (getPcb) => { getPcb(channel.producers.map((p) => ({ producerId: p.id, user: p.appData.user, paused: p.paused }))); }); socket.on('disconnect', () => { socket.removeAllListeners(); SfuController.clients.delete(socket.id); const userInPilotDisconnect = PilotController.clients.get(user._id.toString()); if (userInPilotDisconnect) { userInPilotDisconnect.voiceChannel = undefined; PilotController.clients.set(user._id.toString(), userInPilotDisconnect); PilotController.observer.emit('stations-changed'); } }); socket.on('set-should-transmit', (eventData: { shouldTransmit: boolean; source: string }) => { SfuController.clients.forEach((client) => { if (client.user._id.toString() === user._id.toString()) { client.socket.emit('set-should-transmit', eventData); } }); }); } }; SfuController.init(); export default SfuController;