import type { ChadSocket, ClientToServerEvents, ExtractCallbackPayload, SocketServer, } from '../types/socket.ts' import { consola } from 'consola' import { channelPublicSelect } from '../dto/channel.dto.ts' import prisma from '../prisma/client.ts' import { socketToClient } from '../utils/socket-to-client.ts' export default async function (io: SocketServer, socket: ChadSocket) { // io.on('channel:join', async (cb) => { // if (socket.data.joined) { // consola.error('[WebRtc]', 'Already joined') // cb({ error: 'Already joined' }) // return // } // // socket.data.joined = true // socket.data.rtpCapabilities = rtpCapabilities // // // Get current channel from Socket.IO rooms // const currentChannelId = Array.from(socket.rooms).find(room => room !== socket.id) || 'default' // const joinedSockets = await getJoinedSockets(socket.id, currentChannelId) // // cb(joinedSockets.map(socketToClient)) // // for (const joinedSocket of joinedSockets) { // for (const producer of joinedSocket.data.producers.values()) { // createConsumer( // socket, // joinedSocket, // producer, // ) // } // } // // // Broadcast only to same channel using Socket.IO room // socket.to(currentChannelId).emit('newPeer', socketToClient(socket)) // }) socket.on('channel:join', async ({ channelId }, cb) => { try { cb(await handleJoin(channelId)) } catch (e) { cb(e) } }) await handleJoin('default') const channels = await prisma.channel.findMany({ select: channelPublicSelect, orderBy: { name: 'asc' }, }) type ChannelJoinCallback = ExtractCallbackPayload async function handleJoin(channelId: string): Promise { try { const channel = await prisma.channel.findUnique({ where: { id: channelId }, select: channelPublicSelect, }) if (!channel) { return { error: 'Channel not found' } } if (channel.maxClients) { const socketsInChannel = await io.in(channelId).fetchSockets() if (socketsInChannel.length >= channel.maxClients) { return { error: 'Channel is full' } } } const oldChannelId = Array.from(socket.rooms).find(room => room !== socket.id) // for (const producer of socket.data.producers.values()) { // producer.close() // } // socket.data.producers.clear() // // for (const consumer of socket.data.consumers.values()) { // consumer.close() // } // socket.data.consumers.clear() if (oldChannelId) { await socket.leave(oldChannelId) io.emit('channel:user-left', { channelId: oldChannelId, clientId: socket.id }) // // Auto-delete non-persistent empty channels // if (isLeavingNonPersistentChannel) { // const oldChannelSockets = await io.in(oldChannelId).fetchSockets() // // if (oldChannelSockets.length === 0) { // const oldChannel = await prisma.channel.findUnique({ // where: { id: oldChannelId }, // select: { persistent: true, id: true }, // }) // // if (oldChannel && !oldChannel.persistent) { // await prisma.channel.delete({ where: { id: oldChannelId } }) // io.emit('channelDeleted', { channelId: oldChannelId }) // consola.info('[Channel]', `Auto-deleted empty non-persistent channel: ${oldChannelId}`) // } // } // } } await socket.join(channelId) // Get new channel members // const newChannelSockets = await getJoinedSockets(socket.id, channelId) // // // Create consumers for existing producers in new channel // for (const peer of newChannelSockets) { // for (const producer of peer.data.producers.values()) { // createConsumer(socket, peer, producer) // } // } io.emit('channel:user-joined', { channelId, client: socketToClient(socket), }) return { channel, clients: newChannelSockets.map(socketToClient), } } catch (error) { consola.error('[channel:join]', error) if (error instanceof Error) { return { error: error.message } } else { return { error: 'Something went wrong' } } } } return { channels, } }