{"version":3,"sources":["src/sdk/Transcription/Conversation.ts"],"names":[],"mappings":"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","file":"Conversation.d.ts","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved.\r\n// Licensed under the MIT license.\r\n// Multi-device Conversation is a Preview feature.\r\n\r\n/* eslint-disable max-classes-per-file */\r\n\r\nimport {\r\n    ConversationConnectionConfig,\r\n    ConversationManager,\r\n    ConversationReceivedTranslationEventArgs,\r\n    ConversationRecognizer,\r\n    ConversationRecognizerFactory,\r\n    ConversationTranslatorCommandTypes,\r\n    ConversationTranslatorMessageTypes,\r\n    IAuthentication,\r\n    IInternalConversation,\r\n    IInternalParticipant,\r\n    InternalParticipants,\r\n    MuteAllEventArgs,\r\n    ParticipantAttributeEventArgs,\r\n    ParticipantEventArgs,\r\n    ParticipantsListEventArgs,\r\n    TranscriberRecognizer\r\n} from \"../../common.speech/Exports.js\";\r\nimport {\r\n    IDisposable,\r\n    IErrorMessages,\r\n    marshalPromiseToCallbacks\r\n} from \"../../common/Exports.js\";\r\nimport { Contracts } from \"../Contracts.js\";\r\nimport {\r\n    ConnectionEventArgs,\r\n    ConversationExpirationEventArgs,\r\n    ConversationParticipantsChangedEventArgs,\r\n    ConversationTranslationCanceledEventArgs,\r\n    ConversationTranslationEventArgs,\r\n    ConversationTranslator,\r\n    Participant,\r\n    ParticipantChangedReason,\r\n    ProfanityOption,\r\n    PropertyCollection,\r\n    PropertyId,\r\n    SpeechTranslationConfig,\r\n} from \"../Exports.js\";\r\nimport { SpeechTranslationConfigImpl } from \"../SpeechTranslationConfig.js\";\r\nimport { Callback, ConversationInfo, ConversationProperties, IConversation } from \"./IConversation.js\";\r\nimport { IParticipant, IUser, TranscriptionParticipant } from \"./IParticipant.js\";\r\n\r\nexport abstract class Conversation implements IConversation {\r\n\r\n    protected constructor() {\r\n        return;\r\n    }\r\n\r\n    public abstract get authorizationToken(): string;\r\n\r\n    public abstract get config(): SpeechTranslationConfig;\r\n\r\n    public abstract get conversationId(): string;\r\n    public abstract get conversationInfo(): ConversationInfo;\r\n    public abstract get properties(): PropertyCollection;\r\n    public abstract get speechRecognitionLanguage(): string;\r\n    public abstract get participants(): Participant[];\r\n    public abstract set authorizationToken(value: string);\r\n    public abstract get isConnected(): boolean;\r\n\r\n    /**\r\n     * Create a conversation\r\n     * @param speechConfig\r\n     * @param cb\r\n     * @param err\r\n     */\r\n    public static createConversationAsync(speechConfig: SpeechTranslationConfig, arg2?: string | Callback, arg3?: Callback, arg4?: Callback): Conversation {\r\n        Contracts.throwIfNullOrUndefined(speechConfig, ConversationConnectionConfig.restErrors.invalidArgs.replace(\"{arg}\", \"config\"));\r\n        Contracts.throwIfNullOrUndefined(speechConfig.region, ConversationConnectionConfig.restErrors.invalidArgs.replace(\"{arg}\", \"SpeechServiceConnection_Region\"));\r\n        if (!speechConfig.subscriptionKey && !speechConfig.getProperty(PropertyId[PropertyId.SpeechServiceAuthorization_Token])) {\r\n            Contracts.throwIfNullOrUndefined(speechConfig.subscriptionKey, ConversationConnectionConfig.restErrors.invalidArgs.replace(\"{arg}\", \"SpeechServiceConnection_Key\"));\r\n        }\r\n        let conversationImpl: ConversationImpl;\r\n        let cb: Callback;\r\n        let err: Callback;\r\n        if (typeof arg2 === \"string\") {\r\n            conversationImpl = new ConversationImpl(speechConfig, arg2);\r\n            // eslint-disable-next-line @typescript-eslint/no-empty-function\r\n            marshalPromiseToCallbacks((async (): Promise<void> => {})(), arg3, arg4);\r\n        } else {\r\n            conversationImpl = new ConversationImpl(speechConfig);\r\n            cb = arg2;\r\n            err = arg3;\r\n            conversationImpl.createConversationAsync(\r\n                ((): void => {\r\n                    if (!!cb) {\r\n                        cb();\r\n                    }\r\n                }),\r\n                (error: any): void => {\r\n                    if (!!err) {\r\n                        err(error);\r\n                    }\r\n                });\r\n        }\r\n        return conversationImpl;\r\n\r\n    }\r\n\r\n    /** Start a conversation. */\r\n    public abstract startConversationAsync(cb?: Callback, err?: Callback): void;\r\n\r\n    /** Delete a conversation. After this no one will be able to join the conversation. */\r\n    public abstract deleteConversationAsync(cb?: Callback, err?: Callback): void;\r\n\r\n    /** End a conversation. */\r\n    public abstract endConversationAsync(cb?: Callback, err?: Callback): void;\r\n\r\n    /** Lock a conversation. This will prevent new participants from joining. */\r\n    public abstract lockConversationAsync(cb?: Callback, err?: Callback): void;\r\n\r\n    /** Add Participant to Conversation. */\r\n    public abstract addParticipantAsync(participant: IParticipant, cb?: Callback, err?: Callback): void;\r\n\r\n    /**\r\n     * Mute all other participants in the conversation. After this no other participants will\r\n     * have their speech recognitions broadcast, nor be able to send text messages.\r\n     */\r\n    public abstract muteAllParticipantsAsync(cb?: Callback, err?: Callback): void;\r\n\r\n    /**\r\n     * Mute a participant.\r\n     * @param userId A user identifier\r\n     */\r\n    public abstract muteParticipantAsync(userId: string, cb?: Callback, err?: Callback): void;\r\n\r\n    /**\r\n     * Remove a participant from a conversation using the user id, Participant or User object\r\n     * @param userId A user identifier\r\n     */\r\n    public abstract removeParticipantAsync(userId: string | IParticipant | IUser, cb?: Callback, err?: Callback): void;\r\n\r\n    /** Unlocks a conversation. */\r\n    public abstract unlockConversationAsync(cb?: Callback, err?: Callback): void;\r\n\r\n    /** Unmute all other participants in the conversation. */\r\n    public abstract unmuteAllParticipantsAsync(cb?: Callback, err?: Callback): void;\r\n\r\n    /**\r\n     * Unmute a participant.\r\n     * @param userId A user identifier\r\n     */\r\n    public abstract unmuteParticipantAsync(userId: string, cb?: Callback, err?: Callback): void;\r\n}\r\n\r\nexport class ConversationImpl extends Conversation implements IDisposable {\r\n\r\n    private privConfig: SpeechTranslationConfig;\r\n    private privProperties: PropertyCollection;\r\n    private privLanguage: string;\r\n    private privToken: string;\r\n    private privIsDisposed: boolean;\r\n    private privRoom: IInternalConversation;\r\n    private privManager: ConversationManager;\r\n    private privConversationRecognizer: ConversationRecognizer;\r\n    private privIsConnected: boolean;\r\n    private privParticipants: InternalParticipants;\r\n    private privIsReady: boolean;\r\n    private privConversationTranslator: ConversationTranslator;\r\n    private privTranscriberRecognizer: TranscriberRecognizer;\r\n    private privErrors: IErrorMessages = ConversationConnectionConfig.restErrors;\r\n    private privConversationId: string;\r\n    private readonly privTextMessageMaxLength: number;\r\n\r\n    /**\r\n     * Create a conversation impl\r\n     * @param speechConfig\r\n     * @param {string} id - optional conversationId\r\n     */\r\n    public constructor(speechConfig: SpeechTranslationConfig, id?: string) {\r\n        super();\r\n        this.privIsConnected = false;\r\n        this.privIsDisposed = false;\r\n        this.privConversationId = \"\";\r\n        this.privProperties = new PropertyCollection();\r\n        this.privManager = new ConversationManager();\r\n\r\n        // check the speech language\r\n        const language: string = speechConfig.getProperty(PropertyId[PropertyId.SpeechServiceConnection_RecoLanguage]);\r\n        if (!language) {\r\n            speechConfig.setProperty(PropertyId[PropertyId.SpeechServiceConnection_RecoLanguage], ConversationConnectionConfig.defaultLanguageCode);\r\n        }\r\n        this.privLanguage = speechConfig.getProperty(PropertyId[PropertyId.SpeechServiceConnection_RecoLanguage]);\r\n\r\n        if (!id) {\r\n            // check the target language(s)\r\n            if (speechConfig.targetLanguages.length === 0) {\r\n                speechConfig.addTargetLanguage(this.privLanguage);\r\n            }\r\n\r\n            // check the profanity setting: speech and conversationTranslator should be in sync\r\n            const profanity: string = speechConfig.getProperty(PropertyId[PropertyId.SpeechServiceResponse_ProfanityOption]);\r\n            if (!profanity) {\r\n                speechConfig.setProfanity(ProfanityOption.Masked);\r\n            }\r\n            // check the nickname: it should pass this regex: ^\\w+([\\s-][\\w\\(\\)]+)*$\"\r\n            // TODO: specify the regex required. Nicknames must be unique or get the duplicate nickname error\r\n            // TODO: check what the max length is and if a truncation is required or if the service handles it without an error\r\n            let hostNickname: string = speechConfig.getProperty(PropertyId[PropertyId.ConversationTranslator_Name]);\r\n            if (hostNickname === undefined || hostNickname === null) {\r\n                hostNickname = \"Host\";\r\n            }\r\n            Contracts.throwIfNullOrTooLong(hostNickname, \"nickname\", 50);\r\n            Contracts.throwIfNullOrTooShort(hostNickname, \"nickname\", 2);\r\n            speechConfig.setProperty(PropertyId[PropertyId.ConversationTranslator_Name], hostNickname);\r\n\r\n        } else {\r\n            this.privConversationId = id;\r\n        }\r\n\r\n        // save the speech config for future usage\r\n        this.privConfig = speechConfig;\r\n\r\n        // save the config properties\r\n        const configImpl = speechConfig as SpeechTranslationConfigImpl;\r\n        Contracts.throwIfNull(configImpl, \"speechConfig\");\r\n        this.privProperties = configImpl.properties.clone();\r\n        this.privIsConnected = false;\r\n        this.privParticipants = new InternalParticipants();\r\n        this.privIsReady = false;\r\n        this.privTextMessageMaxLength = 1000;\r\n    }\r\n\r\n    // get the internal data about a conversation\r\n    public get room(): IInternalConversation {\r\n        return this.privRoom;\r\n    }\r\n\r\n    // get the wrapper for connecting to the websockets\r\n    public get connection(): ConversationRecognizer {\r\n        return this.privConversationRecognizer; // this.privConnection;\r\n    }\r\n\r\n    // get the config\r\n    public get config(): SpeechTranslationConfig {\r\n        return this.privConfig;\r\n    }\r\n\r\n    // get the conversation Id\r\n    public get conversationId(): string {\r\n        return this.privRoom ? this.privRoom.roomId : this.privConversationId;\r\n    }\r\n\r\n    // get the properties\r\n    public get properties(): PropertyCollection {\r\n        return this.privProperties;\r\n    }\r\n\r\n    // get the speech language\r\n    public get speechRecognitionLanguage(): string {\r\n        return this.privLanguage;\r\n    }\r\n\r\n    public get isMutedByHost(): boolean {\r\n        return this.privParticipants.me?.isHost ? false : this.privParticipants.me?.isMuted;\r\n    }\r\n\r\n    public get isConnected(): boolean {\r\n        return this.privIsConnected && this.privIsReady;\r\n    }\r\n\r\n    public get participants(): Participant[] {\r\n        return this.toParticipants(true);\r\n    }\r\n\r\n    public get me(): Participant {\r\n        return this.toParticipant(this.privParticipants.me);\r\n    }\r\n\r\n    public get host(): Participant {\r\n        return this.toParticipant(this.privParticipants.host);\r\n    }\r\n\r\n    public get transcriberRecognizer(): TranscriberRecognizer {\r\n        return this.privTranscriberRecognizer;\r\n    }\r\n\r\n    public get conversationInfo(): ConversationInfo {\r\n        const convId: string = this.conversationId;\r\n        const p: TranscriptionParticipant[] = this.participants.map((part: Participant): TranscriptionParticipant => (\r\n            {\r\n                id: part.id,\r\n                preferredLanguage: part.preferredLanguage,\r\n                voice: part.voice\r\n            }\r\n        ));\r\n        const props: ConversationProperties = {};\r\n        for (const key of ConversationConnectionConfig.transcriptionEventKeys) {\r\n            const val: string = this.properties.getProperty(key, \"\");\r\n            if (val !== \"\") {\r\n                props[key] = val;\r\n            }\r\n        }\r\n        const info: ConversationInfo = { id: convId, participants: p, conversationProperties: props };\r\n        return info;\r\n    }\r\n\r\n    private get canSend(): boolean {\r\n        return this.privIsConnected && !this.privParticipants.me?.isMuted;\r\n    }\r\n\r\n    private get canSendAsHost(): boolean {\r\n        return this.privIsConnected && this.privParticipants.me?.isHost;\r\n    }\r\n\r\n    // get / set the speech auth token\r\n    // eslint-disable-next-line @typescript-eslint/member-ordering\r\n    public get authorizationToken(): string {\r\n        return this.privToken;\r\n    }\r\n\r\n    public set authorizationToken(value: string) {\r\n        Contracts.throwIfNullOrWhitespace(value, \"authorizationToken\");\r\n        this.privToken = value;\r\n    }\r\n\r\n    public set conversationTranslator(conversationTranslator: ConversationTranslator) {\r\n        this.privConversationTranslator = conversationTranslator;\r\n    }\r\n\r\n    public onToken(token: IAuthentication): void {\r\n        this.privConversationTranslator.onToken(token);\r\n    }\r\n\r\n    /**\r\n     * Create a new conversation as Host\r\n     * @param cb\r\n     * @param err\r\n     */\r\n    public createConversationAsync(cb?: Callback, err?: Callback): void {\r\n        try {\r\n            if (!!this.privConversationRecognizer) {\r\n                this.handleError(new Error(this.privErrors.permissionDeniedStart), err);\r\n            }\r\n            this.privManager.createOrJoin(this.privProperties, undefined,\r\n                ((room: IInternalConversation): void => {\r\n                    if (!room) {\r\n                        this.handleError(new Error(this.privErrors.permissionDeniedConnect), err);\r\n                    }\r\n                    this.privRoom = room;\r\n                    this.handleCallback(cb, err);\r\n                }),\r\n                ((error: any): void => {\r\n                    this.handleError(error, err);\r\n                }));\r\n        } catch (error) {\r\n            this.handleError(error, err);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Starts a new conversation as host.\r\n     * @param cb\r\n     * @param err\r\n     */\r\n    public startConversationAsync(cb?: Callback, err?: Callback): void {\r\n        try {\r\n            // check if there is already a recognizer\r\n            if (!!this.privConversationRecognizer) {\r\n                this.handleError(new Error(this.privErrors.permissionDeniedStart), err);\r\n            }\r\n            // check if there is conversation data available\r\n            Contracts.throwIfNullOrUndefined(this.privRoom, this.privErrors.permissionDeniedConnect);\r\n            // connect to the conversation websocket\r\n            this.privParticipants.meId = this.privRoom.participantId;\r\n            this.privConversationRecognizer = ConversationRecognizerFactory.fromConfig(this, this.privConfig);\r\n\r\n            // Because ConversationTranslator manually sets up and manages the connection, Conversation\r\n            // has to forward serviceRecognizer connection events that usually get passed automatically\r\n            this.privConversationRecognizer.connected = this.onConnected;\r\n            this.privConversationRecognizer.disconnected = this.onDisconnected;\r\n            this.privConversationRecognizer.canceled = this.onCanceled;\r\n\r\n            this.privConversationRecognizer.participantUpdateCommandReceived = this.onParticipantUpdateCommandReceived;\r\n            this.privConversationRecognizer.lockRoomCommandReceived = this.onLockRoomCommandReceived;\r\n            this.privConversationRecognizer.muteAllCommandReceived = this.onMuteAllCommandReceived;\r\n            this.privConversationRecognizer.participantJoinCommandReceived = this.onParticipantJoinCommandReceived;\r\n            this.privConversationRecognizer.participantLeaveCommandReceived = this.onParticipantLeaveCommandReceived;\r\n            this.privConversationRecognizer.translationReceived = this.onTranslationReceived;\r\n            this.privConversationRecognizer.participantsListReceived = this.onParticipantsListReceived;\r\n            this.privConversationRecognizer.conversationExpiration = this.onConversationExpiration;\r\n\r\n            this.privConversationRecognizer.connect(this.privRoom.token,\r\n                ((): void => {\r\n                    this.handleCallback(cb, err);\r\n                }),\r\n                ((error: any): void => {\r\n                    this.handleError(error, err);\r\n                }));\r\n        } catch (error) {\r\n            this.handleError(error, err);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Join a conversation as a participant.\r\n     * @param { IParticipant } participant - participant to add\r\n     * @param cb\r\n     * @param err\r\n     */\r\n    public addParticipantAsync(participant: IParticipant, cb?: Callback, err?: Callback): void {\r\n        Contracts.throwIfNullOrUndefined(participant, \"Participant\");\r\n        marshalPromiseToCallbacks(this.addParticipantImplAsync(participant), cb, err);\r\n    }\r\n\r\n    /**\r\n     * Join a conversation as a participant.\r\n     * @param conversation\r\n     * @param nickname\r\n     * @param lang\r\n     * @param cb\r\n     * @param err\r\n     */\r\n    public joinConversationAsync(conversationId: string, nickname: string, lang: string, cb?: Callback, err?: Callback): void {\r\n        try {\r\n            // TODO\r\n            // if (!!this.privConversationRecognizer) {\r\n            //     throw new Error(this.privErrors.permissionDeniedStart);\r\n            // }\r\n            Contracts.throwIfNullOrWhitespace(conversationId, this.privErrors.invalidArgs.replace(\"{arg}\", \"conversationId\"));\r\n            Contracts.throwIfNullOrWhitespace(nickname, this.privErrors.invalidArgs.replace(\"{arg}\", \"nickname\"));\r\n            Contracts.throwIfNullOrWhitespace(lang, this.privErrors.invalidArgs.replace(\"{arg}\", \"language\"));\r\n            // join the conversation\r\n            this.privManager.createOrJoin(this.privProperties, conversationId,\r\n                ((room: IInternalConversation): void => {\r\n                    Contracts.throwIfNullOrUndefined(room, this.privErrors.permissionDeniedConnect);\r\n                    this.privRoom = room;\r\n                    this.privConfig.authorizationToken = room.cognitiveSpeechAuthToken;\r\n                    // join callback\r\n                    if (!!cb) {\r\n                        cb(room.cognitiveSpeechAuthToken);\r\n                    }\r\n                }),\r\n                ((error: any): void => {\r\n                    this.handleError(error, err);\r\n                }));\r\n        } catch (error) {\r\n            this.handleError(error, err);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Deletes a conversation\r\n     * @param cb\r\n     * @param err\r\n     */\r\n    public deleteConversationAsync(cb?: Callback, err?: Callback): void {\r\n        marshalPromiseToCallbacks(this.deleteConversationImplAsync(), cb, err);\r\n    }\r\n\r\n    public async deleteConversationImplAsync(): Promise<void> {\r\n            Contracts.throwIfNullOrUndefined(this.privProperties, this.privErrors.permissionDeniedConnect);\r\n            Contracts.throwIfNullOrWhitespace(this.privRoom.token, this.privErrors.permissionDeniedConnect);\r\n            await this.privManager.leave(this.privProperties, this.privRoom.token);\r\n\r\n            this.dispose();\r\n    }\r\n\r\n    /**\r\n     * Issues a request to close the client websockets\r\n     * @param cb\r\n     * @param err\r\n     */\r\n    public endConversationAsync(cb?: Callback, err?: Callback): void {\r\n        marshalPromiseToCallbacks(this.endConversationImplAsync(), cb, err);\r\n    }\r\n\r\n    public endConversationImplAsync(): Promise<void> {\r\n        return this.close(true);\r\n    }\r\n\r\n    /**\r\n     * Issues a request to lock the conversation\r\n     * @param cb\r\n     * @param err\r\n     */\r\n    public lockConversationAsync(cb?: Callback, err?: Callback): void {\r\n        try {\r\n            Contracts.throwIfDisposed(this.privIsDisposed);\r\n            Contracts.throwIfDisposed(this.privConversationRecognizer.isDisposed());\r\n            Contracts.throwIfNullOrUndefined(this.privRoom, this.privErrors.permissionDeniedSend);\r\n            if (!this.canSendAsHost) {\r\n                this.handleError(new Error(this.privErrors.permissionDeniedConversation.replace(\"{command}\", \"lock\")), err);\r\n            }\r\n            if (!!this.privConversationRecognizer) {\r\n                this.privConversationRecognizer.sendRequest(this.getLockCommand(true),\r\n                    ((): void => {\r\n                        this.handleCallback(cb, err);\r\n                    }),\r\n                    ((error: any): void => {\r\n                        this.handleError(error, err);\r\n                    }));\r\n            }\r\n        } catch (error) {\r\n            this.handleError(error, err);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Issues a request to mute the conversation\r\n     * @param cb\r\n     * @param err\r\n     */\r\n    public muteAllParticipantsAsync(cb?: Callback, err?: Callback): void {\r\n        try {\r\n            Contracts.throwIfDisposed(this.privIsDisposed);\r\n            Contracts.throwIfDisposed(this.privConversationRecognizer.isDisposed());\r\n            Contracts.throwIfNullOrUndefined(this.privConversationRecognizer, this.privErrors.permissionDeniedSend);\r\n            Contracts.throwIfNullOrUndefined(this.privRoom, this.privErrors.permissionDeniedSend);\r\n            // check the user's permissions\r\n            if (!this.canSendAsHost) {\r\n                this.handleError(new Error(this.privErrors.permissionDeniedConversation.replace(\"{command}\", \"mute\")), err);\r\n            }\r\n            if (!!this.privConversationRecognizer) {\r\n                this.privConversationRecognizer.sendRequest(this.getMuteAllCommand(true),\r\n                    ((): void => {\r\n                        this.handleCallback(cb, err);\r\n                    }),\r\n                    ((error: any): void => {\r\n                        this.handleError(error, err);\r\n                    }));\r\n            }\r\n        } catch (error) {\r\n            this.handleError(error, err);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Issues a request to mute a participant in the conversation\r\n     * @param userId\r\n     * @param cb\r\n     * @param err\r\n     */\r\n    public muteParticipantAsync(userId: string, cb?: Callback, err?: Callback): void {\r\n        try {\r\n            Contracts.throwIfDisposed(this.privIsDisposed);\r\n            Contracts.throwIfDisposed(this.privConversationRecognizer.isDisposed());\r\n            Contracts.throwIfNullOrWhitespace(userId, this.privErrors.invalidArgs.replace(\"{arg}\", \"userId\"));\r\n            Contracts.throwIfNullOrUndefined(this.privRoom, this.privErrors.permissionDeniedSend);\r\n            // check the connection is open (host + participant can perform the mute command)\r\n            if (!this.canSend) {\r\n                this.handleError(new Error(this.privErrors.permissionDeniedSend), err);\r\n            }\r\n            // if not host, check the participant is not muting another participant\r\n            if (!this.me.isHost && this.me.id !== userId) {\r\n                this.handleError(new Error(this.privErrors.permissionDeniedParticipant.replace(\"{command}\", \"mute\")), err);\r\n            }\r\n            // check the user exists\r\n            const exists: number = this.privParticipants.getParticipantIndex(userId);\r\n            if (exists === -1) {\r\n                this.handleError(new Error(this.privErrors.invalidParticipantRequest), err);\r\n            }\r\n            if (!!this.privConversationRecognizer) {\r\n                this.privConversationRecognizer.sendRequest(this.getMuteCommand(userId, true), ((): void => {\r\n                        this.handleCallback(cb, err);\r\n                    }),\r\n                    ((error: any): void => {\r\n                        this.handleError(error, err);\r\n                    }));\r\n            }\r\n        } catch (error) {\r\n            this.handleError(error, err);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Issues a request to remove a participant from the conversation\r\n     * @param userId\r\n     * @param cb\r\n     * @param err\r\n     */\r\n    public removeParticipantAsync(userId: string | IParticipant | IUser, cb?: Callback, err?: Callback): void {\r\n        try {\r\n            Contracts.throwIfDisposed(this.privIsDisposed);\r\n            if (!!this.privTranscriberRecognizer && userId.hasOwnProperty(\"id\")) {\r\n                // Assume this is a transcription participant\r\n                marshalPromiseToCallbacks(this.removeParticipantImplAsync(userId as IParticipant), cb, err);\r\n            } else {\r\n                Contracts.throwIfDisposed(this.privConversationRecognizer.isDisposed());\r\n                Contracts.throwIfNullOrUndefined(this.privRoom, this.privErrors.permissionDeniedSend);\r\n                if (!this.canSendAsHost) {\r\n                    this.handleError(new Error(this.privErrors.permissionDeniedParticipant.replace(\"{command}\", \"remove\")), err);\r\n                }\r\n                let participantId = \"\";\r\n                if (typeof userId === \"string\") {\r\n                    participantId = userId;\r\n                } else if (userId.hasOwnProperty(\"id\")) {\r\n                    const participant: IParticipant = userId as IParticipant;\r\n                    participantId = participant.id;\r\n                } else if (userId.hasOwnProperty(\"userId\")) {\r\n                    const user: IUser = userId as IUser;\r\n                    participantId = user.userId;\r\n                }\r\n                Contracts.throwIfNullOrWhitespace(participantId, this.privErrors.invalidArgs.replace(\"{arg}\", \"userId\"));\r\n                // check the participant exists\r\n                const index: number = this.participants.findIndex((p: Participant): boolean => p.id === participantId);\r\n                if (index === -1) {\r\n                    this.handleError(new Error(this.privErrors.invalidParticipantRequest), err);\r\n                }\r\n                if (!!this.privConversationRecognizer) {\r\n                    this.privConversationRecognizer.sendRequest(this.getEjectCommand(participantId), ((): void => {\r\n                        this.handleCallback(cb, err);\r\n                    }),\r\n                        ((error: any): void => {\r\n                            this.handleError(error, err);\r\n                        }));\r\n                }\r\n            }\r\n        } catch (error) {\r\n            this.handleError(error, err);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Issues a request to unlock the conversation\r\n     * @param cb\r\n     * @param err\r\n     */\r\n    public unlockConversationAsync(cb?: Callback, err?: Callback): void {\r\n        try {\r\n            Contracts.throwIfDisposed(this.privIsDisposed);\r\n            Contracts.throwIfDisposed(this.privConversationRecognizer.isDisposed());\r\n            Contracts.throwIfNullOrUndefined(this.privRoom, this.privErrors.permissionDeniedSend);\r\n            if (!this.canSendAsHost) {\r\n                this.handleError(new Error(this.privErrors.permissionDeniedConversation.replace(\"{command}\", \"unlock\")), err);\r\n            }\r\n            if (!!this.privConversationRecognizer) {\r\n                this.privConversationRecognizer.sendRequest(this.getLockCommand(false), ((): void => {\r\n                    this.handleCallback(cb, err);\r\n                }),\r\n                    ((error: any): void => {\r\n                        this.handleError(error, err);\r\n                    }));\r\n                }\r\n        } catch (error) {\r\n            this.handleError(error, err);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Issues a request to unmute all participants in the conversation\r\n     * @param cb\r\n     * @param err\r\n     */\r\n    public unmuteAllParticipantsAsync(cb?: Callback, err?: Callback): void {\r\n        try {\r\n            Contracts.throwIfDisposed(this.privIsDisposed);\r\n            Contracts.throwIfDisposed(this.privConversationRecognizer.isDisposed());\r\n            Contracts.throwIfNullOrUndefined(this.privRoom, this.privErrors.permissionDeniedSend);\r\n            if (!this.canSendAsHost) {\r\n                this.handleError(new Error(this.privErrors.permissionDeniedConversation.replace(\"{command}\", \"unmute all\")), err);\r\n            }\r\n            if (!!this.privConversationRecognizer) {\r\n                this.privConversationRecognizer.sendRequest(this.getMuteAllCommand(false), ((): void => {\r\n                    this.handleCallback(cb, err);\r\n                }),\r\n                    ((error: any): void => {\r\n                        this.handleError(error, err);\r\n                    }));\r\n            }\r\n        } catch (error) {\r\n            this.handleError(error, err);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Issues a request to unmute a participant in the conversation\r\n     * @param userId\r\n     * @param cb\r\n     * @param err\r\n     */\r\n    public unmuteParticipantAsync(userId: string, cb?: Callback, err?: Callback): void {\r\n        try {\r\n            Contracts.throwIfDisposed(this.privIsDisposed);\r\n            Contracts.throwIfDisposed(this.privConversationRecognizer.isDisposed());\r\n            Contracts.throwIfNullOrWhitespace(userId, this.privErrors.invalidArgs.replace(\"{arg}\", \"userId\"));\r\n            Contracts.throwIfNullOrUndefined(this.privRoom, this.privErrors.permissionDeniedSend);\r\n            // check the connection is open (host + participant can perform the mute command)\r\n            if (!this.canSend) {\r\n                this.handleError(new Error(this.privErrors.permissionDeniedSend), err);\r\n            }\r\n            // if not host, check the participant is not muting another participant\r\n            if (!this.me.isHost && this.me.id !== userId) {\r\n                this.handleError(new Error(this.privErrors.permissionDeniedParticipant.replace(\"{command}\", \"mute\")), err);\r\n            }\r\n            // check the user exists\r\n            const exists: number = this.privParticipants.getParticipantIndex(userId);\r\n            if (exists === -1) {\r\n                this.handleError(new Error(this.privErrors.invalidParticipantRequest), err);\r\n            }\r\n            if (!!this.privConversationRecognizer) {\r\n                this.privConversationRecognizer.sendRequest(this.getMuteCommand(userId, false), ((): void => {\r\n                    this.handleCallback(cb, err);\r\n                }),\r\n                    ((error: any): void => {\r\n                        this.handleError(error, err);\r\n                    }));\r\n            }\r\n        } catch (error) {\r\n            this.handleError(error, err);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Send a text message\r\n     * @param message\r\n     * @param cb\r\n     * @param err\r\n     */\r\n    public sendTextMessageAsync(message: string, cb?: Callback, err?: Callback): void {\r\n        try {\r\n            Contracts.throwIfDisposed(this.privIsDisposed);\r\n            Contracts.throwIfDisposed(this.privConversationRecognizer.isDisposed());\r\n            Contracts.throwIfNullOrWhitespace(message, this.privErrors.invalidArgs.replace(\"{arg}\", \"message\"));\r\n            Contracts.throwIfNullOrUndefined(this.privRoom, this.privErrors.permissionDeniedSend);\r\n            if (!this.canSend) {\r\n                this.handleError(new Error(this.privErrors.permissionDeniedSend), err);\r\n            }\r\n            // TODO: is a max length check required?\r\n            if (message.length > this.privTextMessageMaxLength) {\r\n                this.handleError(new Error(this.privErrors.invalidArgs.replace(\"{arg}\", \"message length\")), err);\r\n            }\r\n            if (!!this.privConversationRecognizer) {\r\n                this.privConversationRecognizer.sendRequest(this.getMessageCommand(message), ((): void => {\r\n                    this.handleCallback(cb, err);\r\n                }),\r\n                    ((error: any): void => {\r\n                        this.handleError(error, err);\r\n                    }));\r\n            }\r\n        } catch (error) {\r\n            this.handleError(error, err);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Set translated to languages\r\n     * @param {string[]} languages - languages to translate to\r\n     * @param cb\r\n     * @param err\r\n     */\r\n    public setTranslatedLanguagesAsync(languages: string[], cb?: Callback, err?: Callback): void {\r\n        try {\r\n            Contracts.throwIfDisposed(this.privIsDisposed);\r\n            Contracts.throwIfDisposed(this.privConversationRecognizer.isDisposed());\r\n            Contracts.throwIfArrayEmptyOrWhitespace(languages, this.privErrors.invalidArgs.replace(\"{arg}\", \"languages\"));\r\n            Contracts.throwIfNullOrUndefined(this.privRoom, this.privErrors.permissionDeniedSend);\r\n            if (!this.canSend) {\r\n                this.handleError(new Error(this.privErrors.permissionDeniedSend), err);\r\n            }\r\n            if (!!this.privConversationRecognizer) {\r\n                this.privConversationRecognizer.sendRequest(this.getSetTranslateToLanguagesCommand(languages),\r\n                    ((): void => {\r\n                        this.handleCallback(cb, err);\r\n                    }),\r\n                    ((error: any): void => {\r\n                        this.handleError(error, err);\r\n                    }));\r\n            }\r\n        } catch (error) {\r\n            this.handleError(error, err);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Change nickname\r\n     * @param {string} nickname - new nickname for the room\r\n     * @param cb\r\n     * @param err\r\n     */\r\n    public changeNicknameAsync(nickname: string, cb?: Callback, err?: Callback): void {\r\n        try {\r\n            Contracts.throwIfDisposed(this.privIsDisposed);\r\n            Contracts.throwIfDisposed(this.privConversationRecognizer.isDisposed());\r\n            Contracts.throwIfNullOrWhitespace(nickname, this.privErrors.invalidArgs.replace(\"{arg}\", \"nickname\"));\r\n            Contracts.throwIfNullOrUndefined(this.privRoom, this.privErrors.permissionDeniedSend);\r\n            if (!this.canSend) {\r\n                this.handleError(new Error(this.privErrors.permissionDeniedSend), err);\r\n            }\r\n            if (!!this.privConversationRecognizer) {\r\n                this.privConversationRecognizer.sendRequest(this.getChangeNicknameCommand(nickname),\r\n                    ((): void => {\r\n                        this.handleCallback(cb, err);\r\n                    }),\r\n                    ((error: any): void => {\r\n                        this.handleError(error, err);\r\n                    }));\r\n            }\r\n        } catch (error) {\r\n            this.handleError(error, err);\r\n        }\r\n    }\r\n\r\n    public isDisposed(): boolean {\r\n        return this.privIsDisposed;\r\n    }\r\n\r\n    public dispose(): void {\r\n        if (this.isDisposed) {\r\n            return;\r\n        }\r\n        this.privIsDisposed = true;\r\n        if (!!this.config) {\r\n            this.config.close();\r\n        }\r\n        this.privConfig = undefined;\r\n        this.privLanguage = undefined;\r\n        this.privProperties = undefined;\r\n        this.privRoom = undefined;\r\n        this.privToken = undefined;\r\n        this.privManager = undefined;\r\n        this.privIsConnected = false;\r\n        this.privIsReady = false;\r\n        this.privParticipants = undefined;\r\n    }\r\n\r\n    public async connectTranscriberRecognizer(recognizer: TranscriberRecognizer): Promise<void> {\r\n        if (!!this.privTranscriberRecognizer) {\r\n            await this.privTranscriberRecognizer.close();\r\n        }\r\n        await recognizer.enforceAudioGating();\r\n        this.privTranscriberRecognizer = recognizer;\r\n        this.privTranscriberRecognizer.conversation = this;\r\n    }\r\n\r\n    public getKeepAlive(): string {\r\n        const nickname: string = (!!this.me) ? this.me.displayName : \"default_nickname\";\r\n        return JSON.stringify({\r\n            id: \"0\",\r\n            nickname,\r\n            participantId: this.privRoom.participantId,\r\n            roomId: this.privRoom.roomId,\r\n            type: ConversationTranslatorMessageTypes.keepAlive\r\n        });\r\n    }\r\n\r\n    /** websocket callbacks */\r\n    /* eslint-disable @typescript-eslint/typedef */\r\n    private onConnected = (e: ConnectionEventArgs): void => {\r\n        this.privIsConnected = true;\r\n        try {\r\n            if (!!this.privConversationTranslator?.sessionStarted) {\r\n                this.privConversationTranslator.sessionStarted(this.privConversationTranslator, e);\r\n            }\r\n        } catch (e) {\r\n            //\r\n        }\r\n    };\r\n\r\n    private onDisconnected = (e: ConnectionEventArgs): void => {\r\n        try {\r\n            if (!!this.privConversationTranslator?.sessionStopped) {\r\n                this.privConversationTranslator.sessionStopped(this.privConversationTranslator, e);\r\n            }\r\n        } catch (e) {\r\n            //\r\n        } finally {\r\n            void this.close(false);\r\n        }\r\n    };\r\n\r\n    private onCanceled = (r: ConversationRecognizer, e: ConversationTranslationCanceledEventArgs): void => {\r\n        try {\r\n            if (!!this.privConversationTranslator?.canceled) {\r\n                this.privConversationTranslator.canceled(this.privConversationTranslator, e);\r\n            }\r\n        } catch (e) {\r\n            //\r\n        }\r\n    };\r\n\r\n    private onParticipantUpdateCommandReceived = (r: ConversationRecognizer, e: ParticipantAttributeEventArgs): void => {\r\n        try {\r\n            const updatedParticipant: IInternalParticipant = this.privParticipants.getParticipant(e.id);\r\n            if (updatedParticipant !== undefined) {\r\n\r\n                switch (e.key) {\r\n                    case ConversationTranslatorCommandTypes.changeNickname:\r\n                        updatedParticipant.displayName = e.value as string;\r\n                        break;\r\n                    case ConversationTranslatorCommandTypes.setUseTTS:\r\n                        updatedParticipant.isUsingTts = e.value as boolean;\r\n                        break;\r\n                    case ConversationTranslatorCommandTypes.setProfanityFiltering:\r\n                        updatedParticipant.profanity = e.value as boolean;\r\n                        break;\r\n                    case ConversationTranslatorCommandTypes.setMute:\r\n                        updatedParticipant.isMuted = e.value as boolean;\r\n                        break;\r\n                    case ConversationTranslatorCommandTypes.setTranslateToLanguages:\r\n                        updatedParticipant.translateToLanguages = e.value as string[];\r\n                        break;\r\n                }\r\n                this.privParticipants.addOrUpdateParticipant(updatedParticipant);\r\n\r\n                if (!!this.privConversationTranslator) {\r\n                    this.privConversationTranslator.participantsChanged(\r\n                        this.privConversationTranslator,\r\n                        new ConversationParticipantsChangedEventArgs(ParticipantChangedReason.Updated,\r\n                            [this.toParticipant(updatedParticipant)], e.sessionId));\r\n                }\r\n            }\r\n        } catch (e) {\r\n            //\r\n        }\r\n    };\r\n\r\n    private onLockRoomCommandReceived = (): void => {\r\n        // TODO\r\n    };\r\n\r\n    private onMuteAllCommandReceived = (r: ConversationRecognizer, e: MuteAllEventArgs): void => {\r\n        try {\r\n            this.privParticipants.participants.forEach((p: IInternalParticipant): boolean => p.isMuted = (p.isHost ? false : e.isMuted));\r\n            if (!!this.privConversationTranslator) {\r\n                this.privConversationTranslator.participantsChanged(\r\n                    this.privConversationTranslator,\r\n                    new ConversationParticipantsChangedEventArgs(ParticipantChangedReason.Updated,\r\n                        this.toParticipants(false), e.sessionId));\r\n            }\r\n        } catch (e) {\r\n            //\r\n        }\r\n    };\r\n\r\n    private onParticipantJoinCommandReceived = (r: ConversationRecognizer, e: ParticipantEventArgs): void => {\r\n        try {\r\n            const newParticipant: IInternalParticipant = this.privParticipants.addOrUpdateParticipant(e.participant);\r\n            if (newParticipant !== undefined) {\r\n                if (!!this.privConversationTranslator) {\r\n                    this.privConversationTranslator.participantsChanged(\r\n                        this.privConversationTranslator,\r\n                        new ConversationParticipantsChangedEventArgs(ParticipantChangedReason.JoinedConversation,\r\n                            [this.toParticipant(newParticipant)], e.sessionId));\r\n                }\r\n            }\r\n        } catch (e) {\r\n            //\r\n        }\r\n    };\r\n\r\n    private onParticipantLeaveCommandReceived = (r: ConversationRecognizer, e: ParticipantEventArgs): void => {\r\n        try {\r\n            const ejectedParticipant: IInternalParticipant = this.privParticipants.getParticipant(e.participant.id);\r\n            if (ejectedParticipant !== undefined) {\r\n                // remove the participant from the internal participants list\r\n                this.privParticipants.deleteParticipant(e.participant.id);\r\n                if (!!this.privConversationTranslator) {\r\n                    // notify subscribers that the participant has left the conversation\r\n                    this.privConversationTranslator.participantsChanged(\r\n                        this.privConversationTranslator,\r\n                        new ConversationParticipantsChangedEventArgs(ParticipantChangedReason.LeftConversation,\r\n                            [this.toParticipant(ejectedParticipant)], e.sessionId));\r\n                }\r\n            }\r\n        } catch (e) {\r\n            //\r\n        }\r\n    };\r\n\r\n    private onTranslationReceived = (r: ConversationRecognizer, e: ConversationReceivedTranslationEventArgs): void => {\r\n        try {\r\n            switch (e.command) {\r\n                case ConversationTranslatorMessageTypes.final:\r\n                    if (!!this.privConversationTranslator) {\r\n                        this.privConversationTranslator.transcribed(\r\n                            this.privConversationTranslator,\r\n                            new ConversationTranslationEventArgs(e.payload, undefined, e.sessionId));\r\n                    }\r\n                    break;\r\n                case ConversationTranslatorMessageTypes.partial:\r\n                    if (!!this.privConversationTranslator) {\r\n                        this.privConversationTranslator.transcribing(\r\n                            this.privConversationTranslator,\r\n                            new ConversationTranslationEventArgs(e.payload, undefined, e.sessionId));\r\n                    }\r\n                    break;\r\n                case ConversationTranslatorMessageTypes.instantMessage:\r\n                    if (!!this.privConversationTranslator) {\r\n                        this.privConversationTranslator.textMessageReceived(\r\n                            this.privConversationTranslator,\r\n                            new ConversationTranslationEventArgs(e.payload, undefined, e.sessionId));\r\n                    }\r\n                    break;\r\n            }\r\n        } catch (e) {\r\n            //\r\n        }\r\n    };\r\n\r\n    private onParticipantsListReceived = (r: ConversationRecognizer, e: ParticipantsListEventArgs): void => {\r\n        try {\r\n            // check if the session token needs to be updated\r\n            if (e.sessionToken !== undefined && e.sessionToken !== null) {\r\n                this.privRoom.token = e.sessionToken;\r\n            }\r\n            // save the participants\r\n            this.privParticipants.participants = [...e.participants];\r\n            // enable the conversation\r\n            if (this.privParticipants.me !== undefined) {\r\n                this.privIsReady = true;\r\n            }\r\n            if (!!this.privConversationTranslator) {\r\n                this.privConversationTranslator.participantsChanged(\r\n                    this.privConversationTranslator,\r\n                    new ConversationParticipantsChangedEventArgs(ParticipantChangedReason.JoinedConversation, this.toParticipants(true), e.sessionId));\r\n            }\r\n            // if this is the host, update the nickname if needed\r\n            if (this.me.isHost) {\r\n                const nickname: string = this.privConversationTranslator?.properties.getProperty(PropertyId.ConversationTranslator_Name);\r\n                if (nickname !== undefined && nickname.length > 0 && nickname !== this.me.displayName) {\r\n                    // issue a change nickname request\r\n                    this.changeNicknameAsync(nickname);\r\n                }\r\n            }\r\n        } catch (e) {\r\n            //\r\n        }\r\n    };\r\n\r\n    private onConversationExpiration = (r: ConversationRecognizer, e: ConversationExpirationEventArgs): void => {\r\n        try {\r\n            if (!!this.privConversationTranslator) {\r\n                this.privConversationTranslator.conversationExpiration(this.privConversationTranslator, e);\r\n            }\r\n        } catch (e) {\r\n            //\r\n        }\r\n    };\r\n    /* eslint-enable @typescript-eslint/typedef */\r\n\r\n    private addParticipantImplAsync(participant: IParticipant): Promise<void> {\r\n        const newParticipant: IInternalParticipant = this.privParticipants.addOrUpdateParticipant(participant);\r\n        if (newParticipant !== undefined) {\r\n            if (!!this.privTranscriberRecognizer) {\r\n                const conversationInfo = this.conversationInfo;\r\n                conversationInfo.participants = [participant];\r\n                return this.privTranscriberRecognizer.pushConversationEvent(conversationInfo, \"join\");\r\n            }\r\n        }\r\n    }\r\n\r\n    private removeParticipantImplAsync(participant: IParticipant): Promise<void> {\r\n        this.privParticipants.deleteParticipant(participant.id);\r\n        const conversationInfo = this.conversationInfo;\r\n        conversationInfo.participants = [participant];\r\n        return this.privTranscriberRecognizer.pushConversationEvent(conversationInfo, \"leave\");\r\n    }\r\n\r\n    private async close(dispose: boolean): Promise<void> {\r\n        try {\r\n            this.privIsConnected = false;\r\n            await this.privConversationRecognizer?.close();\r\n            this.privConversationRecognizer = undefined;\r\n            if (!!this.privConversationTranslator) {\r\n                this.privConversationTranslator.dispose();\r\n            }\r\n        } catch (e) {\r\n            // ignore error\r\n            throw e;\r\n        }\r\n        if (dispose) {\r\n            this.dispose();\r\n        }\r\n    }\r\n\r\n    /** Helpers */\r\n    private handleCallback(cb: () => void, err: (message: string) => void): void {\r\n        if (!!cb) {\r\n            try {\r\n                cb();\r\n            } catch (e) {\r\n                if (!!err) {\r\n                    err(e as string);\r\n                }\r\n            }\r\n            cb = undefined;\r\n        }\r\n    }\r\n\r\n    private handleError(error: any, err: (message: string) => void): void {\r\n        if (!!err) {\r\n            if (error instanceof Error) {\r\n                const typedError: Error = error;\r\n                err(typedError.name + \": \" + typedError.message);\r\n\r\n            } else {\r\n                err(error as string);\r\n            }\r\n        }\r\n    }\r\n\r\n    /** Participant Helpers */\r\n    private toParticipants(includeHost: boolean): Participant[] {\r\n\r\n        const participants: Participant[] = this.privParticipants.participants.map((p: IInternalParticipant): Participant => ( this.toParticipant(p) ) );\r\n        if (!includeHost) {\r\n            return participants.filter((p: Participant): boolean => p.isHost === false);\r\n        } else {\r\n            return participants;\r\n        }\r\n    }\r\n\r\n    private toParticipant(p: IInternalParticipant): Participant {\r\n        return new Participant(p.id, p.avatar, p.displayName, p.isHost, p.isMuted, p.isUsingTts, p.preferredLanguage, p.voice);\r\n    }\r\n\r\n    private getMuteAllCommand(isMuted: boolean): string {\r\n        Contracts.throwIfNullOrWhitespace(this.privRoom.roomId, \"conversationId\");\r\n        Contracts.throwIfNullOrWhitespace(this.privRoom.participantId, \"participantId\");\r\n\r\n        return JSON.stringify({\r\n            command: ConversationTranslatorCommandTypes.setMuteAll,\r\n            participantId: this.privRoom.participantId, // the id of the host\r\n            roomid: this.privRoom.roomId,\r\n            type: ConversationTranslatorMessageTypes.participantCommand,\r\n            value: isMuted\r\n        });\r\n    }\r\n\r\n    private getMuteCommand(participantId: string, isMuted: boolean): string {\r\n        Contracts.throwIfNullOrWhitespace(this.privRoom.roomId, \"conversationId\");\r\n        Contracts.throwIfNullOrWhitespace(participantId, \"participantId\");\r\n\r\n        return JSON.stringify({\r\n            command: ConversationTranslatorCommandTypes.setMute,\r\n            // eslint-disable-next-line object-shorthand\r\n            participantId: participantId,\r\n            roomid: this.privRoom.roomId,\r\n            type: ConversationTranslatorMessageTypes.participantCommand,\r\n            value: isMuted\r\n        });\r\n    }\r\n\r\n    private getLockCommand(isLocked: boolean): string {\r\n        Contracts.throwIfNullOrWhitespace(this.privRoom.roomId, \"conversationId\");\r\n        Contracts.throwIfNullOrWhitespace(this.privRoom.participantId, \"participantId\");\r\n\r\n        return JSON.stringify({\r\n            command: ConversationTranslatorCommandTypes.setLockState,\r\n            participantId: this.privRoom.participantId,\r\n            roomid: this.privRoom.roomId,\r\n            type: ConversationTranslatorMessageTypes.participantCommand,\r\n            value: isLocked\r\n        });\r\n    }\r\n\r\n    private getEjectCommand(participantId: string): string {\r\n        Contracts.throwIfNullOrWhitespace(this.privRoom.roomId, \"conversationId\");\r\n        Contracts.throwIfNullOrWhitespace(participantId, \"participantId\");\r\n\r\n        return JSON.stringify({\r\n            command: ConversationTranslatorCommandTypes.ejectParticipant,\r\n            // eslint-disable-next-line object-shorthand\r\n            participantId: participantId,\r\n            roomid: this.privRoom.roomId,\r\n            type: ConversationTranslatorMessageTypes.participantCommand,\r\n        });\r\n    }\r\n\r\n    private getSetTranslateToLanguagesCommand(languages: string[]): string {\r\n        Contracts.throwIfNullOrWhitespace(this.privRoom.roomId, \"conversationId\");\r\n        Contracts.throwIfNullOrWhitespace(this.privRoom.participantId, \"participantId\");\r\n\r\n        return JSON.stringify({\r\n            command: ConversationTranslatorCommandTypes.setTranslateToLanguages,\r\n            participantId: this.privRoom.participantId, // the id of the host\r\n            roomid: this.privRoom.roomId,\r\n            type: ConversationTranslatorMessageTypes.participantCommand,\r\n            value: languages\r\n        });\r\n    }\r\n\r\n    private getChangeNicknameCommand(nickname: string): string {\r\n        Contracts.throwIfNullOrWhitespace(this.privRoom.roomId, \"conversationId\");\r\n        Contracts.throwIfNullOrWhitespace(nickname, \"nickname\");\r\n        Contracts.throwIfNullOrWhitespace(this.privRoom.participantId, \"participantId\");\r\n\r\n        return JSON.stringify({\r\n            command: ConversationTranslatorCommandTypes.changeNickname,\r\n            nickname,\r\n            participantId: this.privRoom.participantId, // the id of the host\r\n            roomid: this.privRoom.roomId,\r\n            type: ConversationTranslatorMessageTypes.participantCommand,\r\n            value: nickname\r\n        });\r\n    }\r\n\r\n    private getMessageCommand(message: string): string {\r\n        Contracts.throwIfNullOrWhitespace(this.privRoom.roomId, \"conversationId\");\r\n        Contracts.throwIfNullOrWhitespace(this.privRoom.participantId, \"participantId\");\r\n        Contracts.throwIfNullOrWhitespace(message, \"message\");\r\n\r\n        return JSON.stringify({\r\n            participantId: this.privRoom.participantId,\r\n            roomId: this.privRoom.roomId,\r\n            text: message,\r\n            type: ConversationTranslatorMessageTypes.instantMessage\r\n        });\r\n    }\r\n\r\n}\r\n"]}