148 lines
4.7 KiB
TypeScript
148 lines
4.7 KiB
TypeScript
import { MeetRecordingInfo, MeetRoom, ParticipantRole } from '@typings-ce';
|
|
import { inject, injectable } from 'inversify';
|
|
import { SendDataOptions } from 'livekit-server-sdk';
|
|
import { OpenViduComponentsAdapterHelper, OpenViduComponentsSignalPayload } from '../helpers/index.js';
|
|
import {
|
|
MeetParticipantRoleUpdatedPayload,
|
|
MeetRoomConfigUpdatedPayload,
|
|
MeetSignalPayload,
|
|
MeetSignalType
|
|
} from '../typings/ce/event.model.js';
|
|
import { LiveKitService, LoggerService } from './index.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,
|
|
recordingInfo: MeetRecordingInfo[]
|
|
) {
|
|
this.logger.debug(`Sending room status signal for room ${roomId} to OpenVidu Components.`);
|
|
|
|
try {
|
|
// Construct the payload and signal options
|
|
const { payload, options } = OpenViduComponentsAdapterHelper.generateRoomStatusSignal(
|
|
recordingInfo,
|
|
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 config.
|
|
*/
|
|
async sendRoomConfigUpdatedSignal(roomId: string, updatedRoom: MeetRoom): Promise<void> {
|
|
this.logger.debug(`Sending room config updated signal for room ${roomId}`);
|
|
|
|
try {
|
|
const payload: MeetRoomConfigUpdatedPayload = {
|
|
roomId,
|
|
config: updatedRoom.config,
|
|
timestamp: Date.now()
|
|
};
|
|
|
|
const options: SendDataOptions = {
|
|
topic: MeetSignalType.MEET_ROOM_CONFIG_UPDATED
|
|
};
|
|
|
|
await this.sendSignal(roomId, payload, options);
|
|
} catch (error) {
|
|
this.logger.error(`Error sending room config updated signal for room ${roomId}:`, error);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sends a signal to notify participants in a room about updated participant roles.
|
|
*/
|
|
async sendParticipantRoleUpdatedSignal(
|
|
roomId: string,
|
|
participantIdentity: string,
|
|
newRole: ParticipantRole,
|
|
secret: string
|
|
): Promise<void> {
|
|
this.logger.debug(
|
|
`Sending participant role updated signal for participant '${participantIdentity}' in room '${roomId}'`
|
|
);
|
|
|
|
const basePayload: MeetParticipantRoleUpdatedPayload = {
|
|
roomId,
|
|
participantIdentity,
|
|
newRole,
|
|
timestamp: Date.now()
|
|
};
|
|
|
|
const baseOptions: SendDataOptions = {
|
|
topic: MeetSignalType.MEET_PARTICIPANT_ROLE_UPDATED
|
|
};
|
|
|
|
// Send signal with secret to the participant whose role has been updated
|
|
await this.sendSignal(
|
|
roomId,
|
|
{ ...basePayload, secret },
|
|
{ ...baseOptions, destinationIdentities: [participantIdentity] }
|
|
);
|
|
|
|
// Broadcast the role update to all other participants without the secret
|
|
const participants = await this.livekitService.listRoomParticipants(roomId);
|
|
const otherParticipantIdentities = participants
|
|
.filter((p) => p.identity !== participantIdentity)
|
|
.map((p) => p.identity);
|
|
|
|
await this.sendSignal(roomId, basePayload, {
|
|
...baseOptions,
|
|
destinationIdentities: otherParticipantIdentities
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Generic method to send signals to the frontend
|
|
*/
|
|
|
|
protected async sendSignal(
|
|
roomId: string,
|
|
rawData: MeetSignalPayload | OpenViduComponentsSignalPayload,
|
|
options: SendDataOptions
|
|
): Promise<void> {
|
|
this.logger.verbose(`Notifying participants in room ${roomId}: "${options.topic}".`);
|
|
await this.livekitService.sendData(roomId, rawData, options);
|
|
}
|
|
}
|