{"version":3,"file":"index.cjs","sources":["../src/types/addressbook.ts","../src/types/calls.ts","../src/types/chat.ts","../src/types/config.ts","../src/types/janus.ts","../src/types/media.ts","../src/types/proxy.ts","../src/platform.ts","../src/config.ts","../src/Utils.ts","../src/Proxy.ts","../src/AddressBook.ts","../src/Auth.ts","../src/messaging/xmpp/xmpp.utils.ts","../src/messaging/xmpp/ChatUtils.ts","../src/messaging/xmpp/Helpers.ts","../src/messaging/xmpp/StreamManagement.ts","../src/messaging/xmpp/PrivacyList.ts","../src/messaging/xmpp/MultiUserChat.ts","../src/messaging/xmpp/Dialogs.ts","../src/messaging/xmpp/Messages.ts","../src/videocalling/WebRTCSignalingProcessor.ts","../src/messaging/AbstractChatService.ts","../src/messaging/xmpp/index.ts","../src/messaging/xmpp/xmpp.ts","../../../node_modules/@sama-communications/sdk/dist/@sama-communications.sdk.mjs","../src/messaging/sama/BlockList.ts","../src/messaging/sama/index.ts","../src/videocalling_conference/janus.js","../src/videocalling_conference/JanusClient.ts","../src/videocalling_conference/ConferenceSession.ts","../src/videocalling_conference/ConferenceClient.ts","../src/Data.ts","../src/Meetings.ts","../src/PushNotifications.ts","../src/Storage.ts","../src/Users.ts","../src/videocalling/WebRTCHelpers.ts","../src/videocalling/WebRTCPeerConnection.ts","../src/videocalling/WebRTCSignalingProvider.ts","../src/videocalling/WebRTCSession.ts","../src/videocalling/WebRTCClient.ts","../src/Whiteboard.ts","../src/LinkPreview.ts","../src/ConnectyCube.ts","../src/index.ts","../src/types/data.ts","../src/types/pushnotifications.ts","../src/types/dialogs.ts","../src/types/auth.ts","../src/types/meetings.ts"],"sourcesContent":["import type { ForceParams } from './common';\nimport type { ConnectyCubeUsers } from './users';\n\nexport const AddressBookUserDataType = {\n  COMPACT: 1,\n  FULL: 0,\n} as const;\nexport type AddressBookUserDataType = (typeof AddressBookUserDataType)[keyof typeof AddressBookUserDataType];\n\nexport namespace ConnectyCubeAddressBook {\n  export type Contact = { name: string; phone: string; destroy?: number | string };\n  // Request parameters type\n  export type UploadParams = { udid?: string } & ForceParams;\n  export type GetRegisteredUsersParams = boolean | { udid?: string; compact: AddressBookUserDataType | number }; // 1 - compact user data, 0 - full user data\n  // Response data types\n  export type UploadResponse = {\n    deleted: number;\n    rejected: Record<string | number, string[]>;\n    created: number;\n    updated: number;\n  };\n  export type GetRegisteredUsersResponse = {\n    items: Partial<ConnectyCubeUsers.User> & { address_book_name: string }[];\n  };\n}\n","import type { PlainObject } from './common';\nimport type WebRTCSession from '../videocalling/WebRTCSession';\nimport type WebRTCSignalingProvider from '../videocalling/WebRTCSignalingProvider';\n\nexport const CallSignalingModuleIdentifier = 'WebRTCVideoChat';\n\nexport const CallSignalingType = {\n  CALL: 'call',\n  ACCEPT: 'accept',\n  REJECT: 'reject',\n  STOP: 'hangUp',\n  RESTART: 'iceRestart',\n  RESTART_ACCEPT: 'iceRestartAccept',\n  CANDIDATE: 'iceCandidates',\n} as const;\nexport type CallSignalingType = (typeof CallSignalingType)[keyof typeof CallSignalingType];\n\nexport const CallSessionConnectionState = {\n  UNDEFINED: 0,\n  CONNECTING: 1,\n  CONNECTED: 2,\n  FAILED: 3,\n  DISCONNECTED: 4,\n  CLOSED: 5,\n  COMPLETED: 6,\n} as const;\nexport type CallSessionConnectionState = (typeof CallSessionConnectionState)[keyof typeof CallSessionConnectionState];\n\nexport const CallSessionState = {\n  NEW: 1,\n  ACTIVE: 2,\n  STOPPED: 3,\n  REJECTED: 4,\n  CLOSED: 5,\n} as const;\nexport type CallSessionState = (typeof CallSessionState)[keyof typeof CallSessionState];\n\nexport const CallType = {\n  VIDEO: 1,\n  AUDIO: 2,\n} as const;\nexport type CallType = (typeof CallType)[keyof typeof CallType];\n\nexport const CallEvent = {\n  CALL: 'call',\n  ACCEPT: 'accept',\n  REJECT: 'reject',\n  STOP: 'stop',\n  INVALID: 'invalid',\n  NOT_ANSWER: 'not-answer',\n  REMOTE_STREAM: 'remote-stream',\n  CONNECTION_STATE: 'connection-state',\n  CLOSE: 'close',\n  STATS_REPORT: 'stats-report',\n  DEVICES: 'devices',\n} as const;\nexport type CallEvent = (typeof CallEvent)[keyof typeof CallEvent];\n\nexport const PeerConnectionState = {\n  NEW: 1,\n  CONNECTING: 2,\n  CHECKING: 3,\n  CONNECTED: 4,\n  DISCONNECTED: 5,\n  FAILED: 6,\n  CLOSED: 7,\n  COMPLETED: 8,\n} as const;\nexport type PeerConnectionState = (typeof PeerConnectionState)[keyof typeof PeerConnectionState];\n\nexport namespace ConnectyCubeCalls {\n  export type StatsReportObj = {\n    audio: PlainObject;\n    video: PlainObject;\n    candidate: PlainObject;\n  };\n  export type UserInfo<UserInfoExtra = PlainObject> = {\n    maxBandwidth?: number;\n    bandwidth?: number;\n  } & UserInfoExtra;\n  export type ExtensionParams<Extra = PlainObject, UserInfoExtra = PlainObject> = {\n    callType?: number;\n    callerID?: number;\n    iceCandidates?: RTCIceCandidateInit[];\n    opponentsIDs?: number[];\n    userInfo?: UserInfo<UserInfoExtra>;\n    sessionID?: string;\n    moduleIdentifier?: string;\n    signalType?: string;\n    platform?: string;\n    sdp?: string;\n  } & Extra;\n  export type Session = WebRTCSession;\n  export type SignalingProvider = WebRTCSignalingProvider;\n  export type SessionParams = {\n    ID: string | null;\n    initiatorID: number;\n    opponentsIDs: number[];\n    callType: CallType;\n    signalingProvider: SignalingProvider;\n    currentUserID: number;\n    maxBandwidth: number;\n  };\n  // Listeners\n  export type OnCallListener = (session: Session, userInfo: UserInfo) => void;\n  export type OnAcceptCallListener = (session: Session, userID: number, userInfo: UserInfo) => void;\n  export type OnRejectCallListener = (session: Session, userID: number, userInfo: UserInfo) => void;\n  export type OnStopCallListener = (session: Session, userID: number, userInfo: UserInfo) => void;\n  export type OnInvalidEventsListener = (session: Session, userID: number, userInfo: UserInfo) => void;\n  export type OnUserNotAnswerListener = (session: Session, userID: number) => void;\n  export type OnRemoteStreamListener = (session: Session, userID: number, stream: MediaStream) => void;\n  export type OnSessionConnectionStateChangedListener = (\n    session: Session,\n    userID: number,\n    connectionState: CallSessionConnectionState\n  ) => void;\n  export type OnSessionCloseListener = (session: Session) => void;\n  export type OnCallStatsReportListener = (session: Session, userID: number, stats: RTCStatsReport, error: Error) => void;\n  export type OnDevicesChangeListener = ((this: MediaDevices, ev: Event) => void) | ((ev: Event) => void);\n  export type Listeners =\n    | OnCallListener\n    | OnAcceptCallListener\n    | OnRejectCallListener\n    | OnStopCallListener\n    | OnInvalidEventsListener\n    | OnUserNotAnswerListener\n    | OnRemoteStreamListener\n    | OnSessionConnectionStateChangedListener\n    | OnSessionCloseListener\n    | OnCallStatsReportListener\n    | OnDevicesChangeListener;\n  export type ListenerName =\n    | 'onCallListener'\n    | 'onAcceptCallListener'\n    | 'onRejectCallListener'\n    | 'onStopCallListener'\n    | 'onInvalidEventsListener'\n    | 'onUserNotAnswerListener'\n    | 'onRemoteStreamListener'\n    | 'onSessionConnectionStateChangedListener'\n    | 'onSessionCloseListener'\n    | 'onCallStatsReport'\n    | 'onDevicesChangeListener';\n}\n","import type { Element, Node } from '@xmpp/xml';\nimport type { StatusEvents } from '@xmpp/connection';\nimport type { VoidCallback, PlainObject } from './common';\nimport type { ConnectyCubeCalls } from './calls';\nimport type { ConnectyCubeDialogs } from './dialogs';\nimport type { ConnectyCubeUsers } from './users';\nimport type { ConnectyCubeMessages } from './messages';\nimport type ChatHelpers from '../messaging/xmpp/Helpers';\nimport type PrivacyList from '../messaging/xmpp/PrivacyList';\nimport type BlockList from '../messaging/sama/BlockList';\nimport type MultiUserChat from '../messaging/xmpp/MultiUserChat';\nimport type StreamManagement from '../messaging/xmpp/StreamManagement';\n\nexport const ChatType = {\n  CHAT: 'chat',\n  GROUPCHAT: 'groupchat',\n} as const;\nexport type ChatType = (typeof ChatType)[keyof typeof ChatType];\n\nexport const ChatEvent = {\n  STATUS: 'status',\n  ERROR: 'error',\n  DISCONNECTED: 'disconnected',\n  RECONNECTED: 'reconnected',\n  MESSAGE: 'message',\n  SYSTEM_MESSAGE: 'system-message',\n  ERROR_MESSAGE: 'error-message',\n  TYPING_MESSAGE: 'typing-message',\n  UPDATE_MESSAGE: 'update-message',\n  DELETE_MESSAGE: 'delete-message',\n  REACTIONS_MESSAGE: 'reactions-message',\n  DELIVERED_MESSAGE: 'delivered-message',\n  READ_MESSAGE: 'read-message',\n  SENT_MESSAGE: 'sent-message',\n  USER_LAST_ACTIVITY: 'user-last-activity',\n  JOIN: 'join',\n  LEAVE: 'leave',\n  KICK: 'kick',\n} as const;\nexport type ChatEvent = (typeof ChatEvent)[keyof typeof ChatEvent];\n\nexport const PrivacyListAction = {\n  ALLOW: 'allow',\n  DENY: 'deny',\n} as const;\nexport type PrivacyListAction = (typeof PrivacyListAction)[keyof typeof PrivacyListAction];\nexport namespace ConnectyCubeChat {\n  export type XmlElement = Element;\n  export type XmlNode = Node;\n  export type StanzaCallback = (stanza: Element) => void;\n  export type StanzasCallbacks = { [stanzaId: string]: StanzaCallback };\n  export type ConnectionParams = { userId: number; password: string; deviceId?: string };\n  export type ConnectionStatus = keyof StatusEvents;\n\n  export type MessageExtension<Extra = PlainObject, AttachmentExtra = PlainObject, UserInfoExtra = PlainObject> = {\n    date_sent?: string | number;\n    attachments?: ConnectyCubeMessages.Attachment<AttachmentExtra>[];\n    dialog_id?: string;\n    dialogId?: string;\n    addedParticipantsIds?: string;\n    removedParticipantsIds?: string;\n    save_to_history?: number;\n    iceCandidates?: RTCIceCandidateInit[];\n    opponentsIDs?: number[];\n    moduleIdentifier?: string;\n    sdp?: string;\n    sessionID?: string;\n    signalType?: string;\n    callType?: number;\n    callerID?: number;\n    platform?: string;\n    userInfo?: ConnectyCubeCalls.UserInfo<UserInfoExtra>;\n  } & Extra;\n\n  export type ParseExtraParamsResult<\n    Extra = PlainObject,\n    AttachmentExtra = PlainObject,\n    UserInfoExtra = PlainObject,\n  > = { extension: MessageExtension<Extra, AttachmentExtra, UserInfoExtra>; dialogId: string | null };\n  export type ParseReactionsResult = { add: string | null; remove: string | null };\n\n  export type MessageParams<Extra = PlainObject, AttachmentExtra = PlainObject, UserInfoExtra = PlainObject> = {\n    id?: string;\n    type?: ChatType | string;\n    body?: string | null;\n    extension?: MessageExtension<Extra, AttachmentExtra, UserInfoExtra>;\n  };\n  export type Message<Extra = PlainObject, AttachmentExtra = PlainObject, UserInfoExtra = PlainObject> = {\n    id: string;\n    dialog_id: string | null;\n    recipient_id?: string | number | null;\n    is_forwarded?: boolean;\n    type?: ChatType | string;\n    body: string | null;\n    extension: MessageExtension<Extra, AttachmentExtra, UserInfoExtra> | null;\n    delay?: unknown;\n  };\n  export type SystemMessageParams<Extra = PlainObject, AttachmentExtra = PlainObject, UserInfoExtra = PlainObject> = {\n    id?: string;\n    body?: string | null;\n    extension?: MessageExtension<Extra, AttachmentExtra, UserInfoExtra>;\n  };\n  export type SystemMessage<Extra = PlainObject, AttachmentExtra = PlainObject, UserInfoExtra = PlainObject> = {\n    id: string;\n    body: string;\n    userId: number;\n    extension: MessageExtension<Extra, AttachmentExtra, UserInfoExtra> | null;\n  };\n  export type MessageStatusParams = {\n    messageId: string;\n    dialogId: string;\n    userId?: number;\n  };\n  export type DialogReadParams = {\n    dialogId: string;\n  };\n  export type EditMessageParams<Extra = PlainObject, AttachmentExtra = PlainObject, UserInfoExtra = PlainObject> = {\n    to?: string | number;\n    dialogId: string;\n    body: string;\n    originMessageId: string;\n    extension?: MessageExtension<Extra, AttachmentExtra, UserInfoExtra>;\n    last?: boolean;\n  };\n  export type DeleteMessageParams = {\n    to?: string | number;\n    dialogId: string;\n    messageId: string;\n  };\n  export type LastActivity = {\n    userId: number | null;\n    seconds: number;\n  };\n  export type SearchParams = {\n    search_text?: string;\n    start_date?: number | string | Date;\n    end_date?: number | string | Date;\n    chat_dialog_ids?: string | string[];\n  };\n  export type SearchResult = {\n    results: {\n      dialogs: ConnectyCubeDialogs.Dialog[];\n      messages: unknown[];\n      users: ConnectyCubeUsers.User[];\n    };\n  } & PlainObject;\n  export type UserJIDParams = {\n    userId?: number;\n    resource?: string;\n    jid?: string;\n  } & PlainObject;\n  // XMPP client events and listeners\n  export type XMPPClientEvent = string | symbol;\n  export type XMPPClientListener = VoidCallback;\n  export type XMPPClientListeners = Map<XMPPClientEvent, XMPPClientListener>;\n  // Chat listeners\n  export type OnChatStatusListener = (status: ConnectionStatus) => void;\n  export type OnChatConnectionErrorListener = (error: Error) => void;\n  export type OnChatDisconnectedListener = () => void;\n  export type OnChatReconnectedListener = () => void;\n  export type OnMessageListener = (userId: number, message: Message) => void;\n  export type OnMessageSystemListener = (message: SystemMessage) => void;\n  export type OnMessageErrorListener = (messageId: string, error: { code: number; info: string }) => void;\n  export type OnMessageTypingListener = (typing: boolean, userId: number, dialogId: string) => void;\n  export type OnMessageUpdateListener = (\n    messageId: string,\n    isLast: boolean,\n    updatedBody: string,\n    dialogId: string,\n    userId: number,\n    extraParams: object | null\n  ) => void;\n  export type OnMessageDeleteListener = (messageId: string, dialogId: string, userId: number) => void;\n  export type OnMessageReactionsListener = (\n    messageId: string,\n    userId: number,\n    dialogId: string,\n    add: string,\n    remove: string\n  ) => void;\n  export type OnMessageDeliveredListener = (messageId: string, dialogId: string, userId: number) => void;\n  export type OnMessageReadListener = (messageId: string, dialogId: string, userId: number) => void;\n  export type OnMessageSentListener = (lost: MessageParams | null, sent: MessageParams | null) => void;\n  export type OnLastUserActivityListener = (userId: number, seconds: number) => void;\n  export type OnDialogJoinListener = (dialogId: string, userId: number) => void;\n  export type OnDialogLeaveListener = (dialogId: string, userId: number) => void;\n  export type OnDialogKickListener = (dialogId: string, initiatorId: number) => void;\n  export type Listeners =\n    | OnChatStatusListener\n    | OnChatConnectionErrorListener\n    | OnChatDisconnectedListener\n    | OnChatReconnectedListener\n    | OnMessageListener\n    | OnMessageSystemListener\n    | OnMessageErrorListener\n    | OnMessageTypingListener\n    | OnMessageUpdateListener\n    | OnMessageDeleteListener\n    | OnMessageReactionsListener\n    | OnMessageDeliveredListener\n    | OnMessageReadListener\n    | OnMessageSentListener\n    | OnLastUserActivityListener\n    | OnDialogJoinListener\n    | OnDialogLeaveListener\n    | OnDialogKickListener;\n  export type ListenerName =\n    | 'onChatStatusListener'\n    | 'onConnectionErrorListener'\n    | 'onDisconnectedListener'\n    | 'onReconnectListener'\n    | 'onMessageListener'\n    | 'onSystemMessageListener'\n    | 'onMessageErrorListener'\n    | 'onMessageTypingListener'\n    | 'onMessageUpdateListener'\n    | 'onMessageDeleteListener'\n    | 'onMessageReactionsListener'\n    | 'onDeliveredStatusListener'\n    | 'onReadStatusListener'\n    | 'onSentMessageCallback'\n    | 'onLastUserActivityListener'\n    | 'onJoinOccupant'\n    | 'onLeaveOccupant'\n    | 'onKickOccupant';\n  // PrivacyList\n  export type PrivacyListItem = {\n    user_id: string | number;\n    action: PrivacyListAction | string;\n    mutualBlock?: boolean;\n  };\n  export type PrivacyList = {\n    name: string;\n    items: PrivacyListItem[];\n  };\n  export type PrivacyListNames = {\n    default: string | null;\n    active: string | null;\n    names: string[];\n  };\n  export type PrivacyListItemParams = {\n    value: string;\n    action: string;\n    order: number;\n    isMutual: boolean;\n  };\n  export type DialogId = string;\n  export type UserId = number;\n}\n\nexport interface ChatRealTimeService {\n  onChatStatusListener: ConnectyCubeChat.OnChatStatusListener;\n  onConnectionErrorListener: ConnectyCubeChat.OnChatConnectionErrorListener;\n  onDisconnectedListener: ConnectyCubeChat.OnChatDisconnectedListener;\n  onReconnectListener: ConnectyCubeChat.OnChatReconnectedListener;\n  onMessageListener: ConnectyCubeChat.OnMessageListener;\n  onSystemMessageListener: ConnectyCubeChat.OnMessageSystemListener;\n  onMessageTypingListener: ConnectyCubeChat.OnMessageTypingListener;\n  onMessageUpdateListener: ConnectyCubeChat.OnMessageUpdateListener;\n  onMessageDeleteListener: ConnectyCubeChat.OnMessageDeleteListener;\n  onMessageReactionsListener: ConnectyCubeChat.OnMessageReactionsListener;\n  onReadStatusListener: ConnectyCubeChat.OnMessageReadListener;\n  onLastUserActivityListener: ConnectyCubeChat.OnLastUserActivityListener;\n\n  get connectionStatus(): string;\n  get currentUserId(): ConnectyCubeChat.UserId;\n\n  connect(params: ConnectyCubeChat.ConnectionParams): Promise<boolean>;\n  disconnect(): Promise<boolean>;\n  terminate(): void;\n\n  ping(): Promise<void>;\n  pingWithTimeout(timeout: number): Promise<unknown>;\n\n  send(\n    dialogId: ConnectyCubeChat.DialogId | ConnectyCubeChat.UserId,\n    message: ConnectyCubeChat.MessageParams\n  ): string | Promise<string>;\n  sendSystemMessage(\n    userId: ConnectyCubeChat.UserId | ConnectyCubeChat.UserId[],\n    message: ConnectyCubeChat.SystemMessageParams\n  ): string | Promise<string>;\n  sendWebRTCSignalingMessage(\n    userId: ConnectyCubeChat.UserId,\n    message: ConnectyCubeChat.SystemMessageParams\n  ): string | Promise<string>;\n\n  sendIsTypingStatus(dialogId: ConnectyCubeChat.DialogId | ConnectyCubeChat.UserId): void | Promise<void>;\n  sendIsStopTypingStatus(dialogId: ConnectyCubeChat.DialogId | ConnectyCubeChat.UserId): void | Promise<void>;\n\n  sendDeliveredStatus(params: ConnectyCubeChat.MessageStatusParams): void | Promise<void>;\n  sendReadStatus(params: ConnectyCubeChat.MessageStatusParams): void | Promise<void>;\n\n  editMessage(params: ConnectyCubeChat.EditMessageParams): void | Promise<void>;\n  deleteMessage(params: ConnectyCubeChat.DeleteMessageParams): void | Promise<void>;\n\n  getLastUserActivity(userId: ConnectyCubeChat.UserId): Promise<ConnectyCubeChat.LastActivity>;\n  subscribeToUserLastActivityStatus(userId: ConnectyCubeChat.UserId): void;\n  unsubscribeFromUserLastActivityStatus(userId?: ConnectyCubeChat.UserId): void;\n\n  markActive(): void;\n  markInactive(): void;\n\n  addListener(name: ChatEvent, listener: ConnectyCubeChat.Listeners): () => void;\n  removeListener(name: ChatEvent): void;\n  removeAllListeners(): void;\n}\n\nexport interface XMPPChatRealTimeService extends ChatRealTimeService {\n  readonly helpers: ChatHelpers;\n  readonly muc: MultiUserChat;\n  readonly privacylist: PrivacyList;\n  readonly streamManagement: StreamManagement;\n}\n\nexport interface SAMAChatRealTimeService extends ChatRealTimeService {\n  readonly blockList: BlockList;\n}\n","import type { ConnectyCubeAuth } from './auth';\nimport type { Config } from '../config';\n\nexport const ChatProtocol = {\n  BOSH: 1,\n  WS: 2,\n} as const;\nexport type ChatProtocol = (typeof ChatProtocol)[keyof typeof ChatProtocol];\n\nexport const JanusDebugMode = {\n  ALL: 'all',\n  TRACE: 'trace',\n  DEBUG: 'debug',\n  VDEBUG: 'vdebug',\n  LOG: 'log',\n  WARN: 'warn',\n  ERROR: 'error',\n} as const;\nexport type JanusDebugMode = (typeof JanusDebugMode)[keyof typeof JanusDebugMode];\n\nexport const ChatAPIs = {\n  SAMA: 'sama',\n  XMPP: 'xmpp',\n} as const;\nexport type ChatAPIs = (typeof ChatAPIs)[keyof typeof ChatAPIs];\n\nexport namespace ConnectyCubeConfig {\n  export type Object = Partial<Config>;\n  export type Credentials = {\n    appId: number | string;\n    authKey?: string;\n    token?: string;\n    systemApiKey?: string;\n    authSecret?: string;\n  };\n  export type Endpoints = { api: string; api_url?: string; chat: string; chat_url?: string; muc?: string };\n  export type ChatProtocolURLs = { bosh?: string; websocket?: string; active?: ChatProtocol | number };\n  export type ChatStreamManagement = { enable: boolean; acknowledgementTimeout?: number };\n  export type ChatReconnect = { enable: boolean; timeInterval: number };\n  export type Chat = {\n    streamManagement?: ChatStreamManagement;\n    reconnect?: ChatReconnect;\n    apiImp?: ChatAPIs;\n  };\n  export type VideochatIceServer = {\n    urls: string | string[];\n    url?: string;\n    credential?: string;\n    username?: string;\n  };\n  export type Videochat = {\n    alwaysRelayCalls?: boolean;\n    answerTimeInterval?: number;\n    dialingTimeInterval?: number;\n    disconnectTimeInterval?: number;\n    statsReportTimeInterval?: number | null;\n    iceServers?: VideochatIceServer[];\n  };\n  export type JanusDebug = JanusDebugMode | JanusDebugMode[] | boolean;\n  export type Conference = {\n    server: string;\n    debug?: JanusDebug;\n  };\n  export type Whiteboard = {\n    server: string;\n  };\n  export type LinkPreview = {\n    server: string;\n  };\n  export type ApiRoutes = {\n    session: string;\n    login: string;\n    users: string;\n    chat: string;\n    blobs: string;\n    subscriptions: string;\n    events: string;\n    data: string;\n    addressbook: string;\n    meetings: string;\n    whiteboards: string;\n    unfurl: string;\n    calls: string;\n    type: string;\n  };\n  export type SessionHandlerResponse = () => void;\n  export type SessionRetryCallback = (session: Partial<ConnectyCubeAuth.Session>) => void;\n  export type SessionExpiredListener = (\n    handler: SessionHandlerResponse,\n    retry: SessionRetryCallback\n  ) => void | Promise<void>;\n  export type XMPPData = { body?: string; headers?: string };\n  export type XMPPDataListener = (size: number, data?: XMPPData | null) => void;\n  export type Listeners = {\n    sessionExpired?: SessionExpiredListener;\n    xmppDataWrite?: XMPPDataListener;\n    xmppDataRead?: XMPPDataListener;\n  };\n  export type Debug = { mode: number | boolean };\n  export type Options = {\n    creds?: Credentials;\n    endpoints?: Endpoints;\n    chatProtocol?: ChatProtocolURLs;\n    chat?: Chat;\n    videochat?: Videochat;\n    conference?: Conference;\n    whiteboard?: Whiteboard;\n    on?: Listeners;\n    timeout?: number;\n    debug?: Debug;\n  };\n}\n","import type ConferenceSession from '../videocalling_conference/ConferenceSession';\nimport type { VoidCallback } from './common';\n\nexport const DeviceInputType = {\n  VIDEO: 'videoinput',\n  AUDIO: 'audioinput',\n} as const;\nexport type DeviceInputType = (typeof DeviceInputType)[keyof typeof DeviceInputType];\n\nexport const JanusEvent = {\n  PARTICIPANT_JOINED: 'participant_joined',\n  PARTICIPANT_LEFT: 'participant_left',\n  LOCAL_STREAM: 'local_stream',\n  REMOTE_STREAM: 'remote_stream',\n  REMOTE_TRACKS_UPDATED: 'remote_tracks_updated',\n  DATA_CHANNEL_OPEN: 'data_channel_open',\n  DATA_CHANNEL_MESSAGE: 'data_channel_message',\n  ERROR: 'error',\n} as const;\nexport type JanusEvent = (typeof JanusEvent)[keyof typeof JanusEvent];\n\nexport const JanusCallType = {\n  VIDEO: 'video',\n  AUDIO: 'audio',\n} as const;\nexport type JanusCallType = (typeof JanusCallType)[keyof typeof JanusCallType];\n\nexport const JanusMediaTrackReason = {\n  CREATED: 'created',\n  ENDED: 'ended',\n  MUTE: 'mute',\n  UNMUTE: 'unmute',\n} as const;\nexport type JanusMediaTrackReason = (typeof JanusMediaTrackReason)[keyof typeof JanusMediaTrackReason];\n\nexport const ConferenceEvent = {\n  JOIN: 'join',\n  LEFT: 'left',\n  SLOW_LINK: 'slow-link',\n  REMOTE_TRACKS_UPDATED: 'remote-tracks',\n  REMOTE_STREAM: 'remote-stream',\n  REMOTE_CONNECTION_STATE: 'remote-connection-state',\n  DATA_CHANNEL_OPENED: 'data-channel-opened',\n  DATA_CHANNEL_MESSAGE: 'data-channel-message',\n  SESSION_CONNECTION_STATE: 'session-connection-state',\n  ERROR: 'error',\n} as const;\nexport type ConferenceEvent = (typeof ConferenceEvent)[keyof typeof ConferenceEvent];\n\nexport namespace ConnectyCubeJanus {\n  export interface CreateOfferParams {\n    tracks: Array<{\n      type: string;\n      mid?: string;\n      recv?: boolean;\n      capture?: boolean | MediaStreamTrack;\n      replace?: boolean;\n    }>;\n    customizeSdp?(jsep: unknown): void;\n    success?(jsep: unknown): void;\n    error?(error: unknown): void;\n  }\n  export interface VideoRoomPluginHandle {\n    createOffer(opts: CreateOfferParams): void;\n    send(msg: unknown): void;\n    getLocalVolume?(id: unknown, callback: (value: unknown) => void): void;\n    handleRemoteJsep?(opts: { jsep: unknown }): void;\n    getId?(): string | number;\n    detach?(opts: { success?: () => void; error?: (err: unknown) => void }): void;\n    isAudioMuted?(): boolean;\n    unmuteAudio?(): void;\n    muteAudio?(): void;\n    isVideoMuted?(): boolean;\n    unmuteVideo?(): void;\n    muteVideo?(): void;\n    data?(opts: { data: unknown; label: unknown; success: (value?: unknown) => void; error: (err?: unknown) => void }): void;\n    webrtcStuff?: { pc: RTCPeerConnection };\n  }\n  export interface RemoteFeed {\n    userId?: number;\n    stream?: MediaStream;\n    tracks?: Record<string, MediaStreamTrack>;\n    createAnswer(opts: unknown): void;\n    send(msg: unknown): void;\n    detach(): void;\n    getBitrate?(): unknown;\n    getRemoteVolume?(id: unknown, callback: (value: unknown) => void): void;\n  }\n  export interface BitrateDisplayElement {\n    text: ((value?: unknown) => void) | null;\n  }\n  export interface SuccessErrorCallbacks {\n    success?: VoidCallback;\n    error?: (error: unknown) => void;\n  }\n  export interface InitCallbacks extends SuccessErrorCallbacks {\n    destroyed?: () => void;\n    timeoutSessionCallback?: () => void;\n  }\n  export interface PluginCallbacks extends SuccessErrorCallbacks {\n    localStream?: MediaStream;\n    displayName?: string;\n    iceState?: (iceState: unknown) => void;\n    slowLink?: (uplink: unknown, nacks: unknown) => void;\n    consentDialog?: (on: unknown) => void;\n    mediaState?: (medium: unknown, on: unknown) => void;\n    webrtcState?: (on: unknown) => void;\n    oncleanup?: () => void;\n  }\n  export type Session = ConferenceSession;\n  export interface RequestCallbacks extends SuccessErrorCallbacks {\n    displayName?: string;\n  }\n  // Listeners\n  export type OnParticipantJoinedListener = (\n    session: Session,\n    userId: number,\n    userName: string,\n    isExist: boolean\n  ) => void;\n  export type OnParticipantLeftListener = (session: Session, ...args: unknown[]) => void;\n  export type OnSlowLinkListener = (session: Session, userId: number | null, uplink: unknown, nacks: unknown) => void;\n  export type OnRemoteStreamListener = (session: Session, userId: number, stream: MediaStream) => void;\n  export type OnRemoteTracksUpdatedListener = (\n    session: Session,\n    userId: number,\n    track: MediaStreamTrack,\n    eventType: unknown\n  ) => void;\n  export type OnRemoteConnectionStateChangedListener = (session: Session, userId: number, iceState: unknown) => void;\n  export type OnDataChannelOpenedListener = (session: Session, label: unknown) => void;\n  export type OnDataChannelMessageListener = (session: Session, label: unknown, data: unknown) => void;\n  export type OnSessionConnectionStateChangedListener = (session: Session, iceState: unknown) => void;\n  export type OnErrorListener = (session: Session, error: unknown) => void;\n  export type Listeners =\n    | OnParticipantJoinedListener\n    | OnParticipantLeftListener\n    | OnSlowLinkListener\n    | OnRemoteStreamListener\n    | OnRemoteTracksUpdatedListener\n    | OnRemoteConnectionStateChangedListener\n    | OnDataChannelOpenedListener\n    | OnDataChannelMessageListener\n    | OnSessionConnectionStateChangedListener\n    | OnErrorListener;\n  export type ListenerName =\n    | 'onParticipantJoinedListener'\n    | 'onParticipantLeftListener'\n    | 'onSlowLinkListener'\n    | 'onRemoteStreamListener'\n    | 'onRemoteTracksUpdatedListener'\n    | 'onRemoteConnectionStateChangedListener'\n    | 'onDataChannelOpenedListener'\n    | 'onDataChannelMessageListener'\n    | 'onSessionConnectionStateChangedListener'\n    | 'onErrorListener';\n}\n","export const MediaType = {\n  AUDIO: 'audio',\n  VIDEO: 'video',\n  NONE: 'none',\n} as const;\nexport type MediaType = (typeof MediaType)[keyof typeof MediaType];\n\nexport namespace ConnectyCubeMedia {\n  export interface ElementOptions {\n    muted?: boolean;\n    mirror?: boolean;\n  }\n  export interface ElementParams {\n    elementId?: string;\n    options?: ElementOptions;\n  }\n  export interface DisplayParams extends DisplayMediaStreamOptions, ElementParams {}\n  export interface UserParams extends MediaStreamConstraints, ElementParams {}\n  export type DeviceIdOrTrackConstraints = MediaTrackConstraints | string;\n  export type TrackConstraintsOrDeviceIds = {\n    audio?: DeviceIdOrTrackConstraints;\n    video?: DeviceIdOrTrackConstraints;\n  };\n}\n","import type { StringObject } from './common';\nimport type { ConnectyCubeConfig } from './config';\nimport type { ConnectyCubeAuth } from './auth';\n\nexport const ProxyMethod = {\n  GET: 'GET',\n  POST: 'POST',\n  PUT: 'PUT',\n  PATCH: 'PATCH',\n  DELETE: 'DELETE',\n  HEAD: 'HEAD',\n} as const;\nexport type ProxyMethod = (typeof ProxyMethod)[keyof typeof ProxyMethod];\n\nexport const ProxyType = {\n  JSON: 'json',\n  TEXT: 'text',\n} as const;\nexport type ProxyType = (typeof ProxyType)[keyof typeof ProxyType];\n\nexport type ProxyRequestObject = {\n  method: string;\n  body?: BodyInit;\n  headers?: StringObject;\n  signal?: AbortSignal;\n  timeout?: number;\n};\n\nexport type ProxyResponseBody = unknown;\n\nexport type FetchResponse = {\n  ok: boolean;\n  status?: number;\n  url?: string;\n  text(): Promise<string>;\n  json(): Promise<unknown>;\n};\n\nexport namespace ConnectyCubeProxy {\n  export type Params = {\n    url: string;\n    type?: ProxyMethod;\n    data?: unknown;\n    contentType?: boolean;\n    dataType?: ProxyType;\n    useArrayQuery?: boolean;\n    fileToCustomObject?: boolean;\n    authKey?: string;\n    abort_id?: string | number;\n  };\n  export type AbortControllersMap = {\n    [key: string | number]: {\n      controllers: AbortController[];\n      doneRequestsCount?: number;\n    };\n  };\n  export type SDKInstance = {\n    config: ConnectyCubeConfig.Object;\n    session: Partial<ConnectyCubeAuth.Session> | null;\n  };\n  export type ErrorObject = {\n    code?: number;\n    info?: { errors?: { base?: string[] } };\n  };\n}\n","declare global {\n  interface Window {\n    adapter?: unknown;\n  }\n}\n\nexport const sdkVersion = '__package_version__';\n\nexport const isBrowser = typeof window !== 'undefined' && typeof document === 'object';\nexport const isNodeJS: boolean =\n  typeof process === 'object' && typeof process.versions === 'object' && Boolean(process.versions.node);\nexport const isReactNative = false;\nexport const isExpo = false;\n\nexport const adapter = isBrowser ? window.adapter : undefined;\nexport const navigator = isBrowser ? window.navigator : undefined;\nexport const mediaDevices = isBrowser && navigator ? navigator.mediaDevices : undefined;\nexport const MediaStream = isBrowser ? window.MediaStream : undefined;\nexport const MediaStreamTrack = isBrowser ? window.MediaStreamTrack : undefined;\nexport const RTCIceCandidate = isBrowser ? window.RTCIceCandidate : undefined;\nexport const RTCPeerConnection = isBrowser ? window.RTCPeerConnection : undefined;\nexport const RTCRtpReceiver = isBrowser ? window.RTCRtpReceiver : undefined;\nexport const RTCRtpSender = isBrowser ? window.RTCRtpSender : undefined;\nexport const RTCSessionDescription = isBrowser ? window.RTCSessionDescription : undefined;\nexport const isWebRTCAvailable: boolean = isBrowser ? Boolean(mediaDevices && RTCPeerConnection) : false;\n\nif (isWebRTCAvailable && !adapter) {\n  console.warn(\n    'Install WebRTC adapter if you want to use ConnectyCube.videochatconference. More info https://github.com/webrtc/adapter'\n  );\n}\n","import type { Config as ConnectyCubeConfig, PlainObject } from './types';\nimport { ChatAPIs } from './types/constants';\nimport { JanusDebugMode } from './types/constants';\nimport { sdkVersion } from '@platform';\n\nexport class Config {\n  private static instance: Config;\n\n  public version: string = sdkVersion;\n  public creds: ConnectyCubeConfig.Credentials = { appId: '', authKey: '' };\n  public endpoints: ConnectyCubeConfig.Endpoints = {\n    api: 'api.connectycube.com',\n    chat: 'chat.connectycube.com',\n    muc: 'muc.chat.connectycube.com',\n  };\n  public chatProtocol: ConnectyCubeConfig.ChatProtocolURLs = {\n    bosh: 'https://chat.connectycube.com:5281',\n    websocket: 'wss://chat.connectycube.com:5291',\n    active: 2,\n  };\n  public chat: ConnectyCubeConfig.Chat = {\n    streamManagement: { enable: false },\n    reconnect: { enable: true, timeInterval: 5 },\n    apiImp: ChatAPIs.XMPP,\n  };\n  public videochat: ConnectyCubeConfig.Videochat = {\n    alwaysRelayCalls: false,\n    answerTimeInterval: 60,\n    dialingTimeInterval: 5,\n    disconnectTimeInterval: 30,\n    statsReportTimeInterval: null,\n    iceServers: [\n      { urls: 'stun:stun.l.google.com:19302' },\n      { urls: 'stun:turn.connectycube.com' },\n      {\n        urls: 'turn:turn.connectycube.com:5349?transport=udp',\n        username: 'connectycube',\n        credential: '4c29501ca9207b7fb9c4b4b6b04faeb1',\n      },\n      {\n        urls: 'turn:turn.connectycube.com:5349?transport=tcp',\n        username: 'connectycube',\n        credential: '4c29501ca9207b7fb9c4b4b6b04faeb1',\n      },\n    ],\n  };\n  public conference: ConnectyCubeConfig.Conference = {\n    server: 'wss://janus.connectycube.com:8989',\n    debug: JanusDebugMode.ALL,\n  };\n  public whiteboard: ConnectyCubeConfig.Whiteboard = { server: 'https://whiteboard.connectycube.com' };\n  public linkpreview: ConnectyCubeConfig.LinkPreview = { server: 'https://linkpreview.connectycube.com' };\n  readonly urls: ConnectyCubeConfig.ApiRoutes = {\n    session: 'session',\n    login: 'login',\n    users: 'users',\n    chat: 'chat',\n    blobs: 'blobs',\n    subscriptions: 'subscriptions',\n    events: 'events',\n    data: 'data',\n    addressbook: 'address_book',\n    meetings: 'meetings',\n    whiteboards: 'whiteboards',\n    unfurl: 'unfurl',\n    calls: 'calls',\n    type: '.json',\n  };\n  public on: ConnectyCubeConfig.Listeners = {\n    sessionExpired: undefined,\n    xmppDataWrite: undefined,\n    xmppDataRead: undefined,\n  };\n  public timeout: number | null = null;\n  public debug: ConnectyCubeConfig.Debug = { mode: 1 };\n\n  private constructor() {}\n\n  public static getInstance(): Config {\n    if (!Config.instance) {\n      Config.instance = new Config();\n    }\n    return Config.instance;\n  }\n\n  public set(options: ConnectyCubeConfig.Options): void {\n    this.endpoints.api_url = options.endpoints?.api_url;\n\n    if (options.endpoints?.chat) {\n      this.endpoints.muc = `muc.${options.endpoints.chat}`;\n      this.chatProtocol.bosh = `https://${options.endpoints.chat}:5281`;\n      this.chatProtocol.websocket = options.endpoints.chat_url ?? `wss://${options.endpoints.chat}:5291`;\n    }\n\n    Object.keys(options).forEach((key: string) => {\n      if (key !== 'set' && Object.prototype.hasOwnProperty.call(this, key)) {\n        const optionValue = options[key as keyof ConnectyCubeConfig.Options];\n        const _key = key as keyof Config;\n        const _val = this[_key];\n\n        if (typeof optionValue === 'object' && optionValue !== null) {\n          Object.keys(optionValue).forEach((nextKey) => {\n            if (_val !== null && typeof _val === 'object' && Object.prototype.hasOwnProperty.call(_val, nextKey)) {\n              (_val as PlainObject)[nextKey] = (optionValue as PlainObject)[nextKey];\n            }\n          });\n        } else {\n          (this as PlainObject)[key] = optionValue;\n        }\n      }\n    });\n  }\n}\n\nexport default Config.getInstance();\n","import type { Config, VoidCallback } from './types';\nimport { isBrowser, isExpo, isNodeJS, isReactNative } from '@platform';\nimport config from './config';\n\nexport default class Utils {\n  static loggers: Array<VoidCallback> = [];\n\n  static env = {\n    isReactNative,\n    isBrowser,\n    isNodeJS,\n    isExpo,\n  };\n\n  static safeCallbackCall(cb: VoidCallback = () => {}): VoidCallback {\n    return (...args: unknown[]) => {\n      if (typeof cb === 'function') {\n        try {\n          cb(...args);\n        } catch (err) {\n          console.error('Error in listener:', err, `Check the code:\\n>>>\\n${cb.toString()}\\n<<<`);\n        }\n      }\n    };\n  }\n\n  static getUrl(base: Config.ApiRoutes[keyof Config.ApiRoutes], res?: string | number, ext?: string | number): string {\n    const resource = res ? `/${res}` : '';\n    const extension = ext ? `/${ext}` : '';\n    return `${config.endpoints.api_url ?? `https://${config.endpoints.api}`}/${base}${resource}${extension}${config.urls.type}`;\n  }\n\n  static isArray(arg: unknown): arg is unknown[] {\n    return Array.isArray(arg);\n  }\n\n  static isObject(obj: unknown): boolean {\n    return Object.prototype.toString.call(obj) === '[object Object]';\n  }\n\n  static getBsonObjectId(): string {\n    // The object for type MongoDB.Bson.ObjectId\n    // http://docs.mongodb.org/manual/reference/object-id/\n    const ObjectId = {\n      machine: Math.floor(Math.random() * 16777216).toString(16),\n      pid: Math.floor(Math.random() * 32767).toString(16),\n      increment: 0,\n    };\n    const timestamp = Math.floor(Date.now() / 1000).toString(16);\n    const increment = (ObjectId.increment++).toString(16);\n\n    if (parseInt(increment, 16) > 0xffffff) {\n      ObjectId.increment = 0;\n    }\n\n    return (\n      timestamp.padStart(8, '0') +\n      ObjectId.machine.padStart(6, '0') +\n      ObjectId.pid.padStart(4, '0') +\n      increment.padStart(6, '0')\n    );\n  }\n\n  static DLog(...args: unknown[]): void {\n    if (Utils.loggers.length > 0) {\n      Utils.loggers.forEach((logger) => logger(args));\n      return;\n    }\n\n    const consoleLoggerFunction = (): VoidCallback => {\n      return (...args: unknown[]) => console.log(...args);\n    };\n\n    if (typeof config.debug === 'object') {\n      const modes = Array.isArray(config.debug.mode) ? config.debug.mode : [config.debug.mode];\n      modes.forEach((mode) => {\n        if (mode === 1) {\n          Utils.loggers.push(consoleLoggerFunction());\n        }\n      });\n    }\n\n    Utils.loggers.forEach((logger) => logger(args));\n  }\n\n  static callTrafficUsageCallback(callbackName: 'xmppDataRead' | 'xmppDataWrite', data: Config.XMPPData): void {\n    if (typeof config.on[callbackName] !== 'function') return;\n\n    const getStringSize = (str: string): number => new Blob([str]).size;\n    const getDataSize = (data: Config.XMPPData = {}): number => {\n      const { body: b, headers: h } = data;\n      let size = 0;\n      if (b) size += getStringSize(typeof b === 'string' ? b : JSON.stringify(b));\n      if (h) size += getStringSize(JSON.stringify(h));\n      return size;\n    };\n\n    config.on[callbackName](getDataSize(data), data);\n  }\n\n  static cloneObject<T>(obj: T = {} as T, escapeNull: boolean = false): T {\n    try {\n      const json = JSON.stringify(obj);\n      const jsonObject = escapeNull ? json.replace(/null/g, '\"\"') : json;\n\n      return JSON.parse(jsonObject);\n    } catch {\n      return obj;\n    }\n  }\n}\n","import type { Auth, Proxy, PlainObject } from './types';\nimport type { FetchResponse, ProxyRequestObject, ProxyResponseBody } from './types/proxy';\nimport { ProxyMethod, ProxyType } from './types/constants';\n\nimport config from './config';\nimport Utils from './Utils';\n\nexport default class ProxyService {\n  public sdkInstance: Proxy.SDKInstance = {\n    config,\n    session: null,\n  };\n  public requestsNumber: number = 0;\n  private currentUserId: number | undefined;\n  private abortControllersMap: Proxy.AbortControllersMap = {};\n  public requestMethod: typeof ProxyMethod = ProxyMethod;\n  public responseType: typeof ProxyType = ProxyType;\n\n  public setSession(session: Partial<Auth.Session> | null): void {\n    this.sdkInstance.session = session;\n\n    if (session && session.user_id) {\n      this.setCurrentUserId(session.user_id);\n    }\n  }\n\n  public getSession(): Partial<Auth.Session> | null {\n    return this.sdkInstance.session;\n  }\n\n  public setCurrentUserId(userId?: number | null): void {\n    this.currentUserId = userId || undefined;\n  }\n\n  public getCurrentUserId(): number | undefined {\n    return this.currentUserId;\n  }\n\n  public logRequest(params: Proxy.Params, requestId: number): void {\n    Utils.DLog(`[Request][${requestId}]`, `${params.type || 'GET'} ${params.url}`, params);\n  }\n\n  public logResponse(response: ProxyResponseBody, requestId: number): void {\n    Utils.DLog(`[Response][${requestId}]`, response);\n  }\n\n  public buildRequestAndURL(params: Proxy.Params): [ProxyRequestObject, string] {\n    const isGetOrHeadType = !params.type || params.type === 'GET' || params.type === 'HEAD';\n    const isPostOrPutType = params.type ? params.type === 'POST' || params.type === 'PUT' : false;\n    const token = this.sdkInstance && this.sdkInstance.session && this.sdkInstance.session.token;\n    const isInternalRequest = params.url.indexOf('s3.amazonaws.com') === -1;\n    const isMultipartFormData = params.contentType === false;\n    const authKey = params.authKey;\n    const requestObject: ProxyRequestObject = {\n      method: params.type || 'GET',\n    };\n\n    let requestURL = params.url;\n\n    if (params.data) {\n      const requestBody = this.buildRequestBody(params, isMultipartFormData, isPostOrPutType);\n\n      if (isGetOrHeadType) {\n        requestURL += `?${requestBody}`;\n      } else {\n        requestObject.body = requestBody as BodyInit;\n      }\n    }\n\n    if (!isMultipartFormData) {\n      requestObject.headers = {\n        'Content-Type': isPostOrPutType\n          ? 'application/json;charset=utf-8'\n          : 'application/x-www-form-urlencoded; charset=UTF-8',\n      };\n    }\n\n    if (isInternalRequest) {\n      if (!requestObject.headers) {\n        requestObject.headers = {};\n      }\n\n      requestObject.headers['CB-SDK'] = `JS ${config.version} - Client`;\n\n      if (token) {\n        requestObject.headers['CB-Token'] = token;\n      } else if (authKey) {\n        requestObject.headers['CB-AuthKey'] = authKey;\n      }\n    }\n\n    if (config.timeout) {\n      requestObject.timeout = config.timeout;\n    }\n\n    return [requestObject, requestURL];\n  }\n\n  public buildRequestBody(\n    params: Proxy.Params,\n    isMultipartFormData: boolean,\n    isPostOrPutType: boolean\n  ): FormData | string {\n    const data = params.data as PlainObject;\n    const useArrayQuery = params.useArrayQuery;\n\n    let dataObject: FormData | string;\n\n    if (isMultipartFormData) {\n      const formData = new FormData();\n      Object.keys(data).forEach(function (item) {\n        const fileEntry = data[item] as { data: Blob; name: string } | undefined;\n\n        if (params.fileToCustomObject && item === 'file' && fileEntry) {\n          formData.append(item, fileEntry.data, fileEntry.name);\n        } else {\n          const value = data[item];\n          formData.append(item, value instanceof Uint8Array ? new Blob([new Uint8Array(value)]) : (value as string | Blob));\n        }\n      });\n      dataObject = formData;\n    } else if (isPostOrPutType) {\n      dataObject = JSON.stringify(data);\n    } else {\n      dataObject = this.serializeQueryParams(data, '', useArrayQuery, 0);\n    }\n\n    return dataObject;\n  }\n\n  public serializeQueryParams(\n    obj: PlainObject | unknown[],\n    prefix: string,\n    useArrayQuery: boolean | undefined,\n    level = 0\n  ): string {\n    const parts: string[] = [];\n    const objRecord = obj as PlainObject;\n\n    for (const propName in objRecord) {\n      let propQueryName = this.encodeURIComponent(propName);\n\n      if (Utils.isArray(obj)) {\n        propQueryName = '';\n      }\n\n      const key = prefix ? prefix + `[${propQueryName}]` : propQueryName;\n      let value = objRecord[propName] as PlainObject | unknown[];\n      const isArrayVal = Utils.isArray(value);\n\n      if ((isArrayVal && (useArrayQuery || level === 0)) || Utils.isObject(value)) {\n        parts.push(this.serializeQueryParams(value, key, useArrayQuery, ++level));\n      } else {\n        const strVal = isArrayVal ? value.sort().join(',') : String(value);\n        parts.push(`${key}=${this.encodeURIComponent(strVal)}`);\n      }\n    }\n\n    return parts.sort().join('&');\n  }\n\n  public encodeURIComponent(uriComponent: string | number | boolean): string {\n    return encodeURIComponent(uriComponent).replace(/[#$&+,/:;=?@\\[\\]]/g, (c) => `%${c.charCodeAt(0).toString(16)}`);\n  }\n\n  public abortRequest(abortId: string | number): void {\n    if (this.abortControllersMap[abortId]) {\n      const controllers = this.abortControllersMap[abortId].controllers || [];\n\n      controllers.forEach((controller) => {\n        controller.abort();\n      });\n    }\n  }\n\n  public processSuccessfulOrFailedRequest(abort_id?: string | number): void {\n    if (!abort_id || !this.abortControllersMap[abort_id]) {\n      return;\n    }\n\n    const controllers = this.abortControllersMap[abort_id].controllers || [];\n\n    if (!this.abortControllersMap[abort_id].doneRequestsCount) {\n      this.abortControllersMap[abort_id].doneRequestsCount = 1;\n    } else {\n      this.abortControllersMap[abort_id].doneRequestsCount += 1;\n    }\n\n    const doneRequestsCount = this.abortControllersMap[abort_id].doneRequestsCount;\n\n    if (doneRequestsCount === controllers.length) {\n      delete this.abortControllersMap[abort_id];\n    }\n  }\n\n  public async ajax<T>(params: Proxy.Params): Promise<T> {\n    const requestId = ++this.requestsNumber;\n\n    return new Promise((resolve, reject) => {\n      this.logRequest(params, requestId);\n\n      const [requestObject, requestURL] = this.buildRequestAndURL(params);\n      const abort_id = params.abort_id;\n\n      if (abort_id) {\n        let index = 0;\n\n        if (this.abortControllersMap[abort_id]) {\n          const controllers = this.abortControllersMap[abort_id].controllers || [];\n          this.abortControllersMap[abort_id].controllers.push(new AbortController());\n          index = controllers.length - 1;\n        } else {\n          this.abortControllersMap[abort_id] = {\n            controllers: [new AbortController()],\n          };\n        }\n        const signal = this.abortControllersMap[abort_id].controllers[index].signal;\n        Object.assign(requestObject, { signal });\n      }\n\n      let response: FetchResponse | undefined;\n\n      const body = requestObject.body === null ? undefined : requestObject.body;\n      const requestInit = { ...requestObject, body };\n\n      // The Promise returned from fetch() won’t reject on HTTP error\n      // status even if the response is an HTTP 404 or 500.\n      // Instead, it will resolve normally (with ok status set to false),\n      // and it will only reject on network failure or if anything prevented the request from completing.\n      fetch(requestURL, requestInit as unknown as Parameters<typeof fetch>[1])\n        .then((resp: FetchResponse) => {\n          response = resp;\n          const dataType = params.dataType || ProxyType.JSON;\n          return dataType === ProxyType.TEXT ? resp.text() : resp.json();\n        })\n        .then((body: ProxyResponseBody) => {\n          this.processSuccessfulOrFailedRequest(abort_id);\n          if (!response!.ok) {\n            this.processAjaxError(\n              response!,\n              body,\n              null,\n              reject as (reason?: unknown) => void,\n              resolve as (value: ProxyResponseBody) => void,\n              params,\n              requestId\n            );\n          } else {\n            this.processAjaxResponse(body, resolve as (value: ProxyResponseBody) => void, requestId);\n          }\n        })\n        .catch((error: unknown) => {\n          this.processSuccessfulOrFailedRequest(abort_id);\n          this.processAjaxError(\n            response ?? null,\n            ' ',\n            error,\n            reject as (reason?: unknown) => void,\n            resolve as (value: ProxyResponseBody) => void,\n            params,\n            requestId\n          );\n        });\n    });\n  }\n\n  public processAjaxResponse(\n    body: ProxyResponseBody,\n    resolve: (value: ProxyResponseBody) => void,\n    requestId: number\n  ): void {\n    const responseBody = body !== undefined && body !== null && body !== ' ' ? body : 'empty body';\n    this.logResponse(responseBody, requestId);\n\n    resolve(body);\n  }\n\n  public processAjaxError(\n    response: FetchResponse | null,\n    body: ProxyResponseBody,\n    error: unknown,\n    reject: (reason?: unknown) => void,\n    resolve: (value: ProxyResponseBody) => void,\n    params: Proxy.Params,\n    requestId: number\n  ): void {\n    const err = error as { code?: number; errno?: unknown };\n    if (!response && error && !err.code) {\n      reject(error);\n      return;\n    }\n\n    const bodyObj = body as { errors?: unknown } | null;\n    const responseBody = body || error || bodyObj?.errors;\n    const statusCode = response?.status;\n    const code: number | undefined = (response && statusCode) || (error ? err.code : undefined);\n    const rawInfo =\n      (body && typeof body === 'string' && body !== ' ' ? JSON.parse(body) : body) || (error ? err.errno : undefined);\n    const errorObject: Proxy.ErrorObject = {\n      code,\n      info: rawInfo as Proxy.ErrorObject['info'],\n    };\n\n    this.logResponse(responseBody, requestId);\n\n    if ((response?.url ?? '').indexOf(config.urls.session) === -1) {\n      if (this.isExpiredSessionError(errorObject) && typeof config.on.sessionExpired === 'function') {\n        this.handleExpiredSessionResponse(errorObject, null, reject, resolve, params);\n      } else {\n        reject(errorObject);\n      }\n    } else {\n      reject(errorObject);\n    }\n  }\n\n  public handleExpiredSessionResponse(\n    error: Proxy.ErrorObject | null,\n    response: ProxyResponseBody | null,\n    reject: (reason?: unknown) => void,\n    resolve: (value: ProxyResponseBody) => void,\n    params: Proxy.Params\n  ): void {\n    const handleResponse = () => {\n      if (error) {\n        reject(error);\n      } else {\n        resolve(response);\n      }\n    };\n\n    const retryCallback = (session: Partial<Auth.Session>) => {\n      if (session) {\n        this.setSession(session);\n        this.ajax(params).then(resolve).catch(reject);\n      }\n    };\n\n    if (typeof config.on.sessionExpired === 'function') {\n      config.on.sessionExpired(handleResponse, retryCallback);\n    }\n  }\n\n  private isExpiredSessionError(error: Proxy.ErrorObject): boolean {\n    try {\n      return error && error.code === 401 && error.info?.errors?.base?.[0] === 'Required session does not exist';\n    } catch {\n      return false;\n    }\n  }\n}\n","import type { AddressBook } from './types';\nimport { ProxyMethod } from './types/constants';\nimport ProxyService from './Proxy';\nimport Utils from './Utils';\nimport config from './config';\n\nexport default class AddressBookService {\n  public proxy: ProxyService;\n  readonly route = config.urls.addressbook;\n\n  constructor(proxy: ProxyService) {\n    this.proxy = proxy;\n  }\n\n  public async uploadAddressBook(\n    list: AddressBook.Contact[] = [],\n    params: AddressBook.UploadParams = {}\n  ): Promise<AddressBook.UploadResponse> {\n    if (!Utils.isArray(list)) {\n      throw new Error('First parameter must be an Array.');\n    }\n\n    const ajaxParams = {\n      type: ProxyMethod.POST,\n      url: Utils.getUrl(this.route),\n      data: { contacts: list, ...params },\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async get(udid?: string): Promise<AddressBook.Contact[]> {\n    const ajaxParams = {\n      type: ProxyMethod.GET,\n      url: Utils.getUrl(this.route),\n      data: udid ? { udid } : undefined,\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async getRegisteredUsers(\n    params: AddressBook.GetRegisteredUsersParams = false\n  ): Promise<AddressBook.GetRegisteredUsersResponse> {\n    const ajaxParams = {\n      type: ProxyMethod.GET,\n      url: Utils.getUrl(this.route, 'registered_users'),\n      data: typeof params === 'boolean' ? { compact: params ? 1 : 0 } : params,\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n}\n","import type { Auth, Users, EmptyResponse } from './types';\nimport { ProxyMethod, ProxyType } from './types/constants';\nimport ProxyService from './Proxy';\nimport Utils from './Utils';\nimport config from './config';\n\nexport default class AuthService {\n  public proxy: ProxyService;\n\n  readonly routes = {\n    session: config.urls.session,\n    login: config.urls.login,\n  };\n\n  constructor(proxy: ProxyService) {\n    this.proxy = proxy;\n  }\n\n  public setSession = (session: Partial<Auth.Session>): void => {\n    this.proxy.setSession(session);\n  };\n\n  public getSession = async (): Promise<Auth.Session> => {\n    try {\n      const ajaxParams = {\n        type: ProxyMethod.GET,\n        url: Utils.getUrl(this.routes.session),\n      };\n      const response = await this.proxy.ajax<Auth.GetSessionRawResponse>(ajaxParams);\n      return response.session;\n    } catch (error) {\n      throw error;\n    }\n  };\n\n  public createSession = async (params: Auth.LoginParams | {} = {}): Promise<Auth.Session> => {\n    if (config.creds.appId === '' || config.creds.authKey === '') {\n      throw new Error('Cannot create a new session without \"appId\" and \"authKey\"');\n    }\n\n    try {\n      const ajaxParams = {\n        type: ProxyMethod.POST,\n        url: Utils.getUrl(this.routes.session),\n        data: this.generateCreateSessionParams(params),\n      };\n      const response = await this.proxy.ajax<Auth.GetSessionRawResponse>(ajaxParams);\n      this.proxy.setSession(response.session);\n      this.proxy.setCurrentUserId(response.session.user_id);\n      return response.session;\n    } catch (error) {\n      throw error;\n    }\n  };\n\n  public destroySession = async (): Promise<EmptyResponse> => {\n    try {\n      const ajaxParams = {\n        type: ProxyMethod.DELETE,\n        url: Utils.getUrl(this.routes.session),\n        dataType: ProxyType.TEXT,\n      };\n      await this.proxy.ajax(ajaxParams);\n      this.proxy.setSession(null);\n      this.proxy.setCurrentUserId(null);\n    } catch (error) {\n      throw error;\n    }\n  };\n\n  public login = async (params: Auth.LoginParams): Promise<Users.User> => {\n    try {\n      const ajaxParams = {\n        type: ProxyMethod.POST,\n        url: Utils.getUrl(this.routes.login),\n        data: params,\n      };\n      const { user } = await this.proxy.ajax<Auth.LoginRawResponse>(ajaxParams);\n      this.proxy.setCurrentUserId(user.id);\n      return user;\n    } catch (error) {\n      throw error;\n    }\n  };\n\n  public logout = async (): Promise<EmptyResponse> => {\n    const ajaxParams = {\n      type: ProxyMethod.DELETE,\n      url: Utils.getUrl(this.routes.login),\n      dataType: ProxyType.TEXT,\n    };\n    this.proxy.setCurrentUserId(null);\n    return this.proxy.ajax(ajaxParams);\n  };\n\n  private generateCreateSessionParams(params: Auth.LoginParams | {} = {}): Auth.GeneratedSessionParams {\n    const message: Auth.GeneratedSessionParams = {\n      application_id: config.creds.appId ?? '',\n      auth_key: config.creds.authKey ?? '',\n    };\n\n    if ('guest' in params) {\n      message.user = params;\n    } else if ('login' in params && 'password' in params) {\n      message.user = { login: params.login, password: params.password };\n    } else if ('email' in params && 'password' in params) {\n      message.user = { email: params.email, password: params.password };\n    } else if ('provider' in params) {\n      message.provider = params.provider;\n      if ('keys' in params) {\n        message.keys = params.keys;\n      }\n      if ('firebase_phone' in params) {\n        message.firebase_phone = params.firebase_phone;\n      }\n      if ('firebase_email' in params) {\n        message.firebase_email = params.firebase_email;\n      }\n    }\n\n    return message;\n  }\n}\n","import type { XMPPClient, XMPPCredentials, XMPPCredentialsAuth, XMPPOptions, XMPPUserAgent } from '@xmppClient';\nimport type { FAST } from '@xmpp/client-core/src/fast/fast.js';\n\nexport function createOnAuthenticate(credentials: XMPPCredentials = {}, userAgent: XMPPUserAgent) {\n  return async function onAuthenticate(...args: unknown[]) {\n    const [authenticate, mechanisms, fast, entity] = args as [XMPPCredentialsAuth, string[], FAST, XMPPClient];\n\n    if (typeof credentials === 'function') {\n      const mechanism = getMechanism(mechanisms, entity);\n\n      await credentials(authenticate, mechanism);\n    } else {\n      credentials.token ??= await fast?.fetch();\n\n      const mechanism = getMechanism(mechanisms, entity, credentials);\n\n      await authenticate(credentials, mechanism, userAgent);\n    }\n  };\n}\n\nexport function getMechanism(mechanisms: string[], entity: XMPPClient, options?: XMPPOptions): string {\n  const username = options?.username || entity.options?.username;\n  const password = options?.password || entity.options?.password;\n  const token = options?.token || entity.options?.token;\n\n  if (!username && !password && !token && mechanisms.includes('ANONYMOUS')) {\n    return 'ANONYMOUS';\n  }\n\n  if (entity.isSecure() || entity.tcpEnabled) return mechanisms[0];\n\n  return mechanisms.find((mechanism) => mechanism !== 'PLAIN') ?? '';\n}\n\nexport function getDomain(service: string): string {\n  const domain = service.split('://')[1] || service;\n\n  return domain.split(':')[0].split('/')[0];\n}\n\nexport function setupIfAvailable(module?: (...args: any[]) => any, ...args: unknown[]): unknown {\n  if (typeof module !== 'function') {\n    return undefined;\n  }\n\n  return module(...args);\n}\n","import config from '../../config';\nimport { xml } from '@xmpp/client-core';\nimport type { Chat, PlainObject, StringObject, StringOrStringObject } from '../../types/index';\n\nexport default class ChatUtils {\n  static buildUserJid(params: Chat.UserJIDParams = {}): string | void {\n    const { userId, resource, jid } = params;\n    const appId = config.creds.appId;\n    const url = config.endpoints.chat;\n\n    return userId ? `${userId}-${appId}@${url}${resource ? `/${resource}` : ''}` : jid;\n  }\n\n  static buildUserJidLocalPart(userId: string | number): string {\n    return `${userId}-${config.creds.appId}`;\n  }\n\n  static createMessageStanza(attrs?: StringOrStringObject): Chat.XmlElement {\n    return xml('message', attrs);\n  }\n\n  static createIqStanza(attrs?: StringOrStringObject): Chat.XmlElement {\n    return xml('iq', attrs);\n  }\n\n  static createPresenceStanza(attrs?: StringOrStringObject): Chat.XmlElement {\n    return xml('presence', attrs);\n  }\n\n  static createNonza(name: string, attrs?: StringOrStringObject): Chat.XmlElement {\n    return xml(name, attrs);\n  }\n\n  static getAttr(element: Chat.XmlElement | undefined, name: string): string {\n    return element?.getAttr(name) || element?.attrs[name] || '';\n  }\n\n  static getElement(element: Chat.XmlElement | undefined, name: string): Chat.XmlElement | undefined {\n    return element?.getChild(name);\n  }\n\n  static getName(element: Chat.XmlElement): string | null {\n    return element?.getName() || null;\n  }\n\n  static getText(element: Chat.XmlElement): string | null {\n    return element?.getText() || null;\n  }\n\n  static getChildElements(element: Chat.XmlElement | undefined): Chat.XmlElement[] {\n    return element?.getChildElements() || [];\n  }\n\n  static isErrorStanza(element: Chat.XmlElement): boolean {\n    return !!element?.getChild('error');\n  }\n\n  static getAllElements(element: Chat.XmlElement, name: string): Chat.XmlElement[] {\n    return element?.getChildren(name) || [];\n  }\n\n  static getElementText(element: Chat.XmlElement, name: string): string | null {\n    return element?.getChildText(name) || null;\n  }\n\n  static getElementTreePath(element: Chat.XmlElement, elementsPath: string[]): Chat.XmlElement | undefined {\n    return elementsPath.reduce<Chat.XmlElement | undefined>(\n      (prevElement: Chat.XmlElement | undefined, name: string) =>\n        prevElement ? ChatUtils.getElement(prevElement, name) : undefined,\n      element as Chat.XmlElement\n    );\n  }\n\n  static assignObjectToXml(element: Chat.XmlElement, obj: PlainObject, name: string): Chat.XmlElement {\n    element = element.c(name);\n\n    Object.keys(obj).forEach((key: string) => {\n      const val = obj[key] as PlainObject;\n\n      if (val !== null && typeof val === 'object') {\n        ChatUtils.assignObjectToXml(element, val, key);\n      } else {\n        element = element\n          .c(key)\n          .t(String(val ?? ''))\n          .up();\n      }\n    });\n\n    element = element.up();\n\n    return element;\n  }\n\n  static assignExtraParamsToXml(element: Chat.XmlElement, extension: PlainObject): Chat.XmlElement {\n    let extraParams = ChatUtils.getElement(element, 'extraParams');\n\n    Object.keys(extension).forEach((key) => {\n      const val = extension[key];\n\n      if (key === 'attachments' && Array.isArray(val)) {\n        val.forEach((attachment: unknown) => {\n          extraParams!.c('attachment', attachment as StringObject).up();\n        });\n      } else if (val !== null && typeof val === 'object') {\n        ChatUtils.assignObjectToXml(extraParams!, val as PlainObject, key);\n      } else {\n        extraParams!\n          .c(key)\n          .t(String(val ?? ''))\n          .up();\n      }\n    });\n\n    element.up();\n\n    return element;\n  }\n\n  static assignXmlToObject(element: Chat.XmlElement, obj: PlainObject): PlainObject {\n    const { children, name } = element;\n    const item: PlainObject = { [name]: {} };\n\n    children.forEach((node: Chat.XmlNode) => {\n      if (typeof node === 'string') {\n        (item as PlainObject)[name] = node;\n      } else if (node.children.length > 0) {\n        ChatUtils.assignXmlToObject(node, (item[name] as PlainObject) || {});\n      } else {\n        ((item[name] as PlainObject) || {})[node.name] = ChatUtils.getText(node);\n      }\n    });\n\n    return Object.assign(obj, item);\n  }\n\n  static parseExtraParams(element: Chat.XmlElement): Chat.ParseExtraParamsResult | null {\n    if (!element) {\n      return null;\n    }\n\n    const extension: Chat.MessageExtension = { attachments: [] };\n    let dialogId: string | null = null;\n\n    element.children.forEach((node: Chat.XmlNode) => {\n      if (typeof node === 'string') {\n        return;\n      }\n\n      if (node.name === 'attachment') {\n        const attachment: PlainObject = {};\n\n        Object.keys(node.attrs).forEach((key: string) => {\n          attachment[key] = key === 'size' ? parseInt(String(node.attrs.size), 10) : node.attrs[key];\n        });\n\n        extension.attachments!.push(attachment);\n      } else if (node.name === 'dialog_id') {\n        dialogId = ChatUtils.getElementText(element, 'dialog_id');\n        extension.dialog_id = dialogId ?? undefined;\n      }\n\n      if (node.children.length) {\n        ChatUtils.assignXmlToObject(node, extension);\n      }\n    });\n\n    if (Array.isArray(extension.attachments) && extension.attachments.length === 0) {\n      delete extension.attachments;\n    }\n    if (extension.moduleIdentifier) {\n      delete extension.moduleIdentifier;\n    }\n\n    return { extension, dialogId };\n  }\n\n  static buildErrorFromXMPPErrorStanza(errorStanza: Chat.XmlElement): { code: number; info: string | null } {\n    const errorElement = ChatUtils.getElement(errorStanza, 'error');\n    const code = errorElement ? parseInt(ChatUtils.getAttr(errorElement, 'code') || '0', 10) : 0;\n    const info = errorElement ? ChatUtils.getElementText(errorElement, 'text') : null;\n    return { code: code, info: info };\n  }\n\n  static getUniqueId(suffix?: unknown): string {\n    const uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n      const r = (Math.random() * 16) | 0;\n      const v = c == 'x' ? r : (r & 0x3) | 0x8;\n      return v.toString(16);\n    });\n\n    if (typeof suffix === 'string' || typeof suffix === 'number') {\n      return `${uuid}:${suffix}`;\n    } else {\n      return uuid;\n    }\n  }\n\n  static parseReactions(element: Chat.XmlElement): Chat.ParseReactionsResult {\n    const reactions = ChatUtils.getChildElements(element).map((node: Chat.XmlElement) => ({\n      add: ChatUtils.getAttr(node, 'add') === 'true',\n      remove: ChatUtils.getAttr(node, 'remove') === 'true',\n      reaction: ChatUtils.getAttr(node, 'type'),\n    }));\n\n    return reactions.reduce((items, { add, remove, reaction }) => {\n      if (add) {\n        items['add'] = reaction;\n      } else if (remove) {\n        items['remove'] = reaction;\n      }\n      return items;\n    }, {} as Chat.ParseReactionsResult);\n  }\n}\n","import Utils from '../../Utils';\nimport config from '../../config';\nimport ChatUtils from './ChatUtils';\n\nexport default class ChatHelpers {\n  public xmppJID: string = '';\n\n  public get userCurrentJid(): string | '' {\n    return this.xmppJID;\n  }\n\n  public set userCurrentJid(jid: string | null) {\n    this.xmppJID = jid || '';\n  }\n\n  public getUniqueId = ChatUtils.getUniqueId;\n\n  public isNumeric(value: string): boolean {\n    return /^-?\\d+$/.test(value) || /^\\d+\\.\\d+$/.test(value);\n  }\n\n  public jidOrUserId(jidOrUserId: string | number): string {\n    if (typeof jidOrUserId === 'string') {\n      return this.isNumeric(jidOrUserId)\n        ? this.getUserJid(jidOrUserId)\n        : jidOrUserId.includes('@')\n          ? jidOrUserId\n          : this.getRoomJidFromDialogId(jidOrUserId);\n    }\n\n    return this.getUserJid(jidOrUserId);\n  }\n\n  public typeChat(jidOrUserId: string | number): 'chat' | 'groupchat' {\n    switch (typeof jidOrUserId) {\n      case 'string':\n        return this.isNumeric(jidOrUserId)\n          ? 'chat'\n          : jidOrUserId.includes('@')\n            ? jidOrUserId.includes('muc')\n              ? 'groupchat'\n              : 'chat'\n            : 'groupchat';\n      case 'number':\n        return 'chat';\n      default:\n        throw new Error('Unsupported chat type');\n    }\n  }\n\n  public getUserJid(userId: string | number): string {\n    return `${userId}-${config.creds.appId}@${config.endpoints.chat}`;\n  }\n\n  public getUserNickWithMucDomain(userId: string | number): string {\n    return `${config.endpoints.muc}/${userId}`;\n  }\n\n  public getUserIdFromJID(jid: string = this.userCurrentJid): number | null {\n    return jid?.includes('@') ? parseInt(jid.split('@')[0].split('-')[0]) : null;\n  }\n\n  public getDialogIdFromJID(jid: string): string | null {\n    return jid?.includes('@') ? jid.split('@')[0].split('_')[1] : null;\n  }\n\n  public getRoomJidFromDialogId(dialogId: string): string {\n    return `${config.creds.appId}_${dialogId}@${config.endpoints.muc}`;\n  }\n\n  public getRoomJid(jid: string): string {\n    return `${jid}/${this.getUserIdFromJID(this.userCurrentJid)}`;\n  }\n\n  public getIdFromResource(jid: string): number | null {\n    const parts = jid.split('/');\n    return parts.length > 1 ? parseInt(parts.slice(1).join('/')) : null;\n  }\n\n  public getRoomJidFromRoomFullJid(jid: string): string | null {\n    const parts = jid.split('/');\n    return parts.length > 1 ? parts[0] : null;\n  }\n\n  public getBsonObjectId = Utils.getBsonObjectId;\n\n  public getUserIdFromRoomJid(roomJid: string): number | null {\n    const parts = roomJid.split('/');\n    return parts.length > 1 ? parseInt(parts[parts.length - 1]) : null;\n  }\n\n  getDialogJid(identifier: string): string {\n    return identifier.indexOf('@') > 0 ? identifier : this.getRoomJidFromDialogId(identifier);\n  }\n}\n","import type { Chat, StringObject } from '../../types';\nimport type XMPPChatService from '.';\nimport { ChatProtocol, ChatType } from '../../types/constants';\nimport config from '../../config';\nimport ChatUtils from './ChatUtils';\nimport Utils from '../../Utils';\n\nconst NonzaName = {\n  ENABLE: 'enable',\n  ENABLED: 'enabled',\n  REQUEST: 'r',\n  ANSWER: 'a',\n} as const;\n\nexport default class StreamManagement {\n  readonly xmlns = 'urn:xmpp:sm:3';\n\n  private enabled: boolean = false;\n  private clientHandledCounter: number = 0;\n  private serverHandledCounter: number = 0;\n  private messagesQueue: Set<Chat.MessageParams> = new Set();\n  private messagesQueueClearTimer?: NodeJS.Timeout | number;\n\n  constructor(private chat: XMPPChatService) {}\n\n  public get supported(): boolean {\n    return config.chatProtocol.active === ChatProtocol.WS && (config.chat.streamManagement?.enable ?? false);\n  }\n\n  public start(): void {\n    this.enabled = false;\n\n    if (this.supported) {\n      this.removeElementHandler();\n      this.addElementHandler();\n      this.sendNonza(NonzaName.ENABLE);\n    }\n  }\n\n  public stop(): void {\n    this.enabled = false;\n\n    if (this.supported) {\n      this.removeElementHandler();\n      this.markMessagesQueueAsLost();\n    }\n  }\n\n  public async sendAndCount(stanza: Chat.XmlElement, message: Chat.MessageParams): Promise<void> {\n    const type = ChatUtils.getAttr(stanza, 'type');\n    const body = ChatUtils.getElementText(stanza, 'body');\n    const attachments = ChatUtils.getAllElements(stanza, 'attachment');\n    const isMessage = stanza.name === 'message';\n    const isChat = type === ChatType.CHAT || type === ChatType.GROUPCHAT;\n    const isContent = Boolean(body || attachments.length);\n\n    try {\n      await this.chat.xmppClient.sendOnline(stanza);\n\n      if (this.enabled && isMessage && isChat && isContent) {\n        this.messagesQueue.add(message);\n        this.sendNonza(NonzaName.REQUEST);\n      }\n    } catch {\n      this.markMessageAsLost(message);\n    }\n  }\n\n  private elementHandler = (stanza: Chat.XmlElement): void => {\n    const [name, xmlns] = [stanza.name, ChatUtils.getAttr(stanza, 'xmlns')];\n\n    if (xmlns === this.xmlns && name === NonzaName.ENABLED) {\n      this.clientHandledCounter = 0;\n      this.serverHandledCounter = 0;\n      this.enabled = true;\n      return;\n    }\n\n    if (xmlns !== this.xmlns) this.clientHandledCounter++;\n\n    if (name === NonzaName.REQUEST) {\n      this.sendNonza(NonzaName.ANSWER);\n      return;\n    }\n\n    if (name === NonzaName.ANSWER) {\n      const nextHandledCounter = parseInt(ChatUtils.getAttr(stanza, 'h'), 10);\n      const currHandledCounter = Number.isNaN(nextHandledCounter) ? this.serverHandledCounter : nextHandledCounter;\n      const diffHandledCounter = currHandledCounter - this.serverHandledCounter;\n\n      this.serverHandledCounter = currHandledCounter;\n      this.markMessagesQueueAsSent(diffHandledCounter);\n      this.markMessagesQueueAsLostByTimeout();\n    }\n  };\n\n  private markMessageAsSent(message: Chat.MessageParams): void {\n    Utils.safeCallbackCall(this.chat.onSentMessageCallback)(null, message);\n    this.messagesQueue.delete(message);\n  }\n\n  private markMessageAsLost(message: Chat.MessageParams, clear: boolean = true): void {\n    Utils.safeCallbackCall(this.chat.onSentMessageCallback)(message, null);\n    if (clear) this.messagesQueue.delete(message);\n  }\n\n  private markMessagesQueueAsSent(iterations: number = 0): void {\n    const iterator = this.messagesQueue.values();\n\n    for (let i = 0; i < iterations; i++) {\n      const { done, value } = iterator.next();\n      if (done) break;\n      this.markMessageAsSent(value);\n    }\n  }\n\n  private markMessagesQueueAsLost(): void {\n    clearTimeout(this.messagesQueueClearTimer);\n    this.messagesQueueClearTimer = undefined;\n\n    if (this.messagesQueue.size > 0) {\n      this.messagesQueue.forEach((message) => {\n        this.markMessageAsLost(message, false);\n      });\n      this.messagesQueue.clear();\n    }\n  }\n\n  private markMessagesQueueAsLostByTimeout(): void {\n    const ackTimeout = (config.chat.streamManagement?.acknowledgementTimeout ?? 30) * 1000;\n\n    clearTimeout(this.messagesQueueClearTimer);\n    this.messagesQueueClearTimer = setTimeout(() => {\n      this.markMessagesQueueAsLost();\n    }, ackTimeout);\n  }\n\n  private sendNonza(name: string): Promise<void> {\n    const attrs: StringObject =\n      name === NonzaName.ANSWER ? { xmlns: this.xmlns, h: String(this.clientHandledCounter) } : { xmlns: this.xmlns };\n    const nonza = ChatUtils.createNonza(name, attrs);\n\n    return this.chat.xmppClient.sendOnline(nonza);\n  }\n\n  private removeElementHandler(): void {\n    this.chat.xmppClient.removeListener('element', this.elementHandler);\n  }\n\n  private addElementHandler(): void {\n    this.chat.xmppClient.on('element', this.elementHandler);\n  }\n}\n","import type { XMPPClient } from '@xmppClient';\nimport type { Chat } from '../../types';\nimport { PrivacyListAction } from '../../types/constants';\nimport ChatUtils from './ChatUtils';\nimport ChatHelpers from './Helpers';\n\nexport default class PrivacyList {\n  readonly xmlns = 'jabber:iq:privacy';\n  public helpers: ChatHelpers;\n  public xmppClient: XMPPClient;\n  public stanzasCallbacks: Chat.StanzasCallbacks;\n\n  constructor(options: { helpers: ChatHelpers; xmppClient: XMPPClient; stanzasCallbacks: Chat.StanzasCallbacks }) {\n    this.helpers = options.helpers;\n    this.xmppClient = options.xmppClient;\n    this.stanzasCallbacks = options.stanzasCallbacks;\n  }\n\n  public async create(list: Chat.PrivacyList): Promise<void> {\n    return new Promise((resolve, reject) => {\n      const privacyList = list.items.reduce(\n        (acc, { user_id, action, mutualBlock }) => {\n          acc[user_id] = { action, mutualBlock };\n          return acc;\n        },\n        {} as Record<string, Partial<Chat.PrivacyListItem>>\n      );\n\n      const privacyListKeys = Object.keys(privacyList);\n      const iqParams = {\n        type: 'set',\n        from: this.helpers.userCurrentJid,\n        id: ChatUtils.getUniqueId('edit'),\n      };\n\n      let iq = ChatUtils.createIqStanza(iqParams);\n\n      iq.c('query', { xmlns: this.xmlns }).c('list', { name: list.name });\n\n      for (let index = 0, j = 0, len = privacyListKeys.length; index < len; index++, j = j + 2) {\n        const userId = privacyListKeys[index];\n        const { action = '', mutualBlock = false } = privacyList[userId];\n        const isMutual = mutualBlock && action === 'deny';\n        const userJid = this.helpers.jidOrUserId(parseInt(userId, 10));\n        const userMuc = this.helpers.getUserNickWithMucDomain(userId);\n\n        this.assignPrivacyItem(iq, { order: j + 1, value: userJid, action, isMutual });\n        this.assignPrivacyItem(iq, { order: j + 2, value: userMuc, action, isMutual });\n      }\n\n      this.stanzasCallbacks[iqParams.id] = (stanza: Chat.XmlElement) => {\n        ChatUtils.isErrorStanza(stanza) ? reject(ChatUtils.buildErrorFromXMPPErrorStanza(stanza)) : resolve();\n      };\n\n      this.xmppClient.sendOnline(iq);\n    });\n  }\n\n  public async getList(name: string): Promise<Chat.PrivacyList> {\n    return new Promise((resolve, _reject) => {\n      const id = ChatUtils.getUniqueId('getlist');\n      const iq = ChatUtils.createIqStanza({\n        type: 'get',\n        from: this.helpers.userCurrentJid,\n        id,\n      });\n\n      iq.c('query', { xmlns: this.xmlns }).c('list', { name });\n\n      this.stanzasCallbacks[id] = (stanza: Chat.XmlElement): void => {\n        const query = stanza ? ChatUtils.getElement(stanza, 'query') : undefined;\n        const list = query ? ChatUtils.getElement(query, 'list') : undefined;\n\n        const privacyList: Chat.PrivacyList = {\n          name: ChatUtils.getAttr(list, 'name'),\n          items: ChatUtils.getChildElements(list)\n            .map((item, index) => {\n              if (index % 2 === 0) {\n                const { action, value } = item.attrs;\n                return {\n                  user_id: this.helpers.getUserIdFromJID(value),\n                  action: action,\n                } as Chat.PrivacyListItem;\n              }\n              return null;\n            })\n            .filter((item) => item !== null),\n        };\n\n        resolve(privacyList);\n\n        delete this.stanzasCallbacks[id];\n      };\n\n      this.xmppClient.sendOnline(iq);\n    });\n  }\n\n  public async update(list: Chat.PrivacyList): Promise<void> {\n    try {\n      const currentList = await this.getList(list.name);\n      const map = new Map(currentList.items.map((currentListItem) => [currentListItem.user_id, currentListItem]));\n\n      for (const item of list.items) {\n        if (item.action === PrivacyListAction.ALLOW) {\n          map.delete(item.user_id);\n        } else {\n          const updatedItem = Object.assign({}, map.get(item.user_id), item);\n          map.set(item.user_id, updatedItem);\n        }\n      }\n\n      const updatedListItems = Array.from(map.values());\n      const updatedList = { name: list.name, items: updatedListItems };\n\n      await this.create(updatedList);\n    } catch (error) {\n      throw error;\n    }\n  }\n\n  public async getNames(): Promise<Chat.PrivacyListNames> {\n    return new Promise((resolve, reject) => {\n      const id = ChatUtils.getUniqueId('getNames');\n      const iq = ChatUtils.createIqStanza({\n        type: 'get',\n        from: this.helpers.userCurrentJid,\n        id,\n      });\n\n      iq.c('query', { xmlns: this.xmlns });\n\n      this.stanzasCallbacks[id] = (stanza: Chat.XmlElement) => {\n        if (!ChatUtils.isErrorStanza(stanza)) {\n          const query = stanza ? ChatUtils.getElement(stanza, 'query') : undefined;\n          const defaultElement = query ? ChatUtils.getElement(query, 'default') : undefined;\n          const activeElement = query ? ChatUtils.getElement(query, 'active') : undefined;\n          const defaultName = defaultElement ? ChatUtils.getAttr(defaultElement, 'name') : null;\n          const activeName = activeElement ? ChatUtils.getAttr(activeElement, 'name') : null;\n          const allNames = query\n            ? ChatUtils.getChildElements(query).map((listEl) => ChatUtils.getAttr(listEl, 'name'))\n            : [];\n\n          const namesList: Chat.PrivacyListNames = {\n            default: defaultName,\n            active: activeName,\n            names: allNames,\n          };\n\n          resolve(namesList);\n        } else {\n          reject(ChatUtils.buildErrorFromXMPPErrorStanza(stanza));\n        }\n      };\n\n      this.xmppClient.sendOnline(iq);\n    });\n  }\n\n  public async delete(name: string): Promise<void> {\n    return new Promise((resolve, reject) => {\n      const id = ChatUtils.getUniqueId('remove');\n      const iq = ChatUtils.createIqStanza({\n        type: 'set',\n        from: this.helpers.userCurrentJid,\n        id,\n      });\n\n      iq.c('query', { xmlns: this.xmlns }).c('list', { name: name ? name : '' });\n\n      this.stanzasCallbacks[id] = (stanza: Chat.XmlElement) => {\n        ChatUtils.isErrorStanza(stanza) ? reject(ChatUtils.buildErrorFromXMPPErrorStanza(stanza)) : resolve();\n      };\n\n      this.xmppClient.sendOnline(iq);\n    });\n  }\n\n  public async setAsDefault(name: string | null): Promise<void> {\n    return new Promise((resolve, reject) => {\n      const id = ChatUtils.getUniqueId('default');\n      const iq = ChatUtils.createIqStanza({\n        type: 'set',\n        from: this.helpers.userCurrentJid,\n        id,\n      });\n\n      iq.c('query', { xmlns: this.xmlns }).c('default', name ? { name: name } : {});\n\n      this.stanzasCallbacks[id] = (stanza: Chat.XmlElement) => {\n        ChatUtils.isErrorStanza(stanza) ? reject(ChatUtils.buildErrorFromXMPPErrorStanza(stanza)) : resolve();\n      };\n\n      this.xmppClient.sendOnline(iq);\n    });\n  }\n\n  private assignPrivacyItem(iq: Chat.XmlElement, params: Chat.PrivacyListItemParams): void {\n    const { value, action, order, isMutual } = params;\n    const query = iq ? ChatUtils.getElement(iq, 'query') : undefined;\n    const list = query ? ChatUtils.getElement(query, 'list') : undefined;\n\n    if (!list) return;\n\n    const item = list.c('item', { type: 'jid', value, action, order });\n\n    if (isMutual) {\n      item.up();\n\n      if (order % 2 === 0) {\n        iq.up().up();\n      }\n    } else {\n      item.c('message', {}).up().c('presence-in', {}).up().c('presence-out', {}).up().c('iq', {}).up().up();\n    }\n  }\n}\n","import type { XMPPClient } from '@xmppClient';\nimport type { Chat } from '../../types';\nimport ChatHelpers from './Helpers';\nimport ChatUtils from './ChatUtils';\n\nexport default class MultiUserChat {\n  readonly xmlns = 'http://jabber.org/protocol/muc';\n  public helpers: ChatHelpers;\n  public xmppClient: XMPPClient;\n  public stanzasCallbacks: Chat.StanzasCallbacks;\n  public joinedRooms: { [jid: string]: boolean } = {};\n\n  constructor(options: { helpers: ChatHelpers; xmppClient: XMPPClient; stanzasCallbacks: Chat.StanzasCallbacks }) {\n    this.helpers = options.helpers;\n    this.xmppClient = options.xmppClient;\n    this.stanzasCallbacks = options.stanzasCallbacks;\n  }\n\n  public async join(dialogIdOrJid: string): Promise<void> {\n    return new Promise((resolve, reject) => {\n      const id = ChatUtils.getUniqueId('join');\n      const dialogJid = this.helpers.getDialogJid(dialogIdOrJid);\n      const presenceStanza = ChatUtils.createPresenceStanza({\n        id: id,\n        from: this.helpers.userCurrentJid,\n        to: this.helpers.getRoomJid(dialogJid),\n      });\n\n      presenceStanza.c('x', { xmlns: this.xmlns }).c('history', { maxstanzas: 0 });\n\n      this.stanzasCallbacks[id] = (stanza: Chat.XmlElement) => {\n        const x = stanza ? ChatUtils.getElement(stanza, 'x') : undefined;\n        const status = x ? ChatUtils.getElement(x, 'status') : undefined;\n        const code = status ? ChatUtils.getAttr(status, 'code') : undefined;\n\n        if (code === '110') {\n          this.joinedRooms[dialogJid] = true;\n          resolve();\n        } else {\n          const isJoin = ChatUtils.getAttr(x, 'xmlns') === this.xmlns && id.endsWith(':join');\n          const isError = ChatUtils.getAttr(stanza, 'type') === 'error';\n\n          if (isJoin && isError) {\n            const errorElement = ChatUtils.getElement(stanza, 'error');\n\n            if (!errorElement) {\n              reject(new Error('Unknown error'));\n              return;\n            }\n\n            const errorResponse = {\n              code: ChatUtils.getAttr(errorElement, 'code'),\n              message: ChatUtils.getElementText(errorElement, 'text') || 'Unknown issue',\n            };\n\n            reject(errorResponse);\n          }\n        }\n      };\n\n      this.xmppClient.sendOnline(presenceStanza);\n    });\n  }\n\n  public async leave(dialogIdOrJid: string): Promise<void> {\n    return new Promise((resolve) => {\n      const dialogJid = this.helpers.getDialogJid(dialogIdOrJid);\n      const presenceStanza = ChatUtils.createPresenceStanza({\n        type: 'unavailable',\n        from: this.helpers.userCurrentJid,\n        to: this.helpers.getRoomJid(dialogJid),\n      });\n\n      delete this.joinedRooms[dialogJid];\n\n      this.stanzasCallbacks['muc:leave'] = (_stanza: Chat.XmlElement) => {\n        resolve();\n      };\n\n      this.xmppClient.sendOnline(presenceStanza);\n    });\n  }\n\n  public async listOnlineUsers(dialogIdOrJid: string): Promise<number[]> {\n    return new Promise((resolve, _reject) => {\n      const id = ChatUtils.getUniqueId('muc_disco_items');\n      const iqStanza = ChatUtils.createIqStanza({\n        type: 'get',\n        to: this.helpers.getDialogJid(dialogIdOrJid),\n        from: this.helpers.userCurrentJid,\n        id,\n      });\n\n      iqStanza.c('query', { xmlns: 'http://jabber.org/protocol/disco#items' });\n\n      this.stanzasCallbacks[id] = (stanza: Chat.XmlElement) => {\n        const stanzaId = ChatUtils.getAttr(stanza, 'id');\n\n        if (this.stanzasCallbacks[stanzaId]) {\n          const query = ChatUtils.getElement(stanza, 'query');\n          const users = ChatUtils.getChildElements(query)\n            .map((item: Chat.XmlElement): number | null => {\n              const roomJid = ChatUtils.getAttr(item, 'jid');\n              return this.helpers.getUserIdFromRoomJid(roomJid);\n            })\n            .filter((userId: number | null) => userId !== null);\n\n          resolve(users);\n        }\n      };\n\n      this.xmppClient.sendOnline(iqStanza);\n    });\n  }\n}\n","import type { Dialogs, EmptyResponse, ForceParams } from '../../types';\nimport { ProxyMethod, ProxyType } from '../../types/constants';\nimport ProxyService from '../../Proxy';\nimport Utils from '../../Utils';\nimport config from '../../config';\n\nexport default class DialogsService {\n  public proxy: ProxyService;\n  readonly route = `${config.urls.chat}/Dialog`;\n\n  constructor(proxy: ProxyService) {\n    this.proxy = proxy;\n  }\n\n  public async list(params: Dialogs.ListParams = {}): Promise<Dialogs.ListResponse> {\n    const ajaxParams = {\n      type: ProxyMethod.GET,\n      url: Utils.getUrl(this.route),\n      data: params,\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async create(params: Dialogs.CreateParams): Promise<Dialogs.Dialog> {\n    const data = Utils.cloneObject(params);\n\n    const ajaxParams = {\n      type: ProxyMethod.POST,\n      url: Utils.getUrl(this.route),\n      data: {\n        ...data,\n        admins_ids: Utils.isArray(data.admins_ids) ? data.admins_ids.join(', ') : data.admins_ids,\n        occupants_ids: Utils.isArray(data.occupants_ids) ? data.occupants_ids.join(', ') : data.occupants_ids,\n      },\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async update(id: string, params: Dialogs.UpdateParams = {}): Promise<Dialogs.Dialog> {\n    const ajaxParams = {\n      type: ProxyMethod.PUT,\n      url: Utils.getUrl(this.route, id),\n      data: params,\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public delete(id: string, params?: ForceParams): Promise<EmptyResponse>;\n  public delete(ids: string[], params?: ForceParams): Promise<Dialogs.DeleteResponse>;\n  public async delete(\n    idOrIds: string | string[],\n    params: ForceParams = {}\n  ): Promise<Dialogs.DeleteResponse | EmptyResponse> {\n    const idsToDelete = typeof idOrIds === 'string' ? idOrIds.split(',').map((id) => id.trim()) : idOrIds;\n    const ajaxParams = {\n      type: ProxyMethod.DELETE,\n      url: Utils.getUrl(this.route, idsToDelete.toString()),\n      dataType: idsToDelete.length === 1 ? ProxyType.TEXT : ProxyType.JSON,\n      data: params,\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async addAdmins(id: string, admins_ids: number[]): Promise<Dialogs.Dialog> {\n    const ajaxParams = {\n      type: ProxyMethod.PUT,\n      url: Utils.getUrl(this.route, id, 'admins'),\n      data: { push_all: { admins_ids } },\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async removeAdmins(id: string, admins_ids: number[]): Promise<Dialogs.Dialog> {\n    const ajaxParams = {\n      type: ProxyMethod.PUT,\n      url: Utils.getUrl(this.route, id, 'admins'),\n      data: { pull_all: { admins_ids } },\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async subscribe(id: string): Promise<Dialogs.Dialog> {\n    const ajaxParams = {\n      type: ProxyMethod.POST,\n      url: Utils.getUrl(this.route, id, 'subscribe'),\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public subscribeToPublic = this.subscribe;\n\n  public async unsubscribe(id: string): Promise<EmptyResponse> {\n    const ajaxParams = {\n      type: ProxyMethod.DELETE,\n      url: Utils.getUrl(this.route, id, 'subscribe'),\n      dataType: ProxyType.TEXT,\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public unsubscribeFromPublic = this.unsubscribe;\n\n  public async updateNotificationsSettings(\n    id: string,\n    enabled: number | boolean\n  ): Promise<Dialogs.UpdateNotificationsSettingsResponse> {\n    const ajaxParams = {\n      type: ProxyMethod.PUT,\n      url: Utils.getUrl(this.route, id, 'notifications'),\n      data: { enabled: enabled ? 1 : 0 },\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async getNotificationsSettings(id: string): Promise<Dialogs.GetNotificationsSettingsResponse> {\n    const ajaxParams = {\n      type: ProxyMethod.GET,\n      url: Utils.getUrl(this.route, id, 'notifications'),\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async getPublicOccupants(\n    id: string,\n    params: Dialogs.GetPublicOccupantsParams = {}\n  ): Promise<Dialogs.GetPublicOccupantsResponse> {\n    const ajaxParams = {\n      type: ProxyMethod.GET,\n      url: Utils.getUrl(this.route, id, 'occupants'),\n      data: params,\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async clearHistory(id: string): Promise<EmptyResponse> {\n    const ajaxParams = {\n      type: ProxyMethod.DELETE,\n      url: Utils.getUrl(this.route, 'clearHistory', id),\n      dataType: ProxyType.TEXT,\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n}\n","import type { EmptyResponse, ForceParams, Messages } from '../../types';\nimport { ProxyMethod, ProxyType } from '../../types/constants';\nimport ProxyService from '../../Proxy';\nimport Utils from '../../Utils';\nimport config from '../../config';\n\nexport default class MessagesService {\n  public proxy: ProxyService;\n  readonly route = `${config.urls.chat}/Message`;\n\n  constructor(proxy: ProxyService) {\n    this.proxy = proxy;\n  }\n\n  public async list(params: Messages.ListParams = {}): Promise<Messages.ListResponse> {\n    const ajaxParams = {\n      url: Utils.getUrl(this.route),\n      data: params,\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async create(params: Messages.CreateParams = {}): Promise<Messages.Message> {\n    const ajaxParams = {\n      url: Utils.getUrl(this.route),\n      type: ProxyMethod.POST,\n      data: params,\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async update(id: string | string[], params: Messages.UpdateParams = {}): Promise<EmptyResponse> {\n    const ajaxParams = {\n      type: ProxyMethod.PUT,\n      dataType: ProxyType.TEXT,\n      url: Utils.getUrl(this.route, Array.isArray(id) ? id.join(',') : id),\n      data: params,\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async delete(ids: string | string[], params?: ForceParams): Promise<Messages.DeleteResponse> {\n    const res = Utils.isArray(ids) ? ids.join(',') : ids;\n    const ajaxParams = {\n      url: Utils.getUrl(this.route, res),\n      type: ProxyMethod.DELETE,\n      dataType: ProxyType.TEXT,\n      data: params,\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async createSystem(params: Messages.CreateSystemParams): Promise<Messages.CreateSystemResponse> {\n    const ajaxParams = {\n      type: ProxyMethod.POST,\n      url: Utils.getUrl(this.route, 'system'),\n      data: params,\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async unreadCount(params: Messages.UnreadCountParams = {}): Promise<Messages.UnreadCountResponse> {\n    const data = Utils.cloneObject(params);\n\n    if (data && data.chat_dialog_ids && Utils.isArray(data.chat_dialog_ids)) {\n      data.chat_dialog_ids = data.chat_dialog_ids.join(', ');\n    }\n\n    const ajaxParams = {\n      url: Utils.getUrl(this.route, 'unread'),\n      data: data,\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async listReactions(id: string = '_'): Promise<Messages.ListReactionsResponse> {\n    const ajaxParams = {\n      type: ProxyMethod.GET,\n      dataType: ProxyType.JSON,\n      url: Utils.getUrl(this.route, id, 'reactions'),\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async addReaction(id: string, reaction: string): Promise<EmptyResponse> {\n    return this.updateReaction(id, reaction);\n  }\n\n  public async removeReaction(id: string, reaction: string): Promise<EmptyResponse> {\n    return this.updateReaction(id, undefined, reaction);\n  }\n\n  public async updateReaction(id: string, add?: string, remove?: string): Promise<EmptyResponse> {\n    return this.putReaction(id, { add, remove });\n  }\n\n  private async putReaction(id: string, params: Messages.PutReactionParams): Promise<EmptyResponse> {\n    const ajaxParams = {\n      type: ProxyMethod.PUT,\n      dataType: ProxyType.TEXT,\n      url: Utils.getUrl(this.route, id, 'reactions'),\n      data: params,\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n}\n","import type WebRTCClient from './WebRTCClient';\nimport type { Calls } from '../types';\nimport { CallSignalingType } from '../types/constants';\n\nexport default class WebRTCSignalingProcessor {\n  public delegate: WebRTCClient;\n\n  constructor(delegate: WebRTCClient) {\n    this.delegate = delegate;\n  }\n\n  public onMessage = (userID: number, extension: Calls.ExtensionParams): void => {\n    const sessionId = extension?.sessionID ?? '';\n    const signalType = extension?.signalType;\n    /** cleanup */\n    delete extension?.moduleIdentifier;\n    delete extension?.sessionID;\n    delete extension?.signalType;\n\n    switch (signalType) {\n      case CallSignalingType.CALL:\n        this.delegate.onCallHandler(userID, sessionId, extension);\n        break;\n      case CallSignalingType.ACCEPT:\n        this.delegate.onAcceptHandler(userID, sessionId, extension);\n        break;\n      case CallSignalingType.REJECT:\n        this.delegate.onRejectHandler(userID, sessionId, extension);\n        break;\n      case CallSignalingType.STOP:\n        this.delegate.onStopHandler(userID, sessionId, extension);\n        break;\n      case CallSignalingType.CANDIDATE:\n        this.delegate.onIceCandidatesHandler(userID, sessionId, extension);\n        break;\n      case CallSignalingType.RESTART:\n        this.delegate.onIceRestartHandler(userID, sessionId, extension);\n        break;\n      case CallSignalingType.RESTART_ACCEPT:\n        this.delegate.onIceRestartAcceptHandler(userID, sessionId, extension);\n        break;\n    }\n  };\n}\n","import config from '../config';\nimport Utils from '../Utils';\nimport ProxyService from '../Proxy';\nimport DialogsService from './xmpp/Dialogs';\nimport MessagesService from './xmpp/Messages';\nimport WebRTCSignalingProcessor from '../videocalling/WebRTCSignalingProcessor';\nimport type { Chat } from '../types';\nimport { ChatEvent, ProxyMethod } from '../types/constants';\n\nexport default abstract class AbstractChatService {\n  public proxy: ProxyService;\n  public dialog: DialogsService;\n  public message: MessagesService;\n  declare webrtcSignalingProcessor: WebRTCSignalingProcessor;\n\n  public isConnected: boolean = false;\n  protected isConnecting: boolean = false;\n  protected isLogout: boolean = false;\n  protected isReconnect: boolean = false;\n\n  declare onChatStatusListener: Chat.OnChatStatusListener;\n  declare onConnectionErrorListener: Chat.OnChatConnectionErrorListener;\n  declare onDisconnectedListener: Chat.OnChatDisconnectedListener;\n  declare onReconnectListener: Chat.OnChatReconnectedListener;\n  declare onMessageListener: Chat.OnMessageListener;\n  declare onSystemMessageListener: Chat.OnMessageSystemListener;\n  declare onMessageTypingListener: Chat.OnMessageTypingListener;\n  declare onMessageUpdateListener: Chat.OnMessageUpdateListener;\n  declare onMessageDeleteListener: Chat.OnMessageDeleteListener;\n  declare onMessageReactionsListener: Chat.OnMessageReactionsListener;\n  declare onReadStatusListener: Chat.OnMessageReadListener;\n  declare onLastUserActivityListener: Chat.OnLastUserActivityListener;\n  declare onMessageErrorListener: Chat.OnMessageErrorListener;\n  declare onDeliveredStatusListener: Chat.OnMessageDeliveredListener;\n  declare onSentMessageCallback: Chat.OnMessageSentListener;\n  declare onJoinOccupant: Chat.OnDialogJoinListener;\n  declare onLeaveOccupant: Chat.OnDialogLeaveListener;\n  declare onKickOccupant: Chat.OnDialogKickListener;\n\n  constructor(proxy: ProxyService) {\n    this.proxy = proxy;\n    this.dialog = new DialogsService(proxy);\n    this.message = new MessagesService(proxy);\n  }\n\n  public async search(params: Chat.SearchParams): Promise<Chat.SearchResult> {\n    const query = Object.assign({}, params);\n\n    if (query.start_date) {\n      query.start_date = new Date(query.start_date).toISOString();\n    }\n    if (query.end_date) {\n      query.end_date = new Date(query.end_date).toISOString();\n    }\n    if (Utils.isArray(query.chat_dialog_ids)) {\n      query.chat_dialog_ids = (query.chat_dialog_ids as string[]).join(',');\n    }\n\n    const ajaxParams = {\n      type: ProxyMethod.GET,\n      url: Utils.getUrl(`${config.urls.chat}/search`),\n      data: query,\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public abstract ping(): Promise<void>;\n\n  public async pingWithTimeout(timeout: number = 5000): Promise<unknown> {\n    return new Promise(async (resolve, reject) => {\n      const error = `Failed to ping chat server ${config.chatProtocol.websocket}. Timed out after ${timeout}ms`;\n      const timer = setTimeout(() => {\n        Utils.safeCallbackCall(this.onConnectionErrorListener)(error);\n        reject(error);\n      }, timeout);\n\n      try {\n        const result = await this.ping();\n        clearTimeout(timer);\n        resolve(result);\n      } catch {\n        clearTimeout(timer);\n        reject(error);\n      }\n    });\n  }\n\n  protected getListenerByName(name: ChatEvent): Chat.ListenerName | null {\n    switch (name) {\n      case ChatEvent.STATUS:\n        return 'onChatStatusListener';\n      case ChatEvent.ERROR:\n        return 'onConnectionErrorListener';\n      case ChatEvent.DISCONNECTED:\n        return 'onDisconnectedListener';\n      case ChatEvent.RECONNECTED:\n        return 'onReconnectListener';\n      case ChatEvent.MESSAGE:\n        return 'onMessageListener';\n      case ChatEvent.SYSTEM_MESSAGE:\n        return 'onSystemMessageListener';\n      case ChatEvent.ERROR_MESSAGE:\n        return 'onMessageErrorListener';\n      case ChatEvent.TYPING_MESSAGE:\n        return 'onMessageTypingListener';\n      case ChatEvent.UPDATE_MESSAGE:\n        return 'onMessageUpdateListener';\n      case ChatEvent.DELETE_MESSAGE:\n        return 'onMessageDeleteListener';\n      case ChatEvent.REACTIONS_MESSAGE:\n        return 'onMessageReactionsListener';\n      case ChatEvent.DELIVERED_MESSAGE:\n        return 'onDeliveredStatusListener';\n      case ChatEvent.READ_MESSAGE:\n        return 'onReadStatusListener';\n      case ChatEvent.SENT_MESSAGE:\n        return 'onSentMessageCallback';\n      case ChatEvent.USER_LAST_ACTIVITY:\n        return 'onLastUserActivityListener';\n      case ChatEvent.JOIN:\n        return 'onJoinOccupant';\n      case ChatEvent.LEAVE:\n        return 'onLeaveOccupant';\n      case ChatEvent.KICK:\n        return 'onKickOccupant';\n      default:\n        return null;\n    }\n  }\n\n  public addListener(name: ChatEvent, listener: Chat.Listeners): () => void {\n    const listenerName = this.getListenerByName(name);\n    if (listenerName) {\n      (this[listenerName] as Chat.Listeners) = listener;\n    }\n    return this.removeListener.bind(this, name);\n  }\n\n  public removeListener(name: ChatEvent): void {\n    const listenerName = this.getListenerByName(name);\n    if (listenerName) {\n      (this[listenerName] as Chat.Listeners | undefined) = undefined;\n    }\n  }\n\n  public removeAllListeners(): void {\n    Object.keys(this).forEach((key: string) => {\n      if (key.startsWith('on') && key.endsWith('Listener') && typeof this[key as Chat.ListenerName] === 'function') {\n        (this[key as Chat.ListenerName] as Chat.Listeners | undefined) = undefined;\n      }\n    });\n  }\n}\n","import type { XMPPClient } from '@xmppClient';\nimport type { Calls, Chat, PlainObject, StringObject } from '../../types';\nimport type { XMPPChatRealTimeService } from '../../types/chat';\nimport { ChatEvent, CallType, CallSignalingModuleIdentifier } from '../../types/constants';\nimport { xmppClient } from '@xmppClient';\nimport config from '../../config';\nimport Utils from '../../Utils';\nimport ProxyService from '../../Proxy';\nimport ChatHelpers from './Helpers';\nimport ChatUtils from './ChatUtils';\nimport StreamManagement from './StreamManagement';\nimport PrivacyList from './PrivacyList';\nimport MultiUserChat from './MultiUserChat';\nimport AbstractChatService from '../AbstractChatService';\n\nexport default class XMPPChatService extends AbstractChatService implements XMPPChatRealTimeService {\n  declare onMessageErrorListener: Chat.OnMessageErrorListener;\n  declare onSentMessageCallback: Chat.OnMessageSentListener;\n  declare onDeliveredStatusListener: Chat.OnMessageDeliveredListener;\n  declare onJoinOccupant: Chat.OnDialogJoinListener;\n  declare onLeaveOccupant: Chat.OnDialogLeaveListener;\n  declare onKickOccupant: Chat.OnDialogKickListener;\n\n  public xmppClient: XMPPClient;\n  public helpers: ChatHelpers;\n  public privacylist: PrivacyList;\n  public muc: MultiUserChat;\n  public streamManagement: StreamManagement;\n\n  public stanzasCallbacks: Chat.StanzasCallbacks = {};\n  private xmppClientListeners: Chat.XMPPClientListeners = new Map<Chat.XMPPClientEvent, Chat.XMPPClientListener>();\n  private connectPromise: Promise<boolean> | null = null;\n  private earlyIncomingMessagesQueue: Chat.XmlElement[] = [];\n\n  constructor(proxy: ProxyService) {\n    super(proxy);\n    this.helpers = new ChatHelpers();\n\n    this.xmppClient = xmppClient({\n      service: config.chatProtocol.websocket,\n      credentials: (auth, mechanism) =>\n        auth(\n          {\n            username: this.xmppClient?.options?.username,\n            password: this.xmppClient?.options?.password,\n          },\n          mechanism\n        ),\n    });\n\n    if (config.chat.reconnect?.enable) {\n      this.xmppClient.reconnect.delay = config.chat.reconnect.timeInterval * 1000;\n    }\n\n    const options = {\n      xmppClient: this.xmppClient,\n      helpers: this.helpers,\n      stanzasCallbacks: this.stanzasCallbacks,\n    };\n\n    this.muc = new MultiUserChat(options);\n    this.privacylist = new PrivacyList(options);\n    this.streamManagement = new StreamManagement(this);\n  }\n\n  public get connectionStatus() {\n    return this.xmppClient.status;\n  }\n\n  public get currentUserId(): Chat.UserId {\n    const userJID = this.xmppClient.jid?.toString() ?? '';\n    const userID = this.helpers.getUserIdFromJID(userJID) ?? 0;\n    return userID;\n  }\n\n  public async connect(params: Chat.ConnectionParams): Promise<boolean> {\n    this.connectPromise = new Promise((resolve, reject) => {\n      Utils.DLog('[Chat]', 'Connect with parameter:', params);\n\n      if (this.isConnecting) {\n        Utils.DLog('[Chat]', 'Warning! Already in CONNECTING state');\n        resolve(false);\n        return;\n      }\n\n      if (this.isConnected) {\n        Utils.DLog('[Chat]', 'Warning! Chat is already connected!');\n        resolve(false);\n        return;\n      }\n\n      this.isConnecting = true;\n      this.isLogout = false;\n\n      this.removeAllXMPPClientListeners();\n\n      this.addXMPPClientListener('connect', () => {\n        Utils.DLog('[Chat]', this.isReconnect ? 'RECONNECTING' : 'CONNECTING');\n      });\n\n      this.addXMPPClientListener('online', () => {\n        Utils.DLog('[Chat]', 'ONLINE');\n        this.postConnectActions();\n        resolve(true);\n        this.connectPromise = null;\n      });\n\n      this.addXMPPClientListener('offline', () => {\n        Utils.DLog('[Chat]', 'OFFLINE');\n      });\n\n      this.addXMPPClientListener('disconnect', () => {\n        Utils.DLog('[Chat]', 'DISCONNECTED');\n\n        Utils.safeCallbackCall(this.onDisconnectedListener)();\n\n        if (config.chat.reconnect?.enable) {\n          this.isConnected = false;\n          this.isConnecting = false;\n        } else {\n          this.disconnect();\n        }\n      });\n\n      this.addXMPPClientListener('status', (status: Chat.ConnectionStatus, value: unknown) => {\n        Utils.DLog('[Chat]', `status - ${String(status)}`, typeof value === 'object' ? JSON.stringify(value) : '');\n        Utils.safeCallbackCall(this.onChatStatusListener)(status);\n      });\n\n      this.addXMPPClientListener('stanza', (stanza: Chat.XmlElement) => {\n        // it can be a case,\n        // when message came after xmpp auth but before resource binding,\n        // and it can cause some crashes, e.g.\n        // https://github.com/ConnectyCube/connectycube-js-sdk-releases/issues/28\n        if (stanza.is('message') && !this.isConnected) {\n          this.earlyIncomingMessagesQueue.push(stanza);\n          Utils.DLog('[Chat]', \"on 'stanza': enqueue incoming stanza (isConnected=false)\");\n          return;\n        }\n\n        // after 'input' and 'element' (only if stanza, not nonza)\n        if (stanza.is('presence')) {\n          this.onPresence(stanza);\n        } else if (stanza.is('iq')) {\n          this.onIQ(stanza);\n        } else if (stanza.is('message')) {\n          if (stanza.attrs.type === 'headline') {\n            this.onSystemMessage(stanza);\n          } else if (stanza.attrs.type === 'error') {\n            this.onMessageError(stanza);\n          } else {\n            this.onMessage(stanza);\n          }\n        }\n      });\n\n      this.addXMPPClientListener('error', (error: unknown) => {\n        Utils.DLog('[Chat]', 'ERROR:', error, {\n          isReconnect: this.isReconnect,\n          connectPromise: !!this.connectPromise,\n        });\n\n        if (this.connectPromise) {\n          if (!this.isReconnect) {\n            const err = error as { name?: string; condition?: unknown };\n            reject(err.name === 'SASLError' ? err.condition : error);\n            this.connectPromise = null;\n          }\n        } else {\n          Utils.safeCallbackCall(this.onConnectionErrorListener)(error);\n        }\n      });\n\n      this.addXMPPClientListener('output', (str) => {\n        Utils.callTrafficUsageCallback('xmppDataWrite', { body: str });\n        Utils.DLog('[Chat]', 'SENT:', str);\n      });\n\n      this.addXMPPClientListener('input', (str) => {\n        Utils.callTrafficUsageCallback('xmppDataRead', { body: str });\n        Utils.DLog('[Chat]', 'RECV:', str);\n      });\n\n      // save user connection data so they will be used when authenticate (above)\n      this.xmppClient.options.username = ChatUtils.buildUserJidLocalPart(params.userId);\n      this.xmppClient.options.password = params.password;\n      // start connect\n      this.xmppClient.start().catch((error) => {\n        console.error('[Chat] xmppClient.start error', error);\n        if (this.connectPromise) {\n          reject(error);\n          this.connectPromise = null;\n        } else {\n          Utils.safeCallbackCall(this.onConnectionErrorListener)(error);\n        }\n      });\n    });\n\n    return this.connectPromise;\n  }\n\n  public async ping(): Promise<void> {\n    return new Promise((resolve, reject) => {\n      const id = ChatUtils.getUniqueId('ping');\n      const iqStanza = ChatUtils.createIqStanza({ id, type: 'get', to: config.endpoints.chat });\n\n      iqStanza.c('ping', { xmlns: 'urn:xmpp:ping' });\n\n      this.stanzasCallbacks[id] = (stanza: Chat.XmlElement) => {\n        const error = ChatUtils.getElement(stanza, 'error');\n        if (error) {\n          reject(ChatUtils.buildErrorFromXMPPErrorStanza(error));\n        } else {\n          resolve();\n        }\n      };\n\n      this.xmppClient.sendOnline(iqStanza);\n    });\n  }\n\n  public send(dialogId: Chat.DialogId | Chat.UserId, message: Chat.MessageParams = {}): string {\n    const messageId = message.id ?? Utils.getBsonObjectId();\n    const messageStanza = ChatUtils.createMessageStanza({\n      from: this.helpers.userCurrentJid,\n      to: this.helpers.jidOrUserId(dialogId),\n      type: message.type ?? this.helpers.typeChat(dialogId),\n      id: messageId,\n    });\n\n    if (!message.id) {\n      message.id = messageId;\n    }\n\n    if (message.body) {\n      messageStanza.c('body').t(message.body).up();\n    }\n\n    if (message.extension) {\n      messageStanza.c('extraParams', { xmlns: 'jabber:client' });\n      ChatUtils.assignExtraParamsToXml(messageStanza, message.extension);\n    }\n\n    if (this.streamManagement.supported) {\n      this.streamManagement.sendAndCount(messageStanza, message);\n    } else {\n      this.xmppClient.sendOnline(messageStanza);\n    }\n\n    return messageId;\n  }\n\n  public sendSystemMessage(\n    userId: Chat.UserId | Chat.UserId[] | Chat.DialogId,\n    message: Chat.SystemMessageParams\n  ): string {\n    const messageId = message.id ?? Utils.getBsonObjectId();\n    const recipients = Array.isArray(userId) ? userId : [userId];\n\n    for (const recipient of recipients) {\n      const messageStanza = ChatUtils.createMessageStanza({\n        type: 'headline',\n        id: messageId,\n        to: this.helpers.jidOrUserId(recipient as Chat.UserId),\n      });\n\n      if (message.body) {\n        messageStanza.c('body').t(message.body).up();\n      }\n\n      if (message.extension) {\n        messageStanza.c('extraParams', { xmlns: 'jabber:client' }).c('moduleIdentifier').t('SystemNotifications').up();\n        ChatUtils.assignExtraParamsToXml(messageStanza, message.extension);\n      }\n\n      this.xmppClient.sendOnline(messageStanza);\n    }\n\n    return messageId;\n  }\n\n  public sendWebRTCSignalingMessage(\n    userId: Chat.UserId,\n    message: Chat.SystemMessageParams<Calls.ExtensionParams>\n  ): string {\n    const messageId = message.id ?? Utils.getBsonObjectId();\n\n    let messageStanza = ChatUtils.createMessageStanza({\n      to: this.helpers.jidOrUserId(userId),\n      type: 'headline',\n      id: messageId,\n    }).c('extraParams', { xmlns: 'jabber:client' });\n\n    const extension = message.extension ?? {};\n    Object.keys(extension).forEach((name) => {\n      const item = extension[name];\n\n      if (name === 'iceCandidates' && Utils.isArray(item)) {\n        messageStanza = messageStanza.c('iceCandidates');\n        ((item as RTCIceCandidateInit[]) || []).forEach((candidate) => {\n          messageStanza = messageStanza.c('iceCandidate');\n          if (Utils.isObject(candidate)) {\n            Object.entries(candidate).forEach(([key, value]) => {\n              messageStanza = messageStanza\n                .c(key)\n                .t(String(value || ''))\n                .up();\n            });\n          }\n          messageStanza = messageStanza.up();\n        });\n        messageStanza = messageStanza.up();\n      } else if (name === 'opponentsIDs' && Utils.isArray(item)) {\n        messageStanza = messageStanza.c('opponentsIDs');\n        ((item as number[] | string[]) || []).forEach((opponentId) => {\n          messageStanza = messageStanza\n            .c('opponentID')\n            .t(String(opponentId ?? ''))\n            .up();\n        });\n        messageStanza = messageStanza.up();\n      } else if (typeof item === 'object' && item !== null) {\n        ChatUtils.assignObjectToXml(messageStanza, item as PlainObject, name);\n      } else {\n        messageStanza = messageStanza\n          .c(name)\n          .t(String(item ?? ''))\n          .up();\n      }\n    });\n\n    messageStanza = messageStanza.up();\n\n    this.xmppClient.sendOnline(messageStanza);\n\n    return messageId;\n  }\n\n  public sendIsTypingStatus(dialogId: Chat.DialogId | Chat.UserId): void {\n    const messageStanza = ChatUtils.createMessageStanza({\n      from: this.helpers.userCurrentJid,\n      to: this.helpers.jidOrUserId(dialogId),\n      type: this.helpers.typeChat(dialogId),\n    });\n\n    messageStanza.c('composing', { xmlns: 'http://jabber.org/protocol/chatstates' });\n\n    this.xmppClient.sendOnline(messageStanza);\n  }\n\n  public sendIsStopTypingStatus(dialogId: Chat.DialogId | Chat.UserId): void {\n    const messageStanza = ChatUtils.createMessageStanza({\n      from: this.helpers.userCurrentJid,\n      to: this.helpers.jidOrUserId(dialogId),\n      type: this.helpers.typeChat(dialogId),\n    });\n\n    messageStanza.c('paused', { xmlns: 'http://jabber.org/protocol/chatstates' });\n\n    this.xmppClient.sendOnline(messageStanza);\n  }\n\n  public sendDeliveredStatus(params: Chat.MessageStatusParams): void {\n    const messageStanza = ChatUtils.createMessageStanza({\n      type: 'chat',\n      from: this.helpers.userCurrentJid,\n      id: Utils.getBsonObjectId(),\n      to: this.helpers.jidOrUserId(params.userId!),\n    });\n\n    messageStanza.c('received', { xmlns: 'urn:xmpp:chat-markers:0', id: params.messageId }).up();\n    messageStanza.c('extraParams', { xmlns: 'jabber:client' }).c('dialog_id').t(params.dialogId);\n\n    this.xmppClient.sendOnline(messageStanza);\n  }\n\n  public sendReadStatus(params: Chat.MessageStatusParams): void {\n    const messageStanza = ChatUtils.createMessageStanza({\n      type: 'chat',\n      from: this.helpers.userCurrentJid,\n      to: this.helpers.jidOrUserId(params.userId!),\n      id: Utils.getBsonObjectId(),\n    });\n\n    messageStanza.c('displayed', { xmlns: 'urn:xmpp:chat-markers:0', id: params.messageId }).up();\n    messageStanza.c('extraParams', { xmlns: 'jabber:client' }).c('dialog_id').t(params.dialogId);\n\n    this.xmppClient.sendOnline(messageStanza);\n  }\n\n  public editMessage(params: Chat.EditMessageParams): void {\n    const messageStanza = ChatUtils.createMessageStanza({\n      from: this.helpers.userCurrentJid,\n      to: this.helpers.jidOrUserId(params.to ?? params.dialogId),\n      type: this.helpers.typeChat(params.to ?? params.dialogId),\n      id: Utils.getBsonObjectId(),\n    });\n\n    messageStanza.c('body').t(params.body).up();\n    messageStanza\n      .c('replace', {\n        xmlns: 'urn:xmpp:message-correct:0',\n        id: params.originMessageId,\n        last: params.last ? 'true' : 'false',\n      })\n      .up();\n    messageStanza.c('extraParams', { xmlns: 'jabber:client' }).c('dialog_id').t(params.dialogId);\n\n    if (params.extension) {\n      ChatUtils.assignExtraParamsToXml(messageStanza, params.extension!);\n    }\n\n    this.xmppClient.sendOnline(messageStanza);\n  }\n\n  public deleteMessage(params: Chat.DeleteMessageParams): void {\n    const messageStanza = ChatUtils.createMessageStanza({\n      from: this.helpers.userCurrentJid,\n      to: this.helpers.jidOrUserId(params.to ?? params.dialogId),\n      type: this.helpers.typeChat(params.to ?? params.dialogId),\n      id: Utils.getBsonObjectId(),\n    });\n\n    messageStanza.c('remove', { xmlns: 'urn:xmpp:message-delete:0', id: params.messageId }).up();\n    messageStanza.c('extraParams', { xmlns: 'jabber:client' }).c('dialog_id').t(params.dialogId);\n\n    this.xmppClient.sendOnline(messageStanza);\n  }\n\n  public getLastUserActivity(userId: Chat.UserId): Promise<Chat.LastActivity> {\n    return new Promise((resolve, reject) => {\n      const id = ChatUtils.getUniqueId('lastActivity');\n      const iqStanza = ChatUtils.createIqStanza({\n        type: 'get',\n        from: this.helpers.userCurrentJid,\n        to: this.helpers.jidOrUserId(userId),\n        id: id,\n      });\n\n      iqStanza.c('query', { xmlns: 'jabber:iq:last' });\n\n      this.stanzasCallbacks[id] = (stanza: Chat.XmlElement) => {\n        if (ChatUtils.getElement(stanza, 'error')) {\n          reject(ChatUtils.buildErrorFromXMPPErrorStanza(stanza));\n        } else {\n          resolve(this.onLastActivityStanza(stanza));\n        }\n      };\n\n      this.xmppClient.sendOnline(iqStanza);\n    });\n  }\n\n  private onLastActivityStanza(stanza: Chat.XmlElement): Chat.LastActivity {\n    const from = ChatUtils.getAttr(stanza, 'from');\n    const userId = this.helpers.getUserIdFromJID(from);\n    const query = ChatUtils.getElement(stanza, 'query');\n    const seconds = query ? parseInt(ChatUtils.getAttr(query, 'seconds')) : 0;\n\n    Utils.safeCallbackCall(this.onLastUserActivityListener)(userId, seconds);\n\n    return { userId, seconds };\n  }\n\n  public markActive(): void {\n    const iqStanza = ChatUtils.createIqStanza({\n      id: this.helpers.getUniqueId('markActive'),\n      type: 'set',\n    });\n\n    iqStanza.c('mobile', {\n      xmlns: 'http://tigase.org/protocol/mobile#v2',\n      enable: 'false',\n    });\n\n    this.xmppClient.sendOnline(iqStanza);\n  }\n\n  public markInactive(): void {\n    const iqStanza = ChatUtils.createIqStanza({\n      id: this.helpers.getUniqueId('markActive'),\n      type: 'set',\n    });\n\n    iqStanza.c('mobile', {\n      xmlns: 'http://tigase.org/protocol/mobile#v2',\n      enable: 'true',\n    });\n\n    this.xmppClient.sendOnline(iqStanza);\n  }\n\n  public async disconnect(): Promise<boolean> {\n    Utils.DLog('[Chat]', 'disconnect');\n\n    if (this.isLogout) {\n      Utils.DLog('[Chat]', 'Warning! Chat is already disconnected!');\n      return true;\n    }\n\n    this.isLogout = true;\n    this.isReconnect = false;\n    this.isConnected = false;\n    this.isConnecting = false;\n    this.muc.joinedRooms = {};\n    this.helpers.userCurrentJid = '';\n    this.streamManagement.stop();\n\n    try {\n      await this.xmppClient.stop();\n      return true;\n    } catch {\n      return false;\n    }\n  }\n\n  public terminate(): void {\n    Utils.DLog('[Chat]', 'terminated');\n\n    this.isConnected = false;\n    this.isConnecting = false;\n    this.streamManagement.stop();\n    this.xmppClient.socket?.end();\n  }\n\n  private onMessage(rawStanza: Chat.XmlElement): void {\n    const forwardedStanza = ChatUtils.getElementTreePath(rawStanza, ['sent', 'forwarded', 'message']);\n    const stanza = forwardedStanza || rawStanza;\n    const from = ChatUtils.getAttr(stanza, 'from');\n    const type = ChatUtils.getAttr(stanza, 'type');\n    const invite = ChatUtils.getElement(stanza, 'invite');\n    const resource = this.xmppClient.jid?.getResource() || '';\n    const isChat = type === 'chat';\n\n    // ignore private message from the same resource or invite messages from MUC\n    if ((isChat && from.includes(resource)) || invite) {\n      return;\n    }\n\n    const messageId = ChatUtils.getAttr(stanza, 'id');\n    const delivered = ChatUtils.getElement(stanza, 'received');\n    const read = ChatUtils.getElement(stanza, 'displayed');\n    const replaceSubElement = ChatUtils.getElement(stanza, 'replace');\n    const reactionsSubElement = ChatUtils.getElement(stanza, 'reactions');\n    const removeSubElement = ChatUtils.getElement(stanza, 'remove');\n    const composing = Boolean(ChatUtils.getElement(stanza, 'composing'));\n    const paused = ChatUtils.getElement(stanza, 'paused');\n    const delay = ChatUtils.getElement(stanza, 'delay');\n    const extraParams = ChatUtils.getElement(stanza, 'extraParams');\n    const body = ChatUtils.getElementText(stanza, 'body');\n    const isForwarded = Boolean(forwardedStanza);\n    const isGroup = type === 'groupchat';\n    const recipient = isChat ? ChatUtils.getAttr(stanza, 'to') : null;\n    const recipientId = recipient ? this.helpers.getUserIdFromJID(recipient) : null;\n    const ext = extraParams ? ChatUtils.parseExtraParams(extraParams) : null;\n    const extension = ext ? ext.extension : null;\n    const dialogId = isGroup ? this.helpers.getDialogIdFromJID(from) : (ext?.dialogId ?? null);\n    const userId = isGroup ? this.helpers.getIdFromResource(from) : this.helpers.getUserIdFromJID(from);\n    const currentUserJid = this.xmppClient.jid?.toString();\n    const currentUserId = currentUserJid ? this.helpers.getUserIdFromJID(currentUserJid) : 0;\n\n    // typing statuses\n    if (composing || paused) {\n      if (isChat || isGroup || !delay) {\n        Utils.safeCallbackCall(this.onMessageTypingListener)(composing, userId, dialogId);\n      }\n\n      return;\n    }\n\n    // edit message\n    if (replaceSubElement) {\n      Utils.safeCallbackCall(this.onMessageUpdateListener)(\n        ChatUtils.getAttr(replaceSubElement, 'id'),\n        ChatUtils.getAttr(replaceSubElement, 'last') === 'true',\n        body,\n        dialogId,\n        userId,\n        extension\n      );\n\n      return;\n    }\n\n    // reactions\n    if (reactionsSubElement) {\n      if (isForwarded && isGroup) {\n        return;\n      }\n\n      const messageId = ChatUtils.getAttr(reactionsSubElement, 'message_id');\n      const userId = parseInt(ChatUtils.getAttr(reactionsSubElement, 'user_id'));\n      const { add, remove } = ChatUtils.parseReactions(reactionsSubElement);\n\n      Utils.safeCallbackCall(this.onMessageReactionsListener)(messageId, userId, dialogId, add, remove);\n\n      return;\n    }\n\n    // delete message\n    if (removeSubElement) {\n      const messageId = ChatUtils.getAttr(removeSubElement, 'id');\n\n      Utils.safeCallbackCall(this.onMessageDeleteListener)(messageId, dialogId, userId);\n\n      return;\n    }\n\n    // delivered / read statuses\n    if (delivered || read) {\n      if (delivered && isChat) {\n        const id = ChatUtils.getAttr(delivered, 'id');\n        Utils.safeCallbackCall(this.onDeliveredStatusListener)(id, dialogId, userId);\n      }\n      if (read && isChat) {\n        const id = ChatUtils.getAttr(read, 'id');\n        Utils.safeCallbackCall(this.onReadStatusListener)(id, dialogId, userId);\n      }\n\n      return;\n    }\n\n    // auto-send 'received' status (ignore messages from yourself)\n    if (dialogId && userId && userId !== currentUserId) {\n      this.sendDeliveredStatus({ messageId, dialogId, userId });\n    }\n\n    const message: Chat.Message = {\n      id: messageId,\n      dialog_id: dialogId,\n      recipient_id: recipientId,\n      is_forwarded: isForwarded,\n      type,\n      body,\n      extension,\n      delay,\n    };\n\n    if (isChat || isGroup) {\n      Utils.safeCallbackCall(this.onMessageListener)(userId, message);\n    }\n  }\n\n  private onPresence(stanza: Chat.XmlElement): void {\n    const from = ChatUtils.getAttr(stanza, 'from');\n    const id = ChatUtils.getAttr(stanza, 'id');\n    const type = ChatUtils.getAttr(stanza, 'type');\n    const currentUserJid = this.xmppClient.jid?.toString();\n    const currentUserId = this.helpers.getUserIdFromJID(currentUserJid);\n    const x = ChatUtils.getElement(stanza, 'x');\n    const xmlns = x ? ChatUtils.getAttr(x, 'xmlns') : null;\n    const status = x ? ChatUtils.getElement(x, 'xmlns') : null;\n    // const statusCode = status ? ChatUtils.getElement(status, 'code') : null;\n    const statusCode = status ? ChatUtils.getElementText(status, 'code') : null;\n\n    // MUC presences\n    if (xmlns && xmlns.startsWith('http://jabber.org/protocol/muc')) {\n      // Error\n      if (type === 'error') {\n        // JOIN to dialog error\n        if (id.endsWith(':join')) {\n          Utils.safeCallbackCall(this.stanzasCallbacks[id])(stanza);\n        }\n        return;\n      }\n\n      const dialogId = this.helpers.getDialogIdFromJID(from);\n      const mucUserId = this.helpers.getUserIdFromRoomJid(from);\n\n      // self presence\n      if (status) {\n        // KICK from dialog event\n        if (statusCode === '301') {\n          const item = ChatUtils.getElement(stanza, 'item');\n          const actorElement = item ? ChatUtils.getElement(item, 'actor') : null;\n          const initiatorUserJid = actorElement ? ChatUtils.getAttr(actorElement, 'jid') : null;\n          const initiatorId = this.helpers.getUserIdFromJID(initiatorUserJid ?? undefined);\n          const roomJid = this.helpers.getRoomJidFromRoomFullJid(from);\n\n          Utils.safeCallbackCall(this.onKickOccupant)(dialogId, initiatorId);\n\n          if (roomJid) {\n            delete this.muc.joinedRooms[roomJid];\n          }\n\n          return;\n        } else {\n          if (type === 'unavailable') {\n            // LEAVE response\n            if (status && statusCode === '110') {\n              Utils.safeCallbackCall(this.stanzasCallbacks['muc:leave'])(null);\n            }\n            return;\n          }\n          // JOIN response\n          if (id.endsWith(':join') && status && statusCode === '110') {\n            this.stanzasCallbacks[id]?.(stanza);\n            return;\n          }\n        }\n        // Occupants JOIN/LEAVE events\n      } else if (mucUserId != currentUserId) {\n        const listenerName = type === 'unavailable' ? 'onLeaveOccupant' : 'onJoinOccupant';\n\n        Utils.safeCallbackCall(this[listenerName])(dialogId, mucUserId);\n\n        return;\n      }\n    }\n  }\n\n  private onIQ(stanza: Chat.XmlElement): void {\n    const stanzaId = ChatUtils.getAttr(stanza, 'id');\n\n    if (this.stanzasCallbacks[stanzaId]) {\n      Utils.safeCallbackCall(this.stanzasCallbacks[stanzaId])(stanza);\n      delete this.stanzasCallbacks[stanzaId];\n    } else {\n      const from = ChatUtils.getAttr(stanza, 'from');\n      const query = ChatUtils.getElement(stanza, 'query');\n      if (from && query) {\n        this.onLastActivityStanza(stanza);\n      }\n    }\n  }\n\n  private onSystemMessage(rawStanza: Chat.XmlElement): void {\n    const forwardedStanza = ChatUtils.getElementTreePath(rawStanza, ['sent', 'forwarded', 'message']);\n    const stanza = forwardedStanza || rawStanza;\n    const from = ChatUtils.getAttr(stanza, 'from');\n    const messageId = ChatUtils.getAttr(stanza, 'id');\n    const extraParams = ChatUtils.getElement(stanza, 'extraParams');\n    const userId = this.helpers.getUserIdFromJID(from);\n    const delay = ChatUtils.getElement(stanza, 'delay');\n    const moduleIdentifier = extraParams ? ChatUtils.getElementText(extraParams, 'moduleIdentifier') : null;\n    const body = ChatUtils.getElementText(stanza, 'body');\n    const ext = extraParams ? ChatUtils.parseExtraParams(extraParams) : null;\n    const extension = ext ? ext.extension : null;\n\n    switch (moduleIdentifier) {\n      case 'SystemNotifications':\n        Utils.safeCallbackCall(this.onSystemMessageListener)({ id: messageId, userId, body, extension });\n        break;\n      case CallSignalingModuleIdentifier:\n        if (!delay && userId && extraParams) {\n          this.onWebRTCSignalingMessage(userId, extraParams);\n        }\n\n        if (this.webrtcSignalingProcessor && !delay) {\n          Utils.safeCallbackCall(this.webrtcSignalingProcessor.onMessage)(userId, extraParams);\n        }\n        break;\n      default:\n        break;\n    }\n  }\n\n  private onWebRTCSignalingMessage(userId: Chat.UserId, extensionElem: Chat.XmlElement): void {\n    if (!this.webrtcSignalingProcessor) {\n      return;\n    }\n\n    const extraParams = this.getCallExtension(extensionElem);\n\n    Utils.safeCallbackCall(this.webrtcSignalingProcessor.onMessage)(userId, extraParams);\n  }\n\n  private getCallExtension(extraParams?: Chat.XmlElement): Calls.ExtensionParams {\n    if (!extraParams) {\n      return {};\n    }\n\n    const extension: Calls.ExtensionParams = { iceCandidates: [], opponentsIDs: [] };\n    const elements = ChatUtils.getChildElements(extraParams);\n\n    elements.forEach((element: Chat.XmlElement) => {\n      const items = ChatUtils.getChildElements(element);\n      const key = ChatUtils.getName(element) ?? '';\n\n      switch (key) {\n        case 'callerID':\n          extension[key] = parseInt(ChatUtils.getText(element) || '0');\n          break;\n\n        case 'callType':\n          const type = ChatUtils.getText(element);\n          extension[key] = type === '1' ? CallType.VIDEO : type === '2' ? CallType.AUDIO : undefined;\n          break;\n\n        case 'iceCandidates':\n          items.forEach((item) => {\n            const candidate: StringObject = {};\n            ChatUtils.getChildElements(item).forEach((child) => {\n              const childName = ChatUtils.getName(child) || '';\n              const childText = ChatUtils.getText(child);\n              candidate[childName] =\n                childName === 'sdpMLineIndex' ? String(parseInt(childText || '0', 10)) : (childText ?? '');\n            });\n            extension.iceCandidates?.push(candidate);\n          });\n          break;\n\n        case 'opponentsIDs':\n          items.forEach((item) => {\n            extension.opponentsIDs?.push(parseInt(ChatUtils.getText(item) || '0'));\n          });\n          break;\n\n        default:\n          if (items.length > 1) {\n            if ((ChatUtils.getText(element) || '').length > 4096) {\n              extension[key] = items.reduce((acc, item) => acc + ChatUtils.getText(item), '');\n            } else {\n              ChatUtils.assignXmlToObject(element, extension);\n            }\n          } else {\n            if (key === 'userInfo') {\n              ChatUtils.assignXmlToObject(element, extension);\n            } else {\n              extension[key] = ChatUtils.getText(element);\n            }\n          }\n          break;\n      }\n    });\n\n    if (extension.iceCandidates?.length === 0) {\n      delete extension.iceCandidates;\n    }\n\n    if (extension.opponentsIDs?.length === 0) {\n      delete extension.opponentsIDs;\n    }\n\n    return extension;\n  }\n\n  private onMessageError(stanza: Chat.XmlElement): void {\n    // <error code=\"503\" type=\"cancel\">\n    //   <service-unavailable xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\"/>\n    //   <text xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\" xml:lang=\"en\">Service not available.</text>\n    // </error>\n    const messageId = ChatUtils.getAttr(stanza, 'id');\n    const error = ChatUtils.buildErrorFromXMPPErrorStanza(stanza);\n\n    Utils.safeCallbackCall(this.onMessageErrorListener)(messageId, error);\n  }\n\n  private postConnectActions(): void {\n    Utils.DLog('[Chat]', this.isReconnect ? 'RECONNECTED' : 'CONNECTED');\n\n    const presence = ChatUtils.createPresenceStanza();\n\n    this.streamManagement.start();\n    this.helpers.userCurrentJid = this.xmppClient.jid?.toString() ?? null;\n    this.isConnected = true;\n    this.isConnecting = false;\n    this.enableCarbons();\n    this.xmppClient.sendOnline(presence); // initial presence\n\n    if (this.isReconnect) {\n      // reconnect\n      Utils.safeCallbackCall(this.onReconnectListener)();\n    } else {\n      this.isReconnect = true;\n    }\n\n    if (this.earlyIncomingMessagesQueue.length > 0) {\n      Utils.DLog('[Chat]', `Flush 'earlyIncomingMessagesQueue' (length=${this.earlyIncomingMessagesQueue.length})`);\n\n      const stanzasCallback = this.xmppClientListeners.get('stanza');\n\n      this.earlyIncomingMessagesQueue.forEach((stanza) => {\n        stanzasCallback?.(stanza);\n      });\n      this.earlyIncomingMessagesQueue = [];\n    }\n  }\n\n  private enableCarbons(): void {\n    const iqStanza = ChatUtils.createIqStanza({\n      type: 'set',\n      from: this.helpers.userCurrentJid,\n      id: ChatUtils.getUniqueId('enableCarbons'),\n    });\n\n    iqStanza.c('enable', { xmlns: 'urn:xmpp:carbons:2' });\n\n    this.xmppClient.sendOnline(iqStanza);\n  }\n\n  private setSubscriptionToUserLastActivity(userId: Chat.UserId, enable: boolean): void {\n    const iqStanza = ChatUtils.createIqStanza({\n      id: this.helpers.getUniqueId('statusStreaming'),\n      type: 'set',\n    });\n\n    iqStanza.c('subscribe', {\n      xmlns: 'https://connectycube.com/protocol/status_streaming',\n      user_jid: this.helpers.jidOrUserId(userId),\n      enable,\n    });\n\n    this.xmppClient.sendOnline(iqStanza);\n  }\n\n  subscribeToUserLastActivityStatus(userId: Chat.UserId) {\n    this.setSubscriptionToUserLastActivity(userId, true);\n  }\n\n  unsubscribeFromUserLastActivityStatus(userId?: Chat.UserId) {\n    if (userId !== undefined) this.setSubscriptionToUserLastActivity(userId, false);\n  }\n\n  protected override getListenerByName(name: ChatEvent): Chat.ListenerName | null {\n    switch (name) {\n      case ChatEvent.ERROR_MESSAGE:\n        return 'onMessageErrorListener';\n      case ChatEvent.DELIVERED_MESSAGE:\n        return 'onDeliveredStatusListener';\n      case ChatEvent.SENT_MESSAGE:\n        return 'onSentMessageCallback';\n      case ChatEvent.JOIN:\n        return 'onJoinOccupant';\n      case ChatEvent.LEAVE:\n        return 'onLeaveOccupant';\n      case ChatEvent.KICK:\n        return 'onKickOccupant';\n      default:\n        return super.getListenerByName(name);\n    }\n  }\n\n  private addXMPPClientListener(name: Chat.XMPPClientEvent, listener: Chat.XMPPClientListener): void {\n    switch (name) {\n      case 'output':\n        this.xmppClient.middleware.filter(async (context, next) => {\n          listener(context.stanza?.toString());\n          await next();\n        });\n        break;\n\n      case 'input':\n        const _listener = (stanza: Chat.XmlElement) => {\n          listener(stanza.toString());\n        };\n        this.xmppClient.on('element', _listener);\n        this.xmppClientListeners.set(name, _listener);\n        break;\n\n      default:\n        this.xmppClient.on(name, listener);\n        this.xmppClientListeners.set(name, listener);\n        break;\n    }\n  }\n\n  private removeXMPPClientListener(name: Chat.XMPPClientEvent): void {\n    const listener = this.xmppClientListeners.get(name);\n    if (listener) {\n      this.xmppClient.removeListener(name, listener);\n    }\n    this.xmppClientListeners.delete(name);\n  }\n\n  private removeAllXMPPClientListeners(): void {\n    this.xmppClientListeners.forEach((_, name) => this.removeXMPPClientListener(name));\n  }\n}\n","import type { PlainObject } from '../../types';\nimport type { Element } from '@xmpp/xml';\nimport type { Options } from '@xmpp/connection';\nimport type { Reconnect } from '@xmpp/reconnect';\nimport type { Middleware } from '@xmpp/middleware';\nimport type { StreamFeatures } from '@xmpp/stream-features';\nimport type { IQCaller } from '@xmpp/iq/caller.js';\nimport type { IQCallee } from '@xmpp/iq/callee.js';\nimport type { SASL2 } from '@xmpp/sasl2';\nimport type { SASL } from '@xmpp/sasl';\nimport type { Resource } from '@xmpp/resource-binding';\nimport type { Bind2 } from '@xmpp/client-core/src/bind2/bind2.js';\nimport type { Token, FAST } from '@xmpp/client-core/src/fast/fast.js';\n\nimport { jid, xml, Client } from '@xmpp/client-core';\nimport _reconnect from '@xmpp/reconnect';\nimport _websocket from '@xmpp/websocket';\nimport _middleware from '@xmpp/middleware';\nimport _streamFeatures from '@xmpp/stream-features';\nimport _iqCaller from '@xmpp/iq/caller.js';\nimport _iqCallee from '@xmpp/iq/callee.js';\nimport _sasl2 from '@xmpp/sasl2';\nimport _sasl from '@xmpp/sasl';\nimport _resourceBinding from '@xmpp/resource-binding';\nimport _bind2 from '@xmpp/client-core/src/bind2/bind2.js';\nimport _fast from '@xmpp/client-core/src/fast/fast.js';\nimport SASLFactory from 'saslmechanisms';\nimport plain from '@xmpp/sasl-plain';\nimport anonymous from '@xmpp/sasl-anonymous';\nimport htsha256none from '@xmpp/sasl-ht-sha-256-none';\nimport { createOnAuthenticate, getDomain } from './xmpp.utils';\nimport ChatUtils from './ChatUtils';\nimport Utils from '../../Utils';\n\nexport type XMPPResource = Resource | string | (() => Promise<string>) | undefined;\nexport type XMPPCredentialsProp = string | undefined;\nexport type XMPPCredentialsAuth = (\n  credentials: Partial<XMPPCredentialsObj>,\n  mechanism: string,\n  userAgent?: XMPPUserAgent\n) => Promise<void>;\nexport type XMPPCredentials =\n  | Partial<XMPPCredentialsObj>\n  | ((callback: XMPPCredentialsAuth, mechanism: string) => Promise<void>)\n  | undefined;\nexport type XMPPUserAgent = Element | undefined;\n\nexport interface XMPPCredentialsObj {\n  username: XMPPCredentialsProp;\n  password: XMPPCredentialsProp;\n  token: Token;\n}\n\nexport interface XMPPOptions extends Options, Partial<XMPPCredentialsObj> {\n  resource?: XMPPResource;\n  credentials?: XMPPCredentials;\n  userAgent?: XMPPUserAgent;\n}\n\nexport interface XMPPClient extends Client {\n  entity: Client;\n  reconnect: Reconnect<Client>;\n  websocket: ReturnType<typeof _websocket>;\n  middleware: Middleware<Client>;\n  streamFeatures: StreamFeatures<Client>;\n  iqCaller: IQCaller<Client>;\n  iqCallee: IQCallee<Client>;\n  saslFactory: SASLFactory;\n  sasl2: SASL2;\n  sasl: SASL;\n  resourceBinding: ReturnType<typeof _resourceBinding>;\n  mechanisms: PlainObject[];\n  bind2: Bind2;\n  fast: FAST;\n  options: XMPPOptions;\n  sendOnline: (element: Element, ...args: unknown[]) => Promise<void>;\n  tcpEnabled?: boolean;\n  tlsEnabled?: boolean;\n}\n\nexport function xmppClient(options: XMPPOptions): XMPPClient {\n  let { resource, credentials, username, password, userAgent, ...params } = options;\n\n  const { domain, service } = params;\n\n  if (!domain && service) {\n    params.domain = getDomain(service);\n  }\n\n  const entity = new Client(params);\n\n  if (username && params.domain) {\n    entity.jid = jid(username, params.domain);\n  }\n\n  const reconnect = _reconnect({ entity });\n  const websocket = _websocket({ entity });\n  const middleware = _middleware({ entity });\n  const streamFeatures = _streamFeatures({ middleware });\n  const iqCaller = _iqCaller({ middleware, entity });\n  const iqCallee = _iqCallee({ middleware, entity });\n\n  // SASL mechanisms - order matters and define priority\n  const saslFactory = new SASLFactory();\n  const mechanisms = Object.entries({ plain, anonymous }).map(([k, v]) => ({ [k]: v(saslFactory) }));\n\n  userAgent ??= xml('user-agent', { id: ChatUtils.getUniqueId() });\n\n  // Stream features - order matters and define priority\n  const sasl2 = _sasl2(\n    { streamFeatures, saslFactory },\n    createOnAuthenticate(credentials ?? { username, password }, userAgent)\n  );\n  const fast = _fast({ sasl2, entity });\n\n  sasl2.setup({ fast });\n\n  // SASL2 inline features\n  const bind2 = _bind2({ sasl2, entity }, resource as string | (() => Promise<string>));\n\n  // FAST mechanisms - order matters and define priority\n  htsha256none(fast.saslFactory);\n\n  // Stream features - order matters and define priority\n  const sasl = _sasl(\n    { streamFeatures, saslFactory },\n    createOnAuthenticate(credentials ?? { username, password }, userAgent)\n  );\n  const resourceBinding = _resourceBinding({ iqCaller, streamFeatures }, resource as Resource | undefined);\n\n  iqCallee?.get('urn:xmpp:ping', 'ping', () => ({}));\n\n  const sendOnline = function (element: Element, ...args: unknown[]): Promise<void> {\n    if (entity.status === 'online') {\n      return entity.send.call(entity, element, ...args);\n    } else {\n      const message = \"You are not connected to chat. Please call 'connect' function first\";\n\n      Utils.DLog('[Chat][Error]', message);\n\n      return Promise.reject(new Error(message));\n    }\n  };\n\n  return Object.assign(entity, {\n    entity,\n    reconnect,\n    websocket,\n    middleware,\n    streamFeatures,\n    iqCaller,\n    iqCallee,\n    saslFactory,\n    sasl2,\n    sasl,\n    resourceBinding,\n    mechanisms,\n    bind2,\n    fast,\n    sendOnline,\n  });\n}\n","var C = Object.defineProperty;\nvar D = (d, e, s) => e in d ? C(d, e, { enumerable: !0, configurable: !0, writable: !0, value: s }) : d[e] = s;\nvar o = (d, e, s) => D(d, typeof e != \"symbol\" ? e + \"\" : e, s);\nimport U from \"ws\";\nfunction E(d) {\n  const e = \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (s) => {\n    const n = Math.random() * 16 | 0;\n    return (s === \"x\" ? n : n & 3 | 8).toString(16);\n  });\n  return d !== void 0 ? `${e}:${d}` : e;\n}\nconst A = globalThis.WebSocket ?? U;\nclass O {\n  constructor(e) {\n    o(this, \"socket\");\n    o(this, \"config\");\n    o(this, \"currentUserId\");\n    o(this, \"responsesPromises\", {});\n    o(this, \"deviceId\");\n    o(this, \"onMessageListener\");\n    o(this, \"onMessageStatusListener\");\n    o(this, \"onMessageEditListener\");\n    o(this, \"onMessageDeleteListener\");\n    o(this, \"onMessageReactionsListener\");\n    o(this, \"onUserActivityListener\");\n    o(this, \"onUserTypingListener\");\n    o(this, \"onConversationCreateListener\");\n    o(this, \"onConversationUpdateListener\");\n    o(this, \"onConversationDeleteListener\");\n    o(this, \"onConnectEvent\");\n    o(this, \"onMessageEvent\");\n    o(this, \"onSystemMessageEvent\");\n    o(this, \"onDisconnectEvent\");\n    this.config = e;\n  }\n  async connect(e, s) {\n    return e && (this.config.endpoint.ws = e), s && (this.config.endpoint.http = s), new Promise((n, i) => {\n      this.socket = new A(this.config.endpoint.ws), this.socket.onopen = () => {\n        var r;\n        console.log(\"[socket.open]\"), (r = this.onConnectEvent) == null || r.call(this), n();\n      }, this.socket.onmessage = (r) => {\n        var g, _, p, v, f, k, b, q, R, x, w, S, L, P;\n        const t = JSON.parse(r.data);\n        if (console.log(\"[socket.message]\", t), t.typing) {\n          (g = this.onUserTypingListener) == null || g.call(this, t.typing);\n          return;\n        }\n        if (t.system_message || (_ = t.message) != null && _.system_message) {\n          const a = t.system_message ?? ((p = t.message) == null ? void 0 : p.system_message), { conversation_created: l, conversation_updated: m, conversation_kicked: u } = (a == null ? void 0 : a.x) ?? {};\n          if (l) {\n            (v = this.onConversationCreateListener) == null || v.call(this, l);\n            return;\n          }\n          if (m) {\n            (f = this.onConversationUpdateListener) == null || f.call(this, m);\n            return;\n          }\n          if (u) {\n            (k = this.onConversationDeleteListener) == null || k.call(this, u);\n            return;\n          }\n          (b = this.onSystemMessageEvent) == null || b.call(this, a);\n          return;\n        }\n        if (t.last_activity) {\n          (q = this.onUserActivityListener) == null || q.call(this, t.last_activity);\n          return;\n        }\n        if (t.message_read) {\n          (R = this.onMessageStatusListener) == null || R.call(this, t.message_read);\n          return;\n        }\n        if (t.message_edit) {\n          (x = this.onMessageEditListener) == null || x.call(this, t.message_edit);\n          return;\n        }\n        if (t.message_delete) {\n          (w = this.onMessageDeleteListener) == null || w.call(this, t.message_delete);\n          return;\n        }\n        if (t.message_reactions_update) {\n          (S = this.onMessageReactionsListener) == null || S.call(this, t.message_reactions_update);\n          return;\n        }\n        if (t.message) {\n          if (t.message.error) {\n            const a = t.message.id ?? Object.keys(this.responsesPromises).filter((l) => l.length == 37).slice(-1)[0];\n            this.responsesPromises[a].reject(t.message.error), delete this.responsesPromises[a];\n            return;\n          }\n          (L = this.onMessageListener) == null || L.call(this, t.message), t.message.from.toString() !== this.currentUserId && ((P = this.onMessageEvent) == null || P.call(this, t.message));\n          return;\n        }\n        if (t.ask) {\n          const a = t.ask.mid;\n          this.responsesPromises[a].resolve(t.ask), delete this.responsesPromises[a];\n          return;\n        }\n        const c = t.response;\n        if (c) {\n          const a = c.id;\n          if (!a) {\n            console.error(c.error);\n            return;\n          }\n          const { resolve: l, reject: m, resObjKey: u } = this.responsesPromises[a];\n          if (c.error)\n            c.error.status === 403 ? this.responsesPromises[a].reject(c.error) : m(c.error);\n          else if (Array.isArray(u)) {\n            const I = u.reduce((h, y) => (c[y] !== void 0 && (h[y] = c[y]), h), {});\n            u.every((h) => h in I) ? l(I) : m({ message: \"Server error.\" });\n          } else u ? c[u] ? l(c[u]) : m({ message: \"Server error.\" }) : l(c);\n          delete this.responsesPromises[a];\n        }\n      }, this.socket.onerror = (r) => {\n        console.log(\"[socket.error]\", r), i(r);\n      }, this.socket.onclose = () => {\n        var r;\n        console.log(\"[socket.close]\"), (r = this.onDisconnectEvent) == null || r.call(this), this.config.disableAutoReconnect || this.reconnect();\n      };\n    });\n  }\n  reconnect() {\n    const e = () => {\n      navigator.onLine && document.visibilityState === \"visible\" && (this.connect(), window.removeEventListener(\"online\", e), document.removeEventListener(\"visibilitychange\", e));\n    };\n    navigator.onLine && document.visibilityState === \"visible\" ? this.connect() : (window.addEventListener(\"online\", e), document.addEventListener(\"visibilitychange\", e));\n  }\n  async disconnect() {\n    var e;\n    return (e = this.socket) == null ? void 0 : e.close();\n  }\n  async sendRequest(e, s = {}, n = \"success\") {\n    const i = {\n      request: {\n        [e]: s,\n        id: E(e)\n      }\n    };\n    return this.sendPromise(i, n);\n  }\n  async sendPromise(e, s) {\n    return new Promise((n, i) => {\n      if (!this.socket) {\n        i(\"Socket is not connected.\");\n        return;\n      }\n      this.socket.send(JSON.stringify(e)), console.log(\"[socket.send]\", e), this.responsesPromises[e.request.id] = { resolve: n, reject: i, resObjKey: s };\n    });\n  }\n  async sendHttpPromise(e, s, n) {\n    console.log(\"[http.request]\", { request: n });\n    const i = { \"Content-Type\": \"application/json\" }, r = localStorage.getItem(\"sessionId\");\n    r && (i.Authorization = `Bearer ${r}`);\n    const t = {\n      method: e,\n      credentials: \"include\",\n      headers: i\n    };\n    n && (t.body = JSON.stringify(n));\n    const c = await fetch(`${this.config.endpoint.http}/${s}`, t), g = await c.text();\n    if (!c.ok)\n      throw console.error(\"[http.error]\", g), g || c.statusText;\n    const _ = g ? JSON.parse(g) : {};\n    return console.log(\"[http.response]\", { response: _ }), _;\n  }\n  async connectSocket(e) {\n    return this.sendRequest(\"connect\", { token: e.token, device_id: e.deviceId ?? this.deviceId });\n  }\n  async socketLogin(e) {\n    return this.sendRequest(\"user_login\", { organization_id: this.config.organization_id, ...e.user, device_id: e.deviceId ?? this.deviceId, token: e.token }, [\"user\", \"token\"]);\n  }\n  async disconnectSocket() {\n    return this.sendRequest(\"user_logout\");\n  }\n  async userCreate(e) {\n    return this.sendRequest(\"user_create\", { organization_id: this.config.organization_id, login: e.login, email: e.email, password: e.password }, \"user\");\n  }\n  async userEdit(e) {\n    return this.sendRequest(\"user_edit\", e, \"user\");\n  }\n  async userLogin(e) {\n    const { login: s, password: n } = e || {}, i = Date.now();\n    parseInt(localStorage.getItem(\"sessionExpiredAt\") || `${i}`, 10) - i <= 0 && localStorage.removeItem(\"sessionId\");\n    const t = { organization_id: this.config.organization_id, device_id: this.deviceId };\n    return s && n && (t.login = s, t.password = n), await this.sendHttpPromise(\"POST\", \"login\", t);\n  }\n  async userLogout() {\n    return await this.sendHttpPromise(\"POST\", \"logout\", null);\n  }\n  async userSendOTPToken(e) {\n    const s = { organization_id: this.config.organization_id, device_id: this.deviceId, email: e.email };\n    return this.sendRequest(\"user_send_otp\", s);\n  }\n  async userResetPassword(e) {\n    const s = { organization_id: this.config.organization_id, device_id: this.deviceId, email: e.email, token: e.token, new_password: e.new_password };\n    return this.sendRequest(\"user_reset_password\", s);\n  }\n  async userDelete() {\n    return localStorage.removeItem(\"sessionId\"), this.sendRequest(\"user_delete\");\n  }\n  async userSearch(e) {\n    const s = {\n      keyword: e.keyword,\n      ignore_ids: e.ignore_ids || [],\n      ...e.limit && { limit: e.limit },\n      ...e.updated_at && { updated_at: e.updated_at }\n    };\n    return this.sendRequest(\"user_search\", s, \"users\");\n  }\n  async getUsersByIds(e) {\n    return this.sendRequest(\"get_users_by_ids\", { ids: e.ids }, \"users\");\n  }\n  async getParticipantsByCids(e) {\n    return this.sendRequest(\"get_participants_by_cids\", { cids: e.cids }, [\"users\", \"conversations\"]);\n  }\n  async createUploadUrlForFiles(e) {\n    return this.sendRequest(\"create_files\", e.files, \"files\");\n  }\n  async getDownloadUrlForFiles(e) {\n    return this.sendRequest(\"get_file_urls\", { file_ids: e.file_ids }, \"file_urls\");\n  }\n  async messageCreate(e) {\n    return new Promise((s, n) => {\n      var r;\n      const i = {\n        message: {\n          id: e.mid,\n          body: e.body,\n          cid: e.cid,\n          x: e.x,\n          attachments: e.attachments,\n          replied_message_id: e.replied_message_id,\n          forwarded_message_id: e.forwarded_message_id\n        }\n      };\n      this.responsesPromises[i.message.id] = { resolve: s, reject: n }, (r = this.socket) == null || r.send(JSON.stringify(i)), console.log(\"[socket.send]\", i);\n    });\n  }\n  async messageSystem(e) {\n    return new Promise((s, n) => {\n      var r;\n      const i = {\n        system_message: {\n          id: e.mid,\n          uids: e.uids,\n          cid: e.cid,\n          x: e.x\n        }\n      };\n      this.responsesPromises[i.system_message.id] = { resolve: s, reject: n }, (r = this.socket) == null || r.send(JSON.stringify(i)), console.log(\"[socket.send]\", i);\n    });\n  }\n  async messageList(e) {\n    const s = {\n      cid: e.cid,\n      ...e.ids && { ids: e.ids },\n      ...e.limit && { limit: e.limit },\n      ...e.updated_at && { updated_at: e.updated_at }\n    };\n    return this.sendRequest(\"message_list\", s, \"messages\");\n  }\n  async messageSummary(e) {\n    return this.sendRequest(\"message_summary\", { cid: e.cid, filter: e.filter }, \"message\");\n  }\n  async messageTone(e) {\n    return this.sendRequest(\"message_tone\", { body: e.body, tone: e.tone }, \"message\");\n  }\n  async markConversationAsRead(e) {\n    return this.sendRequest(\"message_read\", { cid: e.cid, ids: e.mids });\n  }\n  async messageEdit(e) {\n    return this.sendRequest(\"message_edit\", { id: e.mid, body: e.body });\n  }\n  async messageDelete(e) {\n    return this.sendRequest(\"message_delete\", { cid: e.cid, ids: e.mids, type: e.type ?? \"myself\" });\n  }\n  async getUserActivity(e) {\n    return this.sendRequest(\"user_last_activity\", { ids: e }, \"last_activity\");\n  }\n  async subscribeToUserActivity(e) {\n    return this.sendRequest(\"user_last_activity_subscribe\", { id: e }, \"last_activity\");\n  }\n  async unsubscribeFromUserActivity() {\n    return this.sendRequest(\"user_last_activity_unsubscribe\");\n  }\n  async sendTypingStatus(e) {\n    return new Promise((s, n) => {\n      var r;\n      const i = { typing: { cid: e.cid, status: e.status } };\n      (r = this.socket) == null || r.send(JSON.stringify(i)), console.log(\"[socket.send]\", i), s();\n    });\n  }\n  async conversationCreate(e) {\n    return this.sendRequest(\"conversation_create\", e, \"conversation\");\n  }\n  async conversationUpdate(e) {\n    var s, n;\n    return this.sendRequest(\"conversation_update\", {\n      id: e.cid,\n      name: e.name,\n      description: e.description,\n      participants: {\n        add: (s = e.participants) == null ? void 0 : s.add,\n        remove: (n = e.participants) == null ? void 0 : n.remove\n      },\n      image_object: e.image_object\n    }, \"conversation\");\n  }\n  async conversationList(e) {\n    var n;\n    const s = {\n      ...e.limit && { limit: e.limit },\n      ...e.updated_at && { updated_at: { gt: e.updated_at.gt, lt: e.updated_at.lt } },\n      ...((n = e.ids) == null ? void 0 : n.length) && { ids: e.ids }\n    };\n    return this.sendRequest(\"conversation_list\", s, \"conversations\");\n  }\n  async conversationDelete(e) {\n    return this.sendRequest(\"conversation_delete\", { id: e.cid });\n  }\n  async conversationSearch(e) {\n    return this.sendRequest(\n      \"conversation_search\",\n      { name: e.name, ...e.limit != null && { limit: e.limit } },\n      \"conversations\"\n    );\n  }\n  async conversationHandlerCreate(e) {\n    return this.sendRequest(\"conversation_handler_create\", { cid: e.cid, content: e.content });\n  }\n  async getConversationHandler(e) {\n    return this.sendRequest(\"get_conversation_handler\", { cid: e.cid }, \"conversation_handler\");\n  }\n  async conversationHandlerDelete(e) {\n    return this.sendRequest(\"conversation_handler_delete\", { cid: e.cid });\n  }\n  async pushSubscriptionCreate(e) {\n    return this.sendRequest(\"push_subscription_create\", {\n      platform: \"web\",\n      web_endpoint: e.web_endpoint,\n      web_key_auth: e.web_key_auth,\n      web_key_p256dh: e.web_key_p256dh,\n      device_udid: this.deviceId\n    }, \"subscription\");\n  }\n  async pushSubscriptionDelete() {\n    return this.sendRequest(\"push_subscription_delete\", { device_udid: this.deviceId });\n  }\n  async ping() {\n    return this.sendRequest(\"ping\", {}, \"pong\");\n  }\n  async setActivityStatus(e) {\n    return this.sendRequest(\"activity_status\", { isInactive: !!e }, \"success\");\n  }\n  async blockList() {\n    return this.sendRequest(\"list_blocked_users\", {}, \"users\");\n  }\n  async blockUsers(e) {\n    return this.sendRequest(\"block_user\", { ids: e }, \"success\");\n  }\n  async unblockUsers(e) {\n    return this.sendRequest(\"unblock_user\", { ids: e }, \"success\");\n  }\n  async reactionsUpdate(e, s, n) {\n    return this.sendRequest(\"message_reactions_update\", { mid: e, add: s, remove: n }, \"success\");\n  }\n  async reactionsList(e) {\n    return this.sendRequest(\"message_reactions_list\", { mid: e }, \"reactions\");\n  }\n}\nexport {\n  O as SAMAClient\n};\n","import { SAMAClient } from '@sama-communications/sdk';\nimport type { Chat } from '../../types';\n\nexport default class BlockList {\n  private samaClient: SAMAClient;\n\n  constructor(samaClient: SAMAClient) {\n    this.samaClient = samaClient;\n  }\n\n  public async block(userId: Chat.UserId): Promise<void>;\n  public async block(userIds: Chat.UserId[]): Promise<void>;\n  public async block(userIds: Chat.UserId | Chat.UserId[]): Promise<void> {\n    if (!Array.isArray(userIds)) {\n      userIds = [userIds];\n    }\n\n    await this.samaClient.blockUsers(userIds);\n  }\n\n  public async unblock(userId: Chat.UserId): Promise<void>;\n  public async unblock(userIds: Chat.UserId[]): Promise<void>;\n  public async unblock(userIds: Chat.UserId | Chat.UserId[]): Promise<void> {\n    if (!Array.isArray(userIds)) {\n      userIds = [userIds];\n    }\n\n    await this.samaClient.unblockUsers(userIds);\n  }\n\n  public async list(): Promise<Chat.UserId[]> {\n    const usersIds = await this.samaClient.blockList();\n    return usersIds;\n  }\n}\n","import config from '../../config';\nimport Utils from '../../Utils';\nimport { SAMAClient } from '@sama-communications/sdk';\nimport ProxyService from '../../Proxy';\nimport AbstractChatService from '../AbstractChatService';\nimport BlockList from './BlockList';\nimport type { SAMAChatRealTimeService } from '../../types/chat';\nimport type { Calls, Chat, PlainObject } from '../../types';\nimport { CallSignalingModuleIdentifier, CallType } from '../../types/constants';\n\nexport default class SAMAChatService extends AbstractChatService implements SAMAChatRealTimeService {\n  public samaClient: SAMAClient;\n  public blockList: BlockList;\n  public currentUserNativeId: Chat.UserId = 0;\n\n  constructor(proxy: ProxyService) {\n    super(proxy);\n\n    this.samaClient = new SAMAClient({\n      endpoint: {\n        ws: config.chatProtocol.websocket || '',\n        http: `https://${config.endpoints.api}`,\n      },\n      organization_id: `${config.creds.appId}`,\n      disableAutoReconnect: true,\n    });\n\n    this.blockList = new BlockList(this.samaClient);\n  }\n\n  public get connectionStatus(): string {\n    return '';\n  }\n\n  public get currentUserId(): Chat.UserId {\n    return this.currentUserNativeId || 0;\n  }\n\n  public async connect(params: Chat.ConnectionParams): Promise<boolean> {\n    Utils.DLog('[Chat]', 'Connect with parameter:', params);\n\n    this.samaClient.deviceId = params.deviceId ?? Utils.getBsonObjectId();\n\n    this.removeAllSamaListeners();\n    this.addAllSamaListeners();\n\n    if (!this.isConnected) {\n      await this.samaClient.connect();\n\n      this.isConnected = true;\n    }\n\n    const authorizedUser = await this.samaClient.socketLogin({\n      user: { userId: params.userId, password: params.password },\n    });\n\n    this.currentUserNativeId = authorizedUser.user.native_id;\n    this.isLogout = false;\n\n    return true;\n  }\n\n  public async disconnect(): Promise<boolean> {\n    Utils.DLog('[Chat]', 'disconnect');\n\n    this.isConnected = false;\n\n    try {\n      await this.samaClient.disconnectSocket();\n      await this.samaClient.disconnect();\n      this.currentUserNativeId = 0;\n      return true;\n    } catch {\n      return false;\n    }\n  }\n\n  public terminate(): void {\n    Utils.DLog('[Chat]', 'terminated');\n\n    this.isConnected = false;\n    this.currentUserNativeId = 0;\n\n    this.samaClient.disconnect();\n  }\n\n  private onSamaConnectedListener(): void {\n    Utils.DLog('[Chat]', this.samaClient.deviceId, '[connected]');\n\n    this.isConnected = true;\n\n    Utils.safeCallbackCall(this.onChatStatusListener)('connect');\n  }\n\n  private onSamaDisconnectListener(): void {\n    Utils.DLog('[Chat]', this.samaClient.deviceId, '[disconnect]');\n\n    this.isConnected = false;\n    this.isLogout = true;\n\n    Utils.safeCallbackCall(this.onChatStatusListener)('disconnect');\n    Utils.safeCallbackCall(this.onDisconnectedListener)();\n  }\n\n  private onSamaMessageEventListener(message: any): void {\n    Utils.DLog('[Chat]', '[packet]', this.samaClient.deviceId, message);\n  }\n\n  private onSamaMessageListener(message: any): void {\n    Utils.DLog('[Chat]', '[onMessage]', this.samaClient.deviceId, message);\n\n    const { _id, cid, from, body, t, x, attachments } = message;\n\n    const messageParams: Chat.Message = {\n      id: _id,\n      dialog_id: cid,\n      body: body,\n      extension: Object.assign({ date_sent: t, attachments }, x),\n    };\n\n    Utils.safeCallbackCall(this.onMessageListener)(from, messageParams);\n  }\n\n  private onSamaSystemMessageListener(message: any): void {\n    Utils.DLog('[Chat]', '[onSystem]', this.samaClient.deviceId, message);\n\n    const { _id, from, t, x } = message;\n\n    const systemMessage: Chat.SystemMessage = {\n      id: _id,\n      body: null as unknown as string,\n      userId: from,\n      extension: Object.assign({ date_sent: t }, x),\n    };\n\n    if (systemMessage.extension?.['moduleIdentifier'] === CallSignalingModuleIdentifier) {\n      return this.onWebRTCSignalingSystemMessage(systemMessage);\n    }\n\n    Utils.safeCallbackCall(this.onSystemMessageListener)(systemMessage);\n  }\n\n  private onWebRTCSignalingSystemMessage(systemMessage: Chat.SystemMessage<Calls.ExtensionParams>): void {\n    const extension = systemMessage.extension ?? {};\n\n    Object.keys(extension).forEach((key) => {\n      switch (key) {\n        case 'callerID':\n          extension[key] = parseInt(String(extension[key] || '0'));\n          break;\n\n        case 'callType':\n          const type = extension[key];\n          extension[key] = String(type) === '1' ? CallType.VIDEO : String(type) === '2' ? CallType.AUDIO : undefined;\n          break;\n\n        case 'opponentsIDs':\n          extension[key]?.map((opponentID) => Number(opponentID || '0'));\n          break;\n\n        case 'iceCandidates':\n          (extension[key] as unknown[] | undefined)?.forEach((iceCandidate: unknown) => {\n            const c = iceCandidate as PlainObject;\n            Object.keys(c).forEach((iceObjectKey) => {\n              if (iceObjectKey === 'sdpMLineIndex') {\n                c[iceObjectKey] = parseInt(String(c[iceObjectKey] || '0'));\n              }\n            });\n          });\n          break;\n\n        default:\n          break;\n      }\n    });\n\n    return Utils.safeCallbackCall(this.webrtcSignalingProcessor.onMessage)(\n      systemMessage.userId,\n      systemMessage.extension\n    );\n  }\n\n  private onSamaMessageStatusListener(message: any): void {\n    Utils.DLog('[Chat]', '[onStatus]', this.samaClient.deviceId, message);\n\n    const { ids, cid, from } = message;\n\n    for (const messageId of ids) {\n      Utils.safeCallbackCall(this.onReadStatusListener)(messageId, cid, from);\n    }\n  }\n\n  private onSamaUserLastActivityListener(message: any): void {\n    Utils.DLog('[Chat]', '[onLastActivity]', this.samaClient.deviceId, message);\n\n    Object.entries(message).forEach(([userId, lastActivityTs]) => {\n      Utils.safeCallbackCall(this.onLastUserActivityListener)(Number(userId), Number(lastActivityTs));\n    });\n  }\n\n  private onSamaTypingListener(message: any): void {\n    Utils.DLog('[Chat]', '[onTyping]', this.samaClient.deviceId, message);\n\n    const { cid, from, status } = message;\n    const isTyping = status === 'start';\n\n    Utils.safeCallbackCall(this.onMessageTypingListener)(isTyping, from, cid);\n  }\n\n  private onSamaMessageEditListener(message: any): void {\n    Utils.DLog('[Chat]', '[onEdit]', this.samaClient.deviceId, message);\n\n    const { id, cid, from, body } = message;\n\n    const messageEditParams = {\n      messageId: id,\n      isLast: false,\n      updatedBody: body,\n      dialogId: cid,\n      userId: from,\n      extraParams: {},\n    };\n\n    Utils.safeCallbackCall(this.onMessageUpdateListener)(\n      messageEditParams.messageId,\n      messageEditParams.isLast,\n      messageEditParams.updatedBody,\n      messageEditParams.dialogId,\n      messageEditParams.userId,\n      messageEditParams.extraParams\n    );\n  }\n\n  private onSamaDeleteListener(message: any): void {\n    Utils.DLog('[Chat]', '[onDelete]', this.samaClient.deviceId, message);\n\n    const { ids, cid, from } = message;\n\n    for (const messageId of ids) {\n      Utils.safeCallbackCall(this.onMessageDeleteListener)(messageId, cid, from);\n    }\n  }\n\n  private onSamaMessageReactionListener(messageReaction: any): void {\n    Utils.DLog('[Chat]', '[onReaction]', this.samaClient.deviceId, messageReaction);\n\n    const { mid, cid, from, add, remove } = messageReaction;\n\n    Utils.safeCallbackCall(this.onMessageReactionsListener)(mid, from, cid, add, remove);\n  }\n\n  public async ping(): Promise<void> {\n    await this.samaClient.ping();\n  }\n\n  public async sendIsTypingStatus(dialogId: Chat.DialogId | Chat.UserId): Promise<void> {\n    const requestParams = {\n      cid: String(dialogId),\n      status: 'start',\n    };\n\n    await this.samaClient.sendTypingStatus(requestParams);\n  }\n\n  public async sendIsStopTypingStatus(dialogId: Chat.DialogId | Chat.UserId): Promise<void> {\n    const requestParams = {\n      cid: String(dialogId),\n      status: 'stop',\n    };\n\n    await this.samaClient.sendTypingStatus(requestParams);\n  }\n\n  public async send(dialogId: Chat.DialogId | Chat.UserId, message: Chat.MessageParams): Promise<string> {\n    const mid = message.id ?? Utils.getBsonObjectId();\n    const x = message.extension ?? {};\n    const attachments = x?.['attachments'];\n    delete x?.['attachments'];\n\n    const requestParams = {\n      mid,\n      body: message.body ?? '',\n      x,\n      attachments,\n      cid: String(dialogId),\n    };\n\n    const ack = await this.samaClient.messageCreate(requestParams);\n\n    return ack?.server_mid ?? mid;\n  }\n\n  public sendSystemMessage(userId: Chat.UserId, message: Chat.SystemMessageParams): Promise<string>;\n  public sendSystemMessage(userIds: Array<Chat.UserId>, message: Chat.SystemMessageParams): Promise<string>;\n  public sendSystemMessage(dialogId: Chat.DialogId, message: Chat.SystemMessageParams): Promise<string>;\n  public async sendSystemMessage(\n    userIdsOrDialogId: Chat.UserId | Array<Chat.UserId> | Chat.DialogId,\n    message: Chat.SystemMessageParams\n  ): Promise<string> {\n    const mid = message.id ?? Utils.getBsonObjectId();\n\n    const destinationParams = Array.isArray(userIdsOrDialogId)\n      ? { uids: userIdsOrDialogId }\n      : typeof userIdsOrDialogId === 'number'\n        ? { uids: [userIdsOrDialogId] }\n        : { cid: userIdsOrDialogId };\n\n    const requestParams = {\n      mid,\n      x: message.extension ?? {},\n      ...destinationParams,\n    };\n\n    this.samaClient.messageSystem(requestParams);\n\n    return mid;\n  }\n\n  public async sendWebRTCSignalingMessage(userId: number, message: Chat.SystemMessageParams): Promise<string> {\n    return await this.sendSystemMessage(userId, message);\n  }\n\n  public async sendDeliveredStatus(_params: Chat.MessageStatusParams): Promise<void> {}\n\n  public async sendReadStatus(params: Chat.MessageStatusParams): Promise<void> {\n    const requestParams = {\n      cid: params.dialogId,\n      mids: [params.messageId],\n    };\n\n    await this.samaClient.markConversationAsRead(requestParams);\n  }\n\n  public async markDialogAsRead(params: Chat.DialogReadParams): Promise<void> {\n    const requestParams = {\n      cid: params.dialogId,\n    };\n\n    await this.samaClient.markConversationAsRead(requestParams);\n  }\n\n  public async updateReaction(messageId: string, addReaction: string, removeReaction: string): Promise<void> {\n    await this.samaClient.reactionsUpdate(messageId, addReaction, removeReaction);\n  }\n\n  public async editMessage(params: Chat.EditMessageParams): Promise<void> {\n    const requestParams = {\n      mid: params.originMessageId,\n      body: params.body,\n    };\n\n    await this.samaClient.messageEdit(requestParams);\n  }\n\n  public async deleteMessage(params: Chat.DeleteMessageParams): Promise<void> {\n    const requestParams = {\n      cid: params.dialogId,\n      mids: [params.messageId],\n      type: 'all',\n    };\n\n    await this.samaClient.messageDelete(requestParams);\n  }\n\n  public async getLastUserActivity(userId: Chat.UserId): Promise<Chat.LastActivity> {\n    const result = await this.samaClient.getUserActivity([userId]);\n\n    if (!(userId in result)) {\n      throw new Error('User not found');\n    }\n\n    const activityDate = result[userId];\n\n    if (activityDate === 0) {\n      return { userId, seconds: activityDate };\n    }\n\n    return { userId, seconds: !activityDate ? activityDate : Math.ceil(+new Date() / 1000) - activityDate };\n  }\n\n  public async subscribeToUserLastActivityStatus(userId: Chat.UserId): Promise<void> {\n    return await this.samaClient.subscribeToUserActivity(userId);\n  }\n\n  public async unsubscribeFromUserLastActivityStatus(_userId?: Chat.UserId): Promise<void> {\n    return await this.samaClient.unsubscribeFromUserActivity();\n  }\n\n  public async markActive(): Promise<void> {\n    await this.samaClient.setActivityStatus(false);\n  }\n\n  public async markInactive(): Promise<void> {\n    await this.samaClient.setActivityStatus(true);\n  }\n\n  private addAllSamaListeners() {\n    this.samaClient.onConnectEvent = this.onSamaConnectedListener.bind(this);\n    this.samaClient.onDisconnectEvent = this.onSamaDisconnectListener.bind(this);\n\n    this.samaClient.onMessageListener = this.onSamaMessageEventListener.bind(this);\n    this.samaClient.onMessageEvent = this.onSamaMessageListener.bind(this);\n    this.samaClient.onSystemMessageEvent = this.onSamaSystemMessageListener.bind(this);\n\n    this.samaClient.onMessageStatusListener = this.onSamaMessageStatusListener.bind(this);\n    this.samaClient.onMessageReactionsListener = this.onSamaMessageReactionListener.bind(this);\n\n    this.samaClient.onMessageEditListener = this.onSamaMessageEditListener.bind(this);\n    this.samaClient.onMessageDeleteListener = this.onSamaDeleteListener.bind(this);\n\n    this.samaClient.onUserActivityListener = this.onSamaUserLastActivityListener.bind(this);\n    this.samaClient.onUserTypingListener = this.onSamaTypingListener.bind(this);\n  }\n\n  private removeAllSamaListeners() {\n    this.samaClient.onConnectEvent = void 0;\n    this.samaClient.onDisconnectEvent = void 0;\n\n    this.samaClient.onMessageListener = void 0;\n    this.samaClient.onMessageEvent = void 0;\n    this.samaClient.onSystemMessageEvent = void 0;\n\n    this.samaClient.onMessageStatusListener = void 0;\n    this.samaClient.onMessageReactionsListener = void 0;\n\n    this.samaClient.onMessageEditListener = void 0;\n    this.samaClient.onMessageDeleteListener = void 0;\n\n    this.samaClient.onUserActivityListener = void 0;\n    this.samaClient.onUserTypingListener = void 0;\n  }\n}\n","const {\n  adapter,\n  navigator,\n  MediaStream,\n  MediaStreamTrack,\n  RTCPeerConnection,\n  RTCRtpReceiver,\n  RTCRtpSender,\n  isReactNative\n} = require('@platform');\n\n('use strict');\n/*\n  The MIT License (MIT)\n\n  Copyright (c) 2016 Meetecho\n\n  Permission is hereby granted, free of charge, to any person obtaining\n  a copy of this software and associated documentation files (the \"Software\"),\n  to deal in the Software without restriction, including without limitation\n  the rights to use, copy, modify, merge, publish, distribute, sublicense,\n  and/or sell copies of the Software, and to permit persons to whom the\n  Software is furnished to do so, subject to the following conditions:\n\n  The above copyright notice and this permission notice shall be included\n  in all copies or substantial portions of the Software.\n\n  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR\n  OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n  ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n  OTHER DEALINGS IN THE SOFTWARE.\n */\n\n// List of sessions\nJanus.sessions = {};\n\nJanus.mobile = isReactNative;\n\nJanus.isExtensionEnabled = function () {\n  if (Janus.mobile) {\n    return false;\n  }\n  if (navigator.mediaDevices && navigator.mediaDevices.getDisplayMedia) {\n    // No need for the extension, getDisplayMedia is supported\n    return true;\n  }\n  if (window.navigator.userAgent.match('Chrome')) {\n    let chromever = parseInt(window.navigator.userAgent.match(/Chrome\\/(.*) /)[1], 10);\n    let maxver = 33;\n    if (window.navigator.userAgent.match('Linux')) maxver = 35; // \"known\" crash in chrome 34 and 35 on linux\n    if (chromever >= 26 && chromever <= maxver) {\n      // Older versions of Chrome don't support this extension-based approach, so lie\n      return true;\n    }\n    return Janus.extension.isInstalled();\n  } else {\n    // Firefox and others, no need for the extension (but this doesn't mean it will work)\n    return true;\n  }\n};\n\nconst defaultExtension = {\n  // Screensharing Chrome Extension ID\n  extensionId: 'hapfgfdkleiggjjpfpenajgdnfckjpaj',\n  isInstalled: function () {\n    if (Janus.mobile) {\n      return false;\n    } else {\n      return document.querySelector('#janus-extension-installed') !== null;\n    }\n  },\n  getScreen: function (callback) {\n    if (Janus.mobile) {\n      callback();\n    } else {\n      let pending = window.setTimeout(function () {\n        let error = new Error('NavigatorUserMediaError');\n        error.name =\n          'The required Chrome extension is not installed: click <a href=\"#\">here</a> to install it. (NOTE: this will need you to refresh the page)';\n        return callback(error);\n      }, 1000);\n      this.cache[pending] = callback;\n      window.postMessage({ type: 'janusGetScreen', id: pending }, '*');\n    }\n  },\n  init: function () {\n    let cache = {};\n    this.cache = cache;\n    // Wait for events from the Chrome Extension\n    if (!Janus.mobile) {\n      window.addEventListener('message', function (event) {\n        if (event.origin != window.location.origin) return;\n        if (event.data.type == 'janusGotScreen' && cache[event.data.id]) {\n          let callback = cache[event.data.id];\n          delete cache[event.data.id];\n          if (event.data.sourceId === '') {\n            // user canceled\n            let error = new Error('NavigatorUserMediaError');\n            error.name = 'You cancelled the request for permission, giving up...';\n            callback(error);\n          } else {\n            callback(null, event.data.sourceId);\n          }\n        } else if (event.data.type == 'janusGetScreenPending') {\n          window.clearTimeout(event.data.id);\n        }\n      });\n    }\n  },\n};\n\nJanus.useDefaultDependencies = function (deps) {\n  let f = (deps && deps.fetch) || fetch;\n  let p = (deps && deps.Promise) || Promise;\n  let socketCls = (deps && deps.WebSocket) || WebSocket;\n\n  return {\n    newWebSocket: function (server, proto) {\n      return new socketCls(server, proto);\n    },\n    extension: (deps && deps.extension) || defaultExtension,\n    isArray: function (arr) {\n      return Array.isArray(arr);\n    },\n    webRTCAdapter: (deps && deps.adapter) || adapter,\n    httpAPICall: function (url, options) {\n      let fetchOptions = {\n        method: options.verb,\n        headers: {\n          Accept: 'application/json, text/plain, */*',\n        },\n        cache: 'no-cache',\n      };\n      if (options.verb === 'POST') {\n        fetchOptions.headers['Content-Type'] = 'application/json';\n      }\n      if (typeof options.withCredentials !== 'undefined') {\n        fetchOptions.credentials =\n          options.withCredentials === true ? 'include' : options.withCredentials ? options.withCredentials : 'omit';\n      }\n      if (options.body) {\n        fetchOptions.body = JSON.stringify(options.body);\n      }\n\n      let fetching = f(url, fetchOptions).catch(function (error) {\n        return p.reject({\n          message: 'Probably a network error, is the server down?',\n          error: error,\n        });\n      });\n\n      /*\n       * fetch() does not natively support timeouts.\n       * Work around this by starting a timeout manually, and racing it agains the fetch() to see which thing resolves first.\n       */\n\n      if (options.timeout) {\n        let timeout = new p(function (resolve, reject) {\n          let timerId = setTimeout(function () {\n            clearTimeout(timerId);\n            return reject({\n              message: 'Request timed out',\n              timeout: options.timeout,\n            });\n          }, options.timeout);\n        });\n        fetching = p.race([fetching, timeout]);\n      }\n\n      fetching\n        .then(function (response) {\n          if (response.ok) {\n            if (typeof options.success === typeof Janus.noop) {\n              return response.json().then(\n                function (parsed) {\n                  try {\n                    options.success(parsed);\n                  } catch (error) {\n                    Janus.error('Unhandled httpAPICall success callback error', error);\n                  }\n                },\n                function (error) {\n                  return p.reject({\n                    message: 'Failed to parse response body',\n                    error: error,\n                    response: response,\n                  });\n                }\n              );\n            }\n          } else {\n            return p.reject({ message: 'API call failed', response: response });\n          }\n        })\n        .catch(function (error) {\n          if (typeof options.error === typeof Janus.noop) {\n            options.error(error.message || '<< internal error >>', error);\n          }\n        });\n\n      return fetching;\n    },\n  };\n};\n\nJanus.useOldDependencies = function (deps) {\n  let jq = (deps && deps.jQuery) || jQuery;\n  let socketCls = (deps && deps.WebSocket) || WebSocket;\n  return {\n    newWebSocket: function (server, proto) {\n      return new socketCls(server, proto);\n    },\n    isArray: function (arr) {\n      return jq.isArray(arr);\n    },\n    extension: (deps && deps.extension) || defaultExtension,\n    webRTCAdapter: (deps && deps.adapter) || adapter,\n    httpAPICall: function (url, options) {\n      let payload =\n        typeof options.body !== 'undefined'\n          ? {\n            contentType: 'application/json',\n            data: JSON.stringify(options.body),\n          }\n          : {};\n      let credentials =\n        typeof options.withCredentials !== 'undefined'\n          ? { xhrFields: { withCredentials: options.withCredentials } }\n          : {};\n\n      return jq.ajax(\n        jq.extend(payload, credentials, {\n          url: url,\n          type: options.verb,\n          cache: false,\n          dataType: 'json',\n          async: options.async,\n          timeout: options.timeout,\n          success: function (result) {\n            if (typeof options.success === typeof Janus.noop) {\n              options.success(result);\n            }\n          },\n          error: function (xhr, status, err) {\n            if (typeof options.error === typeof Janus.noop) {\n              options.error(status, err);\n            }\n          },\n        })\n      );\n    },\n  };\n};\n\n// Helper function to convert a deprecated media object to a tracks array\nJanus.mediaToTracks = function (media) {\n  let tracks = [];\n  if (!media) {\n    // Default is bidirectional audio and video, using default devices\n    tracks.push({ type: 'audio', capture: true, recv: true });\n    tracks.push({ type: 'video', capture: true, recv: true });\n  } else {\n    if (\n      !media.keepAudio &&\n      media.audio !== false &&\n      (typeof media.audio === 'undefined' ||\n        media.audio ||\n        media.audioSend ||\n        media.audioRecv ||\n        media.addAudio ||\n        media.replaceAudio ||\n        media.removeAudio)\n    ) {\n      // We may need an audio track\n      let track = { type: 'audio' };\n      if (media.removeAudio) {\n        track.remove = true;\n      } else {\n        if (media.addAudio) track.add = true;\n        else if (media.replaceAudio) track.replace = true;\n        // Check if we need to capture an audio device\n        if (media.audioSend !== false) track.capture = media.audio || true;\n        // Check if we need to receive audio\n        if (media.audioRecv !== false) track.recv = true;\n      }\n      // Add an audio track if needed\n      if (track.remove || track.capture || track.recv) tracks.push(track);\n    }\n    if (\n      !media.keepVideo &&\n      media.video !== false &&\n      (typeof media.video === 'undefined' ||\n        media.video ||\n        media.videoSend ||\n        media.videoRecv ||\n        media.addVideo ||\n        media.replaceVideo ||\n        media.removeVideo)\n    ) {\n      // We may need a video track\n      let track = { type: 'video' };\n      if (media.removeVideo) {\n        track.remove = true;\n      } else {\n        if (media.addVideo) track.add = true;\n        else if (media.replaceVideo) track.replace = true;\n        // Check if we need to capture a video device\n        if (media.videoSend !== false) {\n          track.capture = media.video || true;\n          if (['screen', 'window', 'desktop'].includes(track.capture)) {\n            // Change the type to 'screen'\n            track.type = 'screen';\n            track.capture = { video: {} };\n            // Check if there's constraints\n            if (media.screenshareFrameRate) track.capture.frameRate = media.screenshareFrameRate;\n            if (media.screenshareHeight) track.capture.height = media.screenshareHeight;\n            if (media.screenshareWidth) track.capture.width = media.screenshareWidth;\n          }\n        }\n        // Check if we need to receive video\n        if (media.videoRecv !== false) track.recv = true;\n      }\n      // Add a video track if needed\n      if (track.remove || track.capture || track.recv) tracks.push(track);\n    }\n    if (media.data) {\n      // We need a data channel\n      tracks.push({ type: 'data' });\n    }\n  }\n  // Done\n  return tracks;\n};\n\n// Helper function to convert a track object to a set of constraints\nJanus.trackConstraints = function (track) {\n  let constraints = {};\n  if (!track || !track.capture) return constraints;\n  if (track.type === 'audio') {\n    // Just put the capture part in the constraints\n    constraints.audio = track.capture;\n  } else if (track.type === 'video') {\n    // Check if one of the keywords was passed\n    if ((track.simulcast || track.svc) && track.capture === true) track.capture = 'hires';\n    if (track.capture === true || typeof track.capture === 'object') {\n      // Use the provided capture object as video constraint\n      constraints.video = track.capture;\n    } else {\n      let width = 0;\n      let height = 0;\n      if (track.capture === 'lowres') {\n        // Small resolution, 4:3\n        width = 320;\n        height = 240;\n      } else if (track.capture === 'lowres-16:9') {\n        // Small resolution, 16:9\n        width = 320;\n        height = 180;\n      } else if (track.capture === 'hires' || track.capture === 'hires-16:9' || track.capture === 'hdres') {\n        // High(HD) resolution is only 16:9\n        width = 1280;\n        height = 720;\n      } else if (track.capture === 'fhdres') {\n        // Full HD resolution is only 16:9\n        width = 1920;\n        height = 1080;\n      } else if (track.capture === '4kres') {\n        // 4K resolution is only 16:9\n        width = 3840;\n        height = 2160;\n      } else if (track.capture === 'stdres') {\n        // Normal resolution, 4:3\n        width = 640;\n        height = 480;\n      } else if (track.capture === 'stdres-16:9') {\n        // Normal resolution, 16:9\n        width = 640;\n        height = 360;\n      } else {\n        Janus.log('Default video setting is stdres 4:3');\n        width = 640;\n        height = 480;\n      }\n      constraints.video = {\n        width: { ideal: width },\n        height: { ideal: height },\n      };\n    }\n  } else if (track.type === 'screen') {\n    // Use the provided capture object as video constraint\n    constraints.video = track.capture;\n  }\n  return constraints;\n};\n\nJanus.noop = function () { };\n\nJanus.dataChanDefaultLabel = 'JanusDataChannel';\n\n// Note: in the future we may want to change this, e.g., as was\n// attempted in https://github.com/meetecho/janus-gateway/issues/1670\nJanus.endOfCandidates = null;\n\n// Stop all tracks from a given stream\nJanus.stopAllTracks = function (stream) {\n  try {\n    // Try a MediaStreamTrack.stop() for each track\n    let tracks = stream.getTracks();\n    for (let mst of tracks) {\n      Janus.log(mst);\n      if (mst && mst.dontStop !== true) {\n        mst.stop();\n      }\n    }\n  } catch (e) {\n    // Do nothing if this fails\n  }\n};\n\n// Initialization\nJanus.init = function (options) {\n  options = options || {};\n  options.callback = typeof options.callback == 'function' ? options.callback : Janus.noop;\n  if (Janus.initDone) {\n    // Already initialized\n    options.callback();\n  } else {\n    if (typeof console.log == 'undefined') {\n      console.log = function () { };\n    }\n    // Console logging (all debugging disabled by default)\n    Janus.trace = Janus.noop;\n    Janus.debug = Janus.noop;\n    Janus.vdebug = Janus.noop;\n    Janus.log = Janus.noop;\n    Janus.warn = Janus.noop;\n    Janus.error = Janus.noop;\n    if (options.debug === true || options.debug === 'all') {\n      // Enable all debugging levels\n      Janus.trace = console.trace.bind(console);\n      Janus.debug = console.debug.bind(console);\n      Janus.vdebug = console.debug.bind(console);\n      Janus.log = console.log.bind(console);\n      Janus.warn = console.warn.bind(console);\n      Janus.error = console.error.bind(console);\n    } else if (Array.isArray(options.debug)) {\n      for (let d of options.debug) {\n        switch (d) {\n          case 'trace':\n            Janus.trace = console.trace.bind(console);\n            break;\n          case 'debug':\n            Janus.debug = console.debug.bind(console);\n            break;\n          case 'vdebug':\n            Janus.vdebug = console.debug.bind(console);\n            break;\n          case 'log':\n            Janus.log = console.log.bind(console);\n            break;\n          case 'warn':\n            Janus.warn = console.warn.bind(console);\n            break;\n          case 'error':\n            Janus.error = console.error.bind(console);\n            break;\n          default:\n            console.error(\n              \"Unknown debugging option '\" + d + \"' (supported: 'trace', 'debug', 'vdebug', 'log', warn', 'error')\"\n            );\n            break;\n        }\n      }\n    }\n    Janus.log('Initializing library');\n\n    let usedDependencies = options.dependencies || Janus.useDefaultDependencies();\n    Janus.isArray = usedDependencies.isArray;\n    Janus.webRTCAdapter = usedDependencies.webRTCAdapter;\n    Janus.httpAPICall = usedDependencies.httpAPICall;\n    Janus.newWebSocket = usedDependencies.newWebSocket;\n    Janus.extension = usedDependencies.extension;\n    Janus.extension.init();\n\n    // Helper method to enumerate devices\n    Janus.listDevices = function (callback, config) {\n      callback = typeof callback == 'function' ? callback : Janus.noop;\n      if (!config) config = { audio: true, video: true };\n      if (Janus.isGetUserMediaAvailable()) {\n        navigator.mediaDevices\n          .getUserMedia(config)\n          .then(function (stream) {\n            navigator.mediaDevices.enumerateDevices().then(function (devices) {\n              Janus.debug(devices);\n              callback(devices);\n              // Get rid of the now useless stream\n              Janus.stopAllTracks(stream);\n            });\n          })\n          .catch(function (err) {\n            Janus.error(err);\n            callback([]);\n          });\n      } else {\n        Janus.warn('navigator.mediaDevices unavailable');\n        callback([]);\n      }\n    };\n    // Helper methods to attach/reattach a stream to a video element (previously part of adapter.js)\n    // Janus.attachMediaStream = function(element, stream) {\n    // \ttry {\n    // \t\telement.srcObject = stream;\n    // \t} catch (e) {\n    // \t\ttry {\n    // \t\t\telement.src = URL.createObjectURL(stream);\n    // \t\t} catch (e) {\n    // \t\t\tJanus.error(\"Error attaching stream to element\", e);\n    // \t\t}\n    // \t}\n    // };\n    // Janus.reattachMediaStream = function(to, from) {\n    // \ttry {\n    // \t\tto.srcObject = from.srcObject;\n    // \t} catch (e) {\n    // \t\ttry {\n    // \t\t\tto.src = from.src;\n    // \t\t} catch (e) {\n    // \t\t\tJanus.error(\"Error reattaching stream to element\", e);\n    // \t\t}\n    // \t}\n    // };\n    // Detect tab close: make sure we don't loose existing onbeforeunload handlers\n    // (note: for iOS we need to subscribe to a different event, 'pagehide', see\n    // https://gist.github.com/thehunmonkgroup/6bee8941a49b86be31a787fe8f4b8cfe)\n    // let iOS = ['iPad', 'iPhone', 'iPod'].indexOf(navigator.platform) >= 0;\n    // let eventName = iOS ? 'pagehide' : 'beforeunload';\n    // let oldOBF = window[\"on\" + eventName];\n    // window.addEventListener(eventName, function() {\n    // \tJanus.log(\"Closing window\");\n    // \tfor(let s in Janus.sessions) {\n    // \t\tif(Janus.sessions[s] && Janus.sessions[s].destroyOnUnload) {\n    // \t\t\tJanus.log(\"Destroying session \" + s);\n    // \t\t\tJanus.sessions[s].destroy({unload: true, notifyDestroyed: false});\n    // \t\t}\n    // \t}\n    // \tif(oldOBF && typeof oldOBF == \"function\") {\n    // \t\toldOBF();\n    // \t}\n    // });\n    // If this is a Safari Technology Preview, check if VP8 is supported\n    Janus.safariVp8 = false;\n    if (Janus.webRTCAdapter.browserDetails.browser === 'safari' && Janus.webRTCAdapter.browserDetails.version >= 605) {\n      // Let's see if RTCRtpSender.getCapabilities() is there\n      if (\n        RTCRtpSender &&\n        RTCRtpSender.getCapabilities &&\n        RTCRtpSender.getCapabilities('video') &&\n        RTCRtpSender.getCapabilities('video').codecs &&\n        RTCRtpSender.getCapabilities('video').codecs.length\n      ) {\n        for (let codec of RTCRtpSender.getCapabilities('video').codecs) {\n          if (codec && codec.mimeType && codec.mimeType.toLowerCase() === 'video/vp8') {\n            Janus.safariVp8 = true;\n            break;\n          }\n        }\n        if (Janus.safariVp8) {\n          Janus.log('This version of Safari supports VP8');\n        } else {\n          Janus.warn(\n            \"This version of Safari does NOT support VP8: if you're using a Technology Preview, \" +\n            \"try enabling the 'WebRTC VP8 codec' setting in the 'Experimental Features' Develop menu\"\n          );\n        }\n      } else {\n        // We do it in a very ugly way, as there's no alternative...\n        // We create a PeerConnection to see if VP8 is in an offer\n        let testpc = new RTCPeerConnection({});\n        testpc.createOffer({ offerToReceiveVideo: true }).then(function (offer) {\n          Janus.safariVp8 = offer.sdp.indexOf('VP8') !== -1;\n          if (Janus.safariVp8) {\n            Janus.log('This version of Safari supports VP8');\n          } else {\n            Janus.warn(\n              \"This version of Safari does NOT support VP8: if you're using a Technology Preview, \" +\n              \"try enabling the 'WebRTC VP8 codec' setting in the 'Experimental Features' Develop menu\"\n            );\n          }\n          testpc.close();\n          testpc = null;\n        });\n      }\n    }\n    Janus.initDone = true;\n    options.callback();\n  }\n};\n\n// Helper method to check whether WebRTC is supported by this browser\nJanus.isWebrtcSupported = function () {\n  return !!RTCPeerConnection;\n};\n// Helper method to check whether devices can be accessed by this browser (e.g., not possible via plain HTTP)\nJanus.isGetUserMediaAvailable = function () {\n  return navigator.mediaDevices && navigator.mediaDevices.getUserMedia;\n};\n\n// Helper method to create random identifiers (e.g., transaction)\nJanus.randomString = function (len) {\n  let charSet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n  let randomString = '';\n  for (let i = 0; i < len; i++) {\n    let randomPoz = Math.floor(Math.random() * charSet.length);\n    randomString += charSet.charAt(randomPoz);\n  }\n  return randomString;\n};\n\nfunction Janus(gatewayCallbacks) {\n  gatewayCallbacks = gatewayCallbacks || {};\n  gatewayCallbacks.success = typeof gatewayCallbacks.success == 'function' ? gatewayCallbacks.success : Janus.noop;\n  gatewayCallbacks.error = typeof gatewayCallbacks.error == 'function' ? gatewayCallbacks.error : Janus.noop;\n  gatewayCallbacks.destroyed =\n    typeof gatewayCallbacks.destroyed == 'function' ? gatewayCallbacks.destroyed : Janus.noop;\n  if (!Janus.initDone) {\n    gatewayCallbacks.error('Library not initialized');\n    return {};\n  }\n  if (!Janus.isWebrtcSupported()) {\n    gatewayCallbacks.error('WebRTC not supported by this browser');\n    return {};\n  }\n  Janus.log('Library initialized: ' + Janus.initDone);\n  if (!gatewayCallbacks.server) {\n    gatewayCallbacks.error('Invalid server url');\n    return {};\n  }\n  let websockets = false;\n  let ws = null;\n  let wsHandlers = {};\n  let wsKeepaliveTimeoutId = null;\n  let servers = null;\n  let serversIndex = 0;\n  let server = gatewayCallbacks.server;\n  if (Janus.isArray(server)) {\n    Janus.log('Multiple servers provided (' + server.length + '), will use the first that works');\n    server = null;\n    servers = gatewayCallbacks.server;\n    Janus.debug(servers);\n  } else {\n    if (server.indexOf('ws') === 0) {\n      websockets = true;\n      Janus.log('Using WebSockets to contact Janus: ' + server);\n    } else {\n      websockets = false;\n      Janus.log('Using REST API to contact Janus: ' + server);\n    }\n  }\n  let iceServers = gatewayCallbacks.iceServers || [{ urls: 'stun:stun.l.google.com:19302' }];\n  let iceTransportPolicy = gatewayCallbacks.iceTransportPolicy;\n  let bundlePolicy = gatewayCallbacks.bundlePolicy;\n  // Whether we should enable the withCredentials flag for XHR requests\n  let withCredentials = false;\n  if (typeof gatewayCallbacks.withCredentials !== 'undefined' && gatewayCallbacks.withCredentials !== null)\n    withCredentials = gatewayCallbacks.withCredentials === true;\n  // Optional max events\n  let maxev = 10;\n  if (typeof gatewayCallbacks.max_poll_events !== 'undefined' && gatewayCallbacks.max_poll_events !== null)\n    maxev = gatewayCallbacks.max_poll_events;\n  if (maxev < 1) maxev = 1;\n  // Token to use (only if the token based authentication mechanism is enabled)\n  let token = null;\n  if (typeof gatewayCallbacks.token !== 'undefined' && gatewayCallbacks.token !== null) token = gatewayCallbacks.token;\n  // API secret to use (only if the shared API secret is enabled)\n  let apisecret = null;\n  if (typeof gatewayCallbacks.apisecret !== 'undefined' && gatewayCallbacks.apisecret !== null)\n    apisecret = gatewayCallbacks.apisecret;\n  // Whether we should destroy this session when onbeforeunload is called\n  this.destroyOnUnload = true;\n  if (typeof gatewayCallbacks.destroyOnUnload !== 'undefined' && gatewayCallbacks.destroyOnUnload !== null)\n    this.destroyOnUnload = gatewayCallbacks.destroyOnUnload === true;\n  // Some timeout-related values\n  let keepAlivePeriod = 25000;\n  if (typeof gatewayCallbacks.keepAlivePeriod !== 'undefined' && gatewayCallbacks.keepAlivePeriod !== null)\n    keepAlivePeriod = gatewayCallbacks.keepAlivePeriod;\n  if (isNaN(keepAlivePeriod)) keepAlivePeriod = 25000;\n  let longPollTimeout = 60000;\n  if (typeof gatewayCallbacks.longPollTimeout !== 'undefined' && gatewayCallbacks.longPollTimeout !== null)\n    longPollTimeout = gatewayCallbacks.longPollTimeout;\n  if (isNaN(longPollTimeout)) longPollTimeout = 60000;\n\n  // overrides for default maxBitrate values for simulcasting\n  function getMaxBitrates(simulcastMaxBitrates) {\n    let maxBitrates = {\n      high: 900000,\n      medium: 300000,\n      low: 100000,\n    };\n\n    if (typeof simulcastMaxBitrates !== 'undefined' && simulcastMaxBitrates !== null) {\n      if (simulcastMaxBitrates.high) maxBitrates.high = simulcastMaxBitrates.high;\n      if (simulcastMaxBitrates.medium) maxBitrates.medium = simulcastMaxBitrates.medium;\n      if (simulcastMaxBitrates.low) maxBitrates.low = simulcastMaxBitrates.low;\n    }\n\n    return maxBitrates;\n  }\n\n  let connected = false;\n  let sessionId = null;\n  let pluginHandles = {};\n  let that = this;\n  let retries = 0;\n  let transactions = {};\n  createSession(gatewayCallbacks);\n\n  // Public methods\n  this.getServer = function () {\n    return server;\n  };\n  this.isConnected = function () {\n    return connected;\n  };\n  this.reconnect = function (callbacks) {\n    callbacks = callbacks || {};\n    callbacks.success = typeof callbacks.success == 'function' ? callbacks.success : Janus.noop;\n    callbacks.error = typeof callbacks.error == 'function' ? callbacks.error : Janus.noop;\n    callbacks['reconnect'] = true;\n    createSession(callbacks);\n  };\n  this.getSessionId = function () {\n    return sessionId;\n  };\n  this.getInfo = function (callbacks) {\n    getInfo(callbacks);\n  };\n  this.destroy = function (callbacks) {\n    destroySession(callbacks);\n  };\n  this.attach = function (callbacks) {\n    createHandle(callbacks);\n  };\n\n  function eventHandler() {\n    if (sessionId == null) return;\n    Janus.debug('Long poll...');\n    if (!connected) {\n      Janus.warn('Is the server down? (connected=false)');\n      return;\n    }\n    let longpoll = server + '/' + sessionId + '?rid=' + new Date().getTime();\n    if (maxev) longpoll = longpoll + '&maxev=' + maxev;\n    if (token) longpoll = longpoll + '&token=' + encodeURIComponent(token);\n    if (apisecret) longpoll = longpoll + '&apisecret=' + encodeURIComponent(apisecret);\n    Janus.httpAPICall(longpoll, {\n      verb: 'GET',\n      withCredentials: withCredentials,\n      success: handleEvent,\n      timeout: longPollTimeout,\n      error: function (textStatus, errorThrown) {\n        Janus.error(textStatus + ':', errorThrown);\n        retries++;\n        if (retries > 3) {\n          // Did we just lose the server? :-(\n          connected = false;\n          gatewayCallbacks.error('Lost connection to the server (is it down?)');\n          return;\n        }\n        eventHandler();\n      },\n    });\n  }\n\n  // Private event handler: this will trigger plugin callbacks, if set\n  function handleEvent(json, skipTimeout) {\n    retries = 0;\n    if (!websockets && typeof sessionId !== 'undefined' && sessionId !== null && skipTimeout !== true) eventHandler();\n    if (!websockets && Janus.isArray(json)) {\n      // We got an array: it means we passed a maxev > 1, iterate on all objects\n      for (let i = 0; i < json.length; i++) {\n        handleEvent(json[i], true);\n      }\n      return;\n    }\n    if (json['janus'] === 'keepalive') {\n      // Nothing happened\n      Janus.vdebug('Got a keepalive on session ' + sessionId);\n      return;\n    } else if (json['janus'] === 'server_info') {\n      // Just info on the Janus instance\n      Janus.debug('Got info on the Janus instance');\n      Janus.debug(json);\n      const transaction = json['transaction'];\n      if (transaction) {\n        const reportSuccess = transactions[transaction];\n        if (reportSuccess) reportSuccess(json);\n        delete transactions[transaction];\n      }\n      return;\n    } else if (json['janus'] === 'ack') {\n      // Just an ack, we can probably ignore\n      Janus.debug('Got an ack on session ' + sessionId);\n      Janus.debug(json);\n      const transaction = json['transaction'];\n      if (transaction) {\n        const reportSuccess = transactions[transaction];\n        if (reportSuccess) reportSuccess(json);\n        delete transactions[transaction];\n      }\n      return;\n    } else if (json['janus'] === 'success') {\n      // Success!\n      Janus.debug('Got a success on session ' + sessionId);\n      Janus.debug(json);\n      const transaction = json['transaction'];\n      if (transaction) {\n        const reportSuccess = transactions[transaction];\n        if (reportSuccess) reportSuccess(json);\n        delete transactions[transaction];\n      }\n      return;\n    } else if (json['janus'] === 'trickle') {\n      // We got a trickle candidate from Janus\n      const sender = json['sender'];\n      if (!sender) {\n        Janus.warn('Missing sender...');\n        return;\n      }\n      const pluginHandle = pluginHandles[sender];\n      if (!pluginHandle) {\n        Janus.debug('This handle is not attached to this session');\n        return;\n      }\n      let candidate = json['candidate'];\n      Janus.debug('Got a trickled candidate on session ' + sessionId);\n      Janus.debug(candidate);\n      let config = pluginHandle.webrtcStuff;\n      if (config.pc && config.remoteSdp) {\n        // Add candidate right now\n        Janus.debug('Adding remote candidate:', candidate);\n        if (!candidate || candidate.completed === true) {\n          // end-of-candidates\n          config.pc.addIceCandidate(Janus.endOfCandidates);\n        } else {\n          // New candidate\n          config.pc.addIceCandidate(candidate);\n        }\n      } else {\n        // We didn't do setRemoteDescription (trickle got here before the offer?)\n        Janus.debug(\"We didn't do setRemoteDescription (trickle got here before the offer?), caching candidate\");\n        if (!config.candidates) config.candidates = [];\n        config.candidates.push(candidate);\n        Janus.debug(config.candidates);\n      }\n    } else if (json['janus'] === 'webrtcup') {\n      // The PeerConnection with the server is up! Notify this\n      Janus.debug('Got a webrtcup event on session ' + sessionId);\n      Janus.debug(json);\n      const sender = json['sender'];\n      if (!sender) {\n        Janus.warn('Missing sender...');\n        return;\n      }\n      const pluginHandle = pluginHandles[sender];\n      if (!pluginHandle) {\n        Janus.debug('This handle is not attached to this session');\n        return;\n      }\n      pluginHandle.webrtcState(true);\n      return;\n    } else if (json['janus'] === 'hangup') {\n      // A plugin asked the core to hangup a PeerConnection on one of our handles\n      Janus.debug('Got a hangup event on session ' + sessionId);\n      Janus.debug(json);\n      const sender = json['sender'];\n      if (!sender) {\n        Janus.warn('Missing sender...');\n        return;\n      }\n      const pluginHandle = pluginHandles[sender];\n      if (!pluginHandle) {\n        Janus.debug('This handle is not attached to this session');\n        return;\n      }\n      pluginHandle.webrtcState(false, json['reason']);\n      pluginHandle.hangup();\n    } else if (json['janus'] === 'detached') {\n      // A plugin asked the core to detach one of our handles\n      Janus.debug('Got a detached event on session ' + sessionId);\n      Janus.debug(json);\n      const sender = json['sender'];\n      if (!sender) {\n        Janus.warn('Missing sender...');\n        return;\n      }\n      const pluginHandle = pluginHandles[sender];\n      if (!pluginHandle) {\n        // Don't warn here because destroyHandle causes this situation.\n        return;\n      }\n      pluginHandle.ondetached();\n      pluginHandle.detach();\n    } else if (json['janus'] === 'media') {\n      // Media started/stopped flowing\n      Janus.debug('Got a media event on session ' + sessionId);\n      Janus.debug(json);\n      const sender = json['sender'];\n      if (!sender) {\n        Janus.warn('Missing sender...');\n        return;\n      }\n      const pluginHandle = pluginHandles[sender];\n      if (!pluginHandle) {\n        Janus.debug('This handle is not attached to this session');\n        return;\n      }\n      pluginHandle.mediaState(json['type'], json['receiving'], json['mid']);\n    } else if (json['janus'] === 'slowlink') {\n      Janus.debug('Got a slowlink event on session ' + sessionId);\n      Janus.debug(json);\n      // Trouble uplink or downlink\n      const sender = json['sender'];\n      if (!sender) {\n        Janus.warn('Missing sender...');\n        return;\n      }\n      const pluginHandle = pluginHandles[sender];\n      if (!pluginHandle) {\n        Janus.debug('This handle is not attached to this session');\n        return;\n      }\n      pluginHandle.slowLink(json['uplink'], json['lost'], json['mid']);\n    } else if (json['janus'] === 'error') {\n      // Oops, something wrong happened\n      Janus.error('Ooops: ' + json['error'].code + ' ' + json['error'].reason); // FIXME\n      Janus.debug(json);\n      let transaction = json['transaction'];\n      if (transaction) {\n        let reportSuccess = transactions[transaction];\n        if (reportSuccess) {\n          reportSuccess(json);\n        }\n        delete transactions[transaction];\n      }\n      return;\n    } else if (json['janus'] === 'event') {\n      Janus.debug('Got a plugin event on session ' + sessionId);\n      Janus.debug(json);\n      const sender = json['sender'];\n      if (!sender) {\n        Janus.warn('Missing sender...');\n        return;\n      }\n      let plugindata = json['plugindata'];\n      if (!plugindata) {\n        Janus.warn('Missing plugindata...');\n        return;\n      }\n      Janus.debug('  -- Event is coming from ' + sender + ' (' + plugindata['plugin'] + ')');\n      let data = plugindata['data'];\n      Janus.debug(data);\n      const pluginHandle = pluginHandles[sender];\n      if (!pluginHandle) {\n        Janus.warn('This handle is not attached to this session');\n        return;\n      }\n      let jsep = json['jsep'];\n      if (jsep) {\n        Janus.debug('Handling SDP as well...');\n        Janus.debug(jsep);\n      }\n      let callback = pluginHandle.onmessage;\n      if (callback) {\n        Janus.debug('Notifying application...');\n        // Send to callback specified when attaching plugin handle\n        callback(data, jsep);\n      } else {\n        // Send to generic callback (?)\n        Janus.debug('No provided notification callback');\n      }\n    } else if (json['janus'] === 'timeout') {\n      Janus.error('Timeout on session ' + sessionId);\n      Janus.debug(json);\n      if (websockets) {\n        ws.close(3504, 'Gateway timeout');\n      }\n      return;\n    } else {\n      Janus.warn(\"Unknown message/event  '\" + json['janus'] + \"' on session \" + sessionId);\n      Janus.debug(json);\n    }\n  }\n\n  // Private helper to send keep-alive messages on WebSockets\n  function keepAlive() {\n    if (!server || !websockets || !connected) return;\n    wsKeepaliveTimeoutId = setTimeout(keepAlive, keepAlivePeriod);\n    let request = {\n      janus: 'keepalive',\n      session_id: sessionId,\n      transaction: Janus.randomString(12),\n    };\n    if (token) request['token'] = token;\n    if (apisecret) request['apisecret'] = apisecret;\n    ws.send(JSON.stringify(request));\n  }\n\n  // Private method to create a session\n  function createSession(callbacks) {\n    let transaction = Janus.randomString(12);\n    let request = { janus: 'create', transaction: transaction };\n    if (callbacks['reconnect']) {\n      // We're reconnecting, claim the session\n      connected = false;\n      request['janus'] = 'claim';\n      request['session_id'] = sessionId;\n      // If we were using websockets, ignore the old connection\n      if (ws) {\n        ws.onopen = null;\n        ws.onerror = null;\n        ws.onclose = null;\n        if (wsKeepaliveTimeoutId) {\n          clearTimeout(wsKeepaliveTimeoutId);\n          wsKeepaliveTimeoutId = null;\n        }\n      }\n    }\n    if (token) request['token'] = token;\n    if (apisecret) request['apisecret'] = apisecret;\n    if (!server && Janus.isArray(servers)) {\n      // We still need to find a working server from the list we were given\n      server = servers[serversIndex];\n      if (server.indexOf('ws') === 0) {\n        websockets = true;\n        Janus.log('Server #' + (serversIndex + 1) + ': trying WebSockets to contact Janus (' + server + ')');\n      } else {\n        websockets = false;\n        Janus.log('Server #' + (serversIndex + 1) + ': trying REST API to contact Janus (' + server + ')');\n      }\n    }\n    if (websockets) {\n      ws = Janus.newWebSocket(server, 'janus-protocol');\n      wsHandlers = {\n        error: function () {\n          Janus.error('Error connecting to the Janus WebSockets server... ' + server);\n          if (Janus.isArray(servers) && !callbacks['reconnect']) {\n            serversIndex++;\n            if (serversIndex === servers.length) {\n              // We tried all the servers the user gave us and they all failed\n              callbacks.error('Error connecting to any of the provided Janus servers: Is the server down?');\n              return;\n            }\n            // Let's try the next server\n            server = null;\n            setTimeout(function () {\n              createSession(callbacks);\n            }, 200);\n            return;\n          }\n          callbacks.error('Error connecting to the Janus WebSockets server: Is the server down?');\n        },\n\n        open: function () {\n          // We need to be notified about the success\n          transactions[transaction] = function (json) {\n            Janus.debug(json);\n            if (json['janus'] !== 'success') {\n              Janus.error('Ooops: ' + json['error'].code + ' ' + json['error'].reason); // FIXME\n              callbacks.error(json['error'].reason);\n              return;\n            }\n            wsKeepaliveTimeoutId = setTimeout(keepAlive, keepAlivePeriod);\n            connected = true;\n            sessionId = json['session_id'] ? json['session_id'] : json.data['id'];\n            if (callbacks['reconnect']) {\n              Janus.log('Claimed session: ' + sessionId);\n            } else {\n              Janus.log('Created session: ' + sessionId);\n            }\n            Janus.sessions[sessionId] = that;\n            callbacks.success();\n          };\n          ws.send(JSON.stringify(request));\n        },\n\n        message: function (event) {\n          handleEvent(JSON.parse(event.data));\n        },\n\n        close: function () {\n          if (!server || !connected) {\n            return;\n          }\n          connected = false;\n          // FIXME What if this is called when the page is closed?\n          gatewayCallbacks.error('Lost connection to the server (is it down?)');\n        },\n      };\n\n      for (let eventName in wsHandlers) {\n        ws.addEventListener(eventName, wsHandlers[eventName]);\n      }\n\n      return;\n    }\n    Janus.httpAPICall(server, {\n      verb: 'POST',\n      withCredentials: withCredentials,\n      body: request,\n      success: function (json) {\n        Janus.debug(json);\n        if (json['janus'] !== 'success') {\n          Janus.error('Ooops: ' + json['error'].code + ' ' + json['error'].reason); // FIXME\n          callbacks.error(json['error'].reason);\n          return;\n        }\n        connected = true;\n        sessionId = json['session_id'] ? json['session_id'] : json.data['id'];\n        if (callbacks['reconnect']) {\n          Janus.log('Claimed session: ' + sessionId);\n        } else {\n          Janus.log('Created session: ' + sessionId);\n        }\n        Janus.sessions[sessionId] = that;\n        eventHandler();\n        callbacks.success();\n      },\n      error: function (textStatus, errorThrown) {\n        Janus.error(textStatus + ':', errorThrown); // FIXME\n        if (Janus.isArray(servers) && !callbacks['reconnect']) {\n          serversIndex++;\n          if (serversIndex === servers.length) {\n            // We tried all the servers the user gave us and they all failed\n            callbacks.error('Error connecting to any of the provided Janus servers: Is the server down?');\n            return;\n          }\n          // Let's try the next server\n          server = null;\n          setTimeout(function () {\n            createSession(callbacks);\n          }, 200);\n          return;\n        }\n        if (errorThrown === '') callbacks.error(textStatus + ': Is the server down?');\n        else if (errorThrown && errorThrown.error) callbacks.error(textStatus + ': ' + errorThrown.error.message);\n        else callbacks.error(textStatus + ': ' + errorThrown);\n      },\n    });\n  }\n\n  // Private method to get info on the server\n  function getInfo(callbacks) {\n    callbacks = callbacks || {};\n    // FIXME This method triggers a success even when we fail\n    callbacks.success = typeof callbacks.success == 'function' ? callbacks.success : Janus.noop;\n    callbacks.error = typeof callbacks.error == 'function' ? callbacks.error : Janus.noop;\n    Janus.log('Getting info on Janus instance');\n    if (!connected) {\n      Janus.warn('Is the server down? (connected=false)');\n      callbacks.error('Is the server down? (connected=false)');\n      return;\n    }\n    // We just need to send an \"info\" request\n    let transaction = Janus.randomString(12);\n    let request = { janus: 'info', transaction: transaction };\n    if (token) request['token'] = token;\n    if (apisecret) request['apisecret'] = apisecret;\n    if (websockets) {\n      transactions[transaction] = function (json) {\n        Janus.log('Server info:');\n        Janus.debug(json);\n        if (json['janus'] !== 'server_info') {\n          Janus.error('Ooops: ' + json['error'].code + ' ' + json['error'].reason); // FIXME\n        }\n        callbacks.success(json);\n      };\n      ws.send(JSON.stringify(request));\n      return;\n    }\n    Janus.httpAPICall(server, {\n      verb: 'POST',\n      withCredentials: withCredentials,\n      body: request,\n      success: function (json) {\n        Janus.log('Server info:');\n        Janus.debug(json);\n        if (json['janus'] !== 'server_info') {\n          Janus.error('Ooops: ' + json['error'].code + ' ' + json['error'].reason); // FIXME\n        }\n        callbacks.success(json);\n      },\n      error: function (textStatus, errorThrown) {\n        Janus.error(textStatus + ':', errorThrown); // FIXME\n        if (errorThrown === '') callbacks.error(textStatus + ': Is the server down?');\n        else callbacks.error(textStatus + ': ' + errorThrown);\n      },\n    });\n  }\n\n  // Private method to destroy a session\n  function destroySession(callbacks) {\n    callbacks = callbacks || {};\n    // FIXME This method triggers a success even when we fail\n    callbacks.success = typeof callbacks.success == 'function' ? callbacks.success : Janus.noop;\n    callbacks.error = typeof callbacks.error == 'function' ? callbacks.error : Janus.noop;\n    let unload = callbacks.unload === true;\n    let notifyDestroyed = true;\n    if (typeof callbacks.notifyDestroyed !== 'undefined' && callbacks.notifyDestroyed !== null)\n      notifyDestroyed = callbacks.notifyDestroyed === true;\n    let cleanupHandles = callbacks.cleanupHandles === true;\n    Janus.log('Destroying session ' + sessionId + ' (unload=' + unload + ')');\n    if (!sessionId) {\n      Janus.warn('No session to destroy');\n      callbacks.success();\n      if (notifyDestroyed) gatewayCallbacks.destroyed();\n      return;\n    }\n    if (cleanupHandles) {\n      for (let handleId in pluginHandles) destroyHandle(handleId, { noRequest: true });\n    }\n    if (!connected) {\n      Janus.warn('Is the server down? (connected=false)');\n      sessionId = null;\n      callbacks.success();\n      return;\n    }\n    // No need to destroy all handles first, Janus will do that itself\n    let request = { janus: 'destroy', transaction: Janus.randomString(12) };\n    if (token) request['token'] = token;\n    if (apisecret) request['apisecret'] = apisecret;\n    if (unload) {\n      // We're unloading the page: use sendBeacon for HTTP instead,\n      // or just close the WebSocket connection if we're using that\n      if (websockets) {\n        ws.onclose = null;\n        ws.close();\n        ws = null;\n      } else {\n        navigator.sendBeacon(server + '/' + sessionId, JSON.stringify(request));\n      }\n      Janus.log('Destroyed session:');\n      sessionId = null;\n      connected = false;\n      callbacks.success();\n      if (notifyDestroyed) gatewayCallbacks.destroyed();\n      return;\n    }\n    if (websockets) {\n      request['session_id'] = sessionId;\n\n      let unbindWebSocket = function () {\n        for (let eventName in wsHandlers) {\n          ws.removeEventListener(eventName, wsHandlers[eventName]);\n        }\n        ws.removeEventListener('message', onUnbindMessage);\n        ws.removeEventListener('error', onUnbindError);\n        if (wsKeepaliveTimeoutId) {\n          clearTimeout(wsKeepaliveTimeoutId);\n        }\n        ws.close();\n      };\n\n      let onUnbindMessage = function (event) {\n        let data = JSON.parse(event.data);\n        if (data.session_id == request.session_id && data.transaction == request.transaction) {\n          unbindWebSocket();\n          callbacks.success();\n          if (notifyDestroyed) gatewayCallbacks.destroyed();\n        }\n      };\n      let onUnbindError = function () {\n        unbindWebSocket();\n        callbacks.error('Failed to destroy the server: Is the server down?');\n        if (notifyDestroyed) gatewayCallbacks.destroyed();\n      };\n\n      ws.addEventListener('message', onUnbindMessage);\n      ws.addEventListener('error', onUnbindError);\n\n      if (ws.readyState === 1) {\n        ws.send(JSON.stringify(request));\n      } else {\n        onUnbindError();\n      }\n\n      return;\n    }\n    Janus.httpAPICall(server + '/' + sessionId, {\n      verb: 'POST',\n      withCredentials: withCredentials,\n      body: request,\n      success: function (json) {\n        Janus.log('Destroyed session:');\n        Janus.debug(json);\n        sessionId = null;\n        connected = false;\n        if (json['janus'] !== 'success') {\n          Janus.error('Ooops: ' + json['error'].code + ' ' + json['error'].reason); // FIXME\n        }\n        callbacks.success();\n        if (notifyDestroyed) gatewayCallbacks.destroyed();\n      },\n      error: function (textStatus, errorThrown) {\n        Janus.error(textStatus + ':', errorThrown); // FIXME\n        // Reset everything anyway\n        sessionId = null;\n        connected = false;\n        callbacks.success();\n        if (notifyDestroyed) gatewayCallbacks.destroyed();\n      },\n    });\n  }\n\n  // Private method to create a plugin handle\n  function createHandle(callbacks) {\n    callbacks = callbacks || {};\n    callbacks.success = typeof callbacks.success == 'function' ? callbacks.success : Janus.noop;\n    callbacks.error = typeof callbacks.error == 'function' ? callbacks.error : Janus.noop;\n    callbacks.dataChannelOptions = callbacks.dataChannelOptions || {\n      ordered: true,\n    };\n    callbacks.consentDialog = typeof callbacks.consentDialog == 'function' ? callbacks.consentDialog : Janus.noop;\n    callbacks.iceState = typeof callbacks.iceState == 'function' ? callbacks.iceState : Janus.noop;\n    callbacks.mediaState = typeof callbacks.mediaState == 'function' ? callbacks.mediaState : Janus.noop;\n    callbacks.webrtcState = typeof callbacks.webrtcState == 'function' ? callbacks.webrtcState : Janus.noop;\n    callbacks.slowLink = typeof callbacks.slowLink == 'function' ? callbacks.slowLink : Janus.noop;\n    callbacks.onmessage = typeof callbacks.onmessage == 'function' ? callbacks.onmessage : Janus.noop;\n    callbacks.onlocaltrack = typeof callbacks.onlocaltrack == 'function' ? callbacks.onlocaltrack : Janus.noop;\n    callbacks.onremotetrack = typeof callbacks.onremotetrack == 'function' ? callbacks.onremotetrack : Janus.noop;\n    callbacks.ondata = typeof callbacks.ondata == 'function' ? callbacks.ondata : Janus.noop;\n    callbacks.ondataopen = typeof callbacks.ondataopen == 'function' ? callbacks.ondataopen : Janus.noop;\n    callbacks.oncleanup = typeof callbacks.oncleanup == 'function' ? callbacks.oncleanup : Janus.noop;\n    callbacks.ondetached = typeof callbacks.ondetached == 'function' ? callbacks.ondetached : Janus.noop;\n    if (!connected) {\n      Janus.warn('Is the server down? (connected=false)');\n      callbacks.error('Is the server down? (connected=false)');\n      return;\n    }\n    let plugin = callbacks.plugin;\n    if (!plugin) {\n      Janus.error('Invalid plugin');\n      callbacks.error('Invalid plugin');\n      return;\n    }\n    let opaqueId = callbacks.opaqueId;\n    let loopIndex = callbacks.loopIndex;\n    let handleToken = callbacks.token ? callbacks.token : token;\n    let transaction = Janus.randomString(12);\n    let request = {\n      janus: 'attach',\n      plugin: plugin,\n      opaque_id: opaqueId,\n      loop_index: loopIndex,\n      transaction: transaction,\n    };\n    if (handleToken) request['token'] = handleToken;\n    if (apisecret) request['apisecret'] = apisecret;\n    if (websockets) {\n      transactions[transaction] = function (json) {\n        Janus.debug(json);\n        if (json['janus'] !== 'success') {\n          Janus.error('Ooops: ' + json['error'].code + ' ' + json['error'].reason); // FIXME\n          callbacks.error('Ooops: ' + json['error'].code + ' ' + json['error'].reason);\n          return;\n        }\n        let handleId = json.data['id'];\n        Janus.log('Created handle: ' + handleId);\n        let pluginHandle = {\n          session: that,\n          plugin: plugin,\n          id: handleId,\n          token: handleToken,\n          detached: false,\n          webrtcStuff: {\n            started: false,\n            myStream: null,\n            streamExternal: false,\n            mySdp: null,\n            mediaConstraints: null,\n            pc: null,\n            dataChannelOptions: callbacks.dataChannelOptions,\n            dataChannel: {},\n            dtmfSender: null,\n            trickle: true,\n            iceDone: false,\n            bitrate: {},\n          },\n          getId: function () {\n            return handleId;\n          },\n          getPlugin: function () {\n            return plugin;\n          },\n          getVolume: function (mid, result) {\n            return getVolume(handleId, mid, true, result);\n          },\n          getRemoteVolume: function (mid, result) {\n            return getVolume(handleId, mid, true, result);\n          },\n          getLocalVolume: function (mid, result) {\n            return getVolume(handleId, mid, false, result);\n          },\n          isAudioMuted: function (mid) {\n            return isMuted(handleId, mid, false);\n          },\n          muteAudio: function (mid) {\n            return mute(handleId, mid, false, true);\n          },\n          unmuteAudio: function (mid) {\n            return mute(handleId, mid, false, false);\n          },\n          isVideoMuted: function (mid) {\n            return isMuted(handleId, mid, true);\n          },\n          muteVideo: function (mid) {\n            return mute(handleId, mid, true, true);\n          },\n          unmuteVideo: function (mid) {\n            return mute(handleId, mid, true, false);\n          },\n          getBitrate: function (mid) {\n            return getBitrate(handleId, mid);\n          },\n          setMaxBitrate: function (mid, bitrate) {\n            return setBitrate(handleId, mid, bitrate);\n          },\n          send: function (callbacks) {\n            sendMessage(handleId, callbacks);\n          },\n          data: function (callbacks) {\n            sendData(handleId, callbacks);\n          },\n          dtmf: function (callbacks) {\n            sendDtmf(handleId, callbacks);\n          },\n          consentDialog: callbacks.consentDialog,\n          iceState: callbacks.iceState,\n          mediaState: callbacks.mediaState,\n          webrtcState: callbacks.webrtcState,\n          slowLink: callbacks.slowLink,\n          onmessage: callbacks.onmessage,\n          createOffer: function (callbacks) {\n            prepareWebrtc(handleId, true, callbacks);\n          },\n          createAnswer: function (callbacks) {\n            prepareWebrtc(handleId, false, callbacks);\n          },\n          handleRemoteJsep: function (callbacks) {\n            prepareWebrtcPeer(handleId, callbacks);\n          },\n          replaceTracks: function (callbacks) {\n            replaceTracks(handleId, callbacks);\n          },\n          getLocalTracks: function () {\n            return getLocalTracks(handleId);\n          },\n          getRemoteTracks: function () {\n            return getRemoteTracks(handleId);\n          },\n          onlocaltrack: callbacks.onlocaltrack,\n          onremotetrack: callbacks.onremotetrack,\n          ondata: callbacks.ondata,\n          ondataopen: callbacks.ondataopen,\n          oncleanup: callbacks.oncleanup,\n          ondetached: callbacks.ondetached,\n          hangup: function (sendRequest) {\n            cleanupWebrtc(handleId, sendRequest === true);\n          },\n          detach: function (callbacks) {\n            destroyHandle(handleId, callbacks);\n          },\n        };\n        pluginHandles[handleId] = pluginHandle;\n        callbacks.success(pluginHandle);\n      };\n      request['session_id'] = sessionId;\n      ws.send(JSON.stringify(request));\n      return;\n    }\n    Janus.httpAPICall(server + '/' + sessionId, {\n      verb: 'POST',\n      withCredentials: withCredentials,\n      body: request,\n      success: function (json) {\n        Janus.debug(json);\n        if (json['janus'] !== 'success') {\n          Janus.error('Ooops: ' + json['error'].code + ' ' + json['error'].reason); // FIXME\n          callbacks.error('Ooops: ' + json['error'].code + ' ' + json['error'].reason);\n          return;\n        }\n        let handleId = json.data['id'];\n        Janus.log('Created handle: ' + handleId);\n        let pluginHandle = {\n          session: that,\n          plugin: plugin,\n          id: handleId,\n          token: handleToken,\n          detached: false,\n          webrtcStuff: {\n            started: false,\n            myStream: null,\n            streamExternal: false,\n            mySdp: null,\n            mediaConstraints: null,\n            pc: null,\n            dataChannelOptions: callbacks.dataChannelOptions,\n            dataChannel: {},\n            dtmfSender: null,\n            trickle: true,\n            iceDone: false,\n            bitrate: {},\n          },\n          getId: function () {\n            return handleId;\n          },\n          getPlugin: function () {\n            return plugin;\n          },\n          getVolume: function (mid, result) {\n            return getVolume(handleId, mid, true, result);\n          },\n          getRemoteVolume: function (mid, result) {\n            return getVolume(handleId, mid, true, result);\n          },\n          getLocalVolume: function (mid, result) {\n            return getVolume(handleId, mid, false, result);\n          },\n          isAudioMuted: function (mid) {\n            return isMuted(handleId, mid, false);\n          },\n          muteAudio: function (mid) {\n            return mute(handleId, mid, false, true);\n          },\n          unmuteAudio: function (mid) {\n            return mute(handleId, mid, false, false);\n          },\n          isVideoMuted: function (mid) {\n            return isMuted(handleId, mid, true);\n          },\n          muteVideo: function (mid) {\n            return mute(handleId, mid, true, true);\n          },\n          unmuteVideo: function (mid) {\n            return mute(handleId, mid, true, false);\n          },\n          getBitrate: function (mid) {\n            return getBitrate(handleId, mid);\n          },\n          setMaxBitrate: function (mid, bitrate) {\n            return setBitrate(handleId, mid, bitrate);\n          },\n          send: function (callbacks) {\n            sendMessage(handleId, callbacks);\n          },\n          data: function (callbacks) {\n            sendData(handleId, callbacks);\n          },\n          dtmf: function (callbacks) {\n            sendDtmf(handleId, callbacks);\n          },\n          consentDialog: callbacks.consentDialog,\n          iceState: callbacks.iceState,\n          mediaState: callbacks.mediaState,\n          webrtcState: callbacks.webrtcState,\n          slowLink: callbacks.slowLink,\n          onmessage: callbacks.onmessage,\n          createOffer: function (callbacks) {\n            prepareWebrtc(handleId, true, callbacks);\n          },\n          createAnswer: function (callbacks) {\n            prepareWebrtc(handleId, false, callbacks);\n          },\n          handleRemoteJsep: function (callbacks) {\n            prepareWebrtcPeer(handleId, callbacks);\n          },\n          replaceTracks: function (callbacks) {\n            replaceTracks(handleId, callbacks);\n          },\n          getLocalTracks: function () {\n            return getLocalTracks(handleId);\n          },\n          getRemoteTracks: function () {\n            return getRemoteTracks(handleId);\n          },\n          onlocaltrack: callbacks.onlocaltrack,\n          onremotetrack: callbacks.onremotetrack,\n          ondata: callbacks.ondata,\n          ondataopen: callbacks.ondataopen,\n          oncleanup: callbacks.oncleanup,\n          ondetached: callbacks.ondetached,\n          hangup: function (sendRequest) {\n            cleanupWebrtc(handleId, sendRequest === true);\n          },\n          detach: function (callbacks) {\n            destroyHandle(handleId, callbacks);\n          },\n        };\n        pluginHandles[handleId] = pluginHandle;\n        callbacks.success(pluginHandle);\n      },\n      error: function (textStatus, errorThrown) {\n        Janus.error(textStatus + ':', errorThrown); // FIXME\n        if (errorThrown === '') callbacks.error(textStatus + ': Is the server down?');\n        else callbacks.error(textStatus + ': ' + errorThrown);\n      },\n    });\n  }\n\n  // Private method to send a message\n  function sendMessage(handleId, callbacks) {\n    callbacks = callbacks || {};\n    callbacks.success = typeof callbacks.success == 'function' ? callbacks.success : Janus.noop;\n    callbacks.error = typeof callbacks.error == 'function' ? callbacks.error : Janus.noop;\n    if (!connected) {\n      Janus.warn('Is the server down? (connected=false)');\n      callbacks.error('Is the server down? (connected=false)');\n      return;\n    }\n    let pluginHandle = pluginHandles[handleId];\n    if (!pluginHandle || !pluginHandle.webrtcStuff) {\n      Janus.warn('Invalid handle');\n      callbacks.error('Invalid handle');\n      return;\n    }\n    let message = callbacks.message;\n    let jsep = callbacks.jsep;\n    let transaction = Janus.randomString(12);\n    let request = { janus: 'message', body: message, transaction: transaction };\n    if (pluginHandle.token) request['token'] = pluginHandle.token;\n    if (apisecret) request['apisecret'] = apisecret;\n    if (jsep) {\n      request.jsep = {\n        type: jsep.type,\n        sdp: jsep.sdp,\n      };\n      if (jsep.e2ee) request.jsep.e2ee = true;\n      if (jsep.rid_order === 'hml' || jsep.rid_order === 'lmh') request.jsep.rid_order = jsep.rid_order;\n      if (jsep.force_relay) request.jsep.force_relay = true;\n    }\n    Janus.debug('Sending message to plugin (handle=' + handleId + '):');\n    Janus.debug(request);\n    if (websockets) {\n      request['session_id'] = sessionId;\n      request['handle_id'] = handleId;\n      transactions[transaction] = function (json) {\n        Janus.debug('Message sent!');\n        Janus.debug(json);\n        if (json['janus'] === 'success') {\n          // We got a success, must have been a synchronous transaction\n          let plugindata = json['plugindata'];\n          if (!plugindata) {\n            Janus.warn('Request succeeded, but missing plugindata...');\n            callbacks.success();\n            return;\n          }\n          Janus.log('Synchronous transaction successful (' + plugindata['plugin'] + ')');\n          let data = plugindata['data'];\n          Janus.debug(data);\n          callbacks.success(data);\n          return;\n        } else if (json['janus'] !== 'ack') {\n          // Not a success and not an ack, must be an error\n          if (json['error']) {\n            Janus.error('Ooops: ' + json['error'].code + ' ' + json['error'].reason); // FIXME\n            callbacks.error(json['error'].code + ' ' + json['error'].reason);\n          } else {\n            Janus.error('Unknown error'); // FIXME\n            callbacks.error('Unknown error');\n          }\n          return;\n        }\n        // If we got here, the plugin decided to handle the request asynchronously\n        callbacks.success();\n      };\n      ws.send(JSON.stringify(request));\n      return;\n    }\n    Janus.httpAPICall(server + '/' + sessionId + '/' + handleId, {\n      verb: 'POST',\n      withCredentials: withCredentials,\n      body: request,\n      success: function (json) {\n        Janus.debug('Message sent!');\n        Janus.debug(json);\n        if (json['janus'] === 'success') {\n          // We got a success, must have been a synchronous transaction\n          let plugindata = json['plugindata'];\n          if (!plugindata) {\n            Janus.warn('Request succeeded, but missing plugindata...');\n            callbacks.success();\n            return;\n          }\n          Janus.log('Synchronous transaction successful (' + plugindata['plugin'] + ')');\n          let data = plugindata['data'];\n          Janus.debug(data);\n          callbacks.success(data);\n          return;\n        } else if (json['janus'] !== 'ack') {\n          // Not a success and not an ack, must be an error\n          if (json['error']) {\n            Janus.error('Ooops: ' + json['error'].code + ' ' + json['error'].reason); // FIXME\n            callbacks.error(json['error'].code + ' ' + json['error'].reason);\n          } else {\n            Janus.error('Unknown error'); // FIXME\n            callbacks.error('Unknown error');\n          }\n          return;\n        }\n        // If we got here, the plugin decided to handle the request asynchronously\n        callbacks.success();\n      },\n      error: function (textStatus, errorThrown) {\n        Janus.error(textStatus + ':', errorThrown); // FIXME\n        callbacks.error(textStatus + ': ' + errorThrown);\n      },\n    });\n  }\n\n  // Private method to send a trickle candidate\n  function sendTrickleCandidate(handleId, candidate) {\n    if (!connected) {\n      Janus.warn('Is the server down? (connected=false)');\n      return;\n    }\n    let pluginHandle = pluginHandles[handleId];\n    if (!pluginHandle || !pluginHandle.webrtcStuff) {\n      Janus.warn('Invalid handle');\n      return;\n    }\n    let request = {\n      janus: 'trickle',\n      candidate: candidate,\n      transaction: Janus.randomString(12),\n    };\n    if (pluginHandle.token) request['token'] = pluginHandle.token;\n    if (apisecret) request['apisecret'] = apisecret;\n    Janus.vdebug('Sending trickle candidate (handle=' + handleId + '):');\n    Janus.vdebug(request);\n    if (websockets) {\n      request['session_id'] = sessionId;\n      request['handle_id'] = handleId;\n      ws.send(JSON.stringify(request));\n      return;\n    }\n    Janus.httpAPICall(server + '/' + sessionId + '/' + handleId, {\n      verb: 'POST',\n      withCredentials: withCredentials,\n      body: request,\n      success: function (json) {\n        Janus.vdebug('Candidate sent!');\n        Janus.vdebug(json);\n        if (json['janus'] !== 'ack') {\n          Janus.error('Ooops: ' + json['error'].code + ' ' + json['error'].reason); // FIXME\n          return;\n        }\n      },\n      error: function (textStatus, errorThrown) {\n        Janus.error(textStatus + ':', errorThrown); // FIXME\n      },\n    });\n  }\n\n  // Private method to create a data channel\n  function createDataChannel(handleId, dclabel, dcprotocol, incoming, pendingData) {\n    let pluginHandle = pluginHandles[handleId];\n    if (!pluginHandle || !pluginHandle.webrtcStuff) {\n      Janus.warn('Invalid handle');\n      return;\n    }\n    let config = pluginHandle.webrtcStuff;\n    if (!config.pc) {\n      Janus.warn('Invalid PeerConnection');\n      return;\n    }\n    let onDataChannelMessage = function (event) {\n      Janus.log('Received message on data channel:', event);\n      let label = event.target.label;\n      pluginHandle.ondata(event.data, label);\n    };\n    let onDataChannelStateChange = function (event) {\n      Janus.log('Received state change on data channel:', event);\n      let label = event.target.label;\n      let protocol = event.target.protocol;\n      let dcState = config.dataChannel[label] ? config.dataChannel[label].readyState : 'null';\n      Janus.log('State change on <' + label + '> data channel: ' + dcState);\n      if (dcState === 'open') {\n        // Any pending messages to send?\n        if (config.dataChannel[label].pending && config.dataChannel[label].pending.length > 0) {\n          Janus.log('Sending pending messages on <' + label + '>:', config.dataChannel[label].pending.length);\n          for (let data of config.dataChannel[label].pending) {\n            Janus.log('Sending data on data channel <' + label + '>');\n            Janus.debug(data);\n            config.dataChannel[label].send(data);\n          }\n          config.dataChannel[label].pending = [];\n        }\n        // Notify the open data channel\n        pluginHandle.ondataopen(label, protocol);\n      }\n    };\n    let onDataChannelError = function (error) {\n      Janus.error('Got error on data channel:', error);\n      // TODO\n    };\n    if (!incoming) {\n      // FIXME Add options (ordered, maxRetransmits, etc.)\n      let dcoptions = config.dataChannelOptions;\n      if (dcprotocol) dcoptions.protocol = dcprotocol;\n      config.dataChannel[dclabel] = config.pc.createDataChannel(dclabel, dcoptions);\n    } else {\n      // The channel was created by Janus\n      config.dataChannel[dclabel] = incoming;\n    }\n    config.dataChannel[dclabel].onmessage = onDataChannelMessage;\n    config.dataChannel[dclabel].onopen = onDataChannelStateChange;\n    config.dataChannel[dclabel].onclose = onDataChannelStateChange;\n    config.dataChannel[dclabel].onerror = onDataChannelError;\n    config.dataChannel[dclabel].pending = [];\n    if (pendingData) config.dataChannel[dclabel].pending.push(pendingData);\n  }\n\n  // Private method to send a data channel message\n  function sendData(handleId, callbacks) {\n    callbacks = callbacks || {};\n    callbacks.success = typeof callbacks.success == 'function' ? callbacks.success : Janus.noop;\n    callbacks.error = typeof callbacks.error == 'function' ? callbacks.error : Janus.noop;\n    let pluginHandle = pluginHandles[handleId];\n    if (!pluginHandle || !pluginHandle.webrtcStuff) {\n      Janus.warn('Invalid handle');\n      callbacks.error('Invalid handle');\n      return;\n    }\n    let config = pluginHandle.webrtcStuff;\n    let data = callbacks.text || callbacks.data;\n    if (!data) {\n      Janus.warn('Invalid data');\n      callbacks.error('Invalid data');\n      return;\n    }\n    let label = callbacks.label ? callbacks.label : Janus.dataChanDefaultLabel;\n    if (!config.dataChannel[label]) {\n      // Create new data channel and wait for it to open\n      createDataChannel(handleId, label, callbacks.protocol, false, data, callbacks.protocol);\n      callbacks.success();\n      return;\n    }\n    if (config.dataChannel[label].readyState !== 'open') {\n      config.dataChannel[label].pending.push(data);\n      callbacks.success();\n      return;\n    }\n    Janus.log('Sending data on data channel <' + label + '>');\n    Janus.debug(data);\n    config.dataChannel[label].send(data);\n    callbacks.success();\n  }\n\n  // Private method to send a DTMF tone\n  function sendDtmf(handleId, callbacks) {\n    callbacks = callbacks || {};\n    callbacks.success = typeof callbacks.success == 'function' ? callbacks.success : Janus.noop;\n    callbacks.error = typeof callbacks.error == 'function' ? callbacks.error : Janus.noop;\n    let pluginHandle = pluginHandles[handleId];\n    if (!pluginHandle || !pluginHandle.webrtcStuff) {\n      Janus.warn('Invalid handle');\n      callbacks.error('Invalid handle');\n      return;\n    }\n    let config = pluginHandle.webrtcStuff;\n    if (!config.dtmfSender) {\n      // Create the DTMF sender the proper way, if possible\n      if (config.pc) {\n        let senders = config.pc.getSenders();\n        let audioSender = senders.find(function (sender) {\n          return sender.track && sender.track.kind === 'audio';\n        });\n        if (!audioSender) {\n          Janus.warn('Invalid DTMF configuration (no audio track)');\n          callbacks.error('Invalid DTMF configuration (no audio track)');\n          return;\n        }\n        config.dtmfSender = audioSender.dtmf;\n        if (config.dtmfSender) {\n          Janus.log('Created DTMF Sender');\n          config.dtmfSender.ontonechange = function (tone) {\n            Janus.debug('Sent DTMF tone: ' + tone.tone);\n          };\n        }\n      }\n      if (!config.dtmfSender) {\n        Janus.warn('Invalid DTMF configuration');\n        callbacks.error('Invalid DTMF configuration');\n        return;\n      }\n    }\n    let dtmf = callbacks.dtmf;\n    if (!dtmf) {\n      Janus.warn('Invalid DTMF parameters');\n      callbacks.error('Invalid DTMF parameters');\n      return;\n    }\n    let tones = dtmf.tones;\n    if (!tones) {\n      Janus.warn('Invalid DTMF string');\n      callbacks.error('Invalid DTMF string');\n      return;\n    }\n    let duration = typeof dtmf.duration === 'number' ? dtmf.duration : 500; // We choose 500ms as the default duration for a tone\n    let gap = typeof dtmf.gap === 'number' ? dtmf.gap : 50; // We choose 50ms as the default gap between tones\n    Janus.debug('Sending DTMF string ' + tones + ' (duration ' + duration + 'ms, gap ' + gap + 'ms)');\n    config.dtmfSender.insertDTMF(tones, duration, gap);\n    callbacks.success();\n  }\n\n  // Private method to destroy a plugin handle\n  function destroyHandle(handleId, callbacks) {\n    callbacks = callbacks || {};\n    callbacks.success = typeof callbacks.success == 'function' ? callbacks.success : Janus.noop;\n    callbacks.error = typeof callbacks.error == 'function' ? callbacks.error : Janus.noop;\n    let noRequest = callbacks.noRequest === true;\n    Janus.log('Destroying handle ' + handleId + ' (only-locally=' + noRequest + ')');\n    cleanupWebrtc(handleId);\n    let pluginHandle = pluginHandles[handleId];\n    if (!pluginHandle || pluginHandle.detached) {\n      // Plugin was already detached by Janus, calling detach again will return a handle not found error, so just exit here\n      delete pluginHandles[handleId];\n      callbacks.success();\n      return;\n    }\n    pluginHandle.detached = true;\n    if (noRequest) {\n      // We're only removing the handle locally\n      delete pluginHandles[handleId];\n      callbacks.success();\n      return;\n    }\n    if (!connected) {\n      Janus.warn('Is the server down? (connected=false)');\n      callbacks.error('Is the server down? (connected=false)');\n      return;\n    }\n    let request = { janus: 'detach', transaction: Janus.randomString(12) };\n    if (pluginHandle.token) request['token'] = pluginHandle.token;\n    if (apisecret) request['apisecret'] = apisecret;\n    if (websockets) {\n      request['session_id'] = sessionId;\n      request['handle_id'] = handleId;\n      ws.send(JSON.stringify(request));\n      delete pluginHandles[handleId];\n      callbacks.success();\n      return;\n    }\n    Janus.httpAPICall(server + '/' + sessionId + '/' + handleId, {\n      verb: 'POST',\n      withCredentials: withCredentials,\n      body: request,\n      success: function (json) {\n        Janus.log('Destroyed handle:');\n        Janus.debug(json);\n        if (json['janus'] !== 'success') {\n          Janus.error('Ooops: ' + json['error'].code + ' ' + json['error'].reason); // FIXME\n        }\n        delete pluginHandles[handleId];\n        callbacks.success();\n      },\n      error: function (textStatus, errorThrown) {\n        Janus.error(textStatus + ':', errorThrown); // FIXME\n        // We cleanup anyway\n        delete pluginHandles[handleId];\n        callbacks.success();\n      },\n    });\n  }\n\n  // WebRTC stuff\n  // Helper function to create a new PeerConnection, if we need one\n  function createPeerconnectionIfNeeded(handleId, callbacks) {\n    let pluginHandle = pluginHandles[handleId];\n    if (!pluginHandle || !pluginHandle.webrtcStuff) {\n      Janus.warn('Invalid handle');\n      throw 'Invalid handle';\n    }\n    let config = pluginHandle.webrtcStuff;\n    if (config.pc) {\n      // Nothing to do, we have a PeerConnection already\n      return;\n    }\n    let pc_config = {\n      iceServers: iceServers,\n      iceTransportPolicy: iceTransportPolicy,\n      bundlePolicy: bundlePolicy,\n    };\n    pc_config.sdpSemantics = 'unified-plan';\n    // Check if a sender or receiver transform has been provided\n    let insertableStreams = false;\n    if (callbacks.tracks) {\n      for (let track of callbacks.tracks) {\n        if (track.transforms && (track.transforms.sender || track.transforms.receiver)) {\n          insertableStreams = true;\n          break;\n        }\n      }\n    }\n    if (\n      RTCRtpSender &&\n      (RTCRtpSender.prototype.createEncodedStreams ||\n        (RTCRtpSender.prototype.createEncodedAudioStreams && RTCRtpSender.prototype.createEncodedVideoStreams)) &&\n      insertableStreams\n    ) {\n      config.insertableStreams = true;\n      pc_config.forceEncodedAudioInsertableStreams = true;\n      pc_config.forceEncodedVideoInsertableStreams = true;\n      pc_config.encodedInsertableStreams = true;\n    }\n    Janus.log('Creating PeerConnection');\n    config.pc = new RTCPeerConnection(pc_config);\n    Janus.debug(config.pc);\n    if (config.pc.getStats) {\n      // FIXME\n      config.volume = {};\n      config.bitrate.value = '0 kbits/sec';\n    }\n    Janus.log('Preparing local SDP and gathering candidates (trickle=' + config.trickle + ')');\n    config.pc.oniceconnectionstatechange = function () {\n      if (config.pc) pluginHandle.iceState(config.pc.iceConnectionState);\n    };\n    config.pc.onicecandidate = function (event) {\n      if (!event.candidate || (event.candidate.candidate && event.candidate.candidate.indexOf('endOfCandidates') > 0)) {\n        Janus.log('End of candidates.');\n        config.iceDone = true;\n        if (config.trickle === true) {\n          // Notify end of candidates\n          sendTrickleCandidate(handleId, { completed: true });\n        } else {\n          // No trickle, time to send the complete SDP (including all candidates)\n          sendSDP(handleId, callbacks);\n        }\n      } else {\n        // JSON.stringify doesn't work on some WebRTC objects anymore\n        // See https://code.google.com/p/chromium/issues/detail?id=467366\n        let candidate = {\n          candidate: event.candidate.candidate,\n          sdpMid: event.candidate.sdpMid,\n          sdpMLineIndex: event.candidate.sdpMLineIndex,\n        };\n        if (config.trickle === true) {\n          // Send candidate\n          sendTrickleCandidate(handleId, candidate);\n        }\n      }\n    };\n    config.pc.ontrack = function (event) {\n      Janus.log('Handling Remote Track', event);\n      if (!event.streams) return;\n      if (!event.track) return;\n      // Notify about the new track event\n      let mid = event.transceiver ? event.transceiver.mid || event.transceiver._mid : event.track.id;\n      try {\n        pluginHandle.onremotetrack(event.track, mid, true, {\n          reason: 'created',\n        });\n      } catch (e) {\n        Janus.error('Error calling onremotetrack', e);\n      }\n      if (event.track.onended) return;\n      let trackMutedTimeoutId = null;\n      Janus.log('Adding onended callback to track:', event.track);\n      event.track.onended = function (ev) {\n        Janus.log('Remote track removed:', ev);\n        clearTimeout(trackMutedTimeoutId);\n        // Notify the application\n        let transceivers = config.pc ? config.pc.getTransceivers() : null;\n        let transceiver = transceivers\n          ? transceivers.find((transceiver) => {\n            const receiver = transceiver.receiver || transceiver._receiver;\n            const track = receiver.track || receiver._track;\n            return track === ev.target;\n          })\n          : null;\n        let mid = transceiver ? transceiver.mid || transceiver._mid : ev.target.id;\n        try {\n          pluginHandle.onremotetrack(ev.target, mid, false, {\n            reason: 'ended',\n          });\n        } catch (e) {\n          Janus.error('Error calling onremotetrack on removal', e);\n        }\n      };\n      event.track.onmute = function (ev) {\n        Janus.log('Remote track muted:', ev);\n        if (!trackMutedTimeoutId) {\n          const target = ev.target;\n          trackMutedTimeoutId = setTimeout(function () {\n            Janus.log('Removing remote track');\n            // Notify the application the track is gone\n            let transceivers = config.pc ? config.pc.getTransceivers() : null;\n            let transceiver = transceivers\n              ? transceivers.find((transceiver) => {\n                const receiver = transceiver.receiver || transceiver._receiver;\n                const track = receiver.track || receiver._track;\n                return track === target;\n              })\n              : null;\n            let mid = transceiver ? transceiver.mid || transceiver._mid : target.id;\n            try {\n              pluginHandle.onremotetrack(target, mid, false, {\n                reason: 'mute',\n              });\n            } catch (e) {\n              Janus.error('Error calling onremotetrack on mute', e);\n            }\n            trackMutedTimeoutId = null;\n            // Chrome seems to raise mute events only at multiples of 834ms;\n            // we set the timeout to three times this value (rounded to 840ms);\n          }, 3 * 840);\n        }\n      };\n      event.track.onunmute = function (ev) {\n        Janus.log('Remote track flowing again:', ev);\n        if (trackMutedTimeoutId != null) {\n          clearTimeout(trackMutedTimeoutId);\n          trackMutedTimeoutId = null;\n        } else {\n          try {\n            // Notify the application the track is back\n            let transceivers = config.pc ? config.pc.getTransceivers() : null;\n            let transceiver = transceivers\n              ? transceivers.find((transceiver) => {\n                const receiver = transceiver.receiver || transceiver._receiver;\n                const track = receiver.track || receiver._track;\n                return track === ev.target;\n              })\n              : null;\n            let mid = transceiver ? transceiver.mid || transceiver._mid : ev.target.id;\n            pluginHandle.onremotetrack(ev.target, mid, true, {\n              reason: 'unmute',\n            });\n          } catch (e) {\n            Janus.error('Error calling onremotetrack on unmute', e);\n          }\n        }\n      };\n    };\n  }\n\n  // Helper function used when creating either an offer or answer: it\n  // prepares what needs to be prepared, including creating a new\n  // PeerConnection (if needed) and updating the tracks configuration,\n  // before invoking the function to actually generate the offer/answer\n  async function prepareWebrtc(handleId, offer, callbacks) {\n    callbacks = callbacks || {};\n    callbacks.success = typeof callbacks.success == 'function' ? callbacks.success : Janus.noop;\n    callbacks.error = typeof callbacks.error == 'function' ? callbacks.error : webrtcError;\n    let jsep = callbacks.jsep;\n    if (offer && jsep) {\n      Janus.error('Provided a JSEP to a createOffer');\n      callbacks.error('Provided a JSEP to a createOffer');\n      return;\n    } else if (!offer && (!jsep || !jsep.type || !jsep.sdp)) {\n      Janus.error('A valid JSEP is required for createAnswer');\n      callbacks.error('A valid JSEP is required for createAnswer');\n      return;\n    }\n    // If the deprecated media was provided instead of tracks, translate it\n    if (callbacks.media && !callbacks.tracks) {\n      callbacks.tracks = Janus.mediaToTracks(callbacks.media);\n      if (callbacks.simulcast === true || callbacks.simulcast2 === true || callbacks.svc) {\n        // Find the video track and add simulcast/SVC info there\n        for (let track of callbacks.tracks) {\n          if (track.type === 'video') {\n            if (callbacks.simulcast === true || callbacks.simulcast2 === true) track.simulcast = true;\n            else if (callbacks.svc) track.svc = callbacks.svc;\n            break;\n          }\n        }\n      }\n      Janus.warn('Deprecated media object passed, use tracks instead. Automatically translated to:', callbacks.tracks);\n    }\n    // Check that callbacks.array is a valid array\n    if (callbacks.tracks && !Array.isArray(callbacks.tracks)) {\n      Janus.error('Tracks must be an array');\n      callbacks.error('Tracks must be an array');\n      return;\n    }\n    // Get the plugin handle\n    let pluginHandle = pluginHandles[handleId];\n    if (!pluginHandle || !pluginHandle.webrtcStuff) {\n      Janus.warn('Invalid handle');\n      callbacks.error('Invalid handle');\n      return;\n    }\n    let config = pluginHandle.webrtcStuff;\n    config.trickle = isTrickleEnabled(callbacks.trickle);\n    try {\n      // Create a PeerConnection, if needed\n      createPeerconnectionIfNeeded(handleId, callbacks);\n      if (offer) {\n        // Capture devices and setup tracks, if needed\n        await captureDevices(handleId, callbacks);\n      }\n      // Create offer or answer now (depending on the context)\n      if (!jsep) {\n        let offer = await createOffer(handleId, callbacks);\n        callbacks.success(offer);\n      } else {\n        await config.pc.setRemoteDescription(jsep);\n        Janus.log('Remote description accepted!');\n        config.remoteSdp = jsep.sdp;\n        // Any trickle candidate we cached?\n        if (config.candidates && config.candidates.length > 0) {\n          for (let i = 0; i < config.candidates.length; i++) {\n            let candidate = config.candidates[i];\n            Janus.debug('Adding remote candidate:', candidate);\n            if (!candidate || candidate.completed === true) {\n              // end-of-candidates\n              config.pc.addIceCandidate(Janus.endOfCandidates);\n            } else {\n              // New candidate\n              config.pc.addIceCandidate(candidate);\n            }\n          }\n          config.candidates = [];\n        }\n        // Capture devices and setup tracks, if needed\n        await captureDevices(handleId, callbacks);\n        // Create the answer now\n        let answer = await createAnswer(handleId, callbacks);\n        callbacks.success(answer);\n      }\n    } catch (err) {\n      Janus.error(err);\n      callbacks.error(err);\n    }\n  }\n\n  function prepareWebrtcPeer(handleId, callbacks) {\n    callbacks = callbacks || {};\n    callbacks.success = typeof callbacks.success == 'function' ? callbacks.success : Janus.noop;\n    callbacks.error = typeof callbacks.error == 'function' ? callbacks.error : webrtcError;\n    callbacks.customizeSdp = typeof callbacks.customizeSdp == 'function' ? callbacks.customizeSdp : Janus.noop;\n    let jsep = callbacks.jsep;\n    let pluginHandle = pluginHandles[handleId];\n    if (!pluginHandle || !pluginHandle.webrtcStuff) {\n      Janus.warn('Invalid handle');\n      callbacks.error('Invalid handle');\n      return;\n    }\n    let config = pluginHandle.webrtcStuff;\n    if (jsep) {\n      if (!config.pc) {\n        Janus.warn('Wait, no PeerConnection?? if this is an answer, use createAnswer and not handleRemoteJsep');\n        callbacks.error('No PeerConnection: if this is an answer, use createAnswer and not handleRemoteJsep');\n        return;\n      }\n      callbacks.customizeSdp(jsep);\n      config.pc.setRemoteDescription(jsep).then(function () {\n        Janus.log('Remote description accepted!');\n        config.remoteSdp = jsep.sdp;\n        // Any trickle candidate we cached?\n        if (config.candidates && config.candidates.length > 0) {\n          for (let i = 0; i < config.candidates.length; i++) {\n            let candidate = config.candidates[i];\n            Janus.debug('Adding remote candidate:', candidate);\n            if (!candidate || candidate.completed === true) {\n              // end-of-candidates\n              config.pc.addIceCandidate(Janus.endOfCandidates);\n            } else {\n              // New candidate\n              config.pc.addIceCandidate(candidate);\n            }\n          }\n          config.candidates = [];\n        }\n        // Done\n        callbacks.success();\n      }, callbacks.error);\n    } else {\n      callbacks.error('Invalid JSEP');\n    }\n  }\n\n  async function createOffer(handleId, callbacks) {\n    callbacks = callbacks || {};\n    callbacks.customizeSdp = typeof callbacks.customizeSdp == 'function' ? callbacks.customizeSdp : Janus.noop;\n    let pluginHandle = pluginHandles[handleId];\n    if (!pluginHandle || !pluginHandle.webrtcStuff) {\n      Janus.warn('Invalid handle');\n      throw 'Invalid handle';\n    }\n    let config = pluginHandle.webrtcStuff;\n    Janus.log('Creating offer (iceDone=' + config.iceDone + ')');\n    // https://code.google.com/p/webrtc/issues/detail?id=3508\n    let mediaConstraints = {};\n    let iceRestart = callbacks.iceRestart === true;\n    // If we need an ICE restart, set the related constraint\n    if (iceRestart) mediaConstraints.iceRestart = true;\n    Janus.debug(mediaConstraints);\n    let offer = await config.pc.createOffer(mediaConstraints);\n    Janus.debug(offer);\n    // JSON.stringify doesn't work on some WebRTC objects anymore\n    // See https://code.google.com/p/chromium/issues/detail?id=467366\n    let jsep = {\n      type: 'offer',\n      sdp: offer.sdp,\n    };\n    callbacks.customizeSdp(jsep);\n    offer.sdp = jsep.sdp;\n    Janus.log('Setting local description');\n    config.mySdp = {\n      type: 'offer',\n      sdp: offer.sdp,\n    };\n    await config.pc.setLocalDescription(offer);\n    config.mediaConstraints = mediaConstraints;\n    if (!config.iceDone && !config.trickle) {\n      // FIXME Don't do anything until we have all candidates\n      Janus.log('Waiting for all candidates...');\n      return null;\n    }\n    // If transforms are present, notify Janus that the media is end-to-end encrypted\n    if (config.insertableStreams) offer.e2ee = true;\n    return offer;\n  }\n\n  async function createAnswer(handleId, callbacks) {\n    callbacks = callbacks || {};\n    callbacks.customizeSdp = typeof callbacks.customizeSdp == 'function' ? callbacks.customizeSdp : Janus.noop;\n    let pluginHandle = pluginHandles[handleId];\n    if (!pluginHandle || !pluginHandle.webrtcStuff) {\n      Janus.warn('Invalid handle');\n      throw 'Invalid handle';\n    }\n    let config = pluginHandle.webrtcStuff;\n    Janus.log('Creating answer (iceDone=' + config.iceDone + ')');\n    let answer = await config.pc.createAnswer();\n    Janus.debug(answer);\n    // JSON.stringify doesn't work on some WebRTC objects anymore\n    // See https://code.google.com/p/chromium/issues/detail?id=467366\n    let jsep = {\n      type: 'answer',\n      sdp: answer.sdp,\n    };\n    callbacks.customizeSdp(jsep);\n    answer.sdp = jsep.sdp;\n    Janus.log('Setting local description');\n    config.mySdp = {\n      type: 'answer',\n      sdp: answer.sdp,\n    };\n    await config.pc.setLocalDescription(answer);\n    if (!config.iceDone && !config.trickle) {\n      // FIXME Don't do anything until we have all candidates\n      Janus.log('Waiting for all candidates...');\n      return null;\n    }\n    // If transforms are present, notify Janus that the media is end-to-end encrypted\n    if (config.insertableStreams) answer.e2ee = true;\n    return answer;\n  }\n\n  function sendSDP(handleId, callbacks) {\n    callbacks = callbacks || {};\n    callbacks.success = typeof callbacks.success == 'function' ? callbacks.success : Janus.noop;\n    callbacks.error = typeof callbacks.error == 'function' ? callbacks.error : Janus.noop;\n    let pluginHandle = pluginHandles[handleId];\n    if (!pluginHandle || !pluginHandle.webrtcStuff) {\n      Janus.warn('Invalid handle, not sending anything');\n      return;\n    }\n    let config = pluginHandle.webrtcStuff;\n    Janus.log('Sending offer/answer SDP...');\n    if (!config.mySdp) {\n      Janus.warn('Local SDP instance is invalid, not sending anything...');\n      return;\n    }\n    config.mySdp = {\n      type: config.pc.localDescription.type,\n      sdp: config.pc.localDescription.sdp,\n    };\n    if (config.trickle === false) config.mySdp['trickle'] = false;\n    Janus.debug(callbacks);\n    config.sdpSent = true;\n    callbacks.success(config.mySdp);\n  }\n\n  async function replaceTracks(handleId, callbacks) {\n    callbacks = callbacks || {};\n    callbacks.success = typeof callbacks.success == 'function' ? callbacks.success : Janus.noop;\n    callbacks.error = typeof callbacks.error == 'function' ? callbacks.error : Janus.noop;\n    // Check that callbacks.array is a valid array\n    if (callbacks.tracks && !Array.isArray(callbacks.tracks)) {\n      Janus.error('Tracks must be an array');\n      callbacks.error('Tracks must be an array');\n      return;\n    }\n    // Add the replace:true if it's missing\n    for (let track of callbacks.tracks) {\n      if (track.add || (!track.replace && !track.remove)) track.replace = true;\n    }\n    try {\n      await captureDevices(handleId, callbacks);\n      callbacks.success();\n    } catch (err) {\n      Janus.error(err);\n      callbacks.error(err);\n    }\n  }\n\n  async function captureDevices(handleId, callbacks) {\n    let pluginHandle = pluginHandles[handleId];\n    if (!pluginHandle || !pluginHandle.webrtcStuff) {\n      Janus.warn('Invalid handle, not sending anything');\n      throw 'Invalid handle';\n    }\n    let config = pluginHandle.webrtcStuff;\n    if (!config.pc) {\n      Janus.warn('Invalid PeerConnection');\n      throw 'Invalid PeerConnection';\n    }\n    let tracks = callbacks.tracks;\n    if (!tracks || !Array.isArray(tracks) || tracks.length === 0) {\n      // Nothing to do\n      return;\n    }\n    let openedConsentDialog = false;\n    // Check if we can/should group getUserMedia calls\n    let groups = {};\n    for (let track of tracks) {\n      delete track.gumGroup;\n      if (!track.type || !['audio', 'video'].includes(track.type)) continue;\n      if (!track.capture || track.capture instanceof MediaStreamTrack) continue;\n      let group = track.group ? track.group : 'default';\n      if (!groups[group]) groups[group] = {};\n      if (groups[group][track.type]) continue;\n      track.gumGroup = group;\n      groups[group][track.type] = track;\n    }\n    let keys = Object.keys(groups);\n    for (let key of keys) {\n      let group = groups[key];\n      if (!group.audio || !group.video) {\n        if (group.audio) delete group.audio.gumGroup;\n        if (group.video) delete group.video.gumGroup;\n        delete groups[key];\n      }\n    }\n    let answer = callbacks.jsep ? true : false;\n    for (let track of tracks) {\n      if (!track.type) {\n        Janus.warn('Missing track type:', track);\n        continue;\n      }\n      if (track.type === 'data') {\n        // Easy enough: create a datachannel if we don't have one already\n        if (config.pc.ondatachannel) {\n          Janus.warn('Data channel exists already, not creating another one');\n          continue;\n        }\n        Janus.log('Creating default data channel');\n        createDataChannel(handleId, Janus.dataChanDefaultLabel, null, false);\n        config.pc.ondatachannel = function (event) {\n          Janus.log('Data channel created by Janus:', event);\n          createDataChannel(handleId, event.channel.label, event.channel.protocol, event.channel);\n        };\n        continue;\n      }\n      if (\n        typeof track.add === 'undefined' &&\n        track.add === null &&\n        typeof track.remove === 'undefined' &&\n        track.remove === null &&\n        typeof track.replace === 'undefined' &&\n        track.replace === null\n      ) {\n        // Let's default to 'add'\n        track.add = true;\n      }\n      if ((track.add && track.remove) || (track.add && track.remove && track.replace)) {\n        Janus.warn('Conflicting actions for track, ignoring:', track);\n        continue;\n      }\n      if (track.add && track.replace) {\n        Janus.warn('Both add and replace provided, falling back to replace:', track);\n        delete track.add;\n      } else if (track.remove && track.replace) {\n        Janus.warn('Both remove and replace provided, falling back to remove:', track);\n        delete track.replace;\n      }\n      let kind = track.type;\n      if (track.type === 'screen') kind = 'video'; // FIXME\n      let transceiver = null,\n        sender = null;\n      if (track.mid) {\n        // Search by mid\n        transceiver = config.pc.getTransceivers().find((t) => t.mid === track.mid && t.receiver.track.kind === kind);\n      } else {\n        // Find the first track of this type\n        transceiver = config.pc.getTransceivers().find((t) => t.receiver.track.kind === kind);\n      }\n      if (track.replace || track.remove) {\n        if (!transceiver) {\n          Janus.warn(\"Couldn't find a transceiver for track:\", track);\n          continue;\n        }\n        if (!transceiver.sender) {\n          Janus.warn('No sender in the transceiver for track:', track);\n          continue;\n        }\n        sender = transceiver.sender;\n      }\n      if (answer && !transceiver) {\n        transceiver = config.pc.getTransceivers().find((t) => t.receiver.track.kind === kind);\n        if (!transceiver) {\n          Janus.warn(\"Couldn't find a transceiver for track:\", track);\n          continue;\n        }\n      }\n      // Capture the new track, if we need to\n      let nt = null,\n        trackId = null;\n      if (track.remove) {\n        Janus.log('Removing track from PeerConnection', track);\n        trackId = sender.track ? sender.track.id : null;\n        await sender.replaceTrack(null);\n      } else if (track.capture) {\n        if (track.gumGroup && groups[track.gumGroup] && groups[track.gumGroup].stream) {\n          // We did a getUserMedia before already\n          let stream = groups[track.gumGroup].stream;\n          nt = track.type === 'audio' ? stream.getAudioTracks()[0] : stream.getVideoTracks()[0];\n          delete groups[track.gumGroup].stream;\n          delete groups[track.gumGroup];\n          delete track.gumGroup;\n        } else if (track.capture instanceof MediaStreamTrack) {\n          // An external track was provided, use that\n          nt = track.capture;\n        } else {\n          if (!openedConsentDialog) {\n            openedConsentDialog = true;\n            pluginHandle.consentDialog(true);\n          }\n          let constraints = Janus.trackConstraints(track),\n            stream = null;\n          if (track.type === 'audio' || track.type === 'video') {\n            // Use getUserMedia: check if we need to group audio and video together\n            if (track.gumGroup) {\n              let otherType = track.type === 'audio' ? 'video' : 'audio';\n              if (groups[track.gumGroup] && groups[track.gumGroup][otherType]) {\n                let otherTrack = groups[track.gumGroup][otherType];\n                let otherConstraints = Janus.trackConstraints(otherTrack);\n                constraints[otherType] = otherConstraints[otherType];\n              }\n            }\n            stream = await navigator.mediaDevices.getUserMedia(constraints);\n            if (track.gumGroup && constraints.audio && constraints.video) {\n              // We just performed a grouped getUserMedia, keep track of the\n              // stream so that we can immediately assign the track later\n              groups[track.gumGroup].stream = stream;\n              delete track.gumGroup;\n            }\n          } else {\n            // Use getDisplayMedia\n            stream = await navigator.mediaDevices.getDisplayMedia(constraints);\n          }\n          nt = track.type === 'audio' ? stream.getAudioTracks()[0] : stream.getVideoTracks()[0];\n        }\n        if (track.replace) {\n          // Replace the track\n          await sender.replaceTrack(nt);\n          // Update the transceiver direction\n          let newDirection = 'sendrecv';\n          if (track.recv === false || transceiver.direction === 'inactive' || transceiver.direction === 'sendonly')\n            newDirection = 'sendonly';\n          if (transceiver.setDirection) transceiver.setDirection(newDirection);\n          else transceiver.direction = newDirection;\n        } else {\n          // FIXME Add as a new track\n          if (!config.myStream) config.myStream = new MediaStream();\n          if (kind === 'audio' || (!track.simulcast && !track.svc)) {\n            sender = config.pc.addTrack(nt, config.myStream);\n            transceiver = config.pc.getTransceivers().find((t) => t.sender === sender);\n          } else if (track.simulcast) {\n            if (Janus.webRTCAdapter.browserDetails.browser !== 'firefox') {\n              // Standard RID\n              Janus.log('Enabling rid-based simulcasting:', nt);\n              let maxBitrates = getMaxBitrates(track.simulcastMaxBitrates);\n              transceiver = config.pc.addTransceiver(nt, {\n                direction: 'sendrecv',\n                streams: [config.myStream],\n                sendEncodings: track.sendEncodings || [\n                  { rid: 'h', active: true, maxBitrate: maxBitrates.high },\n                  {\n                    rid: 'm',\n                    active: true,\n                    maxBitrate: maxBitrates.medium,\n                    scaleResolutionDownBy: 2,\n                  },\n                  {\n                    rid: 'l',\n                    active: true,\n                    maxBitrate: maxBitrates.low,\n                    scaleResolutionDownBy: 4,\n                  },\n                ],\n              });\n            } else {\n              // Firefox-based RID, based on https://gist.github.com/voluntas/088bc3cc62094730647b\n              Janus.log('Enabling Simulcasting for Firefox (RID)');\n              transceiver = config.pc.addTransceiver(nt, {\n                direction: 'sendrecv',\n                streams: [config.myStream],\n              });\n              sender = transceiver ? transceiver.sender : null;\n              if (sender) {\n                let parameters = sender.getParameters();\n                if (!parameters) parameters = {};\n                let maxBitrates = getMaxBitrates(track.simulcastMaxBitrates);\n                parameters.encodings = track.sendEncodings || [\n                  { rid: 'h', active: true, maxBitrate: maxBitrates.high },\n                  {\n                    rid: 'm',\n                    active: true,\n                    maxBitrate: maxBitrates.medium,\n                    scaleResolutionDownBy: 2,\n                  },\n                  {\n                    rid: 'l',\n                    active: true,\n                    maxBitrate: maxBitrates.low,\n                    scaleResolutionDownBy: 4,\n                  },\n                ];\n                sender.setParameters(parameters);\n              }\n            }\n          } else {\n            Janus.log('Enabling SVC (' + track.svc + '):', nt);\n            transceiver = config.pc.addTransceiver(nt, {\n              direction: 'sendrecv',\n              streams: [config.myStream],\n              sendEncodings: [{ scalabilityMode: track.svc }],\n            });\n          }\n          if (!sender) sender = transceiver ? transceiver.sender : null;\n          // Check if we need to override some settings\n          if (track.codec) {\n            if (Janus.webRTCAdapter.browserDetails.browser === 'firefox') {\n              Janus.warn('setCodecPreferences not supported in Firefox, ignoring codec for track:', track);\n            } else if (typeof track.codec !== 'string') {\n              Janus.warn('Invalid codec value, ignoring for track:', track);\n            } else {\n              let mimeType = kind + '/' + track.codec.toLowerCase();\n              let codecs = RTCRtpReceiver.getCapabilities(kind).codecs.filter(function (codec) {\n                return codec.mimeType.toLowerCase() === mimeType;\n              });\n              if (!codecs || codecs.length === 0) {\n                Janus.warn('Codec not supported in this browser for this track, ignoring:', track);\n              } else if (transceiver) {\n                try {\n                  transceiver.setCodecPreferences(codecs);\n                } catch (err) {\n                  Janus.warn('Failed enforcing codec for this ' + kind + ' track:', err);\n                }\n              }\n            }\n          }\n          if (track.bitrate) {\n            // Override maximum bitrate\n            if (track.simulcast || track.svc) {\n              Janus.warn('Ignoring bitrate for simulcast/SVC track, use sendEncodings for that');\n            } else if (isNaN(track.bitrate) || track.bitrate < 0) {\n              Janus.warn('Ignoring invalid bitrate for track:', track);\n            } else if (sender) {\n              let params = sender.getParameters();\n              if (!params || !params.encodings || params.encodings.length === 0) {\n                Janus.warn('No encodings in the sender parameters, ignoring bitrate for track:', track);\n              } else {\n                params.encodings[0].maxBitrate = track.bitrate;\n                await sender.setParameters(params);\n              }\n            }\n          }\n          if (kind === 'video' && track.framerate) {\n            // Override maximum framerate\n            if (track.simulcast || track.svc) {\n              Janus.warn('Ignoring framerate for simulcast/SVC track, use sendEncodings for that');\n            } else if (isNaN(track.framerate) || track.framerate < 0) {\n              Janus.warn('Ignoring invalid framerate for track:', track);\n            } else if (sender) {\n              let params = sender.getParameters();\n              if (!params || !params.encodings || params.encodings.length === 0) {\n                Janus.warn('No encodings in the sender parameters, ignoring framerate for track:', track);\n              } else {\n                params.encodings[0].maxFramerate = track.framerate;\n                await sender.setParameters(params);\n              }\n            }\n          }\n          // Check if insertable streams are involved\n          if (track.transforms) {\n            if (sender && track.transforms.sender) {\n              // There's a sender transform, set it on the transceiver sender\n              let senderStreams = null;\n              if (RTCRtpSender.prototype.createEncodedStreams) {\n                senderStreams = sender.createEncodedStreams();\n              } else if (\n                RTCRtpSender.prototype.createAudioEncodedStreams ||\n                RTCRtpSender.prototype.createEncodedVideoStreams\n              ) {\n                if (kind === 'audio') {\n                  senderStreams = sender.createEncodedAudioStreams();\n                } else if (kind === 'video') {\n                  senderStreams = sender.createEncodedVideoStreams();\n                }\n              }\n              if (senderStreams) {\n                Janus.log('Insertable Streams sender transform:', senderStreams);\n                if (senderStreams.readableStream && senderStreams.writableStream) {\n                  senderStreams.readableStream\n                    .pipeThrough(track.transforms.sender)\n                    .pipeTo(senderStreams.writableStream);\n                } else if (senderStreams.readable && senderStreams.writable) {\n                  senderStreams.readable.pipeThrough(track.transforms.sender).pipeTo(senderStreams.writable);\n                }\n              }\n            }\n            if (transceiver && transceiver.receiver && track.transforms.receiver) {\n              // There's a receiver transform, set it on the transceiver receiver\n              let receiverStreams = null;\n              if (RTCRtpReceiver.prototype.createEncodedStreams) {\n                receiverStreams = transceiver.receiver.createEncodedStreams();\n              } else if (\n                RTCRtpReceiver.prototype.createAudioEncodedStreams ||\n                RTCRtpReceiver.prototype.createEncodedVideoStreams\n              ) {\n                if (kind === 'audio') {\n                  receiverStreams = transceiver.receiver.createEncodedAudioStreams();\n                } else if (kind === 'video') {\n                  receiverStreams = transceiver.receiver.createEncodedVideoStreams();\n                }\n              }\n              if (receiverStreams) {\n                Janus.log('Insertable Streams receiver transform:', receiverStreams);\n                if (receiverStreams.readableStream && receiverStreams.writableStream) {\n                  receiverStreams.readableStream\n                    .pipeThrough(track.transforms.receiver)\n                    .pipeTo(receiverStreams.writableStream);\n                } else if (receiverStreams.readable && receiverStreams.writable) {\n                  receiverStreams.readable.pipeThrough(track.transforms.receiver).pipeTo(receiverStreams.writable);\n                }\n              }\n            }\n          }\n        }\n        if (nt && track.dontStop === true) nt.dontStop = true;\n      } else if (track.recv && !transceiver) {\n        // Maybe a new recvonly track\n        transceiver = config.pc.addTransceiver(kind);\n        if (transceiver) {\n          // Check if we need to override some settings\n          if (track.codec) {\n            if (Janus.webRTCAdapter.browserDetails.browser === 'firefox') {\n              Janus.warn('setCodecPreferences not supported in Firefox, ignoring codec for track:', track);\n            } else if (typeof track.codec !== 'string') {\n              Janus.warn('Invalid codec value, ignoring for track:', track);\n            } else {\n              let mimeType = kind + '/' + track.codec.toLowerCase();\n              let codecs = RTCRtpReceiver.getCapabilities(kind).codecs.filter(function (codec) {\n                return codec.mimeType.toLowerCase() === mimeType;\n              });\n              if (!codecs || codecs.length === 0) {\n                Janus.warn('Codec not supported in this browser for this track, ignoring:', track);\n              } else {\n                try {\n                  transceiver.setCodecPreferences(codecs);\n                } catch (err) {\n                  Janus.warn('Failed enforcing codec for this ' + kind + ' track:', err);\n                }\n              }\n            }\n          }\n          // Check if insertable streams are involved\n          if (transceiver.receiver && track.transforms && track.transforms.receiver) {\n            // There's a receiver transform, set it on the transceiver receiver\n            let receiverStreams = null;\n            if (RTCRtpReceiver.prototype.createEncodedStreams) {\n              receiverStreams = transceiver.receiver.createEncodedStreams();\n            } else if (\n              RTCRtpReceiver.prototype.createAudioEncodedStreams ||\n              RTCRtpReceiver.prototype.createEncodedVideoStreams\n            ) {\n              if (kind === 'audio') {\n                receiverStreams = transceiver.receiver.createEncodedAudioStreams();\n              } else if (kind === 'video') {\n                receiverStreams = transceiver.receiver.createEncodedVideoStreams();\n              }\n            }\n            if (receiverStreams) {\n              Janus.log('Insertable Streams receiver transform:', receiverStreams);\n              if (receiverStreams.readableStream && receiverStreams.writableStream) {\n                receiverStreams.readableStream\n                  .pipeThrough(track.transforms.receiver)\n                  .pipeTo(receiverStreams.writableStream);\n              } else if (receiverStreams.readable && receiverStreams.writable) {\n                receiverStreams.readable.pipeThrough(track.transforms.receiver).pipeTo(receiverStreams.writable);\n              }\n            }\n          }\n        }\n      }\n      // Get rid of the old track\n      // FIXME We should probably do this *before* capturing the new\n      // track, since this prevents, for instance, just changing the\n      // resolution of the same webcam we're capturing already (the\n      // existing resolution would be returned, or an overconstrained\n      // error). On the other end, closing the track before we capture\n      // the new device means we'd end up with a period of time where\n      // no video is sent (changing device takes some time), and\n      // media would be stopped entirely in case capturing the new\n      // device results in an error. To keep things simpler, we're\n      // doing it after: we can make this configurable in the future.\n      if (trackId && config.myStream) {\n        let rt = null;\n        if (kind === 'audio' && config.myStream.getAudioTracks() && config.myStream.getAudioTracks().length) {\n          for (let t of config.myStream.getAudioTracks()) {\n            if (t.id === trackId) {\n              rt = t;\n              Janus.log('Removing audio track:', rt);\n            }\n          }\n        } else if (kind === 'video' && config.myStream.getVideoTracks() && config.myStream.getVideoTracks().length) {\n          for (let t of config.myStream.getVideoTracks()) {\n            if (t.id === trackId) {\n              rt = t;\n              Janus.log('Removing video track:', rt);\n            }\n          }\n        }\n        if (rt) {\n          // Remove the track and notify the application\n          try {\n            config.myStream.removeTrack(rt);\n            pluginHandle.onlocaltrack(rt, false);\n          } catch (e) {\n            Janus.error('Error calling onlocaltrack on removal for renegotiation', e);\n          }\n          // Close the old track (unless we've been asked not to)\n          if (rt.dontStop !== true) {\n            try {\n              rt.stop();\n            } catch (e) { }\n          }\n        }\n      }\n      if (nt) {\n        // FIXME Add the new track locally\n        config.myStream.addTrack(nt);\n        // Notify the application about the new local track, if any\n        nt.onended = function (ev) {\n          Janus.log('Local track removed:', ev);\n          try {\n            pluginHandle.onlocaltrack(ev.target, false);\n          } catch (e) {\n            Janus.error('Error calling onlocaltrack following end', e);\n          }\n        };\n        try {\n          pluginHandle.onlocaltrack(nt, true);\n        } catch (e) {\n          Janus.error('Error calling onlocaltrack for track add', e);\n        }\n      }\n      // Update the direction of the transceiver\n      if (transceiver) {\n        let curdir = transceiver.direction,\n          newdir = null;\n        let send = nt && transceiver.sender.track,\n          recv = track.recv !== false && transceiver.receiver.track;\n        if (send && recv) newdir = 'sendrecv';\n        else if (send && !recv) newdir = 'sendonly';\n        else if (!send && recv) newdir = 'recvonly';\n        else if (!send && !recv) newdir = 'inactive';\n        if (newdir && newdir !== curdir) {\n          Janus.warn('Changing direction of transceiver to ' + newdir + ' (was ' + curdir + ')', track);\n          if (transceiver.setDirection) transceiver.setDirection(newdir);\n          else transceiver.direction = newdir;\n        }\n      }\n    }\n    if (openedConsentDialog) pluginHandle.consentDialog(false);\n  }\n\n  function getLocalTracks(handleId) {\n    let pluginHandle = pluginHandles[handleId];\n    if (!pluginHandle || !pluginHandle.webrtcStuff) {\n      Janus.warn('Invalid handle');\n      return null;\n    }\n    let config = pluginHandle.webrtcStuff;\n    if (!config.pc) {\n      Janus.warn('Invalid PeerConnection');\n      return null;\n    }\n    let tracks = [];\n    let transceivers = config.pc.getTransceivers();\n    for (let tr of transceivers) {\n      let track = null;\n      if (tr.sender && tr.sender.track) {\n        track = { mid: tr.mid };\n        track.type = tr.sender.track.kind;\n        track.id = tr.sender.track.id;\n        track.label = tr.sender.track.label;\n      }\n      if (track) tracks.push(track);\n    }\n    return tracks;\n  }\n\n  function getRemoteTracks(handleId) {\n    let pluginHandle = pluginHandles[handleId];\n    if (!pluginHandle || !pluginHandle.webrtcStuff) {\n      Janus.warn('Invalid handle');\n      return null;\n    }\n    let config = pluginHandle.webrtcStuff;\n    if (!config.pc) {\n      Janus.warn('Invalid PeerConnection');\n      return null;\n    }\n    let tracks = [];\n    let transceivers = config.pc.getTransceivers();\n    for (let tr of transceivers) {\n      let track = null;\n      if (tr.receiver && tr.receiver.track) {\n        track = { mid: tr.mid };\n        track.type = tr.receiver.track.kind;\n        track.id = tr.receiver.track.id;\n        track.label = tr.receiver.track.label;\n      }\n      if (track) tracks.push(track);\n    }\n    return tracks;\n  }\n\n  function getVolume(handleId, mid, remote, result) {\n    result = typeof result == 'function' ? result : Janus.noop;\n    let pluginHandle = pluginHandles[handleId];\n    if (!pluginHandle || !pluginHandle.webrtcStuff) {\n      Janus.warn('Invalid handle');\n      result(0);\n      return;\n    }\n    let stream = remote ? 'remote' : 'local';\n    let config = pluginHandle.webrtcStuff;\n    if (!config.volume[stream]) config.volume[stream] = { value: 0 };\n    // Start getting the volume, if audioLevel in getStats is supported (apparently\n    // they're only available in Chrome/Safari right now: https://webrtc-stats.callstats.io/)\n    if (\n      config.pc &&\n      config.pc.getStats &&\n      (Janus.webRTCAdapter.browserDetails.browser === 'chrome' ||\n        Janus.webRTCAdapter.browserDetails.browser === 'safari')\n    ) {\n      // Are we interested in a mid in particular?\n      let query = config.pc;\n      if (mid) {\n        let transceiver = config.pc.getTransceivers().find((t) => t.mid === mid && t.receiver.track.kind === 'audio');\n        if (!transceiver) {\n          Janus.warn('No audio transceiver with mid ' + mid);\n          result(0);\n          return;\n        }\n        if (remote && !transceiver.receiver) {\n          Janus.warn('Remote transceiver track unavailable');\n          result(0);\n          return;\n        } else if (!remote && !transceiver.sender) {\n          Janus.warn('Local transceiver track unavailable');\n          result(0);\n          return;\n        }\n        query = remote ? transceiver.receiver : transceiver.sender;\n      }\n      query.getStats().then(function (stats) {\n        stats.forEach(function (res) {\n          if (!res || res.kind !== 'audio') return;\n          if ((remote && !res.remoteSource) || (!remote && res.type !== 'media-source')) return;\n          result(res.audioLevel ? res.audioLevel : 0);\n        });\n      });\n      return config.volume[stream].value;\n    } else {\n      // audioInputLevel and audioOutputLevel seem only available in Chrome? audioLevel\n      // seems to be available on Chrome and Firefox, but they don't seem to work\n      Janus.warn('Getting the ' + stream + ' volume unsupported by browser');\n      result(0);\n      return;\n    }\n  }\n\n  function isMuted(handleId, mid, video) {\n    let pluginHandle = pluginHandles[handleId];\n    if (!pluginHandle || !pluginHandle.webrtcStuff) {\n      Janus.warn('Invalid handle');\n      return true;\n    }\n    let config = pluginHandle.webrtcStuff;\n    if (!config.pc) {\n      Janus.warn('Invalid PeerConnection');\n      return true;\n    }\n    if (!config.myStream) {\n      Janus.warn('Invalid local MediaStream');\n      return true;\n    }\n    if (video) {\n      // Check video track\n      if (!config.myStream.getVideoTracks() || config.myStream.getVideoTracks().length === 0) {\n        Janus.warn('No video track');\n        return true;\n      }\n      if (mid) {\n        let transceiver = config.pc.getTransceivers().find((t) => t.mid === mid && t.receiver.track.kind === 'video');\n        if (!transceiver) {\n          Janus.warn('No video transceiver with mid ' + mid);\n          return true;\n        }\n        if (!transceiver.sender || !transceiver.sender.track) {\n          Janus.warn('No video sender with mid ' + mid);\n          return true;\n        }\n        return !transceiver.sender.track.enabled;\n      } else {\n        return !config.myStream.getVideoTracks()[0].enabled;\n      }\n    } else {\n      // Check audio track\n      if (!config.myStream.getAudioTracks() || config.myStream.getAudioTracks().length === 0) {\n        Janus.warn('No audio track');\n        return true;\n      }\n      if (mid) {\n        let transceiver = config.pc.getTransceivers().find((t) => t.mid === mid && t.receiver.track.kind === 'audio');\n        if (!transceiver) {\n          Janus.warn('No audio transceiver with mid ' + mid);\n          return true;\n        }\n        if (!transceiver.sender || !transceiver.sender.track) {\n          Janus.warn('No audio sender with mid ' + mid);\n          return true;\n        }\n        return !transceiver.sender.track.enabled;\n      } else {\n        return !config.myStream.getAudioTracks()[0].enabled;\n      }\n    }\n  }\n\n  function mute(handleId, mid, video, mute) {\n    let pluginHandle = pluginHandles[handleId];\n    if (!pluginHandle || !pluginHandle.webrtcStuff) {\n      Janus.warn('Invalid handle');\n      return false;\n    }\n    let config = pluginHandle.webrtcStuff;\n    if (!config.pc) {\n      Janus.warn('Invalid PeerConnection');\n      return false;\n    }\n    if (!config.myStream) {\n      Janus.warn('Invalid local MediaStream');\n      return false;\n    }\n    if (video) {\n      // Mute/unmute video track\n      if (!config.myStream.getVideoTracks() || config.myStream.getVideoTracks().length === 0) {\n        Janus.warn('No video track');\n        return false;\n      }\n      if (mid) {\n        let transceiver = config.pc.getTransceivers().find((t) => t.mid === mid && t.receiver.track.kind === 'video');\n        if (!transceiver) {\n          Janus.warn('No video transceiver with mid ' + mid);\n          return false;\n        }\n        if (!transceiver.sender || !transceiver.sender.track) {\n          Janus.warn('No video sender with mid ' + mid);\n          return false;\n        }\n        transceiver.sender.track.enabled = mute ? false : true;\n      } else {\n        for (const videostream of config.myStream.getVideoTracks()) {\n          videostream.enabled = !mute;\n        }\n      }\n    } else {\n      // Mute/unmute audio track\n      if (!config.myStream.getAudioTracks() || config.myStream.getAudioTracks().length === 0) {\n        Janus.warn('No audio track');\n        return false;\n      }\n      if (mid) {\n        let transceiver = config.pc.getTransceivers().find((t) => t.mid === mid && t.receiver.track.kind === 'audio');\n        if (!transceiver) {\n          Janus.warn('No audio transceiver with mid ' + mid);\n          return false;\n        }\n        if (!transceiver.sender || !transceiver.sender.track) {\n          Janus.warn('No audio sender with mid ' + mid);\n          return false;\n        }\n        transceiver.sender.track.enabled = mute ? false : true;\n      } else {\n        for (const audiostream of config.myStream.getAudioTracks()) {\n          audiostream.enabled = !mute;\n        }\n      }\n    }\n    return true;\n  }\n\n  function getBitrate(handleId, mid) {\n    let pluginHandle = pluginHandles[handleId];\n    if (!pluginHandle || !pluginHandle.webrtcStuff) {\n      Janus.warn('Invalid handle');\n      return 'Invalid handle';\n    }\n    let config = pluginHandle.webrtcStuff;\n    if (!config.pc) return 'Invalid PeerConnection';\n    // Start getting the bitrate, if getStats is supported\n    if (config.pc.getStats) {\n      let query = config.pc;\n      let target = mid ? mid : 'default';\n      if (mid) {\n        let transceiver = config.pc.getTransceivers().find((t) => t.mid === mid && t.receiver.track.kind === 'video');\n        if (!transceiver) {\n          Janus.warn('No video transceiver with mid ' + mid);\n          return 'No video transceiver with mid ' + mid;\n        }\n        if (!transceiver.receiver) {\n          Janus.warn('No video receiver with mid ' + mid);\n          return 'No video receiver with mid ' + mid;\n        }\n        query = transceiver.receiver;\n      }\n      if (!config.bitrate[target]) {\n        config.bitrate[target] = {\n          timer: null,\n          bsnow: null,\n          bsbefore: null,\n          tsnow: null,\n          tsbefore: null,\n          value: '0 kbits/sec',\n        };\n      }\n      if (!config.bitrate[target].timer) {\n        Janus.log('Starting bitrate timer' + (mid ? ' for mid ' + mid : '') + ' (via getStats)');\n        config.bitrate[target].timer = setInterval(function () {\n          query.getStats().then(function (stats) {\n            stats.forEach(function (res) {\n              if (!res) return;\n              let inStats = false;\n              // Check if these are statistics on incoming media\n              if (\n                (res.mediaType === 'video' || res.id.toLowerCase().indexOf('video') > -1) &&\n                res.type === 'inbound-rtp' &&\n                res.id.indexOf('rtcp') < 0\n              ) {\n                // New stats\n                inStats = true;\n              } else if (\n                res.type == 'ssrc' &&\n                res.bytesReceived &&\n                (res.googCodecName === 'VP8' || res.googCodecName === '')\n              ) {\n                // Older Chromer versions\n                inStats = true;\n              }\n              // Parse stats now\n              if (inStats) {\n                config.bitrate[target].bsnow = res.bytesReceived;\n                config.bitrate[target].tsnow = res.timestamp;\n                if (config.bitrate[target].bsbefore === null || config.bitrate[target].tsbefore === null) {\n                  // Skip this round\n                  config.bitrate[target].bsbefore = config.bitrate[target].bsnow;\n                  config.bitrate[target].tsbefore = config.bitrate[target].tsnow;\n                } else {\n                  // Calculate bitrate\n                  let timePassed = config.bitrate[target].tsnow - config.bitrate[target].tsbefore;\n                  if (Janus.webRTCAdapter.browserDetails.browser === 'safari') timePassed = timePassed / 1000; // Apparently the timestamp is in microseconds, in Safari\n                  let bitRate = Math.round(\n                    ((config.bitrate[target].bsnow - config.bitrate[target].bsbefore) * 8) / timePassed\n                  );\n                  if (Janus.webRTCAdapter.browserDetails.browser === 'safari') bitRate = parseInt(bitRate / 1000);\n                  config.bitrate[target].value = bitRate + ' kbits/sec';\n                  //~ Janus.log(\"Estimated bitrate is \" + config.bitrate.value);\n                  config.bitrate[target].bsbefore = config.bitrate[target].bsnow;\n                  config.bitrate[target].tsbefore = config.bitrate[target].tsnow;\n                }\n              }\n            });\n          });\n        }, 1000);\n        return '0 kbits/sec'; // We don't have a bitrate value yet\n      }\n      return config.bitrate[target].value;\n    } else {\n      Janus.warn('Getting the video bitrate unsupported by browser');\n      return 'Feature unsupported by browser';\n    }\n  }\n\n  function setBitrate(handleId, mid, bitrate) {\n    let pluginHandle = pluginHandles[handleId];\n    if (!pluginHandle || !pluginHandle.webrtcStuff) {\n      Janus.warn('Invalid handle');\n      return;\n    }\n    let config = pluginHandle.webrtcStuff;\n    if (!config.pc) {\n      Janus.warn('Invalid PeerConnection');\n      return;\n    }\n    let transceiver = config.pc.getTransceivers().find((t) => t.mid === mid);\n    if (!transceiver) {\n      Janus.warn('No transceiver with mid', mid);\n      return;\n    }\n    if (!transceiver.sender) {\n      Janus.warn('No sender for transceiver with mid', mid);\n      return;\n    }\n    let params = transceiver.sender.getParameters();\n    if (!params || !params.encodings || params.encodings.length === 0) {\n      Janus.warn('No parameters encodings');\n    } else if (params.encodings.length > 1) {\n      Janus.warn('Ignoring bitrate for simulcast track, use sendEncodings for that');\n    } else if (isNaN(bitrate) || bitrate < 0) {\n      Janus.warn('Invalid bitrate (must be a positive integer)');\n    } else {\n      params.encodings[0].maxBitrate = bitrate;\n      transceiver.sender.setParameters(params);\n    }\n  }\n\n  function webrtcError(error) {\n    Janus.error('WebRTC error:', error);\n  }\n\n  function cleanupWebrtc(handleId, hangupRequest) {\n    Janus.log('Cleaning WebRTC stuff');\n    let pluginHandle = pluginHandles[handleId];\n    if (!pluginHandle) {\n      // Nothing to clean\n      return;\n    }\n    let config = pluginHandle.webrtcStuff;\n    if (config) {\n      if (hangupRequest === true) {\n        // Send a hangup request (we don't really care about the response)\n        let request = { janus: 'hangup', transaction: Janus.randomString(12) };\n        if (pluginHandle.token) request['token'] = pluginHandle.token;\n        if (apisecret) request['apisecret'] = apisecret;\n        Janus.debug('Sending hangup request (handle=' + handleId + '):');\n        Janus.debug(request);\n        if (websockets) {\n          request['session_id'] = sessionId;\n          request['handle_id'] = handleId;\n          ws.send(JSON.stringify(request));\n        } else {\n          Janus.httpAPICall(server + '/' + sessionId + '/' + handleId, {\n            verb: 'POST',\n            withCredentials: withCredentials,\n            body: request,\n          });\n        }\n      }\n      // Cleanup stack\n      if (config.volume) {\n        if (config.volume['local'] && config.volume['local'].timer) clearInterval(config.volume['local'].timer);\n        if (config.volume['remote'] && config.volume['remote'].timer) clearInterval(config.volume['remote'].timer);\n      }\n      for (let i in config.bitrate) {\n        if (config.bitrate[i].timer) clearInterval(config.bitrate[i].timer);\n      }\n      config.bitrate = {};\n      if (!config.streamExternal && config.myStream) {\n        Janus.log('Stopping local stream tracks');\n        Janus.stopAllTracks(config.myStream);\n      }\n      config.streamExternal = false;\n      config.myStream = null;\n      // Close PeerConnection\n      try {\n        config.pc.close();\n      } catch (e) {\n        // Do nothing\n      }\n      config.pc = null;\n      config.candidates = null;\n      config.mySdp = null;\n      config.remoteSdp = null;\n      config.iceDone = false;\n      config.dataChannel = {};\n      config.dtmfSender = null;\n      config.insertableStreams = false;\n    }\n    pluginHandle.oncleanup();\n  }\n\n  function isTrickleEnabled(trickle) {\n    Janus.debug('isTrickleEnabled:', trickle);\n    return trickle === false ? false : true;\n  }\n}\n\nmodule.exports = Janus;\n","import type { Config, Janus, VoidCallback, PlainObject } from '../types';\nimport { JanusDebugMode, JanusEvent, JanusMediaTrackReason } from '../types/constants';\nimport { adapter, MediaStream } from '@platform';\nimport EventEmitter from 'eventemitter3';\nimport config from '../config';\nimport JanusEngine from './janus.js';\nimport Utils from '../Utils';\n\nexport default class JanusClient {\n  public token: Config.Credentials['token'];\n  public server: Config.Conference['server'];\n  public debug: Config.JanusDebug;\n  declare engine: JanusEngine;\n  public videoRoomPlugin: Janus.VideoRoomPluginHandle | null = null;\n  public isOnlyAudio: boolean = false;\n  public currentRoomId: string | null = null;\n  public currentUserId: number | string | null = null;\n  public remoteFeeds: Record<number | string, Janus.RemoteFeed | null> = {};\n  public remoteJseps: PlainObject<string | number> = {};\n  public remoteFeedsAttachingInProgress: Record<number | string, Janus.RemoteFeed | null> = {};\n  public bitrateTimers: { [userId: number | string]: NodeJS.Timeout | number | null } = {};\n  public emitter: EventEmitter = new EventEmitter();\n\n  constructor(token: Config.Credentials['token']) {\n    if (!Utils.env.isReactNative && !adapter) {\n      throw new Error(\n        'Error: in order to use this library please connect adapter.js. More info https://github.com/webrtc/adapter'\n      );\n    }\n\n    this.token = token;\n    this.server = config.conference.server;\n    this.debug = config.conference.debug ?? JanusDebugMode.ALL;\n\n    if (!this.server) {\n      throw new Error(\"'server' parameter is mandatory\");\n    } else if (this.server.includes('http')) {\n      this.server += '/janus';\n    }\n  }\n\n  public createSession({\n    success = () => {},\n    error = () => {},\n    destroyed = () => {},\n    timeoutSessionCallback = () => {},\n  }: Janus.InitCallbacks): void {\n    JanusEngine.init({\n      debug: this.debug,\n      callback: () => {\n        if (!JanusEngine.isWebrtcSupported()) {\n          Utils.safeCallbackCall(error)(`Your browser does not support WebRTC, so you can't use this functionality.`);\n          return;\n        }\n\n        this.engine = new JanusEngine({\n          server: this.server,\n          iceServers: config.videochat.iceServers,\n          token: this.token,\n          success: () => Utils.safeCallbackCall(success)(),\n          error: (err: unknown) => Utils.safeCallbackCall(error)(err),\n          destroyed: () => Utils.safeCallbackCall(destroyed)(),\n          timeoutSessionCallback: () => Utils.safeCallbackCall(timeoutSessionCallback)(),\n        });\n      },\n    });\n  }\n\n  public getSessionId(): string | null {\n    return this.engine?.getSessionId?.() ?? null;\n  }\n\n  public destroySession({ success = () => {}, error = () => {} }: Janus.SuccessErrorCallbacks): void {\n    this.engine?.destroy?.({\n      success: () => Utils.safeCallbackCall(success)(),\n      error: (err: unknown) => Utils.safeCallbackCall(error)(err),\n    });\n  }\n\n  public attachVideoConferencingPlugin(\n    isRemote: boolean,\n    userId: number,\n    skipMedia: boolean,\n    callbacks: Janus.PluginCallbacks\n  ): void {\n    let remoteFeed: Janus.RemoteFeed | null = null;\n\n    const localStream = callbacks.localStream;\n    delete callbacks.localStream;\n\n    const displayName = callbacks.displayName;\n    delete callbacks.displayName;\n\n    this.engine?.attach?.({\n      plugin: 'janus.plugin.videoroom',\n      success: (pluginHandle: Janus.VideoRoomPluginHandle | Janus.RemoteFeed) => {\n        if (isRemote) {\n          remoteFeed = pluginHandle as Janus.RemoteFeed;\n          remoteFeed.userId = userId;\n          this.remoteFeedsAttachingInProgress[userId] = remoteFeed;\n\n          const listen = {\n            request: 'join',\n            room: this.currentRoomId,\n            ptype: 'listener',\n            feed: userId,\n            display: displayName,\n          };\n\n          remoteFeed?.send({ message: listen });\n        } else {\n          this.videoRoomPlugin = pluginHandle as Janus.VideoRoomPluginHandle;\n        }\n\n        Utils.safeCallbackCall(callbacks.success)();\n      },\n      error: (error: unknown) => {\n        Utils.safeCallbackCall(callbacks.error)(error);\n      },\n      consentDialog: (on: unknown) => {\n        Utils.safeCallbackCall(callbacks.consentDialog)(on);\n      },\n      mediaState: (medium: unknown, on: unknown) => {\n        Utils.safeCallbackCall(callbacks.mediaState)(medium, on);\n      },\n      webrtcState: (on: unknown) => {\n        Utils.safeCallbackCall(callbacks.webrtcState)(on);\n      },\n      slowLink: (uplink: unknown, nacks: unknown) => {\n        Utils.safeCallbackCall(callbacks.slowLink)(uplink, nacks);\n      },\n      iceState: (iceConnectionState: unknown) => {\n        Utils.safeCallbackCall(callbacks.iceState)(iceConnectionState);\n      },\n      onmessage: (msg: PlainObject, jsep: unknown) => {\n        const event = msg?.['videoroom'];\n\n        if (isRemote) {\n          if (event) {\n            // Remote feed attached\n            if (event === 'attached') {\n              const feedId = msg['id'] as number | string;\n              this.remoteFeeds[feedId] = this.remoteFeedsAttachingInProgress[feedId];\n              this.remoteFeedsAttachingInProgress[feedId] = null;\n            } else if (msg['error']) {\n              Utils.safeCallbackCall(callbacks.error)(msg['error']);\n            }\n          }\n\n          if (jsep) {\n            const feedId = msg['id'] as number | string;\n\n            // ICE restart case\n            if (!feedId) {\n            }\n\n            this.remoteJseps[feedId] = jsep;\n\n            const remoteFeed = this.remoteFeeds[feedId];\n\n            if (!remoteFeed) return;\n\n            this.createAnswer(\n              {\n                remoteFeed,\n                jsep,\n              },\n              localStream as MediaStream,\n              {\n                success: () => {},\n                error: (error) => {\n                  Utils.safeCallbackCall(callbacks.error)(error);\n                },\n              }\n            );\n          }\n\n          // local feed\n        } else {\n          if (event) {\n            // We JOINED\n            if (event === 'joined') {\n              const media = skipMedia ? { audio: false, video: false } : { audio: true, video: true };\n              const existedStream = skipMedia ? undefined : localStream;\n              const offerParams = { media, stream: existedStream };\n              this.createOffer(offerParams, {\n                success: () => {\n                  if (msg['publishers']) {\n                    const publishers = msg['publishers'] as Record<string | number, PlainObject>;\n                    for (const f in publishers) {\n                      const userId = publishers[f]['id'] as number;\n                      const userDisplayName = publishers[f]['display'] as string;\n                      this.emitter.emit(JanusEvent.PARTICIPANT_JOINED, userId, userDisplayName, true);\n                    }\n                  }\n                },\n                error: (error) => {\n                  Utils.safeCallbackCall(callbacks.error)(error);\n                },\n              });\n\n              // We JOINED and now receiving who is online\n            } else if (event === 'event') {\n              // Any new feed to attach to?\n              if (msg['publishers']) {\n                const publishers = msg['publishers'] as Record<string | number, PlainObject>;\n\n                for (const f in publishers) {\n                  const userId = publishers[f]['id'] as number;\n                  const userDisplayName = publishers[f]['display'] as string;\n\n                  this.emitter.emit(JanusEvent.PARTICIPANT_JOINED, userId, userDisplayName, false);\n                }\n\n                // Someone is LEAVING\n              } else if (msg['leaving']) {\n                // One of the publishers has gone away?\n                const feedId = msg['leaving'] as number;\n                const success = this.detachRemoteFeed(feedId);\n                if (success) {\n                  this.emitter.emit(JanusEvent.PARTICIPANT_LEFT, feedId, null);\n                }\n              } else if (msg['unpublished']) {\n                // One of the publishers has gone away?\n                const feedId = msg['unpublished'] as number | string;\n                if (feedId !== 'ok') {\n                  const success = this.detachRemoteFeed(Number(feedId));\n                  if (success) {\n                    this.emitter.emit(JanusEvent.PARTICIPANT_LEFT, feedId, null);\n                  }\n                }\n              } else if (msg['error']) {\n                Utils.DLog('[janus error message]', msg['error']);\n                // #define VIDEOROOM_ERROR_ID_EXISTS\t\t\t436\n                // #define VIDEOROOM_ERROR_UNAUTHORIZED\t\t433\n                //\n                this.emitter.emit(JanusEvent.ERROR, msg);\n                Utils.safeCallbackCall(callbacks.error)(msg['error']);\n              }\n            }\n          }\n\n          if (jsep) {\n            this.videoRoomPlugin?.handleRemoteJsep?.({ jsep: jsep });\n\n            // TODO:\n            // handle wrong or unsupported codecs here...\n            // const video = msg['video_codec']\n            // if(mystream && mystream.getVideoTracks() && mystream.getVideoTracks().length > 0 && !video) {\n            // \t\t'Our video stream has been rejected, viewers won't see us'\n            // }\n          }\n        }\n      },\n      onlocaltrack: (track: MediaStreamTrack, on: unknown) => {\n        Utils.DLog('[onlocaltrack]', track, on);\n        this.onLocalTrack(track, on);\n      },\n      onremotetrack: (track: MediaStreamTrack, mid: unknown, on: unknown, metadata: unknown) => {\n        Utils.DLog('[onremotetrack]', track, mid, on, metadata);\n        this.onRemoteTrack(\n          remoteFeed!,\n          track,\n          typeof mid === 'string' ? mid : String(mid),\n          on,\n          metadata as { reason?: string } | undefined\n        );\n      },\n      ondataopen: (channelLabel: string) => {\n        Utils.DLog('[ondataopen]', channelLabel);\n        this.emitter.emit(JanusEvent.DATA_CHANNEL_OPEN, channelLabel);\n      },\n      ondata: (data: unknown, channelLabel: string) => {\n        Utils.DLog('[ondata]', channelLabel, data);\n        this.emitter.emit(JanusEvent.DATA_CHANNEL_MESSAGE, channelLabel, data);\n      },\n      oncleanup: () => {\n        Utils.safeCallbackCall(callbacks.oncleanup)();\n      },\n      detached: () => {},\n    });\n  }\n\n  public onLocalTrack(_track: MediaStreamTrack, _on: unknown): void {\n    // this.emitter.emit(JanusEvent.LOCAL_STREAM, track);\n  }\n\n  public onRemoteTrack(\n    remoteFeed: Janus.RemoteFeed,\n    track: MediaStreamTrack,\n    mid: string,\n    _on: unknown,\n    metadata: { reason?: string } | undefined\n  ): void {\n    const eventType = metadata && metadata.reason;\n    if (eventType === JanusMediaTrackReason.CREATED) {\n      const isStreamNoExistedBefore = !remoteFeed.stream || !remoteFeed.tracks;\n      if (isStreamNoExistedBefore) {\n        remoteFeed.tracks = { [mid]: track };\n        remoteFeed.stream = new MediaStream!([track]);\n      } else {\n        if (remoteFeed.tracks) remoteFeed.tracks[mid] = track;\n        remoteFeed.stream?.addTrack(track);\n      }\n      if (isStreamNoExistedBefore) {\n        this.emitter.emit(JanusEvent.REMOTE_STREAM, remoteFeed.userId, remoteFeed.stream);\n      }\n    } else if (eventType === JanusMediaTrackReason.ENDED) {\n      if (remoteFeed.tracks) delete remoteFeed.tracks[mid];\n      const feedStream = remoteFeed.stream;\n      if (!feedStream) return;\n      const trackToRemove = feedStream\n        .getTracks()\n        .find((streamTrack: MediaStreamTrack) => streamTrack.kind === track.kind);\n      if (trackToRemove) feedStream.removeTrack(trackToRemove);\n    }\n    this.emitter.emit(JanusEvent.REMOTE_TRACKS_UPDATED, remoteFeed.userId, track, eventType);\n  }\n\n  public getPluginId(): string | null {\n    const id = this.videoRoomPlugin?.getId?.();\n    return id != null ? String(id) : null;\n  }\n\n  public detachVideoConferencingPlugin(callbacks: Janus.SuccessErrorCallbacks): void {\n    const clean = () => {\n      this.videoRoomPlugin = null;\n\n      // detach all remote feeds\n      Object.keys(this.remoteFeeds).forEach((userId) => {\n        this.detachRemoteFeed(Number(userId));\n      });\n\n      this.remoteFeeds = {};\n      this.remoteJseps = {};\n      /*\n       * Deprecated\n      this.currentMediaDeviceId = null\n       */\n    };\n\n    this.videoRoomPlugin?.detach?.({\n      success: () => {\n        clean();\n\n        Utils.safeCallbackCall(callbacks.success)();\n      },\n      error: (error: unknown) => {\n        clean();\n\n        Utils.safeCallbackCall(callbacks.error)(error);\n      },\n    });\n  }\n\n  public join(roomId: string, userId: number, isOnlyAudio: boolean, callbacks: Janus.RequestCallbacks): void {\n    const displayName = callbacks.displayName;\n    delete callbacks.displayName;\n\n    this.isOnlyAudio = isOnlyAudio;\n\n    Utils.DLog('isOnlyAudio: ' + this.isOnlyAudio);\n\n    const joinEvent = {\n      request: 'join',\n      room: roomId,\n      ptype: 'publisher',\n      id: userId,\n      display: displayName,\n    };\n\n    this.videoRoomPlugin?.send?.({\n      message: joinEvent,\n      success: (_resp: unknown) => {\n        this.currentRoomId = roomId;\n        this.currentUserId = userId;\n        Utils.safeCallbackCall(callbacks.success)();\n      },\n      error: (error: unknown) => {\n        Utils.safeCallbackCall(callbacks.error)(error);\n      },\n    });\n  }\n\n  public leave(callbacks: Janus.RequestCallbacks): void {\n    Utils.DLog('leave');\n\n    if (!this.engine?.isConnected?.()) {\n      Utils.safeCallbackCall(callbacks.success)();\n      return;\n    }\n\n    const leaveEvent = {\n      request: 'leave',\n      room: this.currentRoomId,\n      id: this.currentUserId,\n    };\n\n    if (this.videoRoomPlugin) {\n      this.videoRoomPlugin?.send?.({ message: leaveEvent });\n    }\n    this.currentRoomId = null;\n    this.currentUserId = null;\n\n    Utils.safeCallbackCall(callbacks.success)();\n  }\n\n  public listOnlineParticipants(roomId: string, callbacks: Janus.SuccessErrorCallbacks): void {\n    const listRequest = { request: 'listparticipants', room: roomId };\n\n    this.videoRoomPlugin?.send?.({\n      message: listRequest,\n      success: (data: { participants?: unknown[] } | null | undefined) => {\n        const participants = data?.participants ?? [];\n        Utils.safeCallbackCall(callbacks.success)(participants);\n      },\n      error: (error: unknown) => {\n        Utils.safeCallbackCall(callbacks.error)(error);\n      },\n    });\n  }\n\n  public toggleAudioMute(): boolean {\n    const muted = this.videoRoomPlugin?.isAudioMuted?.();\n    if (muted) {\n      this.videoRoomPlugin?.unmuteAudio?.();\n    } else {\n      this.videoRoomPlugin?.muteAudio?.();\n    }\n    return this.videoRoomPlugin?.isAudioMuted?.() ?? false;\n  }\n\n  public isAudioMuted(): boolean {\n    try {\n      return this.videoRoomPlugin?.isAudioMuted?.() ?? false;\n    } catch (e) {\n      throw new Error('Unknown audio mute/unmute state. Join the room to manage these settings');\n    }\n  }\n\n  public toggleRemoteAudioMute(userId: number): boolean {\n    const remoteFeed = this.remoteFeeds[userId];\n    if (!remoteFeed) {\n      return false;\n    }\n\n    const audioTracks = remoteFeed.stream?.getAudioTracks?.();\n    if (audioTracks && audioTracks.length > 0) {\n      for (let i = 0; i < audioTracks.length; ++i) {\n        audioTracks[i].enabled = !audioTracks[i].enabled;\n      }\n      return !audioTracks[0].enabled;\n    }\n\n    return false;\n  }\n\n  public isRemoteAudioMuted(userId: number): boolean {\n    const remoteFeed = this.remoteFeeds[userId];\n    if (!remoteFeed) {\n      return false;\n    }\n\n    const audioTracks = remoteFeed.stream?.getAudioTracks?.();\n    if (audioTracks && audioTracks.length > 0) {\n      return !audioTracks[0].enabled;\n    }\n\n    return false;\n  }\n\n  public toggleVideoMute(): boolean {\n    const muted = this.videoRoomPlugin?.isVideoMuted?.();\n    if (muted) {\n      this.videoRoomPlugin?.unmuteVideo?.();\n    } else {\n      this.videoRoomPlugin?.muteVideo?.();\n    }\n    return this.videoRoomPlugin?.isVideoMuted?.() || false;\n  }\n\n  public isVideoMuted(): boolean {\n    try {\n      return this.videoRoomPlugin?.isVideoMuted?.() || false;\n    } catch (e) {\n      throw new Error('Unknown video mute/unmute state. Join the room to manage these settings');\n    }\n  }\n\n  public toggleRemoteVideoMute(userId: number): boolean {\n    const remoteFeed = this.remoteFeeds[userId];\n    if (!remoteFeed) {\n      return false;\n    }\n\n    const videoTracks = remoteFeed.stream?.getVideoTracks?.();\n    if (videoTracks && videoTracks.length > 0) {\n      for (let i = 0; i < videoTracks.length; ++i) {\n        videoTracks[i].enabled = !videoTracks[i].enabled;\n      }\n      return !videoTracks[0].enabled;\n    }\n\n    return false;\n  }\n\n  public isRemoteVideoMuted(userId: number): boolean {\n    const remoteFeed = this.remoteFeeds[userId];\n    if (!remoteFeed) {\n      return false;\n    }\n\n    const videoTracks = remoteFeed.stream?.getVideoTracks?.();\n    if (videoTracks && videoTracks.length > 0) {\n      return !videoTracks[0].enabled;\n    }\n\n    return false;\n  }\n\n  public sendKeyframeRequest(roomId: string, callbacks: Janus.SuccessErrorCallbacks): void {\n    const configureRequest = {\n      request: 'configure',\n      room: roomId,\n      keyframe: true,\n    };\n\n    this.videoRoomPlugin?.send?.({\n      message: configureRequest,\n      success: (response: unknown) => {\n        Utils.safeCallbackCall(callbacks.success)(response);\n      },\n      error: (error: unknown) => {\n        Utils.safeCallbackCall(callbacks.error)(error);\n      },\n    });\n  }\n\n  public getTracksFromStream(stream: MediaStream): { type: string; capture: MediaStreamTrack; recv: boolean }[] {\n    const tracks: { type: string; capture: MediaStreamTrack; recv: boolean }[] = [];\n\n    const audioTracks = stream.getAudioTracks();\n    if (audioTracks.length) {\n      const audioTrack = audioTracks[0];\n      tracks.push({ type: 'audio', capture: audioTrack, recv: false });\n    }\n\n    const videoTracks = stream.getVideoTracks();\n    if (videoTracks.length) {\n      const videoTrack = videoTracks[0];\n      tracks.push({ type: 'video', capture: videoTrack, recv: false });\n    }\n\n    return tracks;\n  }\n\n  public createOffer(\n    mediaParams: { stream?: MediaStream; media: { audio: boolean; video: boolean }; replace?: boolean },\n    callbacks: Janus.SuccessErrorCallbacks\n  ): void {\n    Utils.DLog('[JanusWrapper][createOffer]', mediaParams);\n\n    const { stream: existedStream, media, replace } = mediaParams;\n\n    const createOfferParams: Janus.CreateOfferParams = { tracks: [{ type: 'data' }] };\n\n    if (existedStream) {\n      const tracksFromStream = this.getTracksFromStream(existedStream);\n      createOfferParams.tracks = createOfferParams.tracks.concat(tracksFromStream);\n    } else if (media) {\n      const tracksFromParams: { type: string; capture: boolean; recv: boolean; replace: boolean }[] = [];\n      if (media.audio) {\n        tracksFromParams.push({\n          type: 'audio',\n          capture: media.audio,\n          recv: false,\n          replace: !!replace,\n        });\n      }\n      if (media.video) {\n        tracksFromParams.push({\n          type: 'video',\n          capture: media.video,\n          recv: false,\n          replace: !!replace,\n        });\n      }\n      createOfferParams.tracks = createOfferParams.tracks.concat(tracksFromParams);\n    } else {\n      createOfferParams.tracks = createOfferParams.tracks.concat([\n        { type: 'audio', capture: true, recv: false, replace: !!replace },\n        { type: 'video', capture: true, recv: false, replace: !!replace },\n      ]);\n    }\n\n    Utils.DLog('[JanusWrapper][createOffer][params]', createOfferParams);\n\n    createOfferParams.customizeSdp = (_jsep: unknown) => {};\n\n    createOfferParams.success = (jsep: unknown) => {\n      const publish = {\n        request: 'configure',\n        audio: !!media.audio,\n        video: !!media.video,\n      };\n      Utils.DLog('[JanusWrapper][createOffer][success]', publish);\n\n      this.videoRoomPlugin?.send?.({ message: publish, jsep: jsep });\n\n      Utils.safeCallbackCall(callbacks.success)();\n    };\n\n    createOfferParams.error = (error: unknown) => {\n      Utils.DLog('[JanusWrapper][createOffer][error]', error);\n      if (media.audio) {\n        this.createOffer({ media: { video: false, audio: false } }, callbacks);\n      } else {\n        Utils.safeCallbackCall(callbacks.error)(error);\n      }\n    };\n\n    this.videoRoomPlugin?.createOffer?.(createOfferParams);\n  }\n\n  public getTracksMidsFromStream(stream: MediaStream): { type: string; mid: string; recv: boolean }[] {\n    const tracks: { type: string; mid: string; recv: boolean }[] = [];\n\n    const audioTracks = stream.getAudioTracks();\n    if (audioTracks.length) {\n      const audioTrack = audioTracks[0];\n      tracks.push({ type: 'audio', mid: audioTrack.id, recv: true });\n    }\n\n    const videoTracks = stream.getVideoTracks();\n    if (videoTracks.length) {\n      const videoTrack = videoTracks[0];\n      tracks.push({ type: 'video', mid: videoTrack.id, recv: true });\n    }\n\n    return tracks;\n  }\n\n  public createAnswer(\n    { remoteFeed, jsep }: { remoteFeed: Janus.RemoteFeed; jsep: unknown },\n    existedStream: MediaStream,\n    callbacks: Janus.SuccessErrorCallbacks\n  ): void {\n    Utils.DLog('[JanusWrapper][createAnswer]', jsep, existedStream);\n    let tracks: Array<{ type: string; mid?: string; recv?: boolean }> = [{ type: 'data' }];\n\n    if (existedStream) {\n      const tracksFromStream = this.getTracksMidsFromStream(existedStream);\n      tracks = tracks.concat(tracksFromStream);\n    }\n\n    Utils.DLog('[JanusWrapper][createAnswer][tracks]', tracks);\n\n    remoteFeed.createAnswer({\n      jsep: jsep,\n      tracks: tracks,\n      success: (jsep: unknown) => {\n        const body = { request: 'start', room: this.currentRoomId };\n        Utils.DLog('[JanusWrapper][createAnswer][success]', body);\n\n        remoteFeed.send({ message: body, jsep: jsep });\n\n        Utils.safeCallbackCall(callbacks.success)();\n      },\n      error: (error: unknown) => {\n        Utils.DLog('[JanusWrapper][createAnswer][error]', error);\n        Utils.safeCallbackCall(callbacks.error)(error);\n      },\n    });\n  }\n\n  public detachRemoteFeed(userId: number): boolean {\n    const remoteFeed = this.remoteFeeds[userId];\n    if (remoteFeed) {\n      remoteFeed.detach();\n      this.remoteFeeds[userId] = null;\n      this.remoteJseps[userId] = null;\n      return true;\n    }\n    return false;\n  }\n\n  public getUserBitrate(userId: number): unknown {\n    const remoteFeed = this.remoteFeeds[userId];\n    return remoteFeed?.getBitrate?.();\n  }\n\n  public getVolume(resultCallback: (value: unknown) => void): void {\n    this.videoRoomPlugin?.getLocalVolume?.(null, resultCallback);\n  }\n\n  public getUserVolume(userId: number, resultCallback: (value: unknown) => void): void {\n    const remoteFeed = this.remoteFeeds[userId];\n    return remoteFeed?.getRemoteVolume?.(null, resultCallback);\n  }\n\n  public showBitrate(userId: number, element: Janus.BitrateDisplayElement): void {\n    const remoteFeed = this.remoteFeeds[userId];\n    const adapterDetails = (adapter as { browserDetails?: { browser?: string } })?.browserDetails;\n\n    if (!Utils.env.isReactNative && (adapterDetails?.browser === 'chrome' || adapterDetails?.browser === 'firefox')) {\n      this.bitrateTimers[userId] = setInterval(() => {\n        const bitrate = remoteFeed?.getBitrate?.();\n        if (bitrate != null) element.text?.(bitrate);\n      }, 1000);\n    }\n  }\n\n  public hideBitrate(userId: number, element: Janus.BitrateDisplayElement): void {\n    if (this.bitrateTimers[userId]) {\n      clearInterval(this.bitrateTimers[userId]);\n    }\n    this.bitrateTimers[userId] = null;\n    element.text = null;\n  }\n\n  public on(eventType: JanusEvent, listener: VoidCallback): EventEmitter {\n    return this.emitter.addListener(eventType, listener);\n  }\n\n  public removeAllListeners(eventType?: JanusEvent): EventEmitter {\n    return this.emitter.removeAllListeners(eventType);\n  }\n}\n","import type { Auth, Janus, Media } from '../types';\nimport { JanusCallType, JanusEvent } from '../types/constants';\nimport { mediaDevices } from '@platform';\nimport Utils from '../Utils';\nimport JanusClient from './JanusClient';\n\nexport default class ConferenceSession {\n  private client: JanusClient;\n  public id: string = `${Math.random()}`;\n  public currentUserDisplayName?: string;\n  public localStream?: MediaStream;\n  public mediaParams: MediaStreamConstraints = {};\n  declare onParticipantJoinedListener: Janus.OnParticipantJoinedListener;\n  declare onParticipantLeftListener: Janus.OnParticipantLeftListener;\n  declare onSlowLinkListener: Janus.OnSlowLinkListener;\n  declare onRemoteStreamListener: Janus.OnRemoteStreamListener;\n  declare onRemoteTracksUpdatedListener: Janus.OnRemoteTracksUpdatedListener;\n  declare onRemoteConnectionStateChangedListener: Janus.OnRemoteConnectionStateChangedListener;\n  declare onDataChannelOpenedListener: Janus.OnDataChannelOpenedListener;\n  declare onDataChannelMessageListener: Janus.OnDataChannelMessageListener;\n  declare onSessionConnectionStateChangedListener: Janus.OnSessionConnectionStateChangedListener;\n  declare onErrorListener: Janus.OnErrorListener;\n\n  constructor(token: Auth.Session['token']) {\n    this.client = new JanusClient(token);\n    this.client.on(JanusEvent.PARTICIPANT_JOINED, this.onParticipantJoined);\n    this.client.on(JanusEvent.PARTICIPANT_LEFT, this.onParticipantLeft);\n    this.client.on(JanusEvent.REMOTE_STREAM, this.onRemoteStream);\n    this.client.on(JanusEvent.REMOTE_TRACKS_UPDATED, this.onRemoteTracksUpdated);\n    this.client.on(JanusEvent.DATA_CHANNEL_OPEN, this.onDataChannelOpen);\n    this.client.on(JanusEvent.DATA_CHANNEL_MESSAGE, this.onDataChannelMessage);\n    this.client.on(JanusEvent.ERROR, this.onError);\n  }\n\n  get currentRoomId(): string | null {\n    return this.client.currentRoomId;\n  }\n\n  set currentRoomId(roomId: string | null) {\n    this.client.currentRoomId = roomId;\n  }\n\n  get currentPublisherPC() {\n    return this.client?.videoRoomPlugin?.webrtcStuff?.pc ?? null;\n  }\n\n  private async createSession(): Promise<void> {\n    let isResolved = false;\n\n    return new Promise((resolve, reject) => {\n      this.client.createSession({\n        success: () => {\n          isResolved = true;\n          resolve(void 0);\n        },\n        error: (error) => {\n          if (isResolved) {\n            this.onError(error);\n          } else {\n            reject(error);\n          }\n        },\n      });\n    });\n  }\n\n  // joinAsPublisher+Listener\n  public async join(roomId: string, user_id: number, userDisplayName: string): Promise<void> {\n    this.currentUserDisplayName = userDisplayName;\n    this.currentRoomId = roomId;\n    await this.createSession();\n    await this.createHandler(user_id, false, false);\n    await this.joinInternal(this.currentRoomId, user_id);\n  }\n\n  public async joinAsListener(roomId: string, user_id: number, userDisplayName: string): Promise<void> {\n    this.currentUserDisplayName = userDisplayName;\n    this.currentRoomId = roomId;\n    await this.createSession();\n    await this.createHandler(user_id, false, true);\n    await this.joinInternal(this.currentRoomId, user_id);\n  }\n\n  public async sendKeyframeRequest(roomId: string): Promise<unknown> {\n    return new Promise((resolve, reject) => {\n      this.client.sendKeyframeRequest(roomId, {\n        success: resolve,\n        error: reject,\n      });\n    });\n  }\n\n  private async createHandler(user_id: number, isRemote: boolean, skipMedia: boolean = false): Promise<void> {\n    return new Promise((resolve, reject) => {\n      this.client.attachVideoConferencingPlugin(isRemote, user_id, skipMedia, {\n        success: resolve,\n        error: reject,\n        iceState: isRemote\n          ? (iceState) => this.onRemoteIceStateChanged(user_id, iceState)\n          : (iceState) => this.onLocalIceStateChanged(iceState),\n        slowLink: isRemote\n          ? (uplink, nacks) => this.onSlowLink(user_id, uplink, nacks)\n          : (uplink, nacks) => this.onSlowLink(null, uplink, nacks),\n        localStream: this.localStream,\n        displayName: this.currentUserDisplayName,\n      });\n    });\n  }\n\n  private async joinInternal(roomId: string, user_id: number): Promise<void> {\n    return new Promise((resolve, reject) => {\n      this.client.join(roomId, user_id, false, {\n        success: resolve,\n        error: reject,\n        displayName: this.currentUserDisplayName,\n      });\n    });\n  }\n\n  private onParticipantJoined = (user_id: number, userDisplayName: string, isExistingParticipant: boolean): void => {\n    Utils.DLog('[onParticipantJoined]', user_id, userDisplayName, isExistingParticipant);\n    this.createHandler(user_id, true, false);\n    Utils.safeCallbackCall(this.onParticipantJoinedListener)(this, user_id, userDisplayName, isExistingParticipant);\n  };\n\n  private onParticipantLeft = (user_id: number, userDisplayName: string): void => {\n    Utils.DLog('[onParticipantLeft]', user_id, userDisplayName);\n    Utils.safeCallbackCall(this.onParticipantLeftListener)(this, user_id, userDisplayName);\n  };\n\n  private onError = (error: unknown): void => {\n    Utils.DLog('[onError]', JSON.stringify(error));\n    Utils.safeCallbackCall(this.onErrorListener)(this, error);\n  };\n\n  private onDataChannelOpen = (label: unknown): void => {\n    Utils.DLog('[onDataChannelOpen]', label);\n    Utils.safeCallbackCall(this.onDataChannelOpenedListener)(this, label);\n  };\n\n  private onDataChannelMessage = (user_id: number, data: unknown): void => {\n    Utils.DLog('[onDataChannelMessage]', user_id, data);\n    Utils.safeCallbackCall(this.onDataChannelMessageListener)(this, user_id, data);\n  };\n\n  private onLocalIceStateChanged = (iceState: unknown): void => {\n    Utils.DLog('[onLocalIceStateChanged]', iceState);\n    Utils.safeCallbackCall(this.onSessionConnectionStateChangedListener)(this, iceState);\n  };\n\n  private onRemoteIceStateChanged = (user_id: number, iceState: unknown): void => {\n    Utils.DLog('[onRemoteIceStateChanged]', user_id, iceState);\n    Utils.safeCallbackCall(this.onRemoteConnectionStateChangedListener)(this, user_id, iceState);\n  };\n\n  private onRemoteStream = (user_id: number, stream: MediaStream): void => {\n    Utils.DLog('[onRemoteStream]', user_id, stream);\n    Utils.safeCallbackCall(this.onRemoteStreamListener)(this, user_id, stream);\n  };\n\n  private onRemoteTracksUpdated = (user_id: number, track: MediaStreamTrack, eventType: unknown): void => {\n    Utils.DLog('[onRemoteTracksUpdated]', user_id, track, eventType);\n    Utils.safeCallbackCall(this.onRemoteTracksUpdatedListener)(this, user_id, track, eventType);\n  };\n\n  private onSlowLink = (user_id: number | null, uplink: unknown, nacks: unknown): void => {\n    Utils.DLog('[onSlowLink]', user_id, uplink, nacks);\n    Utils.safeCallbackCall(this.onSlowLinkListener)(this, user_id, uplink, nacks);\n  };\n\n  public async listOfOnlineParticipants(): Promise<unknown> {\n    return new Promise((resolve, reject) => {\n      if (this.currentRoomId) {\n        this.client.listOnlineParticipants(this.currentRoomId, {\n          success: resolve,\n          error: reject,\n        });\n      } else {\n        reject('Room ID is not set');\n      }\n    });\n  }\n\n  public async leave(): Promise<void> {\n    this.currentRoomId = null;\n    this.currentUserDisplayName = undefined;\n    await this.leaveGroup();\n    await this.detachVideoConferencingPlugin();\n    await this.destroy();\n\n    if (this.localStream) {\n      this.localStream.getTracks().forEach((track) => track.stop());\n      this.localStream = undefined;\n      this.mediaParams = {};\n    }\n  }\n\n  public async leaveGroup(): Promise<void> {\n    return new Promise((resolve, reject) => {\n      this.client.leave({\n        success: resolve,\n        error: reject,\n      });\n    });\n  }\n\n  public async destroy(): Promise<void> {\n    return new Promise((resolve, reject) => {\n      this.client.destroySession({\n        success: resolve,\n        error: reject,\n      });\n    });\n  }\n\n  public async detachVideoConferencingPlugin(): Promise<void> {\n    return new Promise((resolve, reject) => {\n      this.client.detachVideoConferencingPlugin({\n        success: resolve,\n        error: reject,\n      });\n    });\n  }\n\n  public async getDisplayMedia(params: Media.DisplayParams): Promise<MediaStream> {\n    if (!mediaDevices?.getDisplayMedia) {\n      throw new Error(\"Your environment does not support 'getDisplayMedia' API\");\n    }\n\n    const elementId = params && params.elementId;\n    const options = params && params.options;\n    const mediaParams = { ...params };\n\n    this.mediaParams = mediaParams;\n    delete mediaParams.elementId;\n    delete mediaParams.options;\n\n    try {\n      const stream = await mediaDevices!.getDisplayMedia(mediaParams);\n      return this.upsertStream(stream, elementId, options);\n    } catch (error) {\n      throw error;\n    }\n  }\n\n  public async getUserMedia(params: Media.UserParams): Promise<MediaStream> {\n    if (!mediaDevices?.getUserMedia) {\n      throw new Error(\"Your environment does not support 'getUserMedia' API\");\n    }\n\n    const elementId = params && params.elementId;\n    const options = params && params.options;\n    const mediaParams = { ...params };\n\n    this.mediaParams = mediaParams;\n    delete mediaParams.elementId;\n    delete mediaParams.options;\n\n    try {\n      const stream = await mediaDevices!.getUserMedia(mediaParams);\n      return this.upsertStream(stream, elementId, options);\n    } catch (error) {\n      throw error;\n    }\n  }\n\n  private upsertStream(\n    stream: MediaStream,\n    elementId: string | null = null,\n    options: Media.ElementOptions = {}\n  ): MediaStream {\n    const shouldUpdateCurrentStream = !!this.localStream;\n\n    if (shouldUpdateCurrentStream) {\n      this.replaceTracks(stream);\n    } else {\n      this.localStream = stream;\n    }\n\n    if (!this.localStream) {\n      throw new Error('Local stream is not defined');\n    }\n\n    if (elementId) {\n      if (shouldUpdateCurrentStream) {\n        this.detachMediaStream(elementId, options);\n      }\n      this.attachMediaStream(elementId, this.localStream, options);\n    }\n\n    this.localStream.getTracks().forEach((track) => {\n      const type = track.kind as 'audio' | 'video';\n      const deviceId = track.getSettings().deviceId;\n\n      if (deviceId) {\n        if (typeof this.mediaParams[type] === 'object') {\n          this.mediaParams[type].deviceId = deviceId;\n        } else {\n          this.mediaParams[type] = { deviceId };\n        }\n      }\n    });\n\n    return this.localStream;\n  }\n\n  private replaceTracks(stream: MediaStream): MediaStream {\n    this.localStream?.getTracks().forEach((localTrack) => {\n      if (localTrack.kind === JanusCallType.AUDIO && stream.getAudioTracks().length === 0) {\n        return;\n      } else {\n        localTrack.stop();\n        this.localStream?.removeTrack(localTrack);\n      }\n    });\n\n    stream.getTracks().forEach((newTrack: MediaStreamTrack) => {\n      const pcSenders = this.currentPublisherPC?.getSenders?.();\n      const sender = pcSenders?.find(({ track }: RTCRtpSender) => newTrack.kind === track?.kind);\n\n      if (newTrack.kind === JanusCallType.AUDIO) {\n        newTrack.enabled = this.localStream?.getAudioTracks().every(({ enabled }) => enabled) ?? true;\n      } else {\n        newTrack.enabled = this.localStream?.getVideoTracks().every(({ enabled }) => enabled) ?? true;\n      }\n\n      if (sender) {\n        sender.replaceTrack(newTrack);\n        this.localStream?.addTrack(newTrack);\n      } else {\n        console.warn(`No sender found for track kind: ${newTrack.kind}`);\n      }\n    });\n\n    if (!this.localStream) {\n      throw new Error('Local stream is not defined');\n    }\n\n    return this.localStream;\n  }\n\n  public async switchMediaTracks(options: Media.TrackConstraintsOrDeviceIds): Promise<MediaStream> {\n    [JanusCallType.AUDIO, JanusCallType.VIDEO].forEach((type) => {\n      const device = type === JanusCallType.AUDIO ? options.audio : type === JanusCallType.VIDEO ? options.video : {};\n      const deviceId = typeof device === 'string' ? device : (device?.deviceId ?? null);\n\n      if (deviceId) {\n        if (typeof this.mediaParams[type] === 'object') {\n          this.mediaParams[type].deviceId = deviceId;\n        } else {\n          this.mediaParams[type] = { deviceId };\n        }\n      }\n    });\n\n    try {\n      const mediaParams = {\n        audio: this.mediaParams?.audio ?? false,\n        video: this.mediaParams?.video ?? false,\n      };\n      const stream = await mediaDevices!.getUserMedia(mediaParams);\n      return this.replaceTracks(stream);\n    } catch (error) {\n      throw error;\n    }\n  }\n\n  public muteVideo(): void {\n    if (!this.isVideoMuted()) {\n      this.client.toggleVideoMute();\n    }\n  }\n\n  public unmuteVideo(): void {\n    if (this.isVideoMuted()) {\n      this.client.toggleVideoMute();\n    }\n  }\n\n  public muteAudio(): void {\n    if (!this.isAudioMuted()) {\n      this.client.toggleAudioMute();\n    }\n  }\n\n  public unmuteAudio(): void {\n    if (this.isAudioMuted()) {\n      this.client.toggleAudioMute();\n    }\n  }\n\n  public isVideoMuted(): boolean {\n    return this.client.isVideoMuted();\n  }\n\n  public isAudioMuted(): boolean {\n    return this.client.isAudioMuted();\n  }\n\n  public async getUserVolume(): Promise<unknown> {\n    return new Promise((resolve, _reject) => {\n      return this.client.getVolume(resolve);\n    });\n  }\n\n  public getRemoteUserBitrate(userId: number): unknown {\n    return this.client.getUserBitrate(userId);\n  }\n\n  public async getRemoteUserVolume(userId: number): Promise<unknown> {\n    return new Promise((resolve) => {\n      return this.client.getUserVolume(userId, resolve);\n    });\n  }\n\n  public attachMediaStream(elementId: string, stream: MediaStream, opt?: Media.ElementOptions): void {\n    const mediaElement = document.getElementById(elementId) as HTMLMediaElement;\n\n    if ('srcObject' in mediaElement) {\n      mediaElement.srcObject = stream;\n      mediaElement.style.transform = opt?.mirror ? 'scaleX(-1)' : 'none';\n      if (typeof opt?.muted === 'boolean') {\n        mediaElement.muted = opt?.muted;\n      }\n      mediaElement.onloadedmetadata = async (_event: Event) => {\n        try {\n          await mediaElement.play();\n        } catch (error) {\n          console.error('[VideoChatConference]:', error);\n        }\n      };\n    } else {\n      throw new Error(`Unable to attach media stream, element #${elementId} is undefined`);\n    }\n  }\n\n  public detachMediaStream(elementId: string, opt?: Media.ElementOptions) {\n    const mediaElement = document.getElementById(elementId) as HTMLMediaElement;\n\n    if ('srcObject' in mediaElement) {\n      mediaElement.pause();\n      mediaElement.srcObject = null;\n      mediaElement.style.transform = opt?.mirror ? 'scaleX(-1)' : 'none';\n      if (typeof opt?.muted === 'boolean') {\n        mediaElement.muted = opt?.muted;\n      }\n    } else {\n      throw new Error(`Unable to attach media stream, element #${elementId} is undefined`);\n    }\n  }\n\n  public async sendData(data: unknown, label: unknown): Promise<unknown> {\n    return new Promise((resolve, reject) => {\n      if (!this.client.videoRoomPlugin?.data) {\n        reject(new Error('Video room plugin or data channel is not available'));\n        return;\n      }\n\n      this.client.videoRoomPlugin.data({\n        data,\n        label,\n        success: resolve,\n        error: reject,\n      });\n    });\n  }\n}\n","import type { Janus } from '../types';\nimport { JanusCallType, ConferenceEvent, DeviceInputType } from '../types/constants';\nimport { mediaDevices } from '@platform';\nimport ConferenceSession from './ConferenceSession';\nimport ProxyService from '../Proxy';\n\nexport default class ConferenceClient {\n  public proxy: ProxyService;\n  public DeviceInputType: typeof DeviceInputType = DeviceInputType;\n  public JanusCallType: typeof JanusCallType = JanusCallType;\n  public sessionsStore: { [id: ConferenceSession['id']]: ConferenceSession } = {};\n  declare onParticipantJoinedListener: Janus.OnParticipantJoinedListener;\n  declare onParticipantLeftListener: Janus.OnParticipantLeftListener;\n  declare onSlowLinkListener: Janus.OnSlowLinkListener;\n  declare onRemoteStreamListener: Janus.OnRemoteStreamListener;\n  declare onRemoteTracksUpdatedListener: Janus.OnRemoteTracksUpdatedListener;\n  declare onRemoteConnectionStateChangedListener: Janus.OnRemoteConnectionStateChangedListener;\n  declare onDataChannelOpenedListener: Janus.OnDataChannelOpenedListener;\n  declare onDataChannelMessageListener: Janus.OnDataChannelMessageListener;\n  declare onSessionConnectionStateChangedListener: Janus.OnSessionConnectionStateChangedListener;\n  declare onErrorListener: Janus.OnErrorListener;\n\n  constructor(proxy: ProxyService) {\n    this.proxy = proxy;\n  }\n\n  createNewSession() {\n    const session = new ConferenceSession(this.getCurrentSessionToken());\n\n    this.sessionsStore[session.id] = session;\n    session.onParticipantJoinedListener = this.onParticipantJoinedListener;\n    session.onParticipantLeftListener = this.onParticipantLeftListener;\n    session.onSlowLinkListener = this.onSlowLinkListener;\n    session.onRemoteStreamListener = this.onRemoteStreamListener;\n    session.onRemoteTracksUpdatedListener = this.onRemoteTracksUpdatedListener;\n    session.onRemoteConnectionStateChangedListener = this.onRemoteConnectionStateChangedListener;\n    session.onDataChannelOpenedListener = this.onDataChannelOpenedListener;\n    session.onDataChannelMessageListener = this.onDataChannelMessageListener;\n    session.onSessionConnectionStateChangedListener = this.onSessionConnectionStateChangedListener;\n    session.onErrorListener = this.onErrorListener;\n\n    return session;\n  }\n\n  public async getMediaDevices(kind?: DeviceInputType): Promise<MediaDeviceInfo[]> {\n    if (mediaDevices?.enumerateDevices) {\n      const devices = await mediaDevices.enumerateDevices();\n      return kind ? devices.filter((device) => device.kind === kind) : devices;\n    } else {\n      throw new Error(\"No 'enumerateDevices' API supported\");\n    }\n  }\n\n  public clearSession(session_id: ConferenceSession['id']): void {\n    delete this.sessionsStore[session_id];\n  }\n\n  public getCurrentSessionToken(): string {\n    const currentSession = this.proxy.getSession();\n\n    if (currentSession?.token) {\n      return currentSession.token;\n    } else {\n      throw new Error('Session does not exist');\n    }\n  }\n\n  private getListenerByName(name: ConferenceEvent): Janus.ListenerName | null {\n    switch (name) {\n      case ConferenceEvent.JOIN:\n        return 'onParticipantJoinedListener';\n      case ConferenceEvent.LEFT:\n        return 'onParticipantLeftListener';\n      case ConferenceEvent.SLOW_LINK:\n        return 'onSlowLinkListener';\n      case ConferenceEvent.REMOTE_STREAM:\n        return 'onRemoteStreamListener';\n      case ConferenceEvent.REMOTE_TRACKS_UPDATED:\n        return 'onRemoteTracksUpdatedListener';\n      case ConferenceEvent.REMOTE_CONNECTION_STATE:\n        return 'onRemoteConnectionStateChangedListener';\n      case ConferenceEvent.DATA_CHANNEL_OPENED:\n        return 'onDataChannelOpenedListener';\n      case ConferenceEvent.DATA_CHANNEL_MESSAGE:\n        return 'onDataChannelMessageListener';\n      case ConferenceEvent.SESSION_CONNECTION_STATE:\n        return 'onSessionConnectionStateChangedListener';\n      case ConferenceEvent.ERROR:\n        return 'onErrorListener';\n      default:\n        return null;\n    }\n  }\n\n  public addListener(name: ConferenceEvent, listener: Janus.Listeners): () => void {\n    const listenerName = this.getListenerByName(name);\n    if (listenerName) {\n      (this[listenerName] as Janus.Listeners) = listener;\n    }\n    return this.removeListener.bind(this, name);\n  }\n\n  public removeListener(name: ConferenceEvent): void {\n    const listenerName = this.getListenerByName(name);\n    if (listenerName) {\n      (this[listenerName] as Janus.Listeners | undefined) = undefined;\n    }\n  }\n\n  public removeAllListeners(): void {\n    Object.keys(this).forEach((key) => {\n      if (key.startsWith('on') && key.endsWith('Listener') && typeof this[key as Janus.ListenerName] === 'function') {\n        (this[key as Janus.ListenerName] as Janus.Listeners | undefined) = undefined;\n      }\n    });\n  }\n}\n","import type { Data, EmptyResponse, SearchCondition } from './types';\nimport { ProxyMethod, ProxyType } from './types/constants';\nimport ProxyService from './Proxy';\nimport Utils from './Utils';\nimport config from './config';\n\nexport default class DataService {\n  public proxy: ProxyService;\n  readonly route = config.urls.data;\n\n  constructor(proxy: ProxyService) {\n    this.proxy = proxy;\n  }\n\n  public async create(className: string, params: Data.CreateParams = {}): Promise<Data.DataRecord> {\n    const isMany = Utils.isArray(params);\n    const multi = isMany ? 'multi' : undefined;\n    const ajaxParams = {\n      type: ProxyMethod.POST,\n      url: Utils.getUrl(this.route, className, multi),\n      data: isMany ? { record: this.createRecord(params) } : params,\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async list(className: string, params: Data.ListParams = {}): Promise<Data.ListResponse> {\n    const ext = typeof params === 'string' ? params : Utils.isArray(params) ? params.toString() : undefined;\n    const ajaxParams = {\n      url: Utils.getUrl(this.route, className, ext),\n      data: ext ? undefined : params,\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async readPermissions(className: string, id: string): Promise<Data.ReadPermissionsResponse> {\n    const ajaxParams = {\n      url: Utils.getUrl(this.route, className, id),\n      data: { permissions: 1 },\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async update(\n    className: string,\n    params: Data.UpdateOptions | Data.UpdateOptions[] = {}\n  ): Promise<Data.UpdateResponse | Data.DataRecord> {\n    const isMany = Utils.isArray(params);\n    const isSearch = !isMany && params.search_criteria;\n    const ext = isMany ? 'multi' : isSearch ? 'by_criteria' : params.id || params._id || '';\n    const ajaxParams = {\n      type: ProxyMethod.PUT,\n      url: Utils.getUrl(this.route, className, ext),\n      data: isMany ? { record: this.createRecord(params) } : params,\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async delete(\n    className: string,\n    params: string | string[] | SearchCondition<string | number | undefined>\n  ): Promise<Data.DeleteResponse | EmptyResponse> {\n    const isCriteria = Utils.isObject(params);\n    const isOne = typeof params === 'string' || (Utils.isArray(params) && params.length === 1);\n    const ext = isCriteria ? 'by_criteria' : typeof params === 'string' ? params : (params?.toString() ?? '');\n    const ajaxParams = {\n      type: ProxyMethod.DELETE,\n      url: Utils.getUrl(this.route, className, ext),\n      data: isCriteria ? params : undefined,\n      dataType: isOne ? ProxyType.TEXT : undefined,\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  private createRecord(params: Data.CreateRecord[] = []): object {\n    return params.reduce((items, item, index) => {\n      const key = index + 1;\n      const id = item.id || item._id;\n      const record = id ? { ...item, id } : item;\n\n      return { ...items, [key]: record };\n    }, {});\n  }\n}\n","import type { EmptyResponse, Meetings } from './types';\nimport { ProxyMethod, ProxyType } from './types/constants';\nimport ProxyService from './Proxy';\nimport Utils from './Utils';\nimport config from './config';\n\nexport default class MeetingsService {\n  public proxy: ProxyService;\n  readonly route = config.urls.meetings;\n\n  constructor(proxy: ProxyService) {\n    this.proxy = proxy;\n  }\n\n  public async get(params: Meetings.GetParams = {}): Promise<Meetings.Meeting | Meetings.Meeting[]> {\n    const ajaxParams = {\n      type: ProxyMethod.GET,\n      url: Utils.getUrl(this.route),\n      data: params,\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async create(params: Meetings.CreateParams = {}): Promise<Meetings.Meeting> {\n    const MINUTE = 60;\n    const startTimestamp = Math.ceil(Date.now() / 1000);\n    const endTimestamp = startTimestamp + 60 * MINUTE;\n    const defaultName = new Date(startTimestamp).toLocaleString('en', {\n      year: 'numeric',\n      month: 'long',\n      day: 'numeric',\n      hour: 'numeric',\n      minute: 'numeric',\n    });\n    const defaultParams = {\n      name: defaultName,\n      start_date: startTimestamp,\n      end_date: endTimestamp,\n      attendees: [],\n      record: false,\n      chat: false,\n    };\n    const ajaxParams = {\n      type: ProxyMethod.POST,\n      url: Utils.getUrl(this.route),\n      data: { ...defaultParams, ...params },\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async update(id: string | number, params: Meetings.MeetingParams): Promise<Meetings.Meeting> {\n    const ajaxParams = {\n      type: ProxyMethod.PUT,\n      url: Utils.getUrl(this.route, id),\n      data: params,\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async delete(id: string | number): Promise<EmptyResponse> {\n    const ajaxParams = {\n      type: ProxyMethod.DELETE,\n      url: Utils.getUrl(this.route, id),\n      dataType: ProxyType.TEXT,\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async getRecordings(id: string | number): Promise<Meetings.Recording[]> {\n    const ajaxParams = {\n      type: ProxyMethod.GET,\n      url: Utils.getUrl(this.route, 'recordings', id),\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n}\n","import type { EmptyResponse, PushNotifications } from './types';\nimport { encode } from 'js-base64';\nimport { ProxyMethod, ProxyType } from './types/constants';\nimport config from './config';\nimport ProxyService from './Proxy';\nimport Utils from './Utils';\n\nexport default class PushNotificationsService {\n  public proxy: ProxyService;\n  public subscriptions: SubscriptionsService;\n  public events: EventsService;\n\n  constructor(proxy: ProxyService) {\n    this.proxy = proxy;\n    this.subscriptions = new SubscriptionsService(proxy);\n    this.events = new EventsService(proxy);\n  }\n\n  public base64Encode = encode;\n}\n\nclass SubscriptionsService {\n  public proxy: ProxyService;\n  readonly route = config.urls.subscriptions;\n\n  constructor(proxy: ProxyService) {\n    this.proxy = proxy;\n  }\n\n  public async create(params: PushNotifications.SubscriptionsCreateParams): Promise<PushNotifications.Subscription> {\n    const ajaxParams = {\n      type: ProxyMethod.POST,\n      url: Utils.getUrl(this.route),\n      data: params,\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async list(): Promise<PushNotifications.Subscription[]> {\n    const ajaxParams = {\n      type: ProxyMethod.GET,\n      url: Utils.getUrl(this.route),\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async delete(id: string | number): Promise<EmptyResponse> {\n    const ajaxParams = {\n      type: ProxyMethod.DELETE,\n      dataType: ProxyType.TEXT,\n      url: Utils.getUrl(this.route, id),\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n}\n\nclass EventsService {\n  public proxy: ProxyService;\n  readonly route = config.urls.events;\n\n  constructor(proxy: ProxyService) {\n    this.proxy = proxy;\n  }\n\n  public async create(event: PushNotifications.EventsCreateParams): Promise<PushNotifications.Event[]> {\n    const ajaxParams = {\n      type: ProxyMethod.POST,\n      url: Utils.getUrl(this.route),\n      data: { event },\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n}\n","import type { EmptyResponse, PlainObject, Proxy, Storage, StringObject, StringOrStringObject } from './types';\nimport { ProxyMethod, ProxyType } from './types/constants';\nimport ProxyService from './Proxy';\nimport Utils from './Utils';\nimport config from './config';\n\nexport default class StorageService {\n  public proxy: ProxyService;\n  readonly route = config.urls.blobs;\n\n  constructor(proxy: ProxyService) {\n    this.proxy = proxy;\n  }\n\n  public async list(params: Storage.ListParams = {}): Promise<Storage.ListResponse> {\n    const ajaxParams = {\n      type: ProxyMethod.GET,\n      url: Utils.getUrl(this.route),\n      data: params,\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async create(params?: Storage.CreateParams): Promise<Storage.BlobResponse> {\n    const ajaxParams = {\n      type: ProxyMethod.POST,\n      url: Utils.getUrl(this.route),\n      data: { blob: params },\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async delete(id: number | string): Promise<EmptyResponse> {\n    const ajaxParams = {\n      type: ProxyMethod.DELETE,\n      url: Utils.getUrl(this.route, id),\n      dataType: ProxyType.TEXT,\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async createAndUpload(params: Storage.CreateAndUploadParams): Promise<Storage.Blob> {\n    const { name, file, size, abort_id, type: content_type, public: isPublic = true } = params;\n    const createParams = { name, content_type, public: isPublic };\n\n    let blob: Storage.Blob;\n\n    return this.create(createParams)\n      .then(({ blob: blobObject }) => {\n        blob = blobObject;\n        const uri = this.parseUri(blob.blob_object_access?.params);\n        const uploadUrl = `${uri.protocol}://${uri.authority}${uri.path}`;\n        const uploadParams: Proxy.Params = { url: uploadUrl, data: {} };\n\n        if (abort_id) {\n          uploadParams.abort_id = abort_id;\n        }\n\n        const queryKey = typeof uri.queryKey === 'object' && uri.queryKey !== null ? uri.queryKey : {};\n        const data = (uploadParams.data ?? {}) as PlainObject;\n\n        Object.keys(queryKey).forEach((key) => {\n          data[key] = decodeURIComponent(queryKey[key]);\n        });\n        data.file = file;\n        uploadParams.data = data;\n\n        return this.upload(uploadParams).then(() => blob);\n      })\n      .then((blob) => this.markUploaded({ id: blob.id, size }).then(() => blob))\n      .then((blob) => ({ ...blob, size }));\n  }\n\n  public async upload(params: Proxy.Params): Promise<any> {\n    const ajaxParams = {\n      ...params,\n      type: ProxyMethod.POST,\n      dataType: ProxyType.TEXT,\n      contentType: false,\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async markUploaded(params: Storage.MarkUploadedParams): Promise<EmptyResponse> {\n    const ajaxParams = {\n      type: ProxyMethod.PUT,\n      url: Utils.getUrl(this.route, params.id, 'complete'),\n      data: {\n        size: params.size,\n      },\n      dataType: ProxyType.TEXT,\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async getInfo(id: number | string): Promise<Storage.BlobResponse> {\n    const ajaxParams = {\n      url: Utils.getUrl(this.route, id),\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async getFile(uid: string): Promise<Storage.BlobResponse> {\n    const ajaxParams = {\n      url: Utils.getUrl(this.route, uid),\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async getFileObject(uid: string, params: Storage.GetFileObjectParams): Promise<Storage.BlobResponse> {\n    const ajaxParams = {\n      type: ProxyMethod.GET,\n      url: Utils.getUrl(this.route, uid, 'object'),\n      data: params,\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async update(params: Storage.UpdateParams): Promise<Storage.BlobResponse> {\n    const data = { blob: {} as PlainObject };\n\n    if (typeof params.name !== 'undefined') {\n      data.blob.name = params.name;\n    }\n\n    const ajaxParams = {\n      url: Utils.getUrl(this.route, params.id),\n      data: data,\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public privateUrl(fileUID: string = ''): string {\n    return `${config.endpoints.api_url ?? `https://${config.endpoints.api}`}/blobs/${fileUID}?token=${this.proxy.getSession()?.token}`;\n  }\n\n  public publicUrl(fileUID: string = ''): string {\n    return `${config.endpoints.api_url ?? `https://${config.endpoints.api}`}/blobs/${fileUID}`;\n  }\n\n  private parseUri(str: string = ''): Record<string, StringOrStringObject> {\n    const options = {\n      strictMode: false,\n      key: [\n        'source',\n        'protocol',\n        'authority',\n        'userInfo',\n        'user',\n        'password',\n        'host',\n        'port',\n        'relative',\n        'path',\n        'directory',\n        'file',\n        'query',\n        'anchor',\n      ] as const,\n      q: {\n        name: 'queryKey',\n        parser: /(?:^|&)([^&=]*)=?([^&]*)/g,\n      },\n      parser: {\n        strict:\n          /^(?:([^:\\/?#]+):)?(?:\\/\\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\\/?#]*)(?::(\\d*))?))?((((?:[^?#\\/]*\\/)*)([^?#]*))(?:\\?([^#]*))?(?:#(.*))?)/,\n        loose:\n          /^(?:(?![^:@]+:[^:@\\/]*@)([^:\\/?#.]+):)?(?:\\/\\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\\/?#]*)(?::(\\d*))?)(((\\/(?:[^?#](?![^?#\\/]*\\.[^?#\\/.]+(?:[?#]|$)))*\\/?)?([^?#\\/]*))(?:\\?([^#]*))?(?:#(.*))?)/,\n      },\n    };\n\n    const m = options.parser[options.strictMode ? 'strict' : 'loose'].exec(str) ?? [];\n\n    const uri = {\n      source: '',\n      protocol: '',\n      authority: '',\n      userInfo: '',\n      user: '',\n      password: '',\n      host: '',\n      port: '',\n      relative: '',\n      path: '',\n      directory: '',\n      file: '',\n      query: '',\n      anchor: '',\n      queryKey: {} as StringObject,\n    };\n\n    options.key.forEach((key, i) => {\n      uri[key] = m[i] ?? '';\n    });\n\n    uri.query.replace(options.q.parser, (_0: string, k: string, v: string) => {\n      if (k) uri.queryKey[k] = v;\n      return '';\n    });\n\n    return uri;\n  }\n}\n","import type { EmptyResponse, PlainObject, StringObject, Users } from './types';\nimport { ProxyMethod, ProxyType } from './types/constants';\nimport config from './config';\nimport ProxyService from './Proxy';\nimport Utils from './Utils';\n\nexport default class UsersService {\n  public proxy: ProxyService;\n  readonly route = config.urls.users;\n\n  constructor(proxy: ProxyService) {\n    this.proxy = proxy;\n  }\n\n  public async getV2(params: Users.GetV2Params): Promise<Users.GetV2Response> {\n    const ajaxParams = {\n      type: ProxyMethod.GET,\n      url: Utils.getUrl(this.route, 'v2'),\n      useArrayQuery: true,\n      data: params,\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async signup(user: Users.SignUpParams, auth_key?: string): Promise<Users.UserResponse> {\n    const ajaxParams = {\n      authKey: auth_key ?? config.creds.authKey,\n      type: ProxyMethod.POST,\n      url: Utils.getUrl(this.route),\n      data: { user },\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async update(user: Users.UpdateParams = {}): Promise<Users.UserResponse> {\n    const ajaxParams = {\n      type: ProxyMethod.PUT,\n      url: Utils.getUrl(this.route, this.proxy.getCurrentUserId()),\n      data: { user },\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async delete(): Promise<EmptyResponse> {\n    const ajaxParams = {\n      type: ProxyMethod.DELETE,\n      url: Utils.getUrl(this.route, this.proxy.getCurrentUserId()),\n      dataType: ProxyType.TEXT,\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async resetPassword(email: string = ''): Promise<EmptyResponse> {\n    const ajaxParams = {\n      type: ProxyMethod.POST,\n      url: Utils.getUrl(this.route, 'password', 'reset'),\n      data: { email },\n      dataType: ProxyType.TEXT,\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async listOnline(params: Users.ListOnlineParams = {}): Promise<Users.UsersResponse> {\n    const ajaxParams = {\n      type: ProxyMethod.GET,\n      url: Utils.getUrl(this.route, 'online'),\n      data: params,\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async getOnlineCount(): Promise<Users.OnlineCountResponse> {\n    const ajaxParams = {\n      type: ProxyMethod.GET,\n      url: Utils.getUrl(this.route, 'online'),\n      data: { count: true },\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  /**\n   * @deprecated Use `getV2(params)` instead.\n   */\n  public async get(params: PlainObject): Promise<Users.OldGetResponse | Users.UserResponse> {\n    let data = Utils.cloneObject(params) as PlainObject;\n    let url: string | number = '';\n\n    const filters: string[] = [];\n    const dateFields = ['created_at', 'updated_at', 'last_request_at'];\n    const numberFields = ['id', 'external_user_id'];\n    const extensions: StringObject = {\n      login: 'by_login',\n      full_name: 'by_full_name',\n      facebook_id: 'by_facebook_id',\n      twitter_id: 'by_twitter_id',\n      phone: 'phone',\n      email: 'by_email',\n      tags: 'by_tags',\n      external: 'external',\n    };\n\n    function generateFilter(filter: PlainObject): string {\n      const obj = Utils.cloneObject(filter) as PlainObject;\n      const field = String(obj.field ?? '');\n      let type = dateFields.includes(field) ? 'date' : typeof obj.value;\n\n      if (Utils.isArray(obj.value)) {\n        if (type === 'object') {\n          type = typeof (obj.value as unknown[])[0];\n        }\n        obj.value = (obj.value as unknown[]).toString();\n      }\n\n      return [type, field, obj.param, obj.value].join(' ');\n    }\n\n    if (data.order) {\n      const order = data.order as PlainObject;\n      const field = String(order.field ?? '');\n      const type = field in dateFields ? 'date' : field in numberFields ? 'number' : 'string';\n      data.order = [order.sort, type, order.field].join(' ');\n    }\n\n    if (data && data.filter) {\n      if (Utils.isArray(data.filter)) {\n        (data.filter as unknown[]).forEach((filter: unknown) => {\n          filters.push(generateFilter((filter as PlainObject) ?? {}));\n        });\n      } else {\n        filters.push(generateFilter((data.filter as PlainObject) ?? {}));\n      }\n      data.filter = filters;\n    }\n\n    if (typeof data === 'number') {\n      url = data;\n      data = undefined as unknown as PlainObject;\n    } else {\n      for (const key in extensions) {\n        if (data[key]) {\n          url = extensions[key];\n\n          if (key === extensions.external) {\n            url += `/${data[extensions.external]}`;\n            data = undefined as unknown as PlainObject;\n          }\n\n          break;\n        }\n      }\n    }\n\n    const ajaxParams = {\n      type: ProxyMethod.GET,\n      url: Utils.getUrl(this.route, url),\n      data,\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n}\n","import { navigator } from '@platform';\nimport config from '../config';\n\nexport default class WebRTCHelpers {\n  static getUserJid(id: string | number): string {\n    return `${id}-${config.creds.appId}@${config.endpoints.chat}`;\n  }\n\n  static getUserIdFromJID(jid: string): number | null {\n    return jid?.includes('@') ? parseInt(jid.split('@')[0].split('-')[0]) : null;\n  }\n\n  static trace(text: string): void {\n    if (config.debug) {\n      console.log('[VideoChat]:', text);\n    }\n  }\n\n  static traceWarning(text: string): void {\n    if (config.debug) {\n      console.warn('[VideoChat]:', text);\n    }\n  }\n\n  static traceError(text: string): void {\n    if (config.debug) {\n      console.error('[VideoChat]:', text);\n    }\n  }\n\n  static get getVersionFirefox(): number {\n    const ua = navigator?.userAgent ?? null;\n    let version = 0;\n    if (ua) {\n      const ffInfo = ua.match(/(?:firefox)[ \\/](\\d+)/i) || [];\n      version = ffInfo[1] ? +ffInfo[1] : 0;\n    }\n    return typeof version === 'string' ? parseInt(version) : version;\n  }\n\n  static get getVersionSafari(): number {\n    const ua = navigator?.userAgent ?? null;\n    let version = 0;\n    if (ua) {\n      const sInfo = ua.match(/(?:safari)[ \\/](\\d+)/i) || [];\n      if (sInfo.length) {\n        const sVer = ua.match(/(?:version)[ \\/](\\d+)/i) || [];\n        if (sVer) {\n          version = sVer[1] ? +sVer[1] : 0;\n        }\n      }\n    }\n\n    return typeof version === 'string' ? parseInt(version) : version;\n  }\n}\n","import type { Calls, Config } from '../types';\nimport type WebRTCSession from './WebRTCSession';\nimport { CallSessionConnectionState, CallType, MediaType, PeerConnectionState } from '../types/constants';\nimport { RTCPeerConnection, RTCSessionDescription, MediaStream } from '@platform';\nimport config from '../config';\nimport WebRTCHelpers from './WebRTCHelpers';\n\nexport default class WebRTCPeerConnection {\n  declare original: RTCPeerConnection;\n  declare session: WebRTCSession;\n  declare userID: number;\n  declare type: RTCSdpType;\n  public remoteSDP: string | null = null;\n  public state: PeerConnectionState = PeerConnectionState.NEW;\n  public iceCandidates: RTCIceCandidateInit[] = [];\n  public answerTimeInterval: number = 0;\n  public onStatusClosedChecker: NodeJS.Timeout | number | null = null;\n  public dialingTimer: NodeJS.Timeout | number | null = null;\n  public statsReportTimer: NodeJS.Timeout | number | null = null;\n  public waitingReconnectTimeoutCallback: NodeJS.Timeout | number | null = null;\n  public released: boolean = false;\n\n  public remoteStream: MediaStream = (() => {\n    if (!MediaStream) {\n      throw new Error('MediaStream is not available');\n    }\n\n    return new MediaStream();\n  })();\n\n  constructor(session: WebRTCSession, userID: number, type: RTCSdpType) {\n    this.create();\n    this.setup(session, userID, type);\n  }\n\n  private create() {\n    const rtcConfiguration: RTCConfiguration = {\n      iceTransportPolicy: (config.videochat.alwaysRelayCalls ? 'relay' : 'all') as RTCIceTransportPolicy,\n      iceServers: config.videochat.iceServers?.map(\n        (item: Config.VideochatIceServer): RTCIceServer => ({\n          urls: item.urls ?? item.url,\n          username: item.username,\n          credential: item.credential,\n        })\n      ) as RTCIceServer[],\n    };\n\n    this.original = RTCPeerConnection ? new RTCPeerConnection(rtcConfiguration) : ({} as RTCPeerConnection);\n\n    WebRTCHelpers.trace(`new RTCPeerConnection(${JSON.stringify(rtcConfiguration, null, 2)})`);\n  }\n\n  private setup(session: WebRTCSession, userID: number, type: RTCSdpType): void {\n    this.type = type;\n    this.userID = userID;\n    this.session = session;\n    this.session.startCallTime = Date.now();\n\n    this.original.addEventListener('track', this.onMediaTrackHandler);\n    this.original.addEventListener('icecandidate', this.onIceCandidateHandler);\n    this.original.addEventListener('signalingstatechange', this.onSignalingStateHandler);\n    this.original.addEventListener('iceconnectionstatechange', this.onIceConnectionStateHandler);\n\n    WebRTCHelpers.trace(`RTCPeerConnection init. ${this.toString()}`);\n  }\n\n  private onMediaTrackHandler = (event: RTCTrackEvent): void => {\n    this.remoteStream.addTrack(event.track);\n\n    if (\n      (this.session.callType == CallType.VIDEO && this.remoteStream.getVideoTracks().length) ||\n      (this.session.callType == CallType.AUDIO && this.remoteStream.getAudioTracks().length)\n    ) {\n      this.session.onRemoteStream(this.userID, this.remoteStream);\n    }\n\n    this.getWrappedStats();\n  };\n\n  private onIceCandidateHandler = (event: RTCPeerConnectionIceEvent): void => {\n    if (event.candidate) {\n      const { sdpMLineIndex, sdpMid, candidate } = event.candidate;\n      const iceCandidate: RTCIceCandidateInit = { sdpMLineIndex, sdpMid, candidate };\n\n      if (this.signalingState === 'stable' && this.original.canTrickleIceCandidates) {\n        this.session.processIceCandidates(this.userID, [iceCandidate]);\n      } else {\n        this.iceCandidates.push(iceCandidate);\n      }\n    }\n  };\n\n  private onSignalingStateHandler = async (): Promise<void> => {\n    WebRTCHelpers.trace(`onSignalingStateHandler: ${this.signalingState}`);\n\n    if (this.signalingState === 'stable' && this.iceCandidates.length > 0) {\n      this.session.processIceCandidates(this.userID, this.iceCandidates);\n      this.iceCandidates.length = 0;\n    }\n  };\n\n  /** handler of remote media stream */\n  private onIceConnectionStateHandler = (): void => {\n    WebRTCHelpers.trace(`onIceConnectionStateHandler: ${this.iceConnectionState}`);\n\n    if (this.onStatusClosedChecker && WebRTCHelpers.getVersionSafari >= 11) {\n      clearTimeout(this.onStatusClosedChecker);\n    }\n\n    switch (this.iceConnectionState) {\n      case 'checking':\n        this.state = PeerConnectionState.CHECKING;\n        this.session.onSessionConnectionStateChanged(this.userID, CallSessionConnectionState.CONNECTING);\n        break;\n      case 'connected':\n        this.state = PeerConnectionState.CONNECTED;\n        this.clearWaitingReconnectTimer();\n        this.session.onSessionConnectionStateChanged(this.userID, CallSessionConnectionState.CONNECTED);\n        break;\n      case 'completed':\n        this.state = PeerConnectionState.COMPLETED;\n        this.clearWaitingReconnectTimer();\n        this.session.onSessionConnectionStateChanged(this.userID, CallSessionConnectionState.COMPLETED);\n        break;\n      case 'failed':\n        this.state = PeerConnectionState.FAILED;\n        this.session.onSessionConnectionStateChanged(this.userID, CallSessionConnectionState.FAILED);\n        break;\n      case 'disconnected':\n        this.state = PeerConnectionState.DISCONNECTED;\n        this.startWaitingReconnectTimer();\n        this.session.onSessionConnectionStateChanged(this.userID, CallSessionConnectionState.DISCONNECTED);\n        if (WebRTCHelpers.getVersionSafari >= 11) {\n          this.onStatusClosedChecker = setTimeout(() => {\n            this.onIceConnectionStateHandler(); // repeat to get status \"closed\"\n          }, 500);\n        }\n        break;\n      case 'closed': // TODO: this state doesn't fires on Safari 11\n        this.state = PeerConnectionState.CLOSED;\n        this.clearWaitingReconnectTimer();\n        this.session.onSessionConnectionStateChanged(this.userID, CallSessionConnectionState.CLOSED);\n        break;\n      default:\n        break;\n    }\n  };\n\n  private clearWaitingReconnectTimer(): void {\n    if (this.waitingReconnectTimeoutCallback) {\n      WebRTCHelpers.trace('clearWaitingReconnectTimer');\n      clearTimeout(this.waitingReconnectTimeoutCallback);\n      this.waitingReconnectTimeoutCallback = null;\n    }\n  }\n\n  private startWaitingReconnectTimer(): void {\n    const timeout = (config.videochat.disconnectTimeInterval ?? 30) * 1000;\n\n    WebRTCHelpers.trace(`startWaitingReconnectTimer, timeout: ${timeout}`);\n\n    this.waitingReconnectTimeoutCallback = setTimeout(() => {\n      WebRTCHelpers.trace('waitingReconnectTimeoutCallback');\n      if (this.waitingReconnectTimeoutCallback) {\n        clearTimeout(this.waitingReconnectTimeoutCallback);\n      }\n      this.release();\n      this.session.closeSessionIfAllConnectionsClosed();\n    }, timeout);\n  }\n\n  private clearStatsReportTimer(): void {\n    if (this.statsReportTimer) {\n      clearInterval(this.statsReportTimer);\n      this.statsReportTimer = null;\n    }\n  }\n\n  public async addCandidates(iceCandidates: RTCIceCandidateInit[]): Promise<void> {\n    for (const iceCandidate of iceCandidates) {\n      if (iceCandidate?.candidate) {\n        try {\n          await this.addIceCandidate(iceCandidate);\n          WebRTCHelpers.trace(`'addIceCandidate' success: ${this.signalingState}`);\n        } catch (error) {\n          WebRTCHelpers.traceError(`'addIceCandidate' error: ${error}`);\n        }\n      }\n    }\n  }\n\n  public release(): void {\n    this.clearDialingTimer();\n    this.clearStatsReportTimer();\n    this.close();\n    if (WebRTCHelpers.getVersionSafari >= 11) {\n      this.onIceConnectionStateHandler(); // TODO: 'closed' state doesn't fires on Safari 11 (do it manually)\n    }\n    this.original.removeEventListener('track', this.onMediaTrackHandler);\n    this.original.removeEventListener('icecandidate', this.onIceCandidateHandler);\n    this.original.removeEventListener('signalingstatechange', this.onSignalingStateHandler);\n    this.original.removeEventListener('iceconnectionstatechange', this.onIceConnectionStateHandler);\n    this.released = true;\n    WebRTCHelpers.trace(`RTCPeerConnection closed. ${this.toString()}`);\n  }\n\n  public clearDialingTimer(): void {\n    if (this.dialingTimer) {\n      WebRTCHelpers.trace('clearDialingTimer');\n      clearInterval(this.dialingTimer);\n      this.dialingTimer = null;\n      this.answerTimeInterval = 0;\n    }\n  }\n\n  public async getAndSetLocalSessionDescription(\n    maxBandwidth: number,\n    iceRestart: boolean = false\n  ): Promise<RTCSessionDescriptionInit> {\n    this.state = PeerConnectionState.CONNECTING;\n\n    try {\n      const offerOptions = iceRestart ? { iceRestart } : undefined;\n      const sessionDescription =\n        this.type === 'offer' ? await this.createOffer(offerOptions) : await this.createAnswer();\n\n      await this.setLocalDescription(sessionDescription);\n      this.setRTCRtpSenderMaxBandwidth(maxBandwidth);\n\n      return sessionDescription;\n    } catch (error) {\n      throw error;\n    }\n  }\n\n  public setRTCRtpSenderMaxBandwidth(maxBandwidth: number): void {\n    const senders = this.getSenders() || [];\n    const maxBitrate = maxBandwidth ? Math.round(maxBandwidth * 1000) : 0;\n\n    senders.forEach((sender: RTCRtpSender) => {\n      if (sender.track?.kind === MediaType.VIDEO) {\n        const params = sender.getParameters();\n\n        params.encodings ??= [{}];\n        params.encodings.forEach((encoding) => {\n          if (maxBitrate > 0) {\n            encoding.maxBitrate = maxBitrate;\n          } else {\n            delete encoding.maxBitrate;\n          }\n        });\n\n        sender\n          .setParameters(params)\n          .then(() => {\n            WebRTCHelpers.trace(\n              `Set 'maxBandwidth' for ${this.userID}: ${maxBandwidth > 0 ? `${maxBandwidth} kbps` : 'unlimited'}`\n            );\n          })\n          .catch((error) => {\n            WebRTCHelpers.traceWarning(`Set 'maxBandwidth' for ${this.userID}: ${error}`);\n          });\n      }\n    });\n  }\n\n  public startDialingTimer(extension: Calls.ExtensionParams, withOnNotAnswerCallback: boolean): void {\n    const dialingTimeInterval = (config.videochat.dialingTimeInterval ?? 5) * 1000;\n    const answerTimeInterval = (config.videochat.answerTimeInterval ?? 60) * 1000;\n\n    WebRTCHelpers.trace(`startDialingTimer, dialingTimeInterval: ${JSON.stringify(dialingTimeInterval)}`);\n\n    const dialingCallback = (\n      extension: Calls.ExtensionParams,\n      withOnNotAnswerCallback: boolean,\n      skipIncrement: boolean\n    ) => {\n      if (!skipIncrement) {\n        this.answerTimeInterval += dialingTimeInterval;\n      }\n\n      WebRTCHelpers.trace(`dialingCallback, extension: ${JSON.stringify(extension)}`);\n\n      if (this.answerTimeInterval >= answerTimeInterval) {\n        this.clearDialingTimer();\n\n        if (withOnNotAnswerCallback) {\n          this.session.processOnNotAnswer(this);\n        }\n      } else {\n        this.session.processCall(this, extension);\n      }\n    };\n\n    this.dialingTimer = setInterval(dialingCallback, dialingTimeInterval, extension, withOnNotAnswerCallback, false);\n\n    dialingCallback(extension, withOnNotAnswerCallback, true); // call for the 1st time\n  }\n\n  public async setRemoteSessionDescription(type: RTCSdpType, sdp: string): Promise<void> {\n    const desc = new RTCSessionDescription!({ sdp, type });\n    return this.setRemoteDescription(desc);\n  }\n\n  private getWrappedStats(): void {\n    if (config.videochat.statsReportTimeInterval) {\n      let lastResult: RTCStatsReport;\n\n      WebRTCHelpers.trace('Stats tracker has been started');\n\n      this.statsReportTimer = setInterval(() => {\n        this.getStatsCustom(\n          lastResult,\n          (results, lastResults) => {\n            lastResult = lastResults;\n            this.session.onCallStatsReport(this.userID, results);\n          },\n          (err) => {\n            WebRTCHelpers.traceError(`Get stats error. ${err.name}: ${err.message}`);\n            this.session.onCallStatsReport(this.userID, null, err);\n          }\n        );\n      }, config.videochat.statsReportTimeInterval * 1000);\n    }\n  }\n\n  set sdpRemote(sdp: string) {\n    if (sdp) {\n      this.remoteSDP = sdp;\n    }\n  }\n\n  get sdpRemote(): string | null {\n    return this.remoteSDP;\n  }\n\n  toString(): string {\n    return `sessionID: ${this.session.ID}, userID: ${this.userID}, type: ${this.type}, state: ${this.state}`;\n  }\n\n  private getStatsCustom(\n    lastResults: RTCStatsReport,\n    onSuccess: (\n      stats: { local: Calls.StatsReportObj; remote: Calls.StatsReportObj },\n      lastResults: RTCStatsReport\n    ) => void,\n    onFail: (err: Error) => void\n  ) {\n    const obj: Calls.StatsReportObj = { audio: {}, video: {}, candidate: {} };\n    const statistic: { local: Calls.StatsReportObj; remote: Calls.StatsReportObj } = {\n      local: Object.assign({}, obj),\n      remote: Object.assign({}, obj),\n    };\n\n    if (WebRTCHelpers.getVersionFirefox) {\n      const localStream = this.session.localStream;\n      const localVideoSettings = localStream?.getVideoTracks()[0].getSettings();\n\n      if (localVideoSettings) {\n        statistic.local.video.frameHeight = localVideoSettings.height;\n        statistic.local.video.frameWidth = localVideoSettings.width;\n      }\n    }\n\n    this.getStats().then((results: RTCStatsReport) => {\n      results.forEach((result) => {\n        let item;\n\n        if (result.bytesReceived && result.type === 'inbound-rtp') {\n          item = statistic.remote[result.mediaType as keyof typeof obj];\n          item.bitrate = this.getBitratePerSecond(result, lastResults, false);\n          item.bytesReceived = result.bytesReceived;\n          item.packetsReceived = result.packetsReceived;\n          item.timestamp = result.timestamp;\n          if (result.mediaType === MediaType.VIDEO && result.framerateMean) {\n            item.framesPerSecond = Math.round(result.framerateMean * 10) / 10;\n          }\n        } else if (result.bytesSent && result.type === 'outbound-rtp') {\n          item = statistic.local[result.mediaType as keyof typeof obj];\n          item.bitrate = this.getBitratePerSecond(result, lastResults, true);\n          item.bytesSent = result.bytesSent;\n          item.packetsSent = result.packetsSent;\n          item.timestamp = result.timestamp;\n          if (result.mediaType === MediaType.VIDEO && result.framerateMean) {\n            item.framesPerSecond = Math.round(result.framerateMean * 10) / 10;\n          }\n        } else if (result.type === 'local-candidate') {\n          item = statistic.local.candidate;\n          if (result.candidateType === 'host' && result.mozLocalTransport === 'udp' && result.transport === 'udp') {\n            item.protocol = result.transport;\n            item.ip = result.ipAddress;\n            item.port = result.portNumber;\n          } else if (!WebRTCHelpers.getVersionFirefox) {\n            item.protocol = result.protocol;\n            item.ip = result.ip;\n            item.port = result.port;\n          }\n        } else if (result.type === 'remote-candidate') {\n          item = statistic.remote.candidate;\n          item.protocol = result.protocol || result.transport;\n          item.ip = result.ip || result.ipAddress;\n          item.port = result.port || result.portNumber;\n        } else if (result.type === 'track' && result.kind === MediaType.VIDEO && !WebRTCHelpers.getVersionFirefox) {\n          if (result.remoteSource) {\n            item = statistic.remote.video;\n            item.frameHeight = result.frameHeight;\n            item.frameWidth = result.frameWidth;\n            item.framesPerSecond = this.getFramesPerSecond(result, lastResults, false);\n          } else {\n            item = statistic.local.video;\n            item.frameHeight = result.frameHeight;\n            item.frameWidth = result.frameWidth;\n            item.framesPerSecond = this.getFramesPerSecond(result, lastResults, true);\n          }\n        }\n      });\n      onSuccess(statistic, results);\n    }, onFail);\n  }\n\n  private getBitratePerSecond(result: RTCStats, lastResults: RTCStatsReport, isLocal: boolean): number {\n    const lastResult = lastResults.get(result.id);\n    const seconds = lastResult ? (result.timestamp - lastResult.timestamp) / 1000 : 5;\n    const kilo = 1024;\n    const bit = 8;\n    const r = result as RTCStats & { bytesSent?: number; bytesReceived?: number };\n    const l = lastResult as (RTCStats & { bytesSent?: number; bytesReceived?: number }) | undefined;\n    const bitrate = !lastResult\n      ? 0\n      : isLocal\n        ? (bit * ((r.bytesSent ?? 0) - (l?.bytesSent ?? 0))) / (kilo * seconds)\n        : (bit * ((r.bytesReceived ?? 0) - (l?.bytesReceived ?? 0))) / (kilo * seconds);\n\n    return Math.round(bitrate);\n  }\n\n  private getFramesPerSecond(result: RTCStats, lastResults: RTCStatsReport, isLocal: boolean): number {\n    const lastResult = lastResults && lastResults.get(result.id);\n    const seconds = lastResult ? (result.timestamp - lastResult.timestamp) / 1000 : 5;\n    const r = result as RTCStats & { framesSent?: number; framesReceived?: number };\n    const l = lastResult as (RTCStats & { framesSent?: number; framesReceived?: number }) | undefined;\n    const framesPerSecond = !lastResult\n      ? 0\n      : isLocal\n        ? ((r.framesSent ?? 0) - (l?.framesSent ?? 0)) / seconds\n        : ((r.framesReceived ?? 0) - (l?.framesReceived ?? 0)) / seconds;\n\n    return Math.round(framesPerSecond * 10) / 10;\n  }\n\n  // original RTCPeerConnection methods\n  close(): void {\n    this.original.close?.();\n  }\n  addTrack(track: MediaStreamTrack, stream: MediaStream): RTCRtpSender {\n    return this.original.addTrack?.(track, stream) ?? null;\n  }\n  getSenders(): RTCRtpSender[] {\n    return this.original.getSenders?.() ?? null;\n  }\n  async createOffer(options?: RTCOfferOptions): Promise<RTCSessionDescriptionInit> {\n    return (await this.original.createOffer?.(options)) ?? null;\n  }\n  async createAnswer(options?: RTCOfferOptions): Promise<RTCSessionDescriptionInit> {\n    return (await this.original.createAnswer?.(options)) ?? null;\n  }\n  async getStats(selector?: MediaStreamTrack | null): Promise<RTCStatsReport> {\n    return (await this.original.getStats?.(selector)) ?? null;\n  }\n  async addIceCandidate(candidate?: RTCIceCandidateInit): Promise<void> {\n    await this.original.addIceCandidate?.(candidate);\n  }\n  async setRemoteDescription(description: RTCSessionDescriptionInit): Promise<void> {\n    await this.original.setRemoteDescription?.(description);\n  }\n  async setLocalDescription(description?: RTCSessionDescriptionInit): Promise<void> {\n    await this.original.setLocalDescription?.(description);\n  }\n  get localDescription(): RTCSessionDescription | null {\n    return this.original.localDescription ?? null;\n  }\n  get signalingState(): RTCSignalingState {\n    return this.original.signalingState ?? 'closed';\n  }\n  get iceConnectionState(): RTCIceConnectionState {\n    return this.original.iceConnectionState ?? 'closed';\n  }\n}\n","import type { Calls, Chat } from '../types';\nimport type { ChatRealTimeService } from '../types/chat';\nimport { CallSignalingModuleIdentifier, CallSignalingType } from '../types/constants';\nimport Utils from '../Utils';\n\nexport default class WebRTCSignalingProvider {\n  public chatService: ChatRealTimeService;\n\n  constructor(chatService: ChatRealTimeService) {\n    this.chatService = chatService;\n  }\n\n  public sendCandidate(\n    userID: Chat.UserId,\n    iceCandidates: RTCIceCandidateInit[],\n    ext: Calls.ExtensionParams = {}\n  ): void {\n    const extension = Object.assign({}, ext, { iceCandidates });\n\n    this.sendMessage(userID, extension, CallSignalingType.CANDIDATE);\n  }\n\n  public sendMessage(userID: Chat.UserId, ext: Calls.ExtensionParams, signalingType: CallSignalingType): void {\n    const extension = Object.assign({}, ext);\n    /** basic parameters */\n    extension.moduleIdentifier = CallSignalingModuleIdentifier;\n    extension.signalType = signalingType;\n    /** extension.sessionID */\n    /** extension.callType */\n    extension.platform = Utils.env.isBrowser ? 'web' : Utils.env.isReactNative || Utils.env.isExpo ? 'mobile' : 'node';\n    /** extension.callerID */\n    /** extension.opponentsIDs */\n    /** extension.sdp */\n\n    if (extension.userInfo) {\n      if (!Object.keys(extension.userInfo).length) {\n        delete extension.userInfo;\n      } else if (extension.userInfo.maxBandwidth === 0) {\n        delete extension.userInfo.maxBandwidth;\n      }\n    }\n\n    const systemCallMessage: Chat.SystemMessageParams = {\n      id: Utils.getBsonObjectId(),\n      extension: extension,\n    };\n\n    this.chatService.sendWebRTCSignalingMessage(userID, systemCallMessage);\n  }\n}\n","import type { Calls, Media } from '../types';\nimport {\n  CallSessionConnectionState,\n  CallSessionState,\n  CallSignalingType,\n  CallType,\n  MediaType,\n  PeerConnectionState,\n} from '../types/constants';\nimport { mediaDevices } from '@platform';\nimport config from '../config';\nimport WebRTCPeerConnection from './WebRTCPeerConnection';\nimport WebRTCSignalingProvider from './WebRTCSignalingProvider';\nimport WebRTCHelpers from './WebRTCHelpers';\nimport Utils from '../Utils';\n\nexport default class WebRTCSession {\n  public ID: string | null = null;\n  public state: CallSessionState = CallSessionState.NEW;\n  declare callType: CallType;\n  declare initiatorID: number;\n  declare currentUserID: number;\n  public opponentsIDs: number[] = [];\n  public maxBandwidth: number = 0;\n  public peerConnections: { [userID: number]: WebRTCPeerConnection } = {};\n  public localStream?: MediaStream;\n  public mediaParams: MediaStreamConstraints = {};\n  declare signalingProvider: WebRTCSignalingProvider;\n  public answerTimer: NodeJS.Timeout | number | null = null;\n  public waitingOfferOrAnswerTimer: NodeJS.Timeout | number | null = null;\n  public startCallTime: number = 0;\n  public acceptCallTime: number = 0;\n  declare onUserNotAnswerListener: Calls.OnUserNotAnswerListener;\n  declare onRemoteStreamListener: Calls.OnRemoteStreamListener;\n  declare onSessionCloseListener: Calls.OnSessionCloseListener;\n  declare onCallStatsReportListener: Calls.OnCallStatsReportListener;\n  declare onSessionConnectionStateChangedListener: Calls.OnSessionConnectionStateChangedListener;\n\n  constructor(params: Calls.SessionParams) {\n    Object.assign(this, params, { ID: params.ID ?? generateUUID() });\n  }\n\n  public async getDisplayMedia(params: Media.DisplayParams): Promise<MediaStream> {\n    if (!mediaDevices?.getDisplayMedia) {\n      throw new Error(\"Your environment does not support 'getDisplayMedia' API\");\n    }\n\n    const elementId = params && params.elementId;\n    const options = params && params.options;\n    const mediaParams = { ...params };\n\n    this.mediaParams = mediaParams;\n\n    delete mediaParams.elementId;\n    delete mediaParams.options;\n\n    try {\n      const stream = await mediaDevices!.getDisplayMedia(mediaParams);\n      const localStream = this.upsertStream(stream, elementId, options);\n      return localStream;\n    } catch (error) {\n      throw error;\n    }\n  }\n\n  public async getUserMedia(params: Media.UserParams): Promise<MediaStream> {\n    if (!mediaDevices?.getUserMedia) {\n      throw new Error(\"Your environment does not support 'getUserMedia' API\");\n    }\n\n    const elementId = params && params.elementId;\n    const options = params && params.options;\n    const mediaParams = { ...params };\n\n    this.mediaParams = mediaParams;\n\n    delete mediaParams.elementId;\n    delete mediaParams.options;\n\n    try {\n      const stream = await mediaDevices!.getUserMedia(mediaParams);\n      const localStream = this.upsertStream(stream, elementId, options);\n      return localStream;\n    } catch (error) {\n      throw error;\n    }\n  }\n\n  private upsertStream(stream: MediaStream, elementId?: string, options?: Media.ElementOptions): MediaStream {\n    const shouldUpdateCurrentStream = !!this.localStream;\n\n    if (shouldUpdateCurrentStream) {\n      this.replaceTracks(stream);\n    } else {\n      this.localStream = stream;\n    }\n\n    if (!this.localStream) {\n      throw new Error('Local stream is not defined');\n    }\n\n    if (elementId) {\n      if (shouldUpdateCurrentStream) {\n        this.detachMediaStream(elementId, options);\n      }\n      this.attachMediaStream(elementId, this.localStream, options);\n    }\n\n    this.localStream.getTracks().forEach((track) => {\n      const type = track.kind as 'audio' | 'video';\n      const deviceId = track.getSettings().deviceId;\n\n      if (deviceId) {\n        if (typeof this.mediaParams[type] === 'object') {\n          this.mediaParams[type].deviceId = deviceId;\n        } else {\n          this.mediaParams[type] = { deviceId };\n        }\n      }\n    });\n\n    return this.localStream;\n  }\n\n  private replaceTracks(stream: MediaStream): MediaStream {\n    this.localStream?.getTracks().forEach((localTrack) => {\n      if (localTrack.kind === MediaType.AUDIO && stream.getAudioTracks().length === 0) {\n        return;\n      } else {\n        localTrack.stop();\n        this.localStream?.removeTrack(localTrack);\n      }\n    });\n\n    stream.getTracks().forEach((newTrack) => {\n      if (newTrack.kind === MediaType.AUDIO) {\n        newTrack.enabled = this.localStream?.getAudioTracks().every(({ enabled }) => enabled) ?? true;\n      } else {\n        newTrack.enabled = this.localStream?.getVideoTracks().every(({ enabled }) => enabled) ?? true;\n      }\n\n      if (newTrack) {\n        Object.values(this.peerConnections).forEach((pc) => {\n          pc.getSenders()\n            .find(({ track }) => newTrack.kind === track?.kind)\n            ?.replaceTrack(newTrack);\n        });\n        this.localStream?.addTrack(newTrack);\n      }\n    });\n\n    if (!this.localStream) {\n      throw new Error('Local stream is not defined');\n    }\n\n    return this.localStream;\n  }\n\n  public async setMaxBandwidth(maxBandwidth: number): Promise<void | void[]> {\n    const peers = this.peerConnections;\n    const peersKeys = Object.keys(peers);\n\n    if (peersKeys.length < 1) {\n      WebRTCHelpers.trace(\"No 'RTCPeerConnection' to set 'maxBandwidth'\");\n      return;\n    }\n\n    return Promise.all(peersKeys.map((userID) => peers[Number(userID)].setRTCRtpSenderMaxBandwidth(maxBandwidth)));\n  }\n\n  public connectionStateForUser(userID: number): PeerConnectionState | null {\n    const peerConnection = this.peerConnections[userID];\n    return peerConnection ? peerConnection.state : null;\n  }\n\n  public attachMediaStream(elementId: string, stream: MediaStream, opt?: Media.ElementOptions): void {\n    const mediaElement = document.getElementById(elementId) as HTMLMediaElement;\n\n    if ('srcObject' in mediaElement) {\n      mediaElement.srcObject = stream;\n      mediaElement.style.transform = opt?.mirror ? 'scaleX(-1)' : 'none';\n      if (typeof opt?.muted === 'boolean') {\n        mediaElement.muted = opt?.muted;\n      }\n      mediaElement.onloadedmetadata = async (_event: Event) => {\n        try {\n          await mediaElement.play();\n        } catch (error) {\n          console.error('[VideoChat]:', error);\n        }\n      };\n    } else {\n      throw new Error(`Unable to attach media stream, element #${elementId} is undefined`);\n    }\n  }\n\n  public detachMediaStream(elementId: string, opt?: Media.ElementOptions): void {\n    const mediaElement = document.getElementById(elementId) as HTMLMediaElement;\n\n    if ('srcObject' in mediaElement) {\n      mediaElement.pause();\n      mediaElement.srcObject = null;\n      mediaElement.style.transform = opt?.mirror ? 'scaleX(-1)' : 'none';\n      if (typeof opt?.muted === 'boolean') {\n        mediaElement.muted = opt?.muted;\n      }\n    } else {\n      throw new Error(`Unable to attach media stream, element #${elementId} is undefined`);\n    }\n  }\n\n  public async switchMediaTracks(options: Media.TrackConstraintsOrDeviceIds = {}): Promise<MediaStream> {\n    Utils.DLog('switchMediaTracks:', options);\n\n    [MediaType.AUDIO, MediaType.VIDEO].forEach((type) => {\n      const device = type === MediaType.AUDIO ? options.audio : type === MediaType.VIDEO ? options.video : {};\n      const deviceId = typeof device === 'string' ? device : (device?.deviceId ?? null);\n\n      if (deviceId) {\n        if (typeof this.mediaParams[type as 'audio' | 'video'] !== 'object') {\n          (this.mediaParams[type as 'audio' | 'video'] as MediaTrackConstraints).deviceId = deviceId;\n        } else {\n          this.mediaParams[type as 'audio' | 'video'] = { deviceId };\n        }\n      }\n    });\n\n    try {\n      const constrains = { audio: this.mediaParams.audio || false, video: this.mediaParams.video || false };\n      const stream = await mediaDevices!.getUserMedia(constrains);\n      const localStream = this.replaceTracks(stream);\n      return localStream;\n    } catch (error) {\n      throw error;\n    }\n  }\n\n  public call(extension: Calls.UserInfo = {}): void {\n    const ext = prepareExtension(extension);\n\n    WebRTCHelpers.trace(`Call, extension: ${JSON.stringify(ext)}`);\n\n    this.state = CallSessionState.ACTIVE;\n    this.maxBandwidth = Number(ext.userInfo?.maxBandwidth ?? 0);\n    this.opponentsIDs.forEach((userID) => {\n      this.callInternal(userID, ext, true);\n    });\n  }\n\n  private async callInternal(\n    userID: number,\n    extension: Calls.ExtensionParams,\n    withOnNotAnswerCallback: boolean\n  ): Promise<void> {\n    const pc = new WebRTCPeerConnection(this, userID, 'offer');\n\n    this.localStream?.getTracks().forEach((track) => {\n      pc.addTrack(track, this.localStream as MediaStream);\n    });\n\n    this.peerConnections[userID] = pc;\n\n    try {\n      await pc.getAndSetLocalSessionDescription(this.maxBandwidth);\n      WebRTCHelpers.trace('getAndSetLocalSessionDescription success');\n      pc.startDialingTimer(extension, withOnNotAnswerCallback); // call requests to user\n    } catch (error) {\n      WebRTCHelpers.traceError(`getAndSetLocalSessionDescription error: ${error}`);\n    }\n  }\n\n  public accept(extension: Calls.UserInfo = {}): void {\n    const ext = prepareExtension(extension);\n\n    WebRTCHelpers.trace(`Accept, extension: ${JSON.stringify(ext)}`);\n\n    if (this.state === CallSessionState.ACTIVE) {\n      WebRTCHelpers.traceError(\"Can't accept, the session is already active, return\");\n      return;\n    }\n\n    if (this.state === CallSessionState.CLOSED) {\n      WebRTCHelpers.traceError(\"Can't accept, the session is already closed, return\");\n      this.stop({});\n      return;\n    }\n\n    this.state = CallSessionState.ACTIVE;\n    this.acceptCallTime = Date.now();\n    this.clearAnswerTimer();\n    this.acceptInternal(this.initiatorID, ext);\n\n    // group call\n    const opponentsIDs = this.opponentsIDs.filter((userID) => userID !== this.currentUserID);\n\n    if (opponentsIDs.length > 0) {\n      this.startWaitingOfferOrAnswerTimer();\n      opponentsIDs.forEach((opponentID) => {\n        if (this.currentUserID > opponentID) {\n          this.callInternal(opponentID, ext, true);\n        }\n      });\n    }\n  }\n\n  private async acceptInternal(userID: number, extension: Calls.ExtensionParams): Promise<void> {\n    const pc = this.peerConnections[userID];\n\n    if (!pc || !pc.sdpRemote) {\n      WebRTCHelpers.traceError(\"Can't accept the call, there is no information about peer connection by some reason\");\n      return;\n    }\n\n    this.localStream?.getTracks().forEach((track) => {\n      pc.addTrack(track, this.localStream as MediaStream);\n    });\n\n    try {\n      await pc.setRemoteSessionDescription('offer', pc.sdpRemote);\n      WebRTCHelpers.trace('setRemoteSessionDescription - success');\n      await pc.getAndSetLocalSessionDescription(this.maxBandwidth);\n      WebRTCHelpers.trace('getAndSetLocalSessionDescription - success');\n\n      const ext = Object.assign({}, extension, {\n        sessionID: this.ID,\n        callType: this.callType,\n        callerID: this.initiatorID,\n        opponentsIDs: this.opponentsIDs,\n        sdp: pc.localDescription?.sdp,\n      });\n\n      this.signalingProvider.sendMessage(userID, ext, CallSignalingType.ACCEPT);\n    } catch (error) {\n      WebRTCHelpers.traceError(`[acceptInternal] Error: ${error}`);\n    }\n  }\n\n  public reject(extension: Calls.UserInfo = {}): void {\n    const ext = prepareExtension(extension);\n\n    WebRTCHelpers.trace(`Reject, extension: ${JSON.stringify(ext.userInfo)}`);\n\n    this.state = CallSessionState.REJECTED;\n    this.clearAnswerTimer();\n    Object.assign(ext, {\n      sessionID: this.ID,\n      callType: this.callType,\n      callerID: this.initiatorID,\n      opponentsIDs: this.opponentsIDs,\n    });\n\n    Object.keys(this.peerConnections).forEach((userID) => {\n      this.signalingProvider.sendMessage(Number(userID), ext, CallSignalingType.REJECT);\n    });\n\n    this.close();\n  }\n\n  public stop(extension: Calls.UserInfo = {}): void {\n    const ext = prepareExtension(extension);\n\n    WebRTCHelpers.trace(`Stop, extension: ${JSON.stringify(ext.userInfo)}`);\n\n    this.state = CallSessionState.STOPPED;\n\n    if (this.answerTimer) {\n      this.clearAnswerTimer();\n    }\n\n    Object.assign(ext, {\n      sessionID: this.ID,\n      callType: this.callType,\n      callerID: this.initiatorID,\n      opponentsIDs: this.opponentsIDs,\n    });\n\n    Object.keys(this.peerConnections).forEach((userID) => {\n      this.signalingProvider.sendMessage(Number(userID), ext, CallSignalingType.STOP);\n    });\n\n    this.close();\n  }\n\n  public canInitiateIceRestart(userID: number): boolean {\n    return this.peerConnections[userID]?.type === 'offer';\n  }\n\n  public async iceRestart(userID: number): Promise<void> {\n    const pc = this.peerConnections[userID];\n\n    if (!pc) {\n      WebRTCHelpers.traceError(\"Can't restart ice, there is no information about peer connection by some reason\");\n      return;\n    }\n\n    try {\n      const { sdp } = await pc.getAndSetLocalSessionDescription(this.maxBandwidth, true);\n      const ext = { sessionID: this.ID ?? '', sdp };\n      this.signalingProvider.sendMessage(userID, ext, CallSignalingType.RESTART);\n      WebRTCHelpers.trace('[iceRestart] OK');\n    } catch (error) {\n      WebRTCHelpers.traceError(`[iceRestart] Error: ${error}`);\n    }\n  }\n\n  public processOnCall(callerID: number, extension: Calls.ExtensionParams): void {\n    const opponentsIDs = [this.initiatorID, ...this.opponentsIDs.filter((userID) => userID !== this.currentUserID)];\n\n    opponentsIDs.forEach((opponentID) => {\n      const pc = this.peerConnections[opponentID];\n\n      if (pc) {\n        if (opponentID === callerID) {\n          pc.sdpRemote = extension.sdp ?? '';\n          /** The group call logic starts here */\n          if (callerID !== this.initiatorID && this.state === CallSessionState.ACTIVE) {\n            this.acceptInternal(callerID, extension);\n          }\n        }\n      } else {\n        /** create peer connections for each opponent */\n        const rtcSdpType = opponentID !== callerID && this.currentUserID > opponentID ? 'offer' : 'answer';\n        const pc = new WebRTCPeerConnection(this, opponentID, rtcSdpType);\n\n        this.peerConnections[opponentID] = pc;\n\n        if (opponentID === callerID) {\n          pc.sdpRemote = extension.sdp ?? '';\n          this.startAnswerTimer();\n        }\n      }\n    });\n  }\n\n  public async processOnAccept(userID: number, extension: Calls.ExtensionParams): Promise<void> {\n    const pc = this.peerConnections[userID];\n\n    if (!pc) {\n      WebRTCHelpers.traceWarning(\"Ignore 'OnAccept', there is no information about peer connection by some reason\");\n    }\n\n    try {\n      pc.clearDialingTimer();\n      await pc.setRemoteSessionDescription('answer', extension.sdp ?? '');\n      WebRTCHelpers.trace(\"'setRemoteSessionDescription' success\");\n    } catch (error) {\n      WebRTCHelpers.traceError(`'setRemoteSessionDescription' error: ${error}`);\n    }\n  }\n\n  public processOnReject(userID: number): void {\n    const pc = this.peerConnections[userID];\n\n    this.clearWaitingOfferOrAnswerTimer();\n\n    if (pc) {\n      pc.release();\n    } else {\n      WebRTCHelpers.traceWarning(\"Ignore 'OnReject', there is no information about peer connection by some reason\");\n    }\n\n    this.closeSessionIfAllConnectionsClosed();\n  }\n\n  public processOnStop(userID: number): void {\n    this.clearAnswerTimer();\n\n    /** drop the call if the initiator did it */\n    if (userID === this.initiatorID) {\n      const pcKeys = Object.keys(this.peerConnections);\n      if (pcKeys.length > 0) {\n        pcKeys.forEach((key: string) => {\n          this.peerConnections[Number(key)].release();\n        });\n      } else {\n        WebRTCHelpers.traceWarning(\"Ignore 'OnStop', there is no information about peer connections by some reason\");\n      }\n    } else {\n      const pc = this.peerConnections[userID];\n      if (pc) {\n        pc.release();\n      } else {\n        WebRTCHelpers.traceWarning('Ignore \"OnStop\", there is no information about peer connection by some reason');\n      }\n    }\n\n    this.closeSessionIfAllConnectionsClosed();\n  }\n\n  public async processOnIceCandidates(userID: number, extension: Calls.ExtensionParams): Promise<void> {\n    const pc = this.peerConnections[userID];\n\n    if (!pc) {\n      WebRTCHelpers.traceWarning(\n        'Ignore \"OnIceCandidates\", there is no information about peer connection by some reason'\n      );\n    }\n\n    if (extension.iceCandidates) {\n      await pc.addCandidates(extension.iceCandidates);\n    }\n  }\n\n  public async processOnIceRestart(userID: number, extension: Calls.ExtensionParams): Promise<void> {\n    const pc = this.peerConnections[userID];\n\n    if (!pc) {\n      WebRTCHelpers.traceWarning('Ignore \"OnIceRestart\", there is no information about peer connection by some reason');\n    }\n\n    try {\n      await pc.setRemoteSessionDescription('offer', extension.sdp ?? '');\n      const { sdp } = await pc.getAndSetLocalSessionDescription(this.maxBandwidth);\n      const ext = { sessionID: this.ID ?? '', sdp };\n      this.signalingProvider.sendMessage(userID, ext, CallSignalingType.RESTART_ACCEPT);\n      WebRTCHelpers.trace('[processOnIceRestart] Success');\n    } catch (error) {\n      WebRTCHelpers.traceError(`[processOnIceRestart] Error: ${error}`);\n    }\n  }\n\n  public async processOnIceRestartAccept(userID: number, extension: Calls.ExtensionParams): Promise<void> {\n    const pc = this.peerConnections[userID];\n\n    if (!pc) {\n      WebRTCHelpers.traceWarning(\n        'Ignore \"OnIceRestartAccept\", there is no information about peer connection by some reason'\n      );\n    }\n\n    try {\n      await pc.setRemoteSessionDescription('answer', extension.sdp ?? '');\n      WebRTCHelpers.trace('[processOnIceRestartAccept] Success');\n    } catch (error) {\n      WebRTCHelpers.traceError(`[processOnIceRestartAccept] Error: ${error}`);\n    }\n  }\n\n  public processCall(peerConnection: WebRTCPeerConnection, extension: Calls.ExtensionParams = {}): void {\n    const ext = Object.assign({ userInfo: {} }, extension, {\n      sessionID: this.ID,\n      callType: this.callType,\n      callerID: this.initiatorID,\n      opponentsIDs: this.opponentsIDs,\n      sdp: peerConnection.localDescription?.sdp,\n    });\n\n    this.signalingProvider.sendMessage(peerConnection.userID, ext, CallSignalingType.CALL);\n  }\n\n  public processIceCandidates(userID: number, iceCandidates: RTCIceCandidateInit[]): void {\n    const extension = {\n      sessionID: this.ID ?? '',\n      callType: this.callType,\n      callerID: this.initiatorID,\n      opponentsIDs: this.opponentsIDs,\n    };\n\n    this.signalingProvider.sendCandidate(userID, iceCandidates, extension);\n  }\n\n  public processOnNotAnswer(peerConnection: WebRTCPeerConnection): void {\n    WebRTCHelpers.trace(`Answer timeout callback for session ${this.ID} for user ${peerConnection.userID}`);\n\n    this.clearWaitingOfferOrAnswerTimer();\n    peerConnection.release();\n    Utils.safeCallbackCall(this.onUserNotAnswerListener)(this, peerConnection.userID);\n    this.closeSessionIfAllConnectionsClosed();\n  }\n\n  public onRemoteStream(userID: number, stream: MediaStream): void {\n    Utils.safeCallbackCall(this.onRemoteStreamListener)(this, userID, stream);\n  }\n\n  public onCallStatsReport(userID: number, stats: unknown, error?: Error): void {\n    Utils.safeCallbackCall(this.onCallStatsReportListener)(this, userID, stats, error);\n  }\n\n  public onSessionConnectionStateChanged(userID: number, connectionState: CallSessionConnectionState): void {\n    Utils.safeCallbackCall(this.onSessionConnectionStateChangedListener)(this, userID, connectionState);\n  }\n\n  private close(): void {\n    Object.values(this.peerConnections).forEach((pc) => {\n      try {\n        pc.release();\n      } catch (e) {\n        Utils.DLog(`Peer close error: ${e}`);\n      }\n    });\n\n    this.closeLocalMediaStream();\n    this.state = CallSessionState.CLOSED;\n    Utils.safeCallbackCall(this.onSessionCloseListener)(this);\n  }\n\n  public closeSessionIfAllConnectionsClosed(): void {\n    const isAllClosed = Object.values(this.peerConnections).every((pc) => {\n      try {\n        /*\n         * TODO:\n         * Uses RTCPeerConnection.signalingState instead RTCPeerConnection.iceConnectionState,\n         * because state 'closed' comes after few time from Safari, but signaling state comes instantly\n         */\n        return pc.iceConnectionState === 'closed' || pc.signalingState === 'closed' || pc.released;\n      } catch (err: unknown) {\n        WebRTCHelpers.traceError(String(err));\n        // need to set peerState to 'closed' on error. FF will crashed without this part.\n        return true;\n      }\n    });\n\n    WebRTCHelpers.trace(`All peer connections closed: ${isAllClosed}`);\n\n    if (isAllClosed) {\n      this.closeLocalMediaStream();\n      Utils.safeCallbackCall(this.onSessionCloseListener)(this);\n      this.state = CallSessionState.CLOSED;\n    }\n  }\n\n  private closeLocalMediaStream(): void {\n    if (this.localStream) {\n      this.localStream.getTracks().forEach((track) => track.stop());\n      this.localStream = undefined;\n      this.mediaParams = {};\n    }\n  }\n\n  public mute(type: MediaType): void {\n    this.muteStream(false, type);\n  }\n\n  public unmute(type: MediaType): void {\n    this.muteStream(true, type);\n  }\n\n  private muteStream(enabled: boolean, type: MediaType = MediaType.NONE): void {\n    const tracks =\n      type === MediaType.AUDIO\n        ? this.localStream?.getAudioTracks()\n        : type === MediaType.VIDEO\n          ? this.localStream?.getVideoTracks()\n          : [];\n\n    tracks?.forEach((track) => {\n      track.enabled = enabled;\n    });\n  }\n\n  private clearAnswerTimer(): void {\n    if (this.answerTimer) {\n      WebRTCHelpers.trace('clearAnswerTimer');\n      clearTimeout(this.answerTimer);\n      this.answerTimer = null;\n    }\n  }\n\n  private startAnswerTimer(): void {\n    WebRTCHelpers.trace('startAnswerTimer');\n\n    this.answerTimer = setTimeout(\n      () => {\n        WebRTCHelpers.trace('answerTimeoutCallback');\n        this.close();\n        this.answerTimer = null;\n      },\n      (config.videochat.answerTimeInterval ?? 60) * 1000\n    );\n  }\n\n  private clearWaitingOfferOrAnswerTimer(): void {\n    if (this.waitingOfferOrAnswerTimer) {\n      WebRTCHelpers.trace('clearWaitingOfferOrAnswerTimer');\n      clearTimeout(this.waitingOfferOrAnswerTimer);\n      this.waitingOfferOrAnswerTimer = null;\n    }\n  }\n\n  private startWaitingOfferOrAnswerTimer(): void {\n    const answerTimeInterval = config.videochat.answerTimeInterval ?? 60;\n    const timeWait = (this.acceptCallTime - this.startCallTime) / 1000;\n    const timeDiff = Math.min(timeWait, answerTimeInterval / 2);\n    const timeout = Math.max(answerTimeInterval - timeDiff, 1);\n\n    WebRTCHelpers.trace(`startWaitingOfferOrAnswerTimer, timeout: ${timeout}`);\n\n    this.waitingOfferOrAnswerTimer = setTimeout(() => {\n      WebRTCHelpers.trace('waitingOfferOrAnswerTimeoutCallback');\n\n      Object.values(this.peerConnections).forEach((pc) => {\n        if (pc.state === PeerConnectionState.CONNECTING || pc.state === PeerConnectionState.NEW) {\n          this.processOnNotAnswer(pc);\n        }\n      });\n\n      this.waitingOfferOrAnswerTimer = null;\n    }, timeout * 1000);\n  }\n\n  public toString(): string {\n    return `ID: ${this.ID}, initiatorID: ${this.initiatorID}, opponentsIDs: ${this.opponentsIDs}, state: ${this.state}, callType: ${this.callType}`;\n  }\n}\n\nfunction generateUUID(): string {\n  let d = Date.now();\n  const uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n    const r = ((d + Math.random() * 16) % 16) | 0;\n    d = Math.floor(d / 16);\n    return (c == 'x' ? r : (r & 0x3) | 0x8).toString(16);\n  });\n  return uuid;\n}\n\nfunction prepareExtension(extension: Calls.UserInfo = {}): Calls.ExtensionParams {\n  const ext = { userInfo: extension };\n\n  try {\n    if (Utils.isObject(extension)) {\n      ext.userInfo = Utils.cloneObject(extension, true);\n    } else {\n      WebRTCHelpers.traceWarning('Ignore \"prepareExtension\", must be an object');\n    }\n  } catch (err: unknown) {\n    WebRTCHelpers.traceWarning(err instanceof Error ? err.message : String(err));\n  }\n\n  return ext;\n}\n","import { mediaDevices } from '@platform';\nimport config from '../config';\nimport ProxyService from '../Proxy';\nimport Utils from '../Utils';\nimport WebRTCSession from './WebRTCSession';\nimport WebRTCSignalingProcessor from './WebRTCSignalingProcessor';\nimport WebRTCSignalingProvider from './WebRTCSignalingProvider';\nimport WebRTCHelpers from './WebRTCHelpers';\nimport type { Calls, EmptyResponse } from '../types';\nimport type { ChatRealTimeService } from '../types/chat';\nimport {\n  CallEvent,\n  CallSessionConnectionState,\n  CallSessionState,\n  CallType,\n  PeerConnectionState,\n  ProxyMethod,\n} from '../types/constants';\n\nexport default class WebRTCClient {\n  public chatService: ChatRealTimeService;\n  public proxy: ProxyService;\n  public signalingProcessor: WebRTCSignalingProcessor;\n  public signalingProvider: WebRTCSignalingProvider;\n  public SessionConnectionState: typeof CallSessionConnectionState = CallSessionConnectionState;\n  public PeerConnectionState: typeof PeerConnectionState = PeerConnectionState;\n  public CallType: typeof CallType = CallType;\n  public sessions: { [key: string]: WebRTCSession } = {};\n  declare onCallListener: Calls.OnCallListener;\n  declare onAcceptCallListener: Calls.OnAcceptCallListener;\n  declare onRejectCallListener: Calls.OnRejectCallListener;\n  declare onStopCallListener: Calls.OnStopCallListener;\n  declare onInvalidEventsListener: Calls.OnInvalidEventsListener;\n  declare onUserNotAnswerListener: Calls.OnUserNotAnswerListener;\n  declare onRemoteStreamListener: Calls.OnRemoteStreamListener;\n  declare onSessionConnectionStateChangedListener: Calls.OnSessionConnectionStateChangedListener;\n  declare onSessionCloseListener: Calls.OnSessionCloseListener;\n  declare onCallStatsReport: Calls.OnCallStatsReportListener;\n  public onDevicesChangeListener: Calls.OnDevicesChangeListener = () => {};\n\n  constructor(chatService: ChatRealTimeService, proxy: ProxyService) {\n    this.chatService = chatService;\n    this.proxy = proxy;\n\n    this.signalingProcessor = new WebRTCSignalingProcessor(this);\n    this.signalingProvider = new WebRTCSignalingProvider(this.chatService);\n\n    if (mediaDevices) {\n      mediaDevices.ondevicechange = Utils.safeCallbackCall(this.onDevicesChangeListener);\n    }\n  }\n\n  private get currentUserID(): number {\n    return this.chatService.currentUserId;\n  }\n\n  public async getMediaDevices(kind?: MediaDeviceKind): Promise<MediaDeviceInfo[]> {\n    if (mediaDevices?.enumerateDevices) {\n      const devices = await mediaDevices.enumerateDevices();\n      return kind ? devices.filter((device) => device.kind === kind) : devices;\n    } else {\n      throw new Error(\"No 'enumerateDevices' API supported\");\n    }\n  }\n\n  public createNewSession(\n    opponentsIDs: number[],\n    callType: CallType,\n    options?: { maxBandwidth?: number; bandwidth?: number }\n  ): WebRTCSession {\n    const maxBandwidth = (options?.maxBandwidth || options?.bandwidth) ?? 0;\n\n    if (!opponentsIDs) {\n      throw new Error(\"Can't create a session without opponentsIDs\");\n    }\n\n    return this.createAndStoreSession(null, this.currentUserID, opponentsIDs, callType, maxBandwidth);\n  }\n\n  private createAndStoreSession(\n    sessionID: string | null,\n    initiatorID: number,\n    opponentsIDs: number[],\n    callType: CallType,\n    maxBandwidth: number = 0\n  ): WebRTCSession {\n    const webRTCSession = new WebRTCSession({\n      ID: sessionID,\n      initiatorID,\n      opponentsIDs,\n      callType,\n      signalingProvider: this.signalingProvider,\n      currentUserID: this.currentUserID,\n      maxBandwidth,\n    });\n\n    webRTCSession.onUserNotAnswerListener = this.onUserNotAnswerListener;\n    webRTCSession.onRemoteStreamListener = this.onRemoteStreamListener;\n    webRTCSession.onSessionConnectionStateChangedListener = this.onSessionConnectionStateChangedListener;\n    webRTCSession.onSessionCloseListener = this.onSessionCloseListener;\n    webRTCSession.onCallStatsReportListener = this.onCallStatsReport;\n\n    if (webRTCSession?.ID) {\n      this.sessions[webRTCSession.ID] = webRTCSession;\n    }\n\n    return webRTCSession;\n  }\n\n  public clearSession(sessionId: string): void {\n    delete this.sessions[sessionId];\n  }\n\n  /// Reject call by http request\n  public callRejectRequest(params: {\n    sessionID: string;\n    recipientId: number;\n    platform: string;\n    userInfo?: Calls.UserInfo;\n  }): Promise<EmptyResponse> {\n    const ajaxParams = {\n      type: ProxyMethod.POST,\n      url: Utils.getUrl(config.urls.calls, 'reject'),\n      data: params,\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  /// DELEGATE (signaling)\n\n  public onCallHandler(userID: number, sessionID: string, extension: Calls.ExtensionParams): void {\n    const userInfo = extension.userInfo || {};\n    const maxBandwidth = Number(userInfo.maxBandwidth ?? 0);\n\n    let session = this.sessions[sessionID];\n\n    WebRTCHelpers.trace(`onCall. userID: ${userID}, sessionID: ${sessionID}, extension: ${JSON.stringify(extension)}`);\n\n    if (!session) {\n      session = this.createAndStoreSession(\n        sessionID,\n        extension.callerID || 0,\n        extension.opponentsIDs || [],\n        (extension.callType as CallType) || CallType.VIDEO,\n        maxBandwidth\n      );\n\n      Utils.safeCallbackCall(this.onCallListener)(session, userInfo);\n    }\n\n    session.processOnCall(userID, extension);\n  }\n\n  public onAcceptHandler(userID: number, sessionID: string, extension: Calls.ExtensionParams): void {\n    const session = this.sessions[sessionID];\n    const userInfo = extension.userInfo || {};\n\n    WebRTCHelpers.trace(\n      `onAccept. UserID: ${userID}, sessionID: ${sessionID}, extension: ${JSON.stringify(extension)}`\n    );\n\n    if (session && (session.state === CallSessionState.ACTIVE || session.state === CallSessionState.NEW)) {\n      Utils.safeCallbackCall(this.onAcceptCallListener)(session, userID, userInfo);\n      session.processOnAccept(userID, extension);\n    } else {\n      WebRTCHelpers.traceWarning(`Ignore 'onAccept', there is no information about session ${sessionID}`);\n    }\n  }\n\n  public onRejectHandler(userID: number, sessionID: string, extension: Calls.ExtensionParams): void {\n    const session = this.sessions[sessionID];\n\n    WebRTCHelpers.trace(\n      `onReject. UserID: ${userID}, sessionID: ${sessionID}, extension: ${JSON.stringify(extension)}`\n    );\n\n    if (session) {\n      const userInfo = extension.userInfo || {};\n\n      Utils.safeCallbackCall(this.onRejectCallListener)(session, userID, userInfo);\n      session.processOnReject(userID);\n    } else {\n      WebRTCHelpers.traceWarning(`Ignore 'onReject', there is no information about session ${sessionID}`);\n    }\n  }\n\n  public onStopHandler(userID: number, sessionID: string, extension: Calls.ExtensionParams) {\n    WebRTCHelpers.trace(`onStop. UserID: ${userID}, sessionID: ${sessionID}, extension: ${JSON.stringify(extension)}`);\n\n    const session = this.sessions[sessionID];\n    const userInfo = extension.userInfo || {};\n\n    if (session && (session.state === CallSessionState.ACTIVE || session.state === CallSessionState.NEW)) {\n      session.processOnStop(userID);\n      Utils.safeCallbackCall(this.onStopCallListener)(session, userID, userInfo);\n    } else {\n      Utils.safeCallbackCall(this.onInvalidEventsListener)(session, userID, userInfo);\n      WebRTCHelpers.traceWarning(`Ignore 'onStop', there is no information about session ${sessionID} by some reason`);\n    }\n  }\n\n  public onIceCandidatesHandler(userID: number, sessionID: string, extension: Calls.ExtensionParams) {\n    const session = this.sessions[sessionID];\n\n    WebRTCHelpers.trace(\n      `onIceCandidates. UserID: ${userID}. SessionID: ${sessionID}. ICE candidates count: ${\n        extension.iceCandidates?.length ?? 0\n      }`\n    );\n\n    if (session) {\n      if (session.state === CallSessionState.ACTIVE) {\n        session.processOnIceCandidates(userID, extension);\n      } else {\n        WebRTCHelpers.traceWarning(`Ignore 'OnIceCandidates', the session ( ${sessionID} ) has invalid state`);\n      }\n    } else {\n      WebRTCHelpers.traceWarning(`Ignore 'OnIceCandidates', there is no information about session ${sessionID}`);\n    }\n  }\n\n  public onIceRestartHandler(userID: number, sessionID: string, extension: Calls.ExtensionParams) {\n    const session = this.sessions[sessionID];\n\n    WebRTCHelpers.trace(\n      `onIceRestart. UserID: ${userID}. SessionID: ${sessionID}. Extension: ${JSON.stringify(extension)}`\n    );\n\n    if (session) {\n      if (session.state === CallSessionState.ACTIVE) {\n        session.processOnIceRestart(userID, extension);\n      } else {\n        WebRTCHelpers.traceWarning(`Ignore 'OnIceRestart', the session (${sessionID}) has invalid state`);\n      }\n    } else {\n      WebRTCHelpers.traceWarning(`Ignore 'OnIceRestart', there is no information about session ${sessionID}`);\n    }\n  }\n\n  public onIceRestartAcceptHandler(userID: number, sessionID: string, extension: Calls.ExtensionParams) {\n    const session = this.sessions[sessionID];\n\n    WebRTCHelpers.trace(\n      `onIceRestartAccept. UserID: ${userID}. SessionID: ${sessionID}. Extension: ${JSON.stringify(extension)}`\n    );\n\n    if (session) {\n      if (session.state === CallSessionState.ACTIVE) {\n        session.processOnIceRestartAccept(userID, extension);\n      } else {\n        WebRTCHelpers.traceWarning(`Ignore 'onIceRestartAccept', the session (${sessionID}) has invalid state`);\n      }\n    } else {\n      WebRTCHelpers.traceWarning(`Ignore 'onIceRestartAccept', there is no information about session ${sessionID}`);\n    }\n  }\n\n  private getListenerByName(name: CallEvent): Calls.ListenerName | null {\n    switch (name) {\n      case CallEvent.CALL:\n        return 'onCallListener';\n      case CallEvent.ACCEPT:\n        return 'onAcceptCallListener';\n      case CallEvent.REJECT:\n        return 'onRejectCallListener';\n      case CallEvent.STOP:\n        return 'onStopCallListener';\n      case CallEvent.INVALID:\n        return 'onInvalidEventsListener';\n      case CallEvent.NOT_ANSWER:\n        return 'onUserNotAnswerListener';\n      case CallEvent.REMOTE_STREAM:\n        return 'onRemoteStreamListener';\n      case CallEvent.CONNECTION_STATE:\n        return 'onSessionConnectionStateChangedListener';\n      case CallEvent.CLOSE:\n        return 'onSessionCloseListener';\n      case CallEvent.STATS_REPORT:\n        return 'onCallStatsReport';\n      case CallEvent.DEVICES:\n        return 'onDevicesChangeListener';\n      default:\n        return null;\n    }\n  }\n\n  public addListener(name: CallEvent, listener: Calls.Listeners): () => void {\n    const listenerName = this.getListenerByName(name);\n    if (listenerName) {\n      (this[listenerName] as Calls.Listeners) = listener;\n    }\n    return this.removeListener.bind(this, name);\n  }\n\n  public removeListener(name: CallEvent): void {\n    const listenerName = this.getListenerByName(name);\n    if (listenerName) {\n      (this[listenerName] as Calls.Listeners | undefined) = name === CallEvent.DEVICES ? () => {} : undefined;\n    }\n  }\n\n  public removeAllListeners(): void {\n    Object.keys(this).forEach((key) => {\n      if (key.startsWith('on') && key.endsWith('Listener') && typeof this[key as Calls.ListenerName] === 'function') {\n        (this[key as Calls.ListenerName] as Calls.Listeners | undefined) =\n          key === 'onDevicesChangeListener' ? () => {} : undefined;\n      }\n    });\n  }\n}\n","import type { EmptyResponse, Whiteboard } from './types';\nimport { ProxyMethod, ProxyType } from './types/constants';\nimport ProxyService from './Proxy';\nimport config from './config';\nimport Utils from './Utils';\n\nexport default class WhiteboardService {\n  public proxy: ProxyService;\n  readonly route = config.urls.whiteboards;\n  readonly server = config.whiteboard.server;\n\n  constructor(proxy: ProxyService) {\n    this.proxy = proxy;\n  }\n\n  public getURL({ id, title, username }: Whiteboard.GetUrlParams): string {\n    return `${this.server}?whiteboardid=${id}&username=${username}&title=${title}`;\n  }\n\n  public async get(paramsOrId: Whiteboard.GetParams): Promise<Whiteboard.Item[]> {\n    const ajaxParams = {\n      type: ProxyMethod.GET,\n      url: Utils.getUrl(this.route),\n      data: typeof paramsOrId === 'string' ? { chat_dialog_id: paramsOrId } : paramsOrId,\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async create(params: Whiteboard.CreateParams): Promise<Whiteboard.Item> {\n    const ajaxParams = {\n      type: ProxyMethod.POST,\n      url: Utils.getUrl(this.route),\n      data: params,\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async update(id: string, params: Whiteboard.UpdateParams): Promise<Whiteboard.Item> {\n    const ajaxParams = {\n      type: ProxyMethod.PUT,\n      url: Utils.getUrl(this.route, id),\n      data: params,\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n\n  public async delete(id: string): Promise<EmptyResponse> {\n    const ajaxParams = {\n      type: ProxyMethod.DELETE,\n      url: Utils.getUrl(this.route, id),\n      dataType: ProxyType.TEXT,\n    };\n\n    return this.proxy.ajax(ajaxParams);\n  }\n}\n","import type { LinkPreview, LinkPreviewCache } from './types';\nimport { ProxyMethod } from './types/constants';\nimport ProxyService from './Proxy';\nimport config from './config';\n\nexport default class LinkPreviewService {\n  public proxy: ProxyService;\n  public cache: LinkPreviewCache = new Map<string, LinkPreview>();\n\n  readonly route = config.urls.unfurl;\n  readonly server = config.linkpreview.server;\n\n  constructor(proxy: ProxyService) {\n    this.proxy = proxy;\n  }\n\n  public async get(url: string): Promise<LinkPreview> {\n    if (!this.cache.has(url)) {\n      let linkPreview: LinkPreview = { url, title: '', description: '', images: [] }\n      \n      try {\n        const ajaxParams = {\n          type: ProxyMethod.POST,\n          url: `${this.server}/${this.route}`,\n          data: { url },\n        };\n\n        linkPreview = (await this.proxy.ajax(ajaxParams)) as LinkPreview;\n      } catch (error) {\n        linkPreview.title = this.getHostFromUrl(url);\n      }\n\n      this.cache.set(url, linkPreview);\n    }\n\n    return this.cache.get(url) as LinkPreview;\n  }\n\n  private getHostFromUrl(url: string): string {\n    if (typeof URL === 'function') {\n      return new URL(url).hostname;\n    }\n\n    const match = url.match(/^(?:https?:\\/\\/)?([^\\/]+)/);\n    return match ? match[1] : url;\n  }\n}\n","import type { Config } from './types';\nimport { ChatAPIs } from './types/constants';\nimport { isWebRTCAvailable, sdkVersion, isBrowser, isNodeJS, isReactNative } from '@platform';\nimport config from './config';\nimport AddressBookService from './AddressBook';\nimport AuthService from './Auth';\nimport XMPPChatService from './messaging/xmpp';\nimport SAMAChatService from './messaging/sama';\nimport ConferenceClient from './videocalling_conference/ConferenceClient';\nimport DataService from './Data';\nimport MeetingsService from './Meetings';\nimport ProxyService from './Proxy';\nimport PushNotificationsService from './PushNotifications';\nimport StorageService from './Storage';\nimport UsersService from './Users';\nimport Utils from './Utils';\nimport WebRTCClient from './videocalling/WebRTCClient';\nimport WhiteboardService from './Whiteboard';\nimport LinkPreviewService from './LinkPreview';\n\nexport default class ConnectyCube<ChatService extends SAMAChatService | XMPPChatService = XMPPChatService> {\n  declare ConnectyCube: typeof ConnectyCube;\n\n  readonly version: string = sdkVersion;\n  readonly platform: string = isBrowser ? 'browser' : isNodeJS ? 'node' : isReactNative ? 'react-native' : 'unknown';\n  readonly isWebRTCAvailable: boolean = isWebRTCAvailable;\n\n  declare utils: Utils;\n  declare service: ProxyService;\n  declare auth: AuthService;\n  declare users: UsersService;\n  declare storage: StorageService;\n  declare pushnotifications: PushNotificationsService;\n  declare data: DataService;\n  declare addressbook: AddressBookService;\n  declare chat: ChatService;\n  declare meeting: MeetingsService;\n  declare whiteboard: WhiteboardService;\n  declare linkpreview: LinkPreviewService;\n  declare videochat: WebRTCClient;\n  declare videochatconference: ConferenceClient;\n  declare setSession: AuthService['setSession'];\n  declare getSession: AuthService['getSession'];\n  declare createSession: AuthService['createSession'];\n  declare destroySession: AuthService['destroySession'];\n  /**\n   * @deprecated ConnectyCube.login(user) is deprecated. Use `ConnectyCube.createSession(user)` or `ConnectyCube.auth.login(user)` instead.\n   */\n  declare login: AuthService['login'];\n  /**\n   * @deprecated ConnectyCube.logout() is deprecated. Use `ConnectyCube.destroySession()` or `ConnectyCube.auth.logout()` instead.\n   */\n  declare logout: AuthService['logout'];\n\n  public init(credentials: Config.Credentials, configMap: Config.Options = {}): void {\n    if (configMap && typeof configMap === 'object') {\n      config.set(configMap);\n    }\n\n    this.utils = Utils;\n    this.service = new ProxyService();\n    this.auth = new AuthService(this.service);\n    this.users = new UsersService(this.service);\n    this.storage = new StorageService(this.service);\n    this.pushnotifications = new PushNotificationsService(this.service);\n    this.data = new DataService(this.service);\n    this.addressbook = new AddressBookService(this.service);\n    this.chat = (\n      config.chat.apiImp === ChatAPIs.SAMA ? new SAMAChatService(this.service) : new XMPPChatService(this.service)\n    ) as ChatService;\n    this.meeting = new MeetingsService(this.service);\n    this.whiteboard = new WhiteboardService(this.service);\n    this.linkpreview = new LinkPreviewService(this.service);\n\n    if (isWebRTCAvailable) {\n      this.videochat = new WebRTCClient(this.chat, this.service);\n      this.chat.webrtcSignalingProcessor = this.videochat.signalingProcessor;\n      this.videochatconference = new ConferenceClient(this.service);\n    }\n\n    if (credentials.token) {\n      config.creds.appId = credentials.appId;\n      this.service.setSession({ token: credentials.token });\n    } else {\n      config.creds.appId = credentials.appId;\n      config.creds.authKey = credentials.authKey;\n    }\n\n    this.setSession = this.auth.setSession;\n    this.getSession = this.auth.getSession;\n    this.createSession = this.auth.createSession;\n    this.destroySession = this.auth.destroySession;\n    this.login = this.auth.login;\n    this.logout = this.auth.logout;\n  }\n}\n\nexport { type XMPPChatService as XMPPChat, type SAMAChatService as SAMAChat };\n","import ConnectyCube from './ConnectyCube';\nimport type { SAMAChat, XMPPChat } from './ConnectyCube';\n\nconst connectycube: ConnectyCube = new ConnectyCube();\n\nconnectycube.ConnectyCube = ConnectyCube;\n\nexport default connectycube;\nexport { ConnectyCube };\nexport * from './types/constants';\nexport type * from './types';\nexport type { XMPPChat, SAMAChat };\n","import type { DeleteIdsResponse, PaginationParams, PlainObject, SearchCondition, Timestamps } from './common';\n\nexport const DataPermission = {\n  CREATE: 'create',\n  READ: 'read',\n  UPDATE: 'update',\n  DELETE: 'delete',\n} as const;\nexport type DataPermission = (typeof DataPermission)[keyof typeof DataPermission];\n\nexport const DataPermissionAccess = {\n  OPEN: 'open',\n  OWNER: 'owner',\n  NOT_ALLOWED: 'not_allowed',\n  OPEN_FOR_GROUPS: 'open_for_groups',\n  OPEN_FOR_USERS_IDS: 'open_for_users_ids',\n} as const;\nexport type DataPermissionAccess = (typeof DataPermissionAccess)[keyof typeof DataPermissionAccess];\n\nexport namespace ConnectyCubeData {\n  export type PermissionOptions = {\n    access: DataPermissionAccess | string;\n    user_ids?: string[];\n    user_groups?: string[];\n  };\n  export type Permissions = Record<DataPermission | string, PermissionOptions>;\n  export type CreateRecord = PlainObject & {\n    permissions?: Permissions;\n  };\n  export type DataRecord = Timestamps & PlainObject & {\n    _id: string;\n    _parent_id: string | null;\n    user_id: number;\n    permissions: Permissions;\n  };\n  // Request parameters type\n  export type CreateParams = CreateRecord | CreateRecord[];\n  export type ListFilter = Omit<PaginationParams, 'offset'> & {\n    count?: number;\n    output?: { include?: string[]; exclude?: string[] };\n    near?: string;\n    [field: string]: SearchCondition<unknown> | undefined;\n  };\n  export type ListParams = string | string[] | ListFilter | undefined;\n  export type ReadParams = { permissions: 1 };\n  export type UpdateOptions = PlainObject & {\n    id?: string | number;\n    _id?: string | number;\n    inc?: Record<string, number>;\n    pull?: PlainObject;\n    pull_with_filter?: Record<string, PlainObject>;\n    pull_all?: Record<string, unknown[]>;\n    pop?: Record<string, 1 | -1>;\n    push?: Record<string, unknown[]>;\n    add_to_set?: Record<string, unknown[]>;\n    update_by_index?: Record<string, PlainObject<number>>;\n    search_criteria?: SearchCondition<unknown>;\n  };\n  // Response data types\n  export type ListResponse = { class_name: string; items: DataRecord[] };\n  export type ReadPermissionsResponse = { record_id: string; permissions: Permissions };\n  export type UpdateResponse = ListResponse & {\n    skip?: number;\n    limit?: number;\n    total_found?: number;\n    not_found?: { ids: string[] };\n  };\n  export type DeleteResponse = DeleteIdsResponse | { total_deleted: number };\n}\n","import type { DateOrTimestamp } from './common';\n\nexport const NotificationChannel = {\n  APNS: 'apns',\n  VOIP: 'apns_voip',\n  GCM: 'gcm',\n  WEB: 'web',\n} as const;\nexport type NotificationChannel = (typeof NotificationChannel)[keyof typeof NotificationChannel];\n\nexport const DevicePlatform = {\n  IOS: 'ios',\n  ANDROID: 'android',\n  WEB: 'web',\n} as const;\nexport type DevicePlatform = (typeof DevicePlatform)[keyof typeof DevicePlatform];\n\nexport const PushEnvironment = {\n  DEV: 'development',\n  PROD: 'production',\n} as const;\nexport type PushEnvironment = (typeof PushEnvironment)[keyof typeof PushEnvironment];\n\nexport namespace ConnectyCubePushNotifications {\n  export type Subscription = {\n    subscription: {\n      id: number | string;\n      notification_channel: {\n        name: NotificationChannel | string;\n      };\n      device: {\n        udid: string;\n        platform: {\n          name: DevicePlatform | string;\n        };\n      };\n    };\n  };\n  export type Event = {\n    event: {\n      id: number;\n      event_type: string | null;\n      message: string | null;\n      date: DateOrTimestamp;\n      period: DateOrTimestamp;\n      name: string | null;\n      occured_count?: number;\n      created_at?: DateOrTimestamp;\n      updated_at?: DateOrTimestamp;\n      end_date?: DateOrTimestamp;\n      active?: boolean | null;\n      application_id: number | null;\n      user_id: number | null;\n      kind: string | null;\n      environment: PushEnvironment | null;\n      tag_query?: string;\n      notification_channel?: {\n        name?: NotificationChannel | null;\n      };\n    };\n  };\n  export type PushTokenBaseParams = {\n    environment: PushEnvironment | string;\n  };\n  export type PushTokenMobileParams = PushTokenBaseParams & {\n    client_identification_sequence: string;\n    bundle_identifier?: string;\n  };\n  export type PushTokenWebParams = PushTokenBaseParams & {\n    web_endpoint: string;\n    web_auth: string;\n    web_p256dh: string;\n  };\n  // Request parameters type\n  export type SubscriptionsCreateParams = {\n    notification_channels: NotificationChannel | string;\n    push_token: PushTokenMobileParams | PushTokenWebParams;\n    device: {\n      platform: DevicePlatform | string;\n      udid: string;\n    };\n  };\n  export type EventsCreateParams = {\n    notification_type: 'push' | string;\n    push_type: NotificationChannel | string;\n    environment: PushEnvironment | string;\n    event_type?: 'one_shot' | string;\n    message?: string | null;\n    user?: {\n      ids: string | number[];\n      tags?: {\n        any?: string;\n        all?: string;\n        exclude?: string;\n      };\n    };\n    external_user?: { ids: string | number[] };\n  };\n}\n","import type {\n  DeleteIdsResponse,\n  PagedResponse,\n  PaginationParams,\n  PlainObject,\n  SearchableProps,\n  Timestamp,\n  Timestamps,\n} from './common';\nimport type { ConnectyCubeUsers } from './users';\n\nexport const DialogType = {\n  PUBLIC: 1,\n  GROUP: 2,\n  PRIVATE: 3,\n  BROADCAST: 4,\n  MEETING: 5,\n} as const;\nexport type DialogType = (typeof DialogType)[keyof typeof DialogType];\n\nexport const LastMessageMessageStatus = {\n  SENT: 'sent',\n  DELIVERED: 'delivered',\n  READ: 'read',\n} as const;\nexport type LastMessageMessageStatus = (typeof LastMessageMessageStatus)[keyof typeof LastMessageMessageStatus];\n\nexport const DialogDateProp = {\n  CREATED: 'created_at',\n  UPDATED: 'updated_at',\n  LAST_MESSAGE: 'last_message_date_sent',\n} as const;\nexport type DialogDateProp = (typeof DialogDateProp)[keyof typeof DialogDateProp];\n\nexport namespace ConnectyCubeDialogs {\n  export type Dialog<ExtensionExtra = PlainObject> = Timestamps & {\n    _id: string;\n    name: string;\n    description: string | null;\n    photo: string | null;\n    type: DialogType;\n    user_id: number;\n    xmpp_room_jid?: string | null;\n    last_message: string | null;\n    last_message_date_sent?: Timestamp;\n    last_message_id: string | null;\n    last_message_user_id: number | null;\n    last_message_status: LastMessageMessageStatus | string | null;\n    occupants_ids: number[];\n    admins_ids: number[];\n    occupants_count?: number;\n    pinned_messages_ids?: string[];\n    unread_messages_count: number;\n    extensions?: ExtensionExtra;\n    permissions?: { allow_preview: boolean | string | number } | null;\n  };\n  // Request parameters type\n  export type ListParams = SearchableProps<Dialog> & Omit<PaginationParams<Dialog>, 'offset'> & { count?: number };\n  export type CreateParams<ExtensionExtra = PlainObject> = Pick<\n    Dialog<ExtensionExtra>,\n    'type' | 'extensions' | 'permissions' | 'pinned_messages_ids'\n  > & {\n    name?: string;\n    photo?: string | null;\n    description?: string | null;\n    occupants_ids?: (string | number)[] | string;\n    admins_ids?: (string | number)[] | string;\n  };\n  export type UpdateParams<ExtensionExtra = PlainObject> = Omit<\n    CreateParams<ExtensionExtra>,\n    'type' | 'occupants_ids' | 'admins_ids'\n  > & {\n    push_all?: Pick<CreateParams<ExtensionExtra>, 'occupants_ids' | 'admins_ids' | 'pinned_messages_ids'>;\n    pull_all?: Pick<CreateParams<ExtensionExtra>, 'occupants_ids' | 'admins_ids' | 'pinned_messages_ids'>;\n  };\n  export type GetPublicOccupantsParams = Pick<PaginationParams, 'skip' | 'limit'>;\n  // Response data types\n  export type ListResponse = PagedResponse<Dialog>;\n  export type DeleteResponse = DeleteIdsResponse;\n  export type NotificationsSettingsResponse = { notifications: { enabled: number | string } };\n  export type GetNotificationsSettingsResponse = NotificationsSettingsResponse;\n  export type UpdateNotificationsSettingsResponse = NotificationsSettingsResponse;\n  export type GetPublicOccupantsResponse = { items: ConnectyCubeUsers.User[] };\n}\n","import type { DateOrTimestamp, PlainObject } from './common';\nimport type { ConnectyCubeUsers } from './users';\n\nexport const LoginProviderNames = {\n  FACEBOOK: 'facebook',\n  TWITTER: 'twitter',\n  FIREBASE_PHONE: 'firebase_phone',\n  FIREBASE_EMAIL: 'firebase_email',\n} as const;\nexport type LoginProviderNames = (typeof LoginProviderNames)[keyof typeof LoginProviderNames];\n\nexport namespace ConnectyCubeAuth {\n  export type Session = {\n    id: number;\n    user_id: number;\n    application_id: string | number;\n    token: string;\n    ts: DateOrTimestamp;\n    created_at: DateOrTimestamp;\n    updated_at: DateOrTimestamp;\n    user?: ConnectyCubeUsers.User | null;\n  };\n  export type LoginProviderKeys = { token: string; secret?: string };\n  export type LoginFirebaseKeys = { project_id: string | number; access_token: string };\n  export type LoginByLogin = { login: string; password: string };\n  export type LoginByEmail = { email: string; password: string };\n  export type LoginByGuest = { guest: '1'; full_name: string };\n  // Login by social providers\n  export type LoginByFacebook = {\n    provider: typeof LoginProviderNames.FACEBOOK;\n    keys: LoginProviderKeys;\n  };\n  export type LoginByTwitter = {\n    provider: typeof LoginProviderNames.TWITTER;\n    keys: LoginProviderKeys;\n  };\n  export type LoginByFirebasePhone = {\n    provider: typeof LoginProviderNames.FIREBASE_PHONE;\n    firebase_phone: LoginFirebaseKeys;\n  };\n  export type LoginByFirebaseEmail = {\n    provider: typeof LoginProviderNames.FIREBASE_EMAIL;\n    firebase_email: LoginFirebaseKeys;\n  };\n  // Request parameters type\n  export type LoginParams =\n    | LoginByLogin\n    | LoginByEmail\n    | LoginByGuest\n    | LoginByFacebook\n    | LoginByTwitter\n    | LoginByFirebasePhone\n    | LoginByFirebaseEmail;\n  export type GeneratedSessionParams = {\n    application_id: string | number;\n    auth_key: string;\n    user?: LoginByLogin | LoginByEmail | LoginByGuest;\n    provider?: LoginProviderNames;\n    keys?: LoginProviderKeys;\n    firebase_phone?: LoginFirebaseKeys;\n    firebase_email?: LoginFirebaseKeys;\n  };\n  // Response data type\n  export type LoginRawResponse = { user: ConnectyCubeUsers.User } & PlainObject;\n  export type GetSessionRawResponse = { session: Session } & PlainObject;\n}\n","import type { DateOrTimestamp, PaginationParams, SearchCondition, SearchableProps, Timestamps } from './common';\n\nexport const MeetingDateMetric = {\n  MINUTES: 'minutes',\n  HOURS: 'hours',\n  DAYS: 'days',\n  WEEK: 'weeks',\n} as const;\nexport type MeetingDateMetric = (typeof MeetingDateMetric)[keyof typeof MeetingDateMetric];\n\nexport namespace ConnectyCubeMeetings {\n  export type Attendee = { id?: number; email?: string };\n  export type MeetingParams = {\n    name?: string;\n    start_date?: DateOrTimestamp;\n    end_date?: DateOrTimestamp;\n    attendees?: Attendee[];\n    record?: boolean | null;\n    public?: boolean;\n    scheduled?: boolean;\n    notify?: boolean;\n    notify_before?: {\n      metric: MeetingDateMetric | string;\n      value: number; // 'minutes' range [0 - 55], 'hours' range [1 - 24], 'days' range [1 - 30], 'weeks' range [1 - 4]\n    };\n    timezone?: {\n      offset: number; // Minutes UTC offset\n      name: string; // Timezone Name\n    };\n  };\n  export type Meeting = Timestamps & {\n    _id: string;\n    chat_dialog_id?: string | null;\n    host_id: number;\n  } & MeetingParams;\n  export type Recording = {\n    _id: string;\n    room_id: string;\n    participants_ids: number[];\n    updated_at: string;\n    created_at: string;\n    download_url: string;\n    participants_count: number;\n    duration: number;\n    size: number;\n  };\n  // Request parameters type\n  export type GetParams = SearchableProps<Pick<Meeting, '_id' | 'updated_at' | 'created_at' | 'scheduled'>>\n    & Pick<PaginationParams, 'offset' | 'limit'>\n    & { start_at?: SearchCondition<DateOrTimestamp>; end_at?: SearchCondition<DateOrTimestamp> };\n  export type CreateParams = { chat?: boolean } & MeetingParams;\n}\n"],"names":["CallSignalingModuleIdentifier","CallSignalingType","CALL","ACCEPT","REJECT","STOP","RESTART","RESTART_ACCEPT","CANDIDATE","CallSessionConnectionState","UNDEFINED","CONNECTING","CONNECTED","FAILED","DISCONNECTED","CLOSED","COMPLETED","CallSessionState","NEW","ACTIVE","STOPPED","REJECTED","CallType","VIDEO","AUDIO","CallEvent","INVALID","NOT_ANSWER","REMOTE_STREAM","CONNECTION_STATE","CLOSE","STATS_REPORT","DEVICES","PeerConnectionState","CHECKING","ChatType","CHAT","GROUPCHAT","ChatEvent","STATUS","ERROR","RECONNECTED","MESSAGE","SYSTEM_MESSAGE","ERROR_MESSAGE","TYPING_MESSAGE","UPDATE_MESSAGE","DELETE_MESSAGE","REACTIONS_MESSAGE","DELIVERED_MESSAGE","READ_MESSAGE","SENT_MESSAGE","USER_LAST_ACTIVITY","JOIN","LEAVE","KICK","PrivacyListAction","ALLOW","DENY","ChatProtocol","BOSH","WS","JanusDebugMode","ALL","TRACE","DEBUG","VDEBUG","LOG","WARN","ChatAPIs","SAMA","XMPP","DeviceInputType","JanusEvent","PARTICIPANT_JOINED","PARTICIPANT_LEFT","LOCAL_STREAM","REMOTE_TRACKS_UPDATED","DATA_CHANNEL_OPEN","DATA_CHANNEL_MESSAGE","JanusCallType","JanusMediaTrackReason","CREATED","ENDED","MUTE","UNMUTE","ConferenceEvent","LEFT","SLOW_LINK","REMOTE_CONNECTION_STATE","DATA_CHANNEL_OPENED","SESSION_CONNECTION_STATE","MediaType","NONE","ProxyMethod","GET","POST","PUT","PATCH","DELETE","HEAD","ProxyType","JSON","TEXT","sdkVersion","isBrowser","window","document","isNodeJS","process","versions","Boolean","node","isReactNative","isExpo","adapter","undefined","navigator","mediaDevices","MediaStream","MediaStreamTrack","RTCIceCandidate","RTCPeerConnection","RTCRtpReceiver","RTCRtpSender","RTCSessionDescription","isWebRTCAvailable","console","warn","Config","static","version","creds","appId","authKey","endpoints","api","chat","muc","chatProtocol","bosh","websocket","active","streamManagement","enable","reconnect","timeInterval","apiImp","videochat","alwaysRelayCalls","answerTimeInterval","dialingTimeInterval","disconnectTimeInterval","statsReportTimeInterval","iceServers","urls","username","credential","conference","server","debug","whiteboard","linkpreview","session","login","users","blobs","subscriptions","events","data","addressbook","meetings","whiteboards","unfurl","calls","type","on","sessionExpired","xmppDataWrite","xmppDataRead","timeout","mode","constructor","getInstance","instance","set","options","this","api_url","chat_url","Object","keys","forEach","key","prototype","hasOwnProperty","call","optionValue","_val","nextKey","config","Utils","safeCallbackCall","cb","args","err","error","toString","getUrl","base","res","ext","resource","extension","isArray","arg","Array","isObject","obj","getBsonObjectId","ObjectId","machine","Math","floor","random","pid","increment","timestamp","Date","now","parseInt","padStart","DLog","loggers","length","logger","push","log","callTrafficUsageCallback","callbackName","getStringSize","str","Blob","size","body","b","headers","h","stringify","getDataSize","cloneObject","escapeNull","json","jsonObject","replace","parse","ProxyService","sdkInstance","requestsNumber","currentUserId","abortControllersMap","requestMethod","responseType","setSession","user_id","setCurrentUserId","getSession","userId","getCurrentUserId","logRequest","params","requestId","url","logResponse","response","buildRequestAndURL","isGetOrHeadType","isPostOrPutType","token","isInternalRequest","indexOf","isMultipartFormData","contentType","requestObject","method","requestURL","requestBody","buildRequestBody","useArrayQuery","dataObject","formData","FormData","item","fileEntry","fileToCustomObject","append","name","value","Uint8Array","serializeQueryParams","prefix","level","parts","objRecord","propName","propQueryName","encodeURIComponent","isArrayVal","strVal","sort","join","String","uriComponent","c","charCodeAt","abortRequest","abortId","controllers","controller","abort","processSuccessfulOrFailedRequest","abort_id","doneRequestsCount","ajax","Promise","resolve","reject","index","AbortController","signal","assign","requestInit","fetch","then","resp","dataType","text","ok","processAjaxResponse","processAjaxError","catch","responseBody","code","bodyObj","errors","statusCode","status","errorObject","info","errno","isExpiredSessionError","handleExpiredSessionResponse","handleResponse","retryCallback","AddressBookService","proxy","route","uploadAddressBook","list","Error","ajaxParams","contacts","get","udid","getRegisteredUsers","compact","AuthService","routes","async","createSession","generateCreateSessionParams","destroySession","user","id","logout","message","application_id","auth_key","password","email","provider","firebase_phone","firebase_email","createOnAuthenticate","credentials","userAgent","authenticate","mechanisms","fast","entity","mechanism","getMechanism","includes","isSecure","tcpEnabled","find","ChatUtils","buildUserJid","jid","buildUserJidLocalPart","createMessageStanza","attrs","xml","createIqStanza","createPresenceStanza","createNonza","getAttr","element","getElement","getChild","getName","getText","getChildElements","isErrorStanza","getAllElements","getChildren","getElementText","getChildText","getElementTreePath","elementsPath","reduce","prevElement","assignObjectToXml","val","t","up","assignExtraParamsToXml","extraParams","attachment","assignXmlToObject","children","parseExtraParams","attachments","dialogId","dialog_id","moduleIdentifier","buildErrorFromXMPPErrorStanza","errorStanza","errorElement","getUniqueId","suffix","uuid","r","parseReactions","map","add","remove","reaction","items","ChatHelpers","xmppJID","userCurrentJid","isNumeric","test","jidOrUserId","getUserJid","getRoomJidFromDialogId","typeChat","getUserNickWithMucDomain","getUserIdFromJID","split","getDialogIdFromJID","getRoomJid","getIdFromResource","slice","getRoomJidFromRoomFullJid","getUserIdFromRoomJid","roomJid","getDialogJid","identifier","NonzaName","StreamManagement","xmlns","enabled","clientHandledCounter","serverHandledCounter","messagesQueue","Set","messagesQueueClearTimer","supported","start","removeElementHandler","addElementHandler","sendNonza","stop","markMessagesQueueAsLost","sendAndCount","stanza","isMessage","isChat","isContent","xmppClient","sendOnline","markMessageAsLost","elementHandler","nextHandledCounter","currHandledCounter","Number","isNaN","diffHandledCounter","markMessagesQueueAsSent","markMessagesQueueAsLostByTimeout","markMessageAsSent","onSentMessageCallback","delete","clear","iterations","iterator","values","i","done","next","clearTimeout","ackTimeout","acknowledgementTimeout","setTimeout","nonza","removeListener","PrivacyList","helpers","stanzasCallbacks","create","privacyList","acc","action","mutualBlock","privacyListKeys","iqParams","from","iq","j","len","isMutual","userJid","userMuc","assignPrivacyItem","order","getList","_reject","query","filter","update","currentList","Map","currentListItem","updatedItem","updatedListItems","updatedList","getNames","defaultElement","activeElement","defaultName","activeName","allNames","listEl","default","names","setAsDefault","MultiUserChat","joinedRooms","dialogIdOrJid","dialogJid","presenceStanza","to","maxstanzas","x","isJoin","endsWith","isError","errorResponse","leave","_stanza","listOnlineUsers","iqStanza","stanzaId","DialogsService","admins_ids","occupants_ids","idOrIds","idsToDelete","trim","addAdmins","push_all","removeAdmins","pull_all","subscribe","subscribeToPublic","unsubscribe","unsubscribeFromPublic","updateNotificationsSettings","getNotificationsSettings","getPublicOccupants","clearHistory","MessagesService","ids","createSystem","unreadCount","chat_dialog_ids","listReactions","addReaction","updateReaction","removeReaction","putReaction","WebRTCSignalingProcessor","delegate","onMessage","userID","sessionId","sessionID","signalType","onCallHandler","onAcceptHandler","onRejectHandler","onStopHandler","onIceCandidatesHandler","onIceRestartHandler","onIceRestartAcceptHandler","AbstractChatService","dialog","isConnected","isConnecting","isLogout","isReconnect","search","start_date","toISOString","end_date","pingWithTimeout","timer","onConnectionErrorListener","result","ping","getListenerByName","addListener","listener","listenerName","bind","removeAllListeners","startsWith","XMPPChatService","privacylist","xmppClientListeners","connectPromise","earlyIncomingMessagesQueue","super","domain","service","getDomain","Client","_reconnect","_websocket","middleware","_middleware","streamFeatures","_streamFeatures","iqCaller","_iqCaller","iqCallee","_iqCallee","saslFactory","SASLFactory","entries","plain","anonymous","k","v","sasl2","_sasl2","_fast","setup","bind2","_bind2","htsha256none","sasl","_sasl","resourceBinding","_resourceBinding","send","auth","delay","connectionStatus","userJID","connect","removeAllXMPPClientListeners","addXMPPClientListener","postConnectActions","onDisconnectedListener","disconnect","onChatStatusListener","is","onPresence","onIQ","onSystemMessage","onMessageError","condition","messageId","messageStanza","sendSystemMessage","recipients","recipient","sendWebRTCSignalingMessage","candidate","opponentId","sendIsTypingStatus","sendIsStopTypingStatus","sendDeliveredStatus","sendReadStatus","editMessage","originMessageId","last","deleteMessage","getLastUserActivity","onLastActivityStanza","seconds","onLastUserActivityListener","markActive","markInactive","terminate","socket","end","rawStanza","forwardedStanza","invite","getResource","delivered","read","replaceSubElement","reactionsSubElement","removeSubElement","composing","paused","isForwarded","isGroup","recipientId","currentUserJid","onMessageTypingListener","onMessageUpdateListener","onMessageReactionsListener","onMessageDeleteListener","onDeliveredStatusListener","onReadStatusListener","recipient_id","is_forwarded","onMessageListener","mucUserId","actorElement","initiatorUserJid","initiatorId","onKickOccupant","onSystemMessageListener","onWebRTCSignalingMessage","webrtcSignalingProcessor","extensionElem","getCallExtension","iceCandidates","opponentsIDs","child","childName","childText","onMessageErrorListener","presence","enableCarbons","onReconnectListener","stanzasCallback","setSubscriptionToUserLastActivity","user_jid","subscribeToUserLastActivityStatus","unsubscribeFromUserLastActivityStatus","context","_listener","removeXMPPClientListener","_","C","defineProperty","o","d","e","s","enumerable","configurable","writable","D","E","n","A","globalThis","WebSocket","O","endpoint","ws","http","onopen","onConnectEvent","onmessage","g","p","f","q","R","w","S","L","P","typing","onUserTypingListener","system_message","a","conversation_created","l","conversation_updated","m","conversation_kicked","u","onConversationCreateListener","onConversationUpdateListener","onConversationDeleteListener","onSystemMessageEvent","last_activity","onUserActivityListener","message_read","onMessageStatusListener","message_edit","onMessageEditListener","message_delete","message_reactions_update","responsesPromises","onMessageEvent","ask","mid","resObjKey","I","y","every","onerror","onclose","onDisconnectEvent","disableAutoReconnect","onLine","visibilityState","removeEventListener","addEventListener","close","sendRequest","request","sendPromise","sendHttpPromise","localStorage","getItem","Authorization","statusText","connectSocket","device_id","deviceId","socketLogin","organization_id","disconnectSocket","userCreate","userEdit","userLogin","removeItem","userLogout","userSendOTPToken","userResetPassword","new_password","userDelete","userSearch","keyword","ignore_ids","limit","updated_at","getUsersByIds","getParticipantsByCids","cids","createUploadUrlForFiles","files","getDownloadUrlForFiles","file_ids","messageCreate","cid","replied_message_id","forwarded_message_id","messageSystem","uids","messageList","messageSummary","messageTone","tone","markConversationAsRead","mids","messageEdit","messageDelete","getUserActivity","subscribeToUserActivity","unsubscribeFromUserActivity","sendTypingStatus","conversationCreate","conversationUpdate","description","participants","image_object","conversationList","gt","lt","conversationDelete","conversationSearch","conversationHandlerCreate","content","getConversationHandler","conversationHandlerDelete","pushSubscriptionCreate","platform","web_endpoint","web_key_auth","web_key_p256dh","device_udid","pushSubscriptionDelete","setActivityStatus","isInactive","blockList","blockUsers","unblockUsers","reactionsUpdate","reactionsList","BlockList","samaClient","block","userIds","unblock","SAMAChatService","currentUserNativeId","SAMAClient","removeAllSamaListeners","addAllSamaListeners","authorizedUser","native_id","onSamaConnectedListener","onSamaDisconnectListener","onSamaMessageEventListener","onSamaMessageListener","_id","messageParams","date_sent","onSamaSystemMessageListener","systemMessage","onWebRTCSignalingSystemMessage","opponentID","iceCandidate","iceObjectKey","onSamaMessageStatusListener","onSamaUserLastActivityListener","lastActivityTs","onSamaTypingListener","isTyping","onSamaMessageEditListener","messageEditParams","isLast","updatedBody","onSamaDeleteListener","onSamaMessageReactionListener","messageReaction","requestParams","ack","server_mid","userIdsOrDialogId","destinationParams","_params","markDialogAsRead","activityDate","ceil","_userId","require$$0","Janus","sessions","mobile","isExtensionEnabled","getDisplayMedia","match","chromever","maxver","isInstalled","defaultExtension","extensionId","querySelector","getScreen","callback","pending","cache","postMessage","init","event","origin","location","sourceId","gatewayCallbacks","success","noop","destroyed","initDone","isWebrtcSupported","websockets","wsHandlers","wsKeepaliveTimeoutId","servers","serversIndex","iceTransportPolicy","bundlePolicy","withCredentials","maxev","max_poll_events","apisecret","destroyOnUnload","keepAlivePeriod","longPollTimeout","getMaxBitrates","simulcastMaxBitrates","maxBitrates","high","medium","low","connected","pluginHandles","that","retries","transactions","eventHandler","longpoll","getTime","httpAPICall","verb","handleEvent","textStatus","errorThrown","skipTimeout","transaction","reportSuccess","sender","pluginHandle","webrtcStuff","pc","remoteSdp","completed","addIceCandidate","endOfCandidates","candidates","webrtcState","hangup","ondetached","detach","mediaState","slowLink","reason","plugindata","jsep","vdebug","keepAlive","janus","session_id","randomString","callbacks","newWebSocket","open","eventName","sendMessage","handleId","sdp","e2ee","rid_order","force_relay","sendTrickleCandidate","createDataChannel","dclabel","dcprotocol","incoming","pendingData","onDataChannelStateChange","label","target","protocol","dcState","dataChannel","readyState","ondataopen","dcoptions","dataChannelOptions","ondata","sendData","dataChanDefaultLabel","sendDtmf","dtmfSender","audioSender","getSenders","track","kind","dtmf","ontonechange","tones","duration","gap","insertDTMF","destroyHandle","noRequest","cleanupWebrtc","detached","createPeerconnectionIfNeeded","pc_config","insertableStreams","tracks","transforms","receiver","createEncodedStreams","createEncodedAudioStreams","createEncodedVideoStreams","forceEncodedAudioInsertableStreams","forceEncodedVideoInsertableStreams","encodedInsertableStreams","getStats","volume","bitrate","trickle","oniceconnectionstatechange","iceState","iceConnectionState","onicecandidate","iceDone","mySdp","localDescription","sdpSent","sendSDP","sdpMid","sdpMLineIndex","ontrack","streams","transceiver","_mid","onremotetrack","onended","trackMutedTimeoutId","ev","transceivers","getTransceivers","_receiver","_track","onmute","onunmute","prepareWebrtc","offer","webrtcError","media","mediaToTracks","simulcast","simulcast2","svc","captureDevices","setRemoteDescription","answer","customizeSdp","createAnswer","setLocalDescription","mediaConstraints","iceRestart","createOffer","prepareWebrtcPeer","replaceTracks","openedConsentDialog","groups","gumGroup","capture","group","audio","video","ondatachannel","channel","nt","trackId","replaceTrack","stream","getAudioTracks","getVideoTracks","consentDialog","constraints","trackConstraints","otherType","otherTrack","otherConstraints","getUserMedia","newDirection","recv","direction","setDirection","myStream","addTrack","webRTCAdapter","browserDetails","browser","addTransceiver","sendEncodings","rid","maxBitrate","scaleResolutionDownBy","parameters","getParameters","encodings","setParameters","scalabilityMode","codec","mimeType","toLowerCase","codecs","getCapabilities","setCodecPreferences","framerate","maxFramerate","senderStreams","createAudioEncodedStreams","readableStream","writableStream","pipeThrough","pipeTo","readable","receiverStreams","dontStop","rt","removeTrack","onlocaltrack","curdir","newdir","getLocalTracks","tr","getRemoteTracks","getVolume","remote","stats","remoteSource","audioLevel","isMuted","mute","videostream","audiostream","getBitrate","bsnow","bsbefore","tsnow","tsbefore","setInterval","inStats","mediaType","bytesReceived","googCodecName","timePassed","bitRate","round","setBitrate","hangupRequest","clearInterval","streamExternal","stopAllTracks","oncleanup","getServer","getSessionId","getInfo","destroy","unload","notifyDestroyed","cleanupHandles","sendBeacon","unbindWebSocket","onUnbindMessage","onUnbindError","attach","ordered","plugin","opaqueId","loopIndex","handleToken","opaque_id","loop_index","started","getId","getPlugin","getRemoteVolume","getLocalVolume","isAudioMuted","muteAudio","unmuteAudio","isVideoMuted","muteVideo","unmuteVideo","setMaxBitrate","handleRemoteJsep","createHandle","useDefaultDependencies","deps","socketCls","proto","arr","fetchOptions","Accept","fetching","timerId","race","parsed","useOldDependencies","jq","jQuery","payload","xhrFields","extend","xhr","keepAudio","audioSend","audioRecv","addAudio","replaceAudio","removeAudio","keepVideo","videoSend","videoRecv","addVideo","replaceVideo","removeVideo","screenshareFrameRate","frameRate","screenshareHeight","height","screenshareWidth","width","ideal","getTracks","mst","trace","usedDependencies","dependencies","listDevices","isGetUserMediaAvailable","enumerateDevices","devices","safariVp8","testpc","offerToReceiveVideo","charSet","randomPoz","charAt","JanusClient","videoRoomPlugin","isOnlyAudio","currentRoomId","remoteFeeds","remoteJseps","remoteFeedsAttachingInProgress","bitrateTimers","emitter","EventEmitter","env","timeoutSessionCallback","JanusEngine","engine","attachVideoConferencingPlugin","isRemote","skipMedia","remoteFeed","localStream","displayName","listen","room","ptype","feed","display","uplink","nacks","msg","feedId","offerParams","publishers","userDisplayName","emit","detachRemoteFeed","onLocalTrack","metadata","onRemoteTrack","channelLabel","_on","eventType","isStreamNoExistedBefore","feedStream","trackToRemove","streamTrack","getPluginId","detachVideoConferencingPlugin","clean","roomId","joinEvent","_resp","leaveEvent","listOnlineParticipants","listRequest","toggleAudioMute","muted","toggleRemoteAudioMute","audioTracks","isRemoteAudioMuted","toggleVideoMute","toggleRemoteVideoMute","videoTracks","isRemoteVideoMuted","sendKeyframeRequest","configureRequest","keyframe","getTracksFromStream","audioTrack","videoTrack","mediaParams","existedStream","createOfferParams","tracksFromStream","concat","tracksFromParams","_jsep","publish","getTracksMidsFromStream","getUserBitrate","resultCallback","getUserVolume","showBitrate","adapterDetails","hideBitrate","ConferenceSession","client","currentUserDisplayName","onParticipantJoined","onParticipantLeft","onRemoteStream","onRemoteTracksUpdated","onDataChannelOpen","onDataChannelMessage","onError","currentPublisherPC","isResolved","createHandler","joinInternal","joinAsListener","onRemoteIceStateChanged","onLocalIceStateChanged","onSlowLink","isExistingParticipant","onParticipantJoinedListener","onParticipantLeftListener","onErrorListener","onDataChannelOpenedListener","onDataChannelMessageListener","onSessionConnectionStateChangedListener","onRemoteConnectionStateChangedListener","onRemoteStreamListener","onRemoteTracksUpdatedListener","onSlowLinkListener","listOfOnlineParticipants","leaveGroup","elementId","upsertStream","shouldUpdateCurrentStream","detachMediaStream","attachMediaStream","getSettings","localTrack","newTrack","pcSenders","switchMediaTracks","device","getRemoteUserBitrate","getRemoteUserVolume","opt","mediaElement","getElementById","srcObject","style","transform","mirror","onloadedmetadata","_event","play","pause","ConferenceClient","sessionsStore","createNewSession","getCurrentSessionToken","getMediaDevices","clearSession","currentSession","DataService","className","isMany","multi","record","createRecord","readPermissions","permissions","isSearch","search_criteria","isCriteria","isOne","MeetingsService","startTimestamp","endTimestamp","defaultParams","toLocaleString","year","month","day","hour","minute","attendees","getRecordings","PushNotificationsService","SubscriptionsService","EventsService","base64Encode","encode","StorageService","blob","createAndUpload","file","content_type","public","isPublic","createParams","blobObject","uri","parseUri","blob_object_access","uploadParams","authority","path","queryKey","decodeURIComponent","upload","markUploaded","getFile","uid","getFileObject","privateUrl","fileUID","publicUrl","parser","strict","loose","exec","source","userInfo","host","port","relative","directory","anchor","_0","UsersService","getV2","signup","resetPassword","listOnline","getOnlineCount","count","filters","dateFields","numberFields","extensions","full_name","facebook_id","twitter_id","phone","tags","external","generateFilter","field","param","WebRTCHelpers","traceWarning","traceError","getVersionFirefox","ua","ffInfo","getVersionSafari","sVer","WebRTCPeerConnection","remoteSDP","state","onStatusClosedChecker","dialingTimer","statsReportTimer","waitingReconnectTimeoutCallback","released","remoteStream","rtcConfiguration","original","startCallTime","onMediaTrackHandler","onIceCandidateHandler","onSignalingStateHandler","onIceConnectionStateHandler","callType","getWrappedStats","signalingState","canTrickleIceCandidates","processIceCandidates","onSessionConnectionStateChanged","clearWaitingReconnectTimer","startWaitingReconnectTimer","release","closeSessionIfAllConnectionsClosed","clearStatsReportTimer","addCandidates","clearDialingTimer","getAndSetLocalSessionDescription","maxBandwidth","offerOptions","sessionDescription","setRTCRtpSenderMaxBandwidth","senders","encoding","startDialingTimer","withOnNotAnswerCallback","dialingCallback","skipIncrement","processOnNotAnswer","processCall","setRemoteSessionDescription","desc","lastResult","getStatsCustom","results","lastResults","onCallStatsReport","sdpRemote","ID","onSuccess","onFail","statistic","local","localVideoSettings","frameHeight","frameWidth","getBitratePerSecond","packetsReceived","framerateMean","framesPerSecond","bytesSent","packetsSent","candidateType","mozLocalTransport","transport","ip","ipAddress","portNumber","getFramesPerSecond","isLocal","framesSent","framesReceived","selector","WebRTCSignalingProvider","chatService","sendCandidate","signalingType","systemCallMessage","WebRTCSession","peerConnections","answerTimer","waitingOfferOrAnswerTimer","acceptCallTime","generateUUID","setMaxBandwidth","peers","peersKeys","all","connectionStateForUser","peerConnection","constrains","prepareExtension","callInternal","accept","clearAnswerTimer","acceptInternal","initiatorID","currentUserID","startWaitingOfferOrAnswerTimer","callerID","signalingProvider","canInitiateIceRestart","processOnCall","rtcSdpType","startAnswerTimer","processOnAccept","processOnReject","clearWaitingOfferOrAnswerTimer","processOnStop","pcKeys","processOnIceCandidates","processOnIceRestart","processOnIceRestartAccept","onUserNotAnswerListener","onCallStatsReportListener","connectionState","closeLocalMediaStream","onSessionCloseListener","isAllClosed","muteStream","unmute","timeWait","timeDiff","min","max","WebRTCClient","signalingProcessor","SessionConnectionState","onDevicesChangeListener","ondevicechange","bandwidth","createAndStoreSession","webRTCSession","callRejectRequest","onCallListener","onAcceptCallListener","onRejectCallListener","onInvalidEventsListener","onStopCallListener","WhiteboardService","getURL","title","paramsOrId","chat_dialog_id","LinkPreviewService","has","linkPreview","images","getHostFromUrl","URL","hostname","ConnectyCube","configMap","utils","storage","pushnotifications","meeting","videochatconference","connectycube","COMPACT","FULL","CREATE","READ","UPDATE","OPEN","OWNER","NOT_ALLOWED","OPEN_FOR_GROUPS","OPEN_FOR_USERS_IDS","IOS","ANDROID","WEB","UPDATED","LAST_MESSAGE","PUBLIC","GROUP","PRIVATE","BROADCAST","MEETING","SENT","DELIVERED","FACEBOOK","TWITTER","FIREBASE_PHONE","FIREBASE_EMAIL","MINUTES","HOURS","DAYS","WEEK","APNS","VOIP","GCM","DEV","PROD"],"mappings":"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","x_google_ignoreList":[25]}