import { MeetRoom, MeetRecordingInfo } from '@typings-ce'; import { inject, injectable } from 'inversify'; import { SendDataOptions } from 'livekit-server-sdk'; import { OpenViduComponentsAdapterHelper } from '../helpers/index.js'; import { LiveKitService, LoggerService } from './index.js'; import { MeetSignalType } from '../typings/ce/event.model.js'; /** * Service responsible for all communication with the frontend * Centralizes all signals and events sent to the frontend */ @injectable() export class FrontendEventService { constructor( @inject(LoggerService) protected logger: LoggerService, @inject(LiveKitService) protected livekitService: LiveKitService ) {} /** * Sends a recording signal to OpenVidu Components within a specified room. * * This method constructs a signal with the appropriate topic and payload, * and sends it to the OpenVidu Components in the given room. The payload * is adapted to match the expected format for OpenVidu Components. */ async sendRecordingSignalToOpenViduComponents(roomId: string, recordingInfo: MeetRecordingInfo) { this.logger.debug(`Sending recording signal to OpenVidu Components for room '${roomId}'`); const { payload, options } = OpenViduComponentsAdapterHelper.generateRecordingSignal(recordingInfo); try { await this.sendSignal(roomId, payload, options); } catch (error) { this.logger.debug(`Error sending recording signal to OpenVidu Components for room '${roomId}': ${error}`); } } /** * Sends a room status signal to OpenVidu Components. * * This method checks if recording is started in the room and sends a signal * with the room status to OpenVidu Components. If recording is not started, * it skips sending the signal. */ async sendRoomStatusSignalToOpenViduComponents(roomId: string, participantSid: string) { this.logger.debug(`Sending room status signal for room ${roomId} to OpenVidu Components.`); try { const recordingEgress = await this.livekitService.getRecordingsEgress(roomId); // Construct the payload and signal options const { payload, options } = OpenViduComponentsAdapterHelper.generateRoomStatusSignal( recordingEgress, participantSid ); await this.sendSignal(roomId, payload, options); } catch (error) { this.logger.debug(`Error sending room status signal for room ${roomId}:`, error); } } /** * Sends a signal to notify participants in a room about updated room preferences. */ async sendRoomPreferencesUpdatedSignal(roomId: string, updatedRoom: MeetRoom): Promise { this.logger.debug(`Sending room preferences updated signal for room ${roomId}`); try { const payload = { roomId, preferences: updatedRoom.preferences }; const options: SendDataOptions = { topic: MeetSignalType.MEET_ROOM_PREFERENCES_UPDATED }; await this.sendSignal(roomId, payload, options); } catch (error) { this.logger.error(`Error sending room preferences updated signal for room ${roomId}:`, error); } } /** * Generic method to send signals to the frontend */ protected async sendSignal( roomId: string, rawData: Record, options: SendDataOptions ): Promise { this.logger.verbose(`Notifying participants in room ${roomId}: "${options.topic}".`); await this.livekitService.sendData(roomId, rawData, options); } }