{"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.\n// Licensed under the MIT license.\n// Multi-device Conversation is a Preview feature.\n\nimport {\n    ConversationConnectionConfig,\n    ConversationManager,\n    ConversationReceivedTranslationEventArgs,\n    ConversationTranslatorCommandTypes,\n    ConversationTranslatorMessageTypes,\n    ConversationTranslatorRecognizer,\n    IInternalConversation,\n    IInternalParticipant,\n    InternalParticipants,\n    LockRoomEventArgs,\n    MuteAllEventArgs,\n    ParticipantAttributeEventArgs,\n    ParticipantEventArgs,\n    ParticipantsListEventArgs\n} from \"../../common.speech/Exports\";\nimport { IDisposable, IErrorMessages } from \"../../common/Exports\";\nimport { Contracts } from \"../Contracts\";\nimport {\n    Connection,\n    ConnectionEventArgs,\n    ConversationExpirationEventArgs,\n    ConversationParticipantsChangedEventArgs,\n    ConversationTranslationCanceledEventArgs,\n    ConversationTranslationEventArgs,\n    ConversationTranslator,\n    Participant,\n    ParticipantChangedReason,\n    ProfanityOption,\n    PropertyCollection,\n    PropertyId,\n    SpeechTranslationConfig\n} from \"../Exports\";\nimport { SpeechTranslationConfigImpl } from \"../SpeechTranslationConfig\";\nimport { Callback, IConversation } from \"./IConversation\";\nimport { IParticipant, IUser } from \"./IParticipant\";\n\nexport abstract class Conversation implements IConversation {\n\n    public abstract get authorizationToken(): string;\n    public abstract set authorizationToken(value: string);\n\n    public abstract get config(): SpeechTranslationConfig;\n\n    public abstract get conversationId(): string;\n    public abstract get properties(): PropertyCollection;\n    public abstract get speechRecognitionLanguage(): string;\n\n    protected constructor() { }\n\n    /**\n     * Create a conversation\n     * @param speechConfig\n     * @param cb\n     * @param err\n     */\n    public static createConversationAsync(speechConfig: SpeechTranslationConfig, cb?: Callback, err?: Callback): Conversation {\n        Contracts.throwIfNullOrUndefined(speechConfig, ConversationConnectionConfig.restErrors.invalidArgs.replace(\"{arg}\", \"config\"));\n        Contracts.throwIfNullOrUndefined(speechConfig.region, ConversationConnectionConfig.restErrors.invalidArgs.replace(\"{arg}\", \"SpeechServiceConnection_Region\"));\n        if (!speechConfig.subscriptionKey && !speechConfig.getProperty(PropertyId[PropertyId.SpeechServiceAuthorization_Token])) {\n            Contracts.throwIfNullOrUndefined(speechConfig.subscriptionKey, ConversationConnectionConfig.restErrors.invalidArgs.replace(\"{arg}\", \"SpeechServiceConnection_Key\"));\n        }\n        const conversationImpl: ConversationImpl = new ConversationImpl(speechConfig);\n\n        conversationImpl.createConversationAsync(\n            (() => {\n                if (!!cb) {\n                    cb();\n                }\n            }),\n            (error: any) => {\n                if (!!err) {\n                    err(error);\n                }\n            });\n\n        return conversationImpl;\n    }\n\n    /** Start a conversation. */\n    public abstract startConversationAsync(cb?: Callback, err?: Callback): void;\n\n    /** Delete a conversation. After this no one will be able to join the conversation. */\n    public abstract deleteConversationAsync(cb?: Callback, err?: Callback): void;\n\n    /** End a conversation. */\n    public abstract endConversationAsync(cb?: Callback, err?: Callback): void;\n\n    /** Lock a conversation. This will prevent new participants from joining. */\n    public abstract lockConversationAsync(cb?: Callback, err?: Callback): void;\n\n    /**\n     * Mute all other participants in the conversation. After this no other participants will\n     * have their speech recognitions broadcast, nor be able to send text messages.\n     */\n    public abstract muteAllParticipantsAsync(cb?: Callback, err?: Callback): void;\n\n    /**\n     * Mute a participant.\n     * @param userId A user identifier\n     */\n    public abstract muteParticipantAsync(userId: string, cb?: Callback, err?: Callback): void;\n\n    /**\n     * Remove a participant from a conversation using the user id, Participant or User object\n     * @param userId A user identifier\n     */\n    public abstract removeParticipantAsync(userId: string | IParticipant | IUser, cb?: Callback, err?: Callback): void;\n\n    /** Unlocks a conversation. */\n    public abstract unlockConversationAsync(cb?: Callback, err?: Callback): void;\n\n    /** Unmute all other participants in the conversation. */\n    public abstract unmuteAllParticipantsAsync(cb?: Callback, err?: Callback): void;\n\n    /**\n     * Unmute a participant.\n     * @param userId A user identifier\n     */\n    public abstract unmuteParticipantAsync(userId: string, cb?: Callback, err?: Callback): void;\n}\n\n// tslint:disable-next-line:max-classes-per-file\nexport class ConversationImpl extends Conversation implements IDisposable {\n\n    private privConfig: SpeechTranslationConfig;\n    private privProperties: PropertyCollection;\n    private privLanguage: string;\n    private privToken: string;\n    private privIsDisposed: boolean = false;\n    private privRoom: IInternalConversation;\n    private privManager: ConversationManager;\n    private privConversationRecognizer: ConversationTranslatorRecognizer;\n    private privConversationRecognizerConnection: Connection;\n    private privIsConnected: boolean = false;\n    private privParticipants: InternalParticipants;\n    private privIsReady: boolean;\n    private privConversationTranslator: ConversationTranslator;\n    private privErrors: IErrorMessages = ConversationConnectionConfig.restErrors;\n    private readonly privTextMessageMaxLength: number;\n\n    public set conversationTranslator(value: ConversationTranslator) {\n        this.privConversationTranslator = value;\n    }\n\n    // get the internal data about a conversation\n    public get room(): IInternalConversation {\n        return this.privRoom;\n    }\n\n    // get the wrapper for connecting to the websockets\n    public get connection(): ConversationTranslatorRecognizer {\n        return this.privConversationRecognizer; // this.privConnection;\n    }\n\n    // get / set the speech auth token\n    public get authorizationToken(): string {\n        return this.privToken;\n    }\n    public set authorizationToken(value: string) {\n        Contracts.throwIfNullOrWhitespace(value, \"authorizationToken\");\n        this.privToken = value;\n    }\n\n    // get the config\n    public get config(): SpeechTranslationConfig {\n        return this.privConfig;\n    }\n    // get the conversation Id\n    public get conversationId(): string {\n        return this.privRoom ? this.privRoom.roomId : \"\";\n    }\n\n    // get the properties\n    public get properties(): PropertyCollection {\n        return this.privProperties;\n    }\n\n    // get the speech language\n    public get speechRecognitionLanguage(): string {\n        return this.privLanguage;\n    }\n\n    public get isMutedByHost(): boolean {\n        return this.privParticipants.me?.isHost ? false : this.privParticipants.me?.isMuted;\n    }\n\n    public get isConnected(): boolean {\n        return this.privIsConnected && this.privIsReady;\n    }\n\n    public get participants(): Participant[] {\n        return this.toParticipants(true);\n    }\n\n    public get me(): Participant {\n        return this.toParticipant(this.privParticipants.me);\n    }\n\n    public get host(): Participant {\n        return this.toParticipant(this.privParticipants.host);\n    }\n\n    /**\n     * Create a conversation impl\n     * @param speechConfig\n     */\n    public constructor(speechConfig: SpeechTranslationConfig) {\n        super();\n        this.privProperties = new PropertyCollection();\n        this.privManager = new ConversationManager();\n\n        // check the speech language\n        const language: string = speechConfig.getProperty(PropertyId[PropertyId.SpeechServiceConnection_RecoLanguage]);\n        if (!language) {\n            speechConfig.setProperty(PropertyId[PropertyId.SpeechServiceConnection_RecoLanguage], ConversationConnectionConfig.defaultLanguageCode);\n        }\n        this.privLanguage = speechConfig.getProperty(PropertyId[PropertyId.SpeechServiceConnection_RecoLanguage]);\n\n        // check the target language(s)\n        if (speechConfig.targetLanguages.length === 0) {\n            speechConfig.addTargetLanguage(this.privLanguage);\n        }\n\n        // check the profanity setting: speech and conversationTranslator should be in sync\n        const profanity: string = speechConfig.getProperty(PropertyId[PropertyId.SpeechServiceResponse_ProfanityOption]);\n        if (!profanity) {\n            speechConfig.setProfanity(ProfanityOption.Masked);\n        }\n\n        // check the nickname: it should pass this regex: ^\\w+([\\s-][\\w\\(\\)]+)*$\"\n        // TODO: specify the regex required. Nicknames must be unique or get the duplicate nickname error\n        // TODO: check what the max length is and if a truncation is required or if the service handles it without an error\n        let hostNickname: string = speechConfig.getProperty(PropertyId[PropertyId.ConversationTranslator_Name]);\n        if (hostNickname === undefined || hostNickname === null || hostNickname.length <= 1 || hostNickname.length > 50) {\n            hostNickname = \"Host\";\n        }\n        speechConfig.setProperty(PropertyId[PropertyId.ConversationTranslator_Name], hostNickname);\n\n        // save the speech config for future usage\n        this.privConfig = speechConfig;\n\n        // save the config properties\n        const configImpl = speechConfig as SpeechTranslationConfigImpl;\n        Contracts.throwIfNull(configImpl, \"speechConfig\");\n        this.privProperties = configImpl.properties.clone();\n        this.privIsConnected = false;\n        this.privParticipants = new InternalParticipants();\n        this.privIsReady = false;\n        this.privTextMessageMaxLength = 1000;\n    }\n\n    /**\n     * Create a new conversation as Host\n     * @param cb\n     * @param err\n     */\n    public createConversationAsync(cb?: Callback, err?: Callback): void {\n        try {\n            if (!!this.privConversationRecognizer) {\n                this.handleError(new Error(this.privErrors.permissionDeniedStart), err);\n            }\n            this.privManager.createOrJoin(this.privProperties, undefined,\n                ((room: IInternalConversation) => {\n                    if (!room) {\n                        this.handleError(new Error(this.privErrors.permissionDeniedConnect), err);\n                    }\n                    this.privRoom = room;\n                    this.handleCallback(cb, err);\n                }),\n                ((error: any) => {\n                    this.handleError(error, err);\n                }));\n        } catch (error) {\n            this.handleError(error, err);\n        }\n    }\n\n    /**\n     * Starts a new conversation as host.\n     * @param cb\n     * @param err\n     */\n    public startConversationAsync(cb?: Callback, err?: Callback): void {\n        try {\n            // check if there is already a recognizer\n            if (!!this.privConversationRecognizer) {\n                this.handleError(new Error(this.privErrors.permissionDeniedStart), err);\n            }\n            // check if there is conversation data available\n            Contracts.throwIfNullOrUndefined(this.privRoom, this.privErrors.permissionDeniedConnect);\n            // connect to the conversation websocket\n            this.privParticipants.meId = this.privRoom.participantId;\n            this.privConversationRecognizer = new ConversationTranslatorRecognizer(this.privConfig);\n            this.privConversationRecognizer.conversation = this.privRoom;\n            this.privConversationRecognizerConnection = Connection.fromRecognizer(this.privConversationRecognizer);\n            this.privConversationRecognizerConnection.connected = this.onConnected;\n            this.privConversationRecognizerConnection.disconnected = this.onDisconnected;\n            this.privConversationRecognizer.canceled = this.onCanceled;\n            this.privConversationRecognizer.participantUpdateCommandReceived = this.onParticipantUpdateCommandReceived;\n            this.privConversationRecognizer.lockRoomCommandReceived = this.onLockRoomCommandReceived;\n            this.privConversationRecognizer.muteAllCommandReceived = this.onMuteAllCommandReceived;\n            this.privConversationRecognizer.participantJoinCommandReceived = this.onParticipantJoinCommandReceived;\n            this.privConversationRecognizer.participantLeaveCommandReceived = this.onParticipantLeaveCommandReceived;\n            this.privConversationRecognizer.translationReceived = this.onTranslationReceived;\n            this.privConversationRecognizer.participantsListReceived = this.onParticipantsListReceived;\n            this.privConversationRecognizer.conversationExpiration = this.onConversationExpiration;\n            this.privConversationRecognizer.connect(this.privRoom.token,\n                (() => {\n                    this.handleCallback(cb, err);\n                }),\n                ((error: any) => {\n                    this.handleError(error, err);\n                }));\n        } catch (error) {\n            this.handleError(error, err);\n        }\n    }\n\n    /**\n     * Join a conversation as a participant.\n     * @param conversation\n     * @param nickname\n     * @param lang\n     * @param cb\n     * @param err\n     */\n    public joinConversationAsync(conversationId: string, nickname: string, lang: string, cb?: Callback, err?: Callback): void {\n        try {\n            // TODO\n            // if (!!this.privConversationRecognizer) {\n            //     throw new Error(this.privErrors.permissionDeniedStart);\n            // }\n            Contracts.throwIfNullOrWhitespace(conversationId, this.privErrors.invalidArgs.replace(\"{arg}\", \"conversationId\"));\n            Contracts.throwIfNullOrWhitespace(nickname, this.privErrors.invalidArgs.replace(\"{arg}\", \"nickname\"));\n            Contracts.throwIfNullOrWhitespace(lang, this.privErrors.invalidArgs.replace(\"{arg}\", \"language\"));\n            // join the conversation\n            this.privManager.createOrJoin(this.privProperties, conversationId,\n                ((room: IInternalConversation) => {\n                    Contracts.throwIfNullOrUndefined(room, this.privErrors.permissionDeniedConnect);\n                    this.privRoom = room;\n                    this.privConfig.authorizationToken = room.cognitiveSpeechAuthToken;\n                    // join callback\n                    if (!!cb) {\n                        cb(room.cognitiveSpeechAuthToken);\n                    }\n                }),\n                ((error: any) => {\n                    this.handleError(error, err);\n                }));\n        } catch (error) {\n            this.handleError(error, err);\n        }\n    }\n\n    /**\n     * Deletes a conversation\n     * @param cb\n     * @param err\n     */\n    public deleteConversationAsync(cb?: Callback, err?: Callback): void {\n        try {\n            Contracts.throwIfNullOrUndefined(this.privProperties, this.privErrors.permissionDeniedConnect);\n            Contracts.throwIfNullOrWhitespace(this.privRoom.token, this.privErrors.permissionDeniedConnect);\n            this.privManager.leave(this.privProperties, this.privRoom.token,\n                (() => {\n                    this.handleCallback(cb, err);\n                }),\n                ((error: any) => {\n                    this.handleError(error, err);\n                }));\n            this.dispose();\n        } catch (error) {\n            this.handleError(error, err);\n        }\n    }\n\n    /**\n     * Issues a request to close the client websockets\n     * @param cb\n     * @param err\n     */\n    public endConversationAsync(cb?: Callback, err?: Callback): void {\n        try {\n            this.close(true);\n            this.handleCallback(cb, err);\n        } catch (error) {\n            this.handleError(error, err);\n        }\n    }\n\n    /**\n     * Issues a request to lock the conversation\n     * @param cb\n     * @param err\n     */\n    public lockConversationAsync(cb?: Callback, err?: Callback): void {\n        try {\n            Contracts.throwIfDisposed(this.privIsDisposed);\n            Contracts.throwIfDisposed(this.privConversationRecognizer.isDisposed());\n            Contracts.throwIfNullOrUndefined(this.privRoom, this.privErrors.permissionDeniedSend);\n            if (!this.canSendAsHost) {\n                this.handleError(new Error(this.privErrors.permissionDeniedConversation.replace(\"{command}\", \"lock\")), err);\n            }\n            this.privConversationRecognizer?.sendLockRequest(true,\n                (() => {\n                    this.handleCallback(cb, err);\n                }),\n                ((error: any) => {\n                    this.handleError(error, err);\n                }));\n        } catch (error) {\n            this.handleError(error, err);\n        }\n    }\n\n    /**\n     * Issues a request to mute the conversation\n     * @param cb\n     * @param err\n     */\n    public muteAllParticipantsAsync(cb?: Callback, err?: Callback): void {\n\n        try {\n            Contracts.throwIfDisposed(this.privIsDisposed);\n            Contracts.throwIfDisposed(this.privConversationRecognizer.isDisposed());\n            Contracts.throwIfNullOrUndefined(this.privConversationRecognizer, this.privErrors.permissionDeniedSend);\n            Contracts.throwIfNullOrUndefined(this.privRoom, this.privErrors.permissionDeniedSend);\n            // check the user's permissions\n            if (!this.canSendAsHost) {\n                this.handleError(new Error(this.privErrors.permissionDeniedConversation.replace(\"{command}\", \"mute\")), err);\n            }\n            this.privConversationRecognizer?.sendMuteAllRequest(true,\n                (() => {\n                    this.handleCallback(cb, err);\n                }),\n                ((error: any) => {\n                    this.handleError(error, err);\n                }));\n        } catch (error) {\n            this.handleError(error, err);\n        }\n    }\n\n    /**\n     * Issues a request to mute a participant in the conversation\n     * @param userId\n     * @param cb\n     * @param err\n     */\n    public muteParticipantAsync(userId: string, cb?: Callback, err?: Callback): void {\n        try {\n            Contracts.throwIfDisposed(this.privIsDisposed);\n            Contracts.throwIfDisposed(this.privConversationRecognizer.isDisposed());\n            Contracts.throwIfNullOrWhitespace(userId, this.privErrors.invalidArgs.replace(\"{arg}\", \"userId\"));\n            Contracts.throwIfNullOrUndefined(this.privRoom, this.privErrors.permissionDeniedSend);\n            // check the connection is open (host + participant can perform the mute command)\n            if (!this.canSend) {\n                this.handleError(new Error(this.privErrors.permissionDeniedSend), err);\n            }\n            // if not host, check the participant is not muting another participant\n            if (!this.me.isHost && this.me.id !== userId) {\n                this.handleError(new Error(this.privErrors.permissionDeniedParticipant.replace(\"{command}\", \"mute\")), err);\n            }\n            // check the user exists\n            const exists: number = this.privParticipants.getParticipantIndex(userId);\n            if (exists === -1) {\n                this.handleError(new Error(this.privErrors.invalidParticipantRequest), err);\n            }\n            this.privConversationRecognizer?.sendMuteRequest(userId, true, (() => {\n                this.handleCallback(cb, err);\n            }),\n                ((error: any) => {\n                    this.handleError(error, err);\n                }));\n        } catch (error) {\n            this.handleError(error, err);\n        }\n    }\n\n    /**\n     * Issues a request to remove a participant from the conversation\n     * @param userId\n     * @param cb\n     * @param err\n     */\n    public removeParticipantAsync(userId: string | IParticipant | IUser, cb?: Callback, err?: Callback): void {\n        try {\n            Contracts.throwIfDisposed(this.privIsDisposed);\n            Contracts.throwIfDisposed(this.privConversationRecognizer.isDisposed());\n            Contracts.throwIfNullOrUndefined(this.privRoom, this.privErrors.permissionDeniedSend);\n            if (!this.canSendAsHost) {\n                this.handleError(new Error(this.privErrors.permissionDeniedParticipant.replace(\"{command}\", \"remove\")), err);\n            }\n            let participantId: string = \"\";\n            if (typeof userId === \"string\") {\n                participantId = userId as string;\n            } else if (userId.hasOwnProperty(\"id\")) {\n                const participant: IParticipant = userId as IParticipant;\n                participantId = participant.id;\n            } else if (userId.hasOwnProperty(\"userId\")) {\n                const user: IUser = userId as IUser;\n                participantId = user.userId;\n            }\n            Contracts.throwIfNullOrWhitespace(participantId, this.privErrors.invalidArgs.replace(\"{arg}\", \"userId\"));\n            // check the participant exists\n            const index: number = this.participants.findIndex((p: Participant) => p.id === participantId);\n            if (index === -1) {\n                this.handleError(new Error(this.privErrors.invalidParticipantRequest), err);\n            }\n            this.privConversationRecognizer?.sendEjectRequest(participantId, (() => {\n                this.handleCallback(cb, err);\n            }),\n                ((error: any) => {\n                    this.handleError(error, err);\n                }));\n        } catch (error) {\n            this.handleError(error, err);\n        }\n    }\n\n    /**\n     * Issues a request to unlock the conversation\n     * @param cb\n     * @param err\n     */\n    public unlockConversationAsync(cb?: Callback, err?: Callback): void {\n        try {\n            Contracts.throwIfDisposed(this.privIsDisposed);\n            Contracts.throwIfDisposed(this.privConversationRecognizer.isDisposed());\n            Contracts.throwIfNullOrUndefined(this.privRoom, this.privErrors.permissionDeniedSend);\n            if (!this.canSendAsHost) {\n                this.handleError(new Error(this.privErrors.permissionDeniedConversation.replace(\"{command}\", \"unlock\")), err);\n            }\n            this.privConversationRecognizer?.sendLockRequest(false, (() => {\n                this.handleCallback(cb, err);\n            }),\n                ((error: any) => {\n                    this.handleError(error, err);\n                }));\n        } catch (error) {\n            this.handleError(error, err);\n        }\n    }\n\n    /**\n     * Issues a request to unmute all participants in the conversation\n     * @param cb\n     * @param err\n     */\n    public unmuteAllParticipantsAsync(cb?: Callback, err?: Callback): void {\n        try {\n            Contracts.throwIfDisposed(this.privIsDisposed);\n            Contracts.throwIfDisposed(this.privConversationRecognizer.isDisposed());\n            Contracts.throwIfNullOrUndefined(this.privRoom, this.privErrors.permissionDeniedSend);\n            if (!this.canSendAsHost) {\n                this.handleError(new Error(this.privErrors.permissionDeniedConversation.replace(\"{command}\", \"unmute all\")), err);\n            }\n            this.privConversationRecognizer?.sendMuteAllRequest(false, (() => {\n                this.handleCallback(cb, err);\n            }),\n                ((error: any) => {\n                    this.handleError(error, err);\n                }));\n        } catch (error) {\n            this.handleError(error, err);\n        }\n    }\n\n    /**\n     * Issues a request to unmute a participant in the conversation\n     * @param userId\n     * @param cb\n     * @param err\n     */\n    public unmuteParticipantAsync(userId: string, cb?: Callback, err?: Callback): void {\n        try {\n            Contracts.throwIfDisposed(this.privIsDisposed);\n            Contracts.throwIfDisposed(this.privConversationRecognizer.isDisposed());\n            Contracts.throwIfNullOrWhitespace(userId, this.privErrors.invalidArgs.replace(\"{arg}\", \"userId\"));\n            Contracts.throwIfNullOrUndefined(this.privRoom, this.privErrors.permissionDeniedSend);\n            // check the connection is open (host + participant can perform the mute command)\n            if (!this.canSend) {\n                this.handleError(new Error(this.privErrors.permissionDeniedSend), err);\n            }\n            // if not host, check the participant is not muting another participant\n            if (!this.me.isHost && this.me.id !== userId) {\n                this.handleError(new Error(this.privErrors.permissionDeniedParticipant.replace(\"{command}\", \"mute\")), err);\n            }\n            // check the user exists\n            const exists: number = this.privParticipants.getParticipantIndex(userId);\n            if (exists === -1) {\n                this.handleError(new Error(this.privErrors.invalidParticipantRequest), err);\n            }\n            this.privConversationRecognizer?.sendMuteRequest(userId, false, (() => {\n                this.handleCallback(cb, err);\n            }),\n                ((error: any) => {\n                    this.handleError(error, err);\n                }));\n        } catch (error) {\n            this.handleError(error, err);\n        }\n    }\n\n    /**\n     * Send a text message\n     * @param message\n     * @param cb\n     * @param err\n     */\n    public sendTextMessageAsync(message: string, cb?: Callback, err?: Callback): void {\n        try {\n            Contracts.throwIfDisposed(this.privIsDisposed);\n            Contracts.throwIfDisposed(this.privConversationRecognizer.isDisposed());\n            Contracts.throwIfNullOrWhitespace(message, this.privErrors.invalidArgs.replace(\"{arg}\", \"message\"));\n            Contracts.throwIfNullOrUndefined(this.privRoom, this.privErrors.permissionDeniedSend);\n            if (!this.canSend) {\n                this.handleError(new Error(this.privErrors.permissionDeniedSend), err);\n            }\n            // TODO: is a max length check required?\n            if (message.length > this.privTextMessageMaxLength) {\n                this.handleError(new Error(this.privErrors.invalidArgs.replace(\"{arg}\", \"message length\")), err);\n            }\n            this.privConversationRecognizer?.sendMessageRequest(message, (() => {\n                this.handleCallback(cb, err);\n            }),\n                ((error: any) => {\n                    this.handleError(error, err);\n                }));\n        } catch (error) {\n            this.handleError(error, err);\n        }\n    }\n\n    /**\n     * Change nickname\n     * @param message\n     * @param cb\n     * @param err\n     */\n    public changeNicknameAsync(nickname: string, cb?: Callback, err?: Callback): void {\n        try {\n            Contracts.throwIfDisposed(this.privIsDisposed);\n            Contracts.throwIfDisposed(this.privConversationRecognizer.isDisposed());\n            Contracts.throwIfNullOrWhitespace(nickname, this.privErrors.invalidArgs.replace(\"{arg}\", \"nickname\"));\n            Contracts.throwIfNullOrUndefined(this.privRoom, this.privErrors.permissionDeniedSend);\n            if (!this.canSend) {\n                this.handleError(new Error(this.privErrors.permissionDeniedSend), err);\n            }\n            this.privConversationRecognizer?.sendChangeNicknameRequest(nickname, (() => {\n                this.handleCallback(cb, err);\n            }),\n                ((error: any) => {\n                    this.handleError(error, err);\n                }));\n        } catch (error) {\n            this.handleError(error, err);\n        }\n    }\n\n    public isDisposed(): boolean {\n        return this.privIsDisposed;\n    }\n\n    public dispose(reason?: string): void {\n        if (this.isDisposed) {\n            return;\n        }\n        this.privIsDisposed = true;\n        this.config?.close();\n        if (this.privConversationRecognizerConnection) {\n            this.privConversationRecognizerConnection.closeConnection();\n            this.privConversationRecognizerConnection.close();\n            this.privConversationRecognizerConnection = undefined;\n        }\n        this.privConfig = undefined;\n        this.privLanguage = undefined;\n        this.privProperties = undefined;\n        this.privRoom = undefined;\n        this.privToken = undefined;\n        this.privManager = undefined;\n        this.privConversationRecognizer = undefined;\n        this.privIsConnected = false;\n        this.privIsReady = false;\n        this.privParticipants = undefined;\n        this.privRoom = undefined;\n    }\n\n    /** websocket callbacks */\n    private onConnected = (e: ConnectionEventArgs): void => {\n        this.privIsConnected = true;\n        try {\n            if (!!this.privConversationTranslator.sessionStarted) {\n                this.privConversationTranslator.sessionStarted(this.privConversationTranslator, e);\n            }\n        } catch (e) {\n            //\n        }\n    }\n\n    private onDisconnected = (e: ConnectionEventArgs): void => {\n        this.close(false);\n        try {\n            if (!!this.privConversationTranslator.sessionStopped) {\n                this.privConversationTranslator.sessionStopped(this.privConversationTranslator, e);\n            }\n        } catch (e) {\n            //\n        }\n    }\n\n    private onCanceled = (r: ConversationTranslatorRecognizer, e: ConversationTranslationCanceledEventArgs): void => {\n        this.close(false); // ?\n        try {\n            if (!!this.privConversationTranslator.canceled) {\n                this.privConversationTranslator.canceled(this.privConversationTranslator, e);\n            }\n        } catch (e) {\n            //\n        }\n    }\n\n    private onParticipantUpdateCommandReceived = (r: ConversationTranslatorRecognizer, e: ParticipantAttributeEventArgs): void => {\n        try {\n            const updatedParticipant: any = this.privParticipants.getParticipant(e.id);\n            if (updatedParticipant !== undefined) {\n\n                switch (e.key) {\n                    case ConversationTranslatorCommandTypes.changeNickname:\n                        updatedParticipant.displayName = e.value;\n                        break;\n                    case ConversationTranslatorCommandTypes.setUseTTS:\n                        updatedParticipant.useTts = e.value;\n                        break;\n                    case ConversationTranslatorCommandTypes.setProfanityFiltering:\n                        updatedParticipant.profanity = e.value;\n                        break;\n                    case ConversationTranslatorCommandTypes.setMute:\n                        updatedParticipant.isMuted = e.value;\n                        break;\n                    case ConversationTranslatorCommandTypes.setTranslateToLanguages:\n                        updatedParticipant.translateToLanguages = e.value;\n                        break;\n                }\n                this.privParticipants.addOrUpdateParticipant(updatedParticipant);\n\n                if (!!this.privConversationTranslator?.participantsChanged) {\n                    this.privConversationTranslator?.participantsChanged(\n                        this.privConversationTranslator,\n                        new ConversationParticipantsChangedEventArgs(ParticipantChangedReason.Updated,\n                            [this.toParticipant(updatedParticipant)], e.sessionId));\n                }\n            }\n        } catch (e) {\n            //\n        }\n    }\n\n    private onLockRoomCommandReceived = (r: ConversationTranslatorRecognizer, e: LockRoomEventArgs): void => {\n        // TODO\n    }\n\n    private onMuteAllCommandReceived = (r: ConversationTranslatorRecognizer, e: MuteAllEventArgs): void => {\n        try {\n            this.privParticipants.participants.forEach((p: IInternalParticipant) => p.isMuted = (p.isHost ? false : e.isMuted));\n            if (!!this.privConversationTranslator?.participantsChanged) {\n                this.privConversationTranslator?.participantsChanged(\n                    this.privConversationTranslator,\n                    new ConversationParticipantsChangedEventArgs(ParticipantChangedReason.Updated,\n                        this.toParticipants(false), e.sessionId));\n            }\n        } catch (e) {\n            //\n        }\n    }\n\n    private onParticipantJoinCommandReceived = (r: ConversationTranslatorRecognizer, e: ParticipantEventArgs): void => {\n        try {\n            const newParticipant: IInternalParticipant = this.privParticipants.addOrUpdateParticipant(e.participant);\n            if (newParticipant !== undefined) {\n                if (!!this.privConversationTranslator?.participantsChanged) {\n                    this.privConversationTranslator?.participantsChanged(\n                        this.privConversationTranslator,\n                        new ConversationParticipantsChangedEventArgs(ParticipantChangedReason.JoinedConversation,\n                            [this.toParticipant(newParticipant)], e.sessionId));\n                }\n            }\n        } catch (e) {\n            //\n        }\n    }\n\n    private onParticipantLeaveCommandReceived = (r: ConversationTranslatorRecognizer, e: ParticipantEventArgs): void => {\n        try {\n            const ejectedParticipant: IInternalParticipant = this.privParticipants.getParticipant(e.participant.id);\n            if (ejectedParticipant !== undefined) {\n                // remove the participant from the internal participants list\n                this.privParticipants.deleteParticipant(e.participant.id);\n                if (!!this.privConversationTranslator?.participantsChanged) {\n                    // notify subscribers that the participant has left the conversation\n                    this.privConversationTranslator?.participantsChanged(\n                        this.privConversationTranslator,\n                        new ConversationParticipantsChangedEventArgs(ParticipantChangedReason.LeftConversation,\n                            [this.toParticipant(ejectedParticipant)], e.sessionId));\n                }\n            }\n        } catch (e) {\n            //\n        }\n    }\n\n    private onTranslationReceived = (r: ConversationTranslatorRecognizer, e: ConversationReceivedTranslationEventArgs): void => {\n        try {\n            switch (e.command) {\n                case ConversationTranslatorMessageTypes.final:\n                    if (!!this.privConversationTranslator?.transcribed) {\n                        this.privConversationTranslator?.transcribed(\n                            this.privConversationTranslator,\n                            new ConversationTranslationEventArgs(e.payload, undefined, e.sessionId));\n                    }\n                    break;\n                case ConversationTranslatorMessageTypes.partial:\n                    if (!!this.privConversationTranslator?.transcribing) {\n                        this.privConversationTranslator?.transcribing(\n                            this.privConversationTranslator,\n                            new ConversationTranslationEventArgs(e.payload, undefined, e.sessionId));\n                    }\n                    break;\n                case ConversationTranslatorMessageTypes.instantMessage:\n                    if (!!this.privConversationTranslator?.textMessageReceived) {\n                        this.privConversationTranslator?.textMessageReceived(\n                            this.privConversationTranslator,\n                            new ConversationTranslationEventArgs(e.payload, undefined, e.sessionId));\n                    }\n                    break;\n            }\n        } catch (e) {\n            //\n        }\n    }\n\n    private onParticipantsListReceived = (r: ConversationTranslatorRecognizer, e: ParticipantsListEventArgs): void => {\n        try {\n            // check if the session token needs to be updated\n            if (e.sessionToken !== undefined && e.sessionToken !== null) {\n                this.privRoom.token = e.sessionToken;\n            }\n            // save the participants\n            this.privParticipants.participants = [...e.participants];\n            // enable the conversation\n            if (this.privParticipants.me !== undefined) {\n                this.privIsReady = true;\n            }\n            if (!!this.privConversationTranslator?.participantsChanged) {\n                this.privConversationTranslator?.participantsChanged(\n                    this.privConversationTranslator,\n                    new ConversationParticipantsChangedEventArgs(ParticipantChangedReason.JoinedConversation, this.toParticipants(true), e.sessionId));\n            }\n            // if this is the host, update the nickname if needed\n            if (this.me.isHost) {\n                const nickname: string = this.privConversationTranslator.properties.getProperty(PropertyId.ConversationTranslator_Name);\n                if (nickname !== undefined && nickname.length > 0 && nickname !== this.me.displayName) {\n                    // issue a change nickname request\n                    this.changeNicknameAsync(nickname);\n                }\n            }\n        } catch (e) {\n            //\n        }\n    }\n\n    private onConversationExpiration = (r: ConversationTranslatorRecognizer, e: ConversationExpirationEventArgs): void => {\n        try {\n            if (!!this.privConversationTranslator?.conversationExpiration) {\n                this.privConversationTranslator?.conversationExpiration(\n                    this.privConversationTranslator,\n                    e);\n            }\n        } catch (e) {\n            //\n        }\n    }\n\n    private close(dispose: boolean): void {\n        try {\n            this.privIsConnected = false;\n            this.privConversationRecognizerConnection?.closeConnection();\n            this.privConversationRecognizerConnection?.close();\n            this.privConversationRecognizer.close();\n            this.privConversationRecognizerConnection = undefined;\n            this.privConversationRecognizer = undefined;\n            this.privConversationTranslator?.dispose();\n        } catch (e) {\n            // ignore error\n        }\n        if (dispose) {\n            this.dispose();\n        }\n    }\n\n    /** Helpers */\n    private get canSend(): boolean {\n        return this.privIsConnected && !this.privParticipants.me?.isMuted;\n    }\n\n    private get canSendAsHost(): boolean {\n        return this.privIsConnected && this.privParticipants.me?.isHost;\n    }\n\n    private handleCallback(cb: any, err: any): void {\n        if (!!cb) {\n            try {\n                cb();\n            } catch (e) {\n                if (!!err) {\n                    err(e);\n                }\n            }\n            cb = undefined;\n        }\n    }\n\n    private handleError(error: any, err: any): void {\n        if (!!err) {\n            if (error instanceof Error) {\n                const typedError: Error = error as Error;\n                err(typedError.name + \": \" + typedError.message);\n\n            } else {\n                err(error);\n            }\n        }\n    }\n\n    /** Participant Helpers */\n    private toParticipants(includeHost: boolean): Participant[] {\n\n        const participants: Participant[] = this.privParticipants.participants.map((p: IInternalParticipant) => {\n            return this.toParticipant(p);\n        });\n        if (!includeHost) {\n            return participants.filter((p: Participant) => p.isHost === false);\n        } else {\n            return participants;\n        }\n    }\n\n    private toParticipant(p: IInternalParticipant): Participant {\n        return new Participant(p.id, p.avatar, p.displayName, p.isHost, p.isMuted, p.isUsingTts, p.preferredLanguage);\n    }\n\n}\n"]}