matrix-js-sdk 42.1.0 → 42.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/lib/@types/beacon.d.ts +1 -1
  3. package/lib/@types/beacon.js +1 -1
  4. package/lib/@types/beacon.js.map +1 -1
  5. package/lib/@types/extensible_events.d.ts.map +1 -1
  6. package/lib/@types/extensible_events.js.map +1 -1
  7. package/lib/autodiscovery.js.map +1 -1
  8. package/lib/browser-index.js.map +1 -1
  9. package/lib/client.d.ts +12 -5
  10. package/lib/client.d.ts.map +1 -1
  11. package/lib/client.js +23 -26
  12. package/lib/client.js.map +1 -1
  13. package/lib/common-crypto/key-passphrase.js +1 -1
  14. package/lib/common-crypto/key-passphrase.js.map +1 -1
  15. package/lib/crypto/store/indexeddb-crypto-store-backend.js +2 -1
  16. package/lib/crypto/store/indexeddb-crypto-store-backend.js.map +1 -1
  17. package/lib/crypto/store/indexeddb-crypto-store.d.ts.map +1 -1
  18. package/lib/crypto/store/indexeddb-crypto-store.js +1 -1
  19. package/lib/crypto/store/indexeddb-crypto-store.js.map +1 -1
  20. package/lib/crypto/store/memory-crypto-store.js.map +1 -1
  21. package/lib/embedded.d.ts +16 -0
  22. package/lib/embedded.d.ts.map +1 -1
  23. package/lib/embedded.js +19 -6
  24. package/lib/embedded.js.map +1 -1
  25. package/lib/matrixrtc/MatrixRTCSession.js.map +1 -1
  26. package/lib/matrixrtc/MembershipManager.js.map +1 -1
  27. package/lib/matrixrtc/MembershipManagerActionScheduler.js.map +1 -1
  28. package/lib/matrixrtc/RTCEncryptionManager.js.map +1 -1
  29. package/lib/matrixrtc/ToDeviceKeyTransport.js.map +1 -1
  30. package/lib/matrixrtc/membershipData/rtc.js.map +1 -1
  31. package/lib/matrixrtc/utils.d.ts +0 -1
  32. package/lib/matrixrtc/utils.d.ts.map +1 -1
  33. package/lib/matrixrtc/utils.js +0 -1
  34. package/lib/matrixrtc/utils.js.map +1 -1
  35. package/lib/models/event-timeline-set.js +3 -3
  36. package/lib/models/event-timeline-set.js.map +1 -1
  37. package/lib/models/event.d.ts.map +1 -1
  38. package/lib/models/event.js.map +1 -1
  39. package/lib/models/invites-ignorer.js.map +1 -1
  40. package/lib/models/poll.js.map +1 -1
  41. package/lib/models/read-receipt.js.map +1 -1
  42. package/lib/models/relations-container.d.ts +10 -0
  43. package/lib/models/relations-container.d.ts.map +1 -1
  44. package/lib/models/relations-container.js +39 -17
  45. package/lib/models/relations-container.js.map +1 -1
  46. package/lib/models/relations.js +1 -1
  47. package/lib/models/relations.js.map +1 -1
  48. package/lib/models/room.js +3 -3
  49. package/lib/models/room.js.map +1 -1
  50. package/lib/models/thread.d.ts +3 -0
  51. package/lib/models/thread.d.ts.map +1 -1
  52. package/lib/models/thread.js +36 -3
  53. package/lib/models/thread.js.map +1 -1
  54. package/lib/oauth/authorize.js +1 -1
  55. package/lib/oauth/authorize.js.map +1 -1
  56. package/lib/oauth/index.js +4 -2
  57. package/lib/oauth/index.js.map +1 -1
  58. package/lib/pollingCachedValue.d.ts +77 -0
  59. package/lib/pollingCachedValue.d.ts.map +1 -0
  60. package/lib/pollingCachedValue.js +160 -0
  61. package/lib/pollingCachedValue.js.map +1 -0
  62. package/lib/pushprocessor.js.map +1 -1
  63. package/lib/receipt-accumulator.d.ts.map +1 -1
  64. package/lib/receipt-accumulator.js.map +1 -1
  65. package/lib/rendezvous/MSC4108SignInWithQR.d.ts.map +1 -1
  66. package/lib/rendezvous/MSC4108SignInWithQR.js +2 -3
  67. package/lib/rendezvous/MSC4108SignInWithQR.js.map +1 -1
  68. package/lib/rtcTransportsCachedValue.d.ts +9 -0
  69. package/lib/rtcTransportsCachedValue.d.ts.map +1 -0
  70. package/lib/rtcTransportsCachedValue.js +38 -0
  71. package/lib/rtcTransportsCachedValue.js.map +1 -0
  72. package/lib/rust-crypto/PerSessionKeyBackupDownloader.js.map +1 -1
  73. package/lib/rust-crypto/backup.d.ts +2 -3
  74. package/lib/rust-crypto/backup.d.ts.map +1 -1
  75. package/lib/rust-crypto/backup.js.map +1 -1
  76. package/lib/rust-crypto/index.d.ts +10 -4
  77. package/lib/rust-crypto/index.d.ts.map +1 -1
  78. package/lib/rust-crypto/index.js +20 -3
  79. package/lib/rust-crypto/index.js.map +1 -1
  80. package/lib/rust-crypto/libolm_migration.js.map +1 -1
  81. package/lib/rust-crypto/rust-crypto.js.map +1 -1
  82. package/lib/sliding-sync-sdk.js.map +1 -1
  83. package/lib/sliding-sync.js.map +1 -1
  84. package/lib/store/indexeddb-local-backend.js +1 -1
  85. package/lib/store/indexeddb-local-backend.js.map +1 -1
  86. package/lib/store/indexeddb-store-worker.d.ts.map +1 -1
  87. package/lib/store/indexeddb-store-worker.js +1 -0
  88. package/lib/store/indexeddb-store-worker.js.map +1 -1
  89. package/lib/sync.d.ts.map +1 -1
  90. package/lib/sync.js.map +1 -1
  91. package/lib/utils.d.ts +1 -1
  92. package/lib/utils.d.ts.map +1 -1
  93. package/lib/utils.js +1 -0
  94. package/lib/utils.js.map +1 -1
  95. package/lib/webrtc/call.js.map +1 -1
  96. package/lib/webrtc/groupCall.js.map +1 -1
  97. package/lib/webrtc/mediaHandler.js.map +1 -1
  98. package/lib/webrtc/stats/callStatsReportGatherer.js.map +1 -1
  99. package/lib/webrtc/stats/transportStatsBuilder.js.map +1 -1
  100. package/lib/wellKnownCachedValue.d.ts +8 -0
  101. package/lib/wellKnownCachedValue.d.ts.map +1 -0
  102. package/lib/wellKnownCachedValue.js +34 -0
  103. package/lib/wellKnownCachedValue.js.map +1 -0
  104. package/package.json +4 -4
  105. package/src/@types/beacon.ts +1 -1
  106. package/src/@types/extensible_events.ts +3 -4
  107. package/src/autodiscovery.ts +2 -2
  108. package/src/browser-index.ts +1 -1
  109. package/src/client.ts +48 -40
  110. package/src/common-crypto/key-passphrase.ts +1 -1
  111. package/src/crypto/store/indexeddb-crypto-store-backend.ts +2 -1
  112. package/src/crypto/store/indexeddb-crypto-store.ts +1 -3
  113. package/src/crypto/store/memory-crypto-store.ts +1 -1
  114. package/src/embedded.ts +34 -11
  115. package/src/matrixrtc/MatrixRTCSession.ts +3 -3
  116. package/src/matrixrtc/MembershipManager.ts +1 -1
  117. package/src/matrixrtc/MembershipManagerActionScheduler.ts +1 -1
  118. package/src/matrixrtc/RTCEncryptionManager.ts +2 -2
  119. package/src/matrixrtc/ToDeviceKeyTransport.ts +3 -3
  120. package/src/matrixrtc/membershipData/rtc.ts +1 -1
  121. package/src/matrixrtc/utils.ts +0 -2
  122. package/src/models/event-timeline-set.ts +3 -3
  123. package/src/models/event.ts +7 -10
  124. package/src/models/invites-ignorer.ts +1 -1
  125. package/src/models/poll.ts +1 -1
  126. package/src/models/read-receipt.ts +1 -1
  127. package/src/models/relations-container.ts +55 -19
  128. package/src/models/relations.ts +1 -1
  129. package/src/models/room.ts +9 -9
  130. package/src/models/thread.ts +49 -4
  131. package/src/oauth/authorize.ts +1 -1
  132. package/src/oauth/index.ts +2 -2
  133. package/src/pollingCachedValue.ts +184 -0
  134. package/src/pushprocessor.ts +3 -3
  135. package/src/receipt-accumulator.ts +1 -2
  136. package/src/rendezvous/MSC4108SignInWithQR.ts +3 -4
  137. package/src/rtcTransportsCachedValue.ts +40 -0
  138. package/src/rust-crypto/PerSessionKeyBackupDownloader.ts +1 -1
  139. package/src/rust-crypto/backup.ts +1 -5
  140. package/src/rust-crypto/index.ts +23 -25
  141. package/src/rust-crypto/libolm_migration.ts +1 -1
  142. package/src/rust-crypto/rust-crypto.ts +3 -3
  143. package/src/sliding-sync-sdk.ts +1 -1
  144. package/src/sliding-sync.ts +1 -1
  145. package/src/store/indexeddb-local-backend.ts +1 -1
  146. package/src/store/indexeddb-store-worker.ts +1 -0
  147. package/src/sync.ts +4 -3
  148. package/src/utils.ts +3 -2
  149. package/src/webrtc/call.ts +6 -6
  150. package/src/webrtc/groupCall.ts +7 -7
  151. package/src/webrtc/mediaHandler.ts +1 -1
  152. package/src/webrtc/stats/callStatsReportGatherer.ts +2 -2
  153. package/src/webrtc/stats/transportStatsBuilder.ts +1 -1
  154. package/src/wellKnownCachedValue.ts +34 -0
@@ -1 +1 @@
1
- {"version":3,"file":"embedded.js","names":["roomId"],"sources":["../src/embedded.ts"],"sourcesContent":["/*\nCopyright 2022 The Matrix.org Foundation C.I.C.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\nimport {\n type WidgetApi,\n WidgetApiToWidgetAction,\n WidgetApiResponseError,\n MatrixCapabilities,\n type IWidgetApiRequest,\n type IWidgetApiAcknowledgeResponseData,\n type ISendEventToWidgetActionRequest,\n type ISendToDeviceToWidgetActionRequest,\n type ISendEventFromWidgetResponseData,\n type IWidgetApiRequestData,\n type WidgetApiAction,\n type IWidgetApiResponse,\n type IWidgetApiResponseData,\n type IUpdateStateToWidgetActionRequest,\n UnstableApiVersion,\n} from \"matrix-widget-api\";\n\nimport { MatrixEvent, type IEvent, type IContent, EventStatus } from \"./models/event.ts\";\nimport {\n type ISendEventResponse,\n type SendDelayedEventRequestOpts,\n type SendDelayedEventResponse,\n UpdateDelayedEventAction,\n isSendDelayedEventRequestOpts,\n} from \"./@types/requests.ts\";\nimport { EventType, type StateEvents } from \"./@types/event.ts\";\nimport { logger } from \"./logger.ts\";\nimport {\n MatrixClient,\n ClientEvent,\n type IMatrixClientCreateOpts,\n type IStartClientOpts,\n type SendToDeviceContentMap,\n type IOpenIDToken,\n UNSTABLE_MSC4140_DELAYED_EVENTS,\n} from \"./client.ts\";\nimport { SyncApi, SyncState } from \"./sync.ts\";\nimport { SlidingSyncSdk } from \"./sliding-sync-sdk.ts\";\nimport { ConnectionError, MatrixError } from \"./http-api/errors.ts\";\nimport { User } from \"./models/user.ts\";\nimport { type Room } from \"./models/room.ts\";\nimport { type ToDeviceBatch, type ToDevicePayload } from \"./models/ToDeviceMessage.ts\";\nimport { MapWithDefault, type QueryDict, recursiveMapToObject } from \"./utils.ts\";\nimport { type EmptyObject, TypedEventEmitter, UnsupportedDelayedEventsEndpointError } from \"./matrix.ts\";\n\ninterface IStateEventRequest {\n eventType: string;\n stateKey?: string;\n}\n\nexport interface ICapabilities {\n /**\n * Event types that this client expects to send.\n */\n sendEvent?: string[];\n /**\n * Event types that this client expects to receive.\n */\n receiveEvent?: string[];\n\n /**\n * Message types that this client expects to send, or true for all message\n * types.\n */\n sendMessage?: string[] | true;\n /**\n * Message types that this client expects to receive, or true for all\n * message types.\n */\n receiveMessage?: string[] | true;\n\n /**\n * Types of state events that this client expects to send.\n */\n sendState?: IStateEventRequest[];\n /**\n * Types of state events that this client expects to receive.\n */\n receiveState?: IStateEventRequest[];\n\n /**\n * To-device event types that this client expects to send.\n */\n sendToDevice?: string[];\n /**\n * To-device event types that this client expects to receive.\n */\n receiveToDevice?: string[];\n\n /**\n * Whether this client needs access to TURN servers.\n * @defaultValue false\n */\n turnServers?: boolean;\n\n /**\n * Whether this client needs to be able to send delayed events.\n * @experimental Part of MSC4140 & MSC4157\n * @defaultValue false\n */\n sendDelayedEvents?: boolean;\n\n /**\n * Whether this client needs to be able to update delayed events.\n * @experimental Part of MSC4140 & MSC4157\n * @defaultValue false\n */\n updateDelayedEvents?: boolean;\n\n /**\n * Whether this client needs to be able to send sticky events.\n * @experimental Part of MSC4354 & MSC4407\n * @defaultValue false\n */\n sendSticky?: boolean;\n\n /**\n * Whether this client needs to be able to receive sticky events.\n * @experimental Part of MSC4354 & MSC4407\n * @defaultValue false\n */\n receiveSticky?: boolean;\n}\n\nexport enum RoomWidgetClientEvent {\n PendingEventsChanged = \"PendingEvent.pendingEventsChanged\",\n}\nexport type EventHandlerMap = { [RoomWidgetClientEvent.PendingEventsChanged]: () => void };\n\n/**\n * A MatrixClient that routes its requests through the widget API instead of the\n * real CS API.\n * @experimental This class is considered unstable!\n */\nexport class RoomWidgetClient extends MatrixClient {\n private room?: Room;\n private readonly widgetApiReady: Promise<void>;\n private readonly roomStateSynced: Promise<void>;\n private lifecycle?: AbortController;\n private syncState: SyncState | null = null;\n\n private pendingSendingEventsTxId: { type: string; id: string | undefined; txId: string }[] = [];\n private eventEmitter = new TypedEventEmitter<keyof EventHandlerMap, EventHandlerMap>();\n\n /**\n *\n * @param widgetApi - The widget api to use for communication.\n * @param capabilities - The capabilities the widget client will request.\n * @param roomId - The room id the widget is associated with.\n * @param opts - The configuration options for this client.\n * @param sendContentLoaded - Whether to send a content loaded widget action immediately after initial setup.\n * Set to `false` if the widget uses `waitForIFrameLoad=true` (in this case the client does not expect a content loaded action at all),\n * or if the the widget wants to send the `ContentLoaded` action at a later point in time after the initial setup.\n */\n public constructor(\n private readonly widgetApi: WidgetApi,\n private readonly capabilities: ICapabilities,\n private readonly roomId: string,\n opts: IMatrixClientCreateOpts,\n sendContentLoaded: boolean,\n ) {\n super(opts);\n\n const transportSend = this.widgetApi.transport.send.bind(this.widgetApi.transport);\n this.widgetApi.transport.send = async <\n T extends IWidgetApiRequestData,\n R extends IWidgetApiResponseData = IWidgetApiAcknowledgeResponseData,\n >(\n action: WidgetApiAction,\n data: T,\n ): Promise<R> => {\n try {\n return await transportSend(action, data);\n } catch (error) {\n processAndThrow(error);\n }\n };\n\n const transportSendComplete = this.widgetApi.transport.sendComplete.bind(this.widgetApi.transport);\n this.widgetApi.transport.sendComplete = async <T extends IWidgetApiRequestData, R extends IWidgetApiResponse>(\n action: WidgetApiAction,\n data: T,\n ): Promise<R> => {\n try {\n return await transportSendComplete(action, data);\n } catch (error) {\n processAndThrow(error);\n }\n };\n\n this.widgetApiReady = new Promise<void>((resolve) => this.widgetApi.once(\"ready\", resolve));\n this.roomStateSynced = capabilities.receiveState?.length\n ? new Promise<void>((resolve) =>\n this.widgetApi.once(`action:${WidgetApiToWidgetAction.UpdateState}`, resolve),\n )\n : Promise.resolve();\n\n this.requestInitialCapabilities(capabilities, roomId);\n\n widgetApi.on(`action:${WidgetApiToWidgetAction.SendEvent}`, this.onEvent);\n widgetApi.on(`action:${WidgetApiToWidgetAction.SendToDevice}`, this.onToDevice);\n widgetApi.on(`action:${WidgetApiToWidgetAction.UpdateState}`, this.onStateUpdate);\n\n // Open communication with the host\n widgetApi.start();\n // Send a content loaded event now we've started the widget API\n // Note that element-web currently does not use waitForIFrameLoad=false and so\n // does *not* (yes, that is the right way around) wait for this event. Let's\n // start sending this, then once this has rolled out, we can change element-web to\n // use waitForIFrameLoad=false and have a widget API that's less racy.\n if (sendContentLoaded) widgetApi.sendContentLoaded();\n }\n\n private requestInitialCapabilities(capabilities: ICapabilities, roomId: string): void {\n // Request capabilities for the functionality this client needs to support\n if (\n capabilities.sendEvent?.length ||\n capabilities.receiveEvent?.length ||\n capabilities.sendMessage === true ||\n (Array.isArray(capabilities.sendMessage) && capabilities.sendMessage.length) ||\n capabilities.receiveMessage === true ||\n (Array.isArray(capabilities.receiveMessage) && capabilities.receiveMessage.length) ||\n capabilities.sendState?.length ||\n capabilities.receiveState?.length\n ) {\n this.widgetApi.requestCapabilityForRoomTimeline(roomId);\n }\n capabilities.sendEvent?.forEach((eventType) => this.widgetApi.requestCapabilityToSendEvent(eventType));\n capabilities.receiveEvent?.forEach((eventType) => this.widgetApi.requestCapabilityToReceiveEvent(eventType));\n if (capabilities.sendMessage === true) {\n this.widgetApi.requestCapabilityToSendMessage();\n } else if (Array.isArray(capabilities.sendMessage)) {\n capabilities.sendMessage.forEach((msgType) => this.widgetApi.requestCapabilityToSendMessage(msgType));\n }\n if (capabilities.receiveMessage === true) {\n this.widgetApi.requestCapabilityToReceiveMessage();\n } else if (Array.isArray(capabilities.receiveMessage)) {\n capabilities.receiveMessage.forEach((msgType) => this.widgetApi.requestCapabilityToReceiveMessage(msgType));\n }\n capabilities.sendState?.forEach(({ eventType, stateKey }) =>\n this.widgetApi.requestCapabilityToSendState(eventType, stateKey),\n );\n capabilities.receiveState?.forEach(({ eventType, stateKey }) =>\n this.widgetApi.requestCapabilityToReceiveState(eventType, stateKey),\n );\n capabilities.sendToDevice?.forEach((eventType) => this.widgetApi.requestCapabilityToSendToDevice(eventType));\n capabilities.receiveToDevice?.forEach((eventType) =>\n this.widgetApi.requestCapabilityToReceiveToDevice(eventType),\n );\n if (\n capabilities.sendDelayedEvents &&\n (capabilities.sendEvent?.length ||\n capabilities.sendMessage === true ||\n (Array.isArray(capabilities.sendMessage) && capabilities.sendMessage.length) ||\n capabilities.sendState?.length)\n ) {\n this.widgetApi.requestCapability(MatrixCapabilities.MSC4157SendDelayedEvent);\n }\n if (capabilities.updateDelayedEvents) {\n this.widgetApi.requestCapability(MatrixCapabilities.MSC4157UpdateDelayedEvent);\n }\n if (capabilities.sendSticky) {\n this.widgetApi.requestCapability(MatrixCapabilities.MSC4407SendStickyEvent);\n }\n if (capabilities.receiveSticky) {\n this.widgetApi.requestCapability(MatrixCapabilities.MSC4407ReceiveStickyEvent);\n }\n if (capabilities.turnServers) {\n this.widgetApi.requestCapability(MatrixCapabilities.MSC3846TurnServers);\n }\n }\n\n public async supportUpdateState(): Promise<boolean> {\n return (await this.widgetApi.getClientVersions()).includes(UnstableApiVersion.MSC2762_UPDATE_STATE);\n }\n\n private readonly syncApiResolver = Promise.withResolvers<void>();\n public async startClient(opts: IStartClientOpts = {}): Promise<void> {\n this.lifecycle = new AbortController();\n\n // Create our own user object artificially (instead of waiting for sync)\n // so it's always available, even if the user is not in any rooms etc.\n const userId = this.getUserId();\n if (userId) {\n this.store.storeUser(new User(userId));\n }\n\n // Even though we have no access token and cannot sync, the sync class\n // still has some valuable helper methods that we make use of, so we\n // instantiate it anyways\n if (opts.slidingSync) {\n this.syncApi = new SlidingSyncSdk(opts.slidingSync, this, opts, this.buildSyncApiOptions());\n } else {\n this.syncApi = new SyncApi(this, opts, this.buildSyncApiOptions());\n }\n this.syncApiResolver.resolve();\n\n this.room = this.syncApi.createRoom(this.roomId);\n this.store.storeRoom(this.room);\n\n await this.widgetApiReady;\n\n // sync room state:\n if (await this.supportUpdateState()) {\n // This will resolve once the client driver has sent us all the allowed room state.\n await this.roomStateSynced;\n } else {\n // Backfill the requested events\n // We only get the most recent event for every type + state key combo,\n // so it doesn't really matter what order we inject them in\n await Promise.all(\n this.capabilities.receiveState?.map(async ({ eventType, stateKey }) => {\n const rawEvents = await this.widgetApi.readStateEvents(eventType, undefined, stateKey, [\n this.roomId,\n ]);\n const events = rawEvents.map((rawEvent) => new MatrixEvent(rawEvent as Partial<IEvent>));\n\n if (this.syncApi instanceof SyncApi) {\n // Passing events as `stateAfterEventList` will update the state.\n await this.syncApi.injectRoomEvents(this.room!, undefined, events);\n } else {\n await this.syncApi!.injectRoomEvents(this.room!, events); // Sliding Sync\n }\n events.forEach((event) => {\n this.emit(ClientEvent.Event, event);\n logger.info(`Backfilled event ${event.getId()} ${event.getType()} ${event.getStateKey()}`);\n });\n }) ?? [],\n );\n }\n\n if (opts.clientWellKnownPollPeriod !== undefined) {\n this.clientWellKnownIntervalID = setInterval(() => {\n this.fetchClientWellKnown();\n }, 1000 * opts.clientWellKnownPollPeriod);\n this.fetchClientWellKnown();\n }\n this.setSyncState(SyncState.Syncing);\n logger.info(\"Finished initial sync\");\n\n this.matrixRTC.start();\n\n // Watch for TURN servers, if requested\n if (this.capabilities.turnServers) this.watchTurnServers();\n }\n\n public stopClient(): void {\n this.widgetApi.off(`action:${WidgetApiToWidgetAction.SendEvent}`, this.onEvent);\n this.widgetApi.off(`action:${WidgetApiToWidgetAction.SendToDevice}`, this.onToDevice);\n this.widgetApi.off(`action:${WidgetApiToWidgetAction.UpdateState}`, this.onStateUpdate);\n\n super.stopClient();\n this.lifecycle!.abort(); // Signal to other async tasks that the client has stopped\n }\n\n public async joinRoom(roomIdOrAlias: string): Promise<Room> {\n if (roomIdOrAlias === this.roomId) return this.room!;\n throw new Error(`Unknown room: ${roomIdOrAlias}`);\n }\n\n protected async encryptAndSendEvent(\n room: Room,\n event: MatrixEvent,\n queryDict?: QueryDict,\n ): Promise<ISendEventResponse>;\n protected async encryptAndSendEvent(\n room: Room,\n event: MatrixEvent,\n delayOpts: SendDelayedEventRequestOpts,\n queryDict?: QueryDict,\n ): Promise<ISendEventResponse>;\n protected async encryptAndSendEvent(\n room: Room,\n event: MatrixEvent,\n delayOptsOrQuery?: SendDelayedEventRequestOpts | QueryDict,\n queryDict?: QueryDict,\n ): Promise<ISendEventResponse | SendDelayedEventResponse> {\n let queryOpts = queryDict;\n let delayOpts: SendDelayedEventRequestOpts | undefined;\n if (delayOptsOrQuery && isSendDelayedEventRequestOpts(delayOptsOrQuery)) {\n delayOpts = delayOptsOrQuery;\n } else if (!queryOpts) {\n queryOpts = delayOptsOrQuery;\n }\n\n const stickyDurationMs = queryOpts?.[\"org.matrix.msc4354.sticky_duration_ms\"];\n if (stickyDurationMs !== undefined && typeof stickyDurationMs !== \"number\") {\n throw new Error(\"Sticky duration must be a number when defined\");\n }\n // This is save since we just checked that above\n // We need the additional as assertion for the EW linter to be happy.\n // It is not capable of implying the type based on the throw if `stickyDurationMs !== undefined && typeof stickyDurationMs !== \"number\"`\n // above\n const stickyDurationMsAsNumber: number | undefined = stickyDurationMs as number | undefined;\n\n // We need to extend the content with the redacts parameter\n // The js sdk uses event.redacts but the widget api uses event.content.redacts\n // This will be converted back to event.redacts in the widget driver.\n const content = event.event.redacts\n ? { ...event.getContent(), redacts: event.event.redacts }\n : event.getContent();\n\n // Delayed event special case.\n if (delayOpts) {\n // TODO: updatePendingEvent for delayed events?\n const response = await this.widgetApi\n .sendRoomEvent(\n event.getType(),\n content,\n room.roomId,\n \"delay\" in delayOpts ? delayOpts.delay : undefined,\n \"parent_delay_id\" in delayOpts ? delayOpts.parent_delay_id : undefined,\n stickyDurationMsAsNumber,\n )\n .catch(timeoutToConnectionError);\n return this.validateSendDelayedEventResponse(response);\n }\n\n const txId = event.getTxnId();\n // Add the txnId to the pending list (still with unknown evID)\n if (txId) this.pendingSendingEventsTxId.push({ type: event.getType(), id: undefined, txId });\n\n let response: ISendEventFromWidgetResponseData;\n try {\n response = await this.widgetApi\n .sendRoomEvent(event.getType(), content, room.roomId, undefined, undefined, stickyDurationMsAsNumber)\n .catch(timeoutToConnectionError);\n } catch (e) {\n this.updatePendingEventStatus(room, event, EventStatus.NOT_SENT);\n throw e;\n }\n // This also checks for an event id on the response\n room.updatePendingEvent(event, EventStatus.SENT, response.event_id);\n\n // Update the pending events list with the eventId\n this.pendingSendingEventsTxId.forEach((p) => {\n if (p.txId === txId) p.id = response.event_id;\n });\n this.eventEmitter.emit(RoomWidgetClientEvent.PendingEventsChanged);\n\n return { event_id: response.event_id! };\n }\n\n public async sendStateEvent(\n roomId: string,\n eventType: string,\n content: any,\n stateKey = \"\",\n ): Promise<ISendEventResponse> {\n const response = await this.widgetApi\n .sendStateEvent(eventType, stateKey, content, roomId)\n .catch(timeoutToConnectionError);\n if (response.event_id === undefined) {\n throw new Error(\"'event_id' absent from response to an event request\");\n }\n return { event_id: response.event_id };\n }\n\n /**\n * @experimental This currently relies on an unstable MSC (MSC4140).\n */\n public async _unstable_sendDelayedStateEvent<K extends keyof StateEvents>(\n roomId: string,\n delayOpts: SendDelayedEventRequestOpts,\n eventType: K,\n content: StateEvents[K],\n stateKey = \"\",\n ): Promise<SendDelayedEventResponse> {\n if (!(await this.doesServerSupportUnstableFeature(UNSTABLE_MSC4140_DELAYED_EVENTS))) {\n throw new UnsupportedDelayedEventsEndpointError(\n \"Server does not support the delayed events API\",\n \"sendDelayedStateEvent\",\n );\n }\n\n const response = await this.widgetApi\n .sendStateEvent(\n eventType,\n stateKey,\n content,\n roomId,\n \"delay\" in delayOpts ? delayOpts.delay : undefined,\n \"parent_delay_id\" in delayOpts ? delayOpts.parent_delay_id : undefined,\n )\n .catch(timeoutToConnectionError);\n return this.validateSendDelayedEventResponse(response);\n }\n\n private validateSendDelayedEventResponse(response: ISendEventFromWidgetResponseData): SendDelayedEventResponse {\n if (response.delay_id === undefined) {\n throw new Error(\"'delay_id' absent from response to a delayed event request\");\n }\n return { delay_id: response.delay_id };\n }\n\n /**\n * @experimental This currently relies on an unstable MSC (MSC4140).\n * @deprecated Instead use one of:\n * - {@link _unstable_cancelScheduledDelayedEvent}\n * - {@link _unstable_restartScheduledDelayedEvent}\n * - {@link _unstable_sendScheduledDelayedEvent}\n */\n public async _unstable_updateDelayedEvent(delayId: string, action: UpdateDelayedEventAction): Promise<EmptyObject> {\n if (!(await this.doesServerSupportUnstableFeature(UNSTABLE_MSC4140_DELAYED_EVENTS))) {\n throw new UnsupportedDelayedEventsEndpointError(\n \"Server does not support the delayed events API\",\n \"updateDelayedEvent\",\n );\n }\n\n switch (action) {\n case UpdateDelayedEventAction.Cancel:\n await this.widgetApi.cancelScheduledDelayedEvent(delayId).catch(timeoutToConnectionError);\n break;\n case UpdateDelayedEventAction.Restart:\n await this.widgetApi.restartScheduledDelayedEvent(delayId).catch(timeoutToConnectionError);\n break;\n case UpdateDelayedEventAction.Send:\n await this.widgetApi.sendScheduledDelayedEvent(delayId).catch(timeoutToConnectionError);\n break;\n }\n return {};\n }\n\n /**\n * @experimental This currently relies on an unstable MSC (MSC4140).\n */\n public async _unstable_cancelScheduledDelayedEvent(delayId: string): Promise<EmptyObject> {\n if (!(await this.doesServerSupportUnstableFeature(UNSTABLE_MSC4140_DELAYED_EVENTS))) {\n throw new UnsupportedDelayedEventsEndpointError(\n \"Server does not support the delayed events API\",\n \"cancelScheduledDelayedEvent\",\n );\n }\n\n await this.widgetApi.cancelScheduledDelayedEvent(delayId).catch(timeoutToConnectionError);\n return {};\n }\n\n /**\n * @experimental This currently relies on an unstable MSC (MSC4140).\n */\n public async _unstable_restartScheduledDelayedEvent(delayId: string): Promise<EmptyObject> {\n if (!(await this.doesServerSupportUnstableFeature(UNSTABLE_MSC4140_DELAYED_EVENTS))) {\n throw new UnsupportedDelayedEventsEndpointError(\n \"Server does not support the delayed events API\",\n \"restartScheduledDelayedEvent\",\n );\n }\n\n await this.widgetApi.restartScheduledDelayedEvent(delayId).catch(timeoutToConnectionError);\n return {};\n }\n\n /**\n * @experimental This currently relies on an unstable MSC (MSC4140).\n */\n public async _unstable_sendScheduledDelayedEvent(delayId: string): Promise<EmptyObject> {\n if (!(await this.doesServerSupportUnstableFeature(UNSTABLE_MSC4140_DELAYED_EVENTS))) {\n throw new UnsupportedDelayedEventsEndpointError(\n \"Server does not support the delayed events API\",\n \"sendScheduledDelayedEvent\",\n );\n }\n\n await this.widgetApi.sendScheduledDelayedEvent(delayId).catch(timeoutToConnectionError);\n return {};\n }\n\n /**\n * by {@link MatrixClient.encryptAndSendToDevice}.\n */\n public async encryptAndSendToDevice(\n eventType: string,\n devices: { userId: string; deviceId: string }[],\n payload: ToDevicePayload,\n ): Promise<void> {\n // map: user Id → device Id → payload\n const contentMap: MapWithDefault<string, Map<string, ToDevicePayload>> = new MapWithDefault(() => new Map());\n for (const { userId, deviceId } of devices) {\n contentMap.getOrCreate(userId).set(deviceId, payload);\n }\n\n await this.widgetApi\n .sendToDevice(eventType, true, recursiveMapToObject(contentMap))\n .catch(timeoutToConnectionError);\n }\n\n public async sendToDevice(eventType: string, contentMap: SendToDeviceContentMap): Promise<EmptyObject> {\n await this.widgetApi\n .sendToDevice(eventType, false, recursiveMapToObject(contentMap))\n .catch(timeoutToConnectionError);\n return {};\n }\n\n public async getOpenIdToken(): Promise<IOpenIDToken> {\n const token = await this.widgetApi.requestOpenIDConnectToken().catch(timeoutToConnectionError);\n // the IOpenIDCredentials from the widget-api and IOpenIDToken form the matrix-js-sdk are compatible.\n // we still recreate the token to make this transparent and catch'able by the linter in case the types change in the future.\n return <IOpenIDToken>{\n access_token: token.access_token,\n expires_in: token.expires_in,\n matrix_server_name: token.matrix_server_name,\n token_type: token.token_type,\n };\n }\n\n public async queueToDevice({ eventType, batch }: ToDeviceBatch): Promise<void> {\n // map: user Id → device Id → payload\n const contentMap: MapWithDefault<string, Map<string, ToDevicePayload>> = new MapWithDefault(() => new Map());\n for (const { userId, deviceId, payload } of batch) {\n contentMap.getOrCreate(userId).set(deviceId, payload);\n }\n\n await this.widgetApi\n .sendToDevice(eventType, false, recursiveMapToObject(contentMap))\n .catch(timeoutToConnectionError);\n }\n\n /**\n * Send an event to a specific list of devices via the widget API. Optionally encrypts the event.\n *\n * If you are using a full MatrixClient you would be calling {@link MatrixClient.getCrypto().encryptToDeviceMessages()} followed\n * by {@link MatrixClient.queueToDevice}.\n *\n * However, this is combined into a single step when running as an embedded widget client. So, we expose this method for those\n * that need it.\n *\n * @param eventType - Type of the event to send.\n * @param encrypted - Whether the event should be encrypted.\n * @param contentMap - The content to send. Map from user_id to device_id to content object.\n */\n public async sendToDeviceViaWidgetApi(\n eventType: string,\n encrypted: boolean,\n contentMap: SendToDeviceContentMap,\n ): Promise<void> {\n await this.widgetApi\n .sendToDevice(eventType, encrypted, recursiveMapToObject(contentMap))\n .catch(timeoutToConnectionError);\n }\n\n // Overridden since we get TURN servers automatically over the widget API,\n // and this method would otherwise complain about missing an access token\n public async checkTurnServers(): Promise<boolean> {\n return this.turnServers.length > 0;\n }\n\n // Overridden since we 'sync' manually without the sync API\n public getSyncState(): SyncState | null {\n return this.syncState;\n }\n\n private setSyncState(state: SyncState): void {\n const oldState = this.syncState;\n this.syncState = state;\n this.emit(ClientEvent.Sync, state, oldState);\n }\n\n private async ack(ev: CustomEvent<IWidgetApiRequest>): Promise<void> {\n this.widgetApi.transport.reply<IWidgetApiAcknowledgeResponseData>(ev.detail, {});\n }\n\n private updateTxId = async (event: MatrixEvent): Promise<void> => {\n // We update the txId for remote echos that originate from this client.\n // This happens with the help of `pendingSendingEventsTxId` where we store all events that are currently sending\n // with their widget txId and once ready the final evId.\n if (\n // This could theoretically be an event send by this device\n // In that case we need to update the txId of the event because the embedded client/widget\n // knows this event with a different transaction Id than what was used by the host client.\n event.getSender() === this.getUserId() &&\n // We optimize by not blocking events from types that we have not send\n // with this client.\n this.pendingSendingEventsTxId.some((p) => event.getType() === p.type)\n ) {\n // Compare by event Id if we have a matching pending event where we know the txId.\n let matchingTxId = this.pendingSendingEventsTxId.find((p) => p.id === event.getId())?.txId;\n // Block any further processing of this event until we have received the sending response.\n // -> until we know the event id.\n // -> until we have not pending events anymore.\n while (!matchingTxId && this.pendingSendingEventsTxId.length > 0) {\n // Recheck whenever the PendingEventsChanged\n await new Promise<void>((resolve) =>\n this.eventEmitter.once(RoomWidgetClientEvent.PendingEventsChanged, () => resolve()),\n );\n matchingTxId = this.pendingSendingEventsTxId.find((p) => p.id === event.getId())?.txId;\n }\n\n // We found the correct txId: we update the event and delete the entry of the pending events.\n if (matchingTxId) {\n event.setTxnId(matchingTxId);\n event.setUnsigned({ ...event.getUnsigned(), transaction_id: matchingTxId });\n }\n this.pendingSendingEventsTxId = this.pendingSendingEventsTxId.filter((p) => p.id !== event.getId());\n\n // Emit once there are no pending events anymore to release all other events that got\n // awaited in the `while (!matchingTxId && this.pendingSendingEventsTxId.length > 0)` loop\n // but are not send by this client.\n if (this.pendingSendingEventsTxId.length === 0) {\n this.eventEmitter.emit(RoomWidgetClientEvent.PendingEventsChanged);\n }\n }\n };\n\n private onEvent = async (ev: CustomEvent<ISendEventToWidgetActionRequest>): Promise<void> => {\n ev.preventDefault();\n\n // Verify the room ID matches, since it's possible for the client to\n // send us events from other rooms if this widget is always on screen\n if (ev.detail.data.room_id === this.roomId) {\n const event = new MatrixEvent(ev.detail.data as Partial<IEvent>);\n\n // Only inject once we have update the txId\n await this.updateTxId(event);\n await this.syncApiResolver.promise;\n if (this.syncApi instanceof SyncApi) {\n if (await this.supportUpdateState()) {\n await this.syncApi.injectRoomEvents(this.room!, undefined, [], [event]);\n } else {\n // Passing undefined for `stateAfterEventList` will make `injectRoomEvents` run in legacy mode\n // -> state events in `timelineEventList` will update the state.\n await this.syncApi.injectRoomEvents(this.room!, [], undefined, [event]);\n }\n } else {\n // Sliding Sync\n if (await this.supportUpdateState()) {\n await this.syncApi!.injectRoomEvents(this.room!, [], [event]);\n } else {\n logger.error(\n \"slididng sync cannot be used in widget mode if the client widget driver does not support the version: 'org.matrix.msc2762_update_state'\",\n );\n }\n }\n\n this.emit(ClientEvent.Event, event);\n if (event.unstableStickyInfo !== undefined) this.room!._unstable_addStickyEvents([event]);\n this.setSyncState(SyncState.Syncing);\n logger.info(`Received event ${event.getId()} ${event.getType()}`);\n } else {\n const { event_id: eventId, room_id: roomId } = ev.detail.data;\n logger.info(`Received event ${eventId} for a different room ${roomId}; discarding`);\n }\n\n await this.ack(ev);\n };\n\n private onToDevice = async (ev: CustomEvent<ISendToDeviceToWidgetActionRequest>): Promise<void> => {\n ev.preventDefault();\n\n const event = new MatrixEvent({\n type: ev.detail.data.type,\n sender: ev.detail.data.sender,\n content: ev.detail.data.content as IContent,\n });\n // Mark the event as encrypted if it was, using fake contents and keys since those are unknown to us\n if (ev.detail.data.encrypted) event.makeEncrypted(EventType.RoomMessageEncrypted, {}, \"\", \"\");\n\n this.emit(ClientEvent.ToDeviceEvent, event);\n this.setSyncState(SyncState.Syncing);\n await this.ack(ev);\n };\n\n private onStateUpdate = async (ev: CustomEvent<IUpdateStateToWidgetActionRequest>): Promise<void> => {\n ev.preventDefault();\n if (!(await this.supportUpdateState())) {\n logger.warn(\n \"received update_state widget action but the widget driver did not claim to support 'org.matrix.msc2762_update_state'\",\n );\n }\n await this.syncApiResolver.promise;\n for (const rawEvent of ev.detail.data.state) {\n // Verify the room ID matches, since it's possible for the client to\n // send us state updates from other rooms if this widget is always\n // on screen\n if (rawEvent.room_id === this.roomId) {\n const event = new MatrixEvent(rawEvent as Partial<IEvent>);\n\n if (this.syncApi instanceof SyncApi) {\n await this.syncApi.injectRoomEvents(this.room!, undefined, [event]);\n } else {\n // Sliding Sync\n await this.syncApi!.injectRoomEvents(this.room!, [event]);\n }\n logger.debug(`Updated state entry ${event.getType()} ${event.getStateKey()} to ${event.getId()}`);\n } else {\n const { event_id: eventId, room_id: roomId } = ev.detail.data;\n logger.info(`Received state entry ${eventId} for a different room ${roomId}; discarding`);\n }\n }\n\n await this.ack(ev);\n };\n\n private async watchTurnServers(): Promise<void> {\n const servers = this.widgetApi.getTurnServers();\n const onClientStopped = (): void => {\n servers.return(undefined);\n };\n this.lifecycle!.signal.addEventListener(\"abort\", onClientStopped);\n\n try {\n for await (const server of servers) {\n this.turnServers = [\n {\n urls: server.uris,\n username: server.username,\n credential: server.password,\n },\n ];\n this.emit(ClientEvent.TurnServers, this.turnServers);\n logger.log(`Received TURN server: ${server.uris}`);\n }\n } catch (e) {\n logger.warn(\"Error watching TURN servers\", e);\n } finally {\n this.lifecycle!.signal.removeEventListener(\"abort\", onClientStopped);\n }\n }\n}\n\nfunction processAndThrow(error: unknown): never {\n if (error instanceof WidgetApiResponseError && error.data.matrix_api_error) {\n throw MatrixError.fromWidgetApiErrorData(error.data.matrix_api_error);\n } else {\n throw error;\n }\n}\n\n/**\n * This converts an \"Request timed out\" error from the PostmessageTransport into a ConnectionError.\n * It either throws the original error or a new ConnectionError.\n **/\nfunction timeoutToConnectionError(error: unknown): never {\n // TODO: this should not check on error.message but instead it should be a specific type\n // error instanceof WidgetTimeoutError\n if (error instanceof Error && error.message === \"Request timed out\") {\n throw new ConnectionError(\"widget api timeout\");\n }\n throw error;\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"embedded.js","names":["roomId"],"sources":["../src/embedded.ts"],"sourcesContent":["/*\nCopyright 2022 The Matrix.org Foundation C.I.C.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\nimport {\n type WidgetApi,\n WidgetApiToWidgetAction,\n WidgetApiResponseError,\n MatrixCapabilities,\n type IWidgetApiRequest,\n type IWidgetApiAcknowledgeResponseData,\n type ISendEventToWidgetActionRequest,\n type ISendToDeviceToWidgetActionRequest,\n type ISendEventFromWidgetResponseData,\n type IWidgetApiRequestData,\n type WidgetApiAction,\n type IWidgetApiResponse,\n type IWidgetApiResponseData,\n type IUpdateStateToWidgetActionRequest,\n UnstableApiVersion,\n} from \"matrix-widget-api\";\n\nimport { type Transport } from \"./matrixrtc/index.ts\";\nimport { MatrixEvent, type IEvent, EventStatus } from \"./models/event.ts\";\nimport {\n type ISendEventResponse,\n type SendDelayedEventRequestOpts,\n type SendDelayedEventResponse,\n UpdateDelayedEventAction,\n isSendDelayedEventRequestOpts,\n} from \"./@types/requests.ts\";\nimport { EventType, type StateEvents } from \"./@types/event.ts\";\nimport { logger } from \"./logger.ts\";\nimport {\n MatrixClient,\n ClientEvent,\n type IMatrixClientCreateOpts,\n type IStartClientOpts,\n type SendToDeviceContentMap,\n type IOpenIDToken,\n UNSTABLE_MSC4140_DELAYED_EVENTS,\n} from \"./client.ts\";\nimport { SyncApi, SyncState } from \"./sync.ts\";\nimport { SlidingSyncSdk } from \"./sliding-sync-sdk.ts\";\nimport { ConnectionError, MatrixError } from \"./http-api/errors.ts\";\nimport { User } from \"./models/user.ts\";\nimport { type Room } from \"./models/room.ts\";\nimport { type ToDeviceBatch, type ToDevicePayload } from \"./models/ToDeviceMessage.ts\";\nimport { MapWithDefault, type QueryDict, recursiveMapToObject } from \"./utils.ts\";\nimport { type EmptyObject, TypedEventEmitter, UnsupportedDelayedEventsEndpointError } from \"./matrix.ts\";\n\ninterface IStateEventRequest {\n eventType: string;\n stateKey?: string;\n}\n\nexport interface ICapabilities {\n /**\n * Event types that this client expects to send.\n */\n sendEvent?: string[];\n /**\n * Event types that this client expects to receive.\n */\n receiveEvent?: string[];\n\n /**\n * Message types that this client expects to send, or true for all message\n * types.\n */\n sendMessage?: string[] | true;\n /**\n * Message types that this client expects to receive, or true for all\n * message types.\n */\n receiveMessage?: string[] | true;\n\n /**\n * Types of state events that this client expects to send.\n */\n sendState?: IStateEventRequest[];\n /**\n * Types of state events that this client expects to receive.\n */\n receiveState?: IStateEventRequest[];\n\n /**\n * To-device event types that this client expects to send.\n */\n sendToDevice?: string[];\n /**\n * To-device event types that this client expects to receive.\n */\n receiveToDevice?: string[];\n\n /**\n * Whether this client needs access to TURN servers.\n * @defaultValue false\n */\n turnServers?: boolean;\n\n /**\n * Whether this client needs to be able to send delayed events.\n * @experimental Part of MSC4140 & MSC4157\n * @defaultValue false\n */\n sendDelayedEvents?: boolean;\n\n /**\n * Whether this client needs to be able to update delayed events.\n * @experimental Part of MSC4140 & MSC4157\n * @defaultValue false\n */\n updateDelayedEvents?: boolean;\n\n /**\n * Whether this client needs to be able to send sticky events.\n * @experimental Part of MSC4354 & MSC4407\n * @defaultValue false\n */\n sendSticky?: boolean;\n\n /**\n * Whether this client needs to be able to receive sticky events.\n * @experimental Part of MSC4354 & MSC4407\n * @defaultValue false\n */\n receiveSticky?: boolean;\n\n /**\n * Whether this client needs to be able to discover the RTC transports the host can reach.\n * @experimental Part of MSC4515\n * @defaultValue false\n */\n rtcTransports?: boolean;\n}\n\nexport enum RoomWidgetClientEvent {\n PendingEventsChanged = \"PendingEvent.pendingEventsChanged\",\n}\nexport type EventHandlerMap = { [RoomWidgetClientEvent.PendingEventsChanged]: () => void };\n\n/**\n * A MatrixClient that routes its requests through the widget API instead of the\n * real CS API.\n * @experimental This class is considered unstable!\n */\nexport class RoomWidgetClient extends MatrixClient {\n private room?: Room;\n private readonly widgetApiReady: Promise<void>;\n private readonly roomStateSynced: Promise<void>;\n private lifecycle?: AbortController;\n private syncState: SyncState | null = null;\n\n private pendingSendingEventsTxId: { type: string; id: string | undefined; txId: string }[] = [];\n private eventEmitter = new TypedEventEmitter<keyof EventHandlerMap, EventHandlerMap>();\n\n /**\n *\n * @param widgetApi - The widget api to use for communication.\n * @param capabilities - The capabilities the widget client will request.\n * @param roomId - The room id the widget is associated with.\n * @param opts - The configuration options for this client.\n * @param sendContentLoaded - Whether to send a content loaded widget action immediately after initial setup.\n * Set to `false` if the widget uses `waitForIFrameLoad=true` (in this case the client does not expect a content loaded action at all),\n * or if the the widget wants to send the `ContentLoaded` action at a later point in time after the initial setup.\n */\n public constructor(\n private readonly widgetApi: WidgetApi,\n private readonly capabilities: ICapabilities,\n private readonly roomId: string,\n opts: IMatrixClientCreateOpts,\n sendContentLoaded: boolean,\n ) {\n super(opts);\n\n const transportSend = this.widgetApi.transport.send.bind(this.widgetApi.transport);\n this.widgetApi.transport.send = async <\n T extends IWidgetApiRequestData,\n R extends IWidgetApiResponseData = IWidgetApiAcknowledgeResponseData,\n >(\n action: WidgetApiAction,\n data: T,\n ): Promise<R> => {\n try {\n return await transportSend(action, data);\n } catch (error) {\n processAndThrow(error);\n }\n };\n\n const transportSendComplete = this.widgetApi.transport.sendComplete.bind(this.widgetApi.transport);\n this.widgetApi.transport.sendComplete = async <T extends IWidgetApiRequestData, R extends IWidgetApiResponse>(\n action: WidgetApiAction,\n data: T,\n ): Promise<R> => {\n try {\n return await transportSendComplete(action, data);\n } catch (error) {\n processAndThrow(error);\n }\n };\n\n this.widgetApiReady = new Promise<void>((resolve) => this.widgetApi.once(\"ready\", resolve));\n this.roomStateSynced = capabilities.receiveState?.length\n ? new Promise<void>((resolve) =>\n this.widgetApi.once(`action:${WidgetApiToWidgetAction.UpdateState}`, resolve),\n )\n : Promise.resolve();\n\n this.requestInitialCapabilities(capabilities, roomId);\n\n widgetApi.on(`action:${WidgetApiToWidgetAction.SendEvent}`, this.onEvent);\n widgetApi.on(`action:${WidgetApiToWidgetAction.SendToDevice}`, this.onToDevice);\n widgetApi.on(`action:${WidgetApiToWidgetAction.UpdateState}`, this.onStateUpdate);\n\n // Open communication with the host\n widgetApi.start();\n // Send a content loaded event now we've started the widget API\n // Note that element-web currently does not use waitForIFrameLoad=false and so\n // does *not* (yes, that is the right way around) wait for this event. Let's\n // start sending this, then once this has rolled out, we can change element-web to\n // use waitForIFrameLoad=false and have a widget API that's less racy.\n if (sendContentLoaded) widgetApi.sendContentLoaded();\n }\n\n private requestInitialCapabilities(capabilities: ICapabilities, roomId: string): void {\n // Request capabilities for the functionality this client needs to support\n if (\n capabilities.sendEvent?.length ||\n capabilities.receiveEvent?.length ||\n capabilities.sendMessage === true ||\n (Array.isArray(capabilities.sendMessage) && capabilities.sendMessage.length) ||\n capabilities.receiveMessage === true ||\n (Array.isArray(capabilities.receiveMessage) && capabilities.receiveMessage.length) ||\n capabilities.sendState?.length ||\n capabilities.receiveState?.length\n ) {\n this.widgetApi.requestCapabilityForRoomTimeline(roomId);\n }\n capabilities.sendEvent?.forEach((eventType) => this.widgetApi.requestCapabilityToSendEvent(eventType));\n capabilities.receiveEvent?.forEach((eventType) => this.widgetApi.requestCapabilityToReceiveEvent(eventType));\n if (capabilities.sendMessage === true) {\n this.widgetApi.requestCapabilityToSendMessage();\n } else if (Array.isArray(capabilities.sendMessage)) {\n capabilities.sendMessage.forEach((msgType) => this.widgetApi.requestCapabilityToSendMessage(msgType));\n }\n if (capabilities.receiveMessage === true) {\n this.widgetApi.requestCapabilityToReceiveMessage();\n } else if (Array.isArray(capabilities.receiveMessage)) {\n capabilities.receiveMessage.forEach((msgType) => this.widgetApi.requestCapabilityToReceiveMessage(msgType));\n }\n capabilities.sendState?.forEach(({ eventType, stateKey }) =>\n this.widgetApi.requestCapabilityToSendState(eventType, stateKey),\n );\n capabilities.receiveState?.forEach(({ eventType, stateKey }) =>\n this.widgetApi.requestCapabilityToReceiveState(eventType, stateKey),\n );\n capabilities.sendToDevice?.forEach((eventType) => this.widgetApi.requestCapabilityToSendToDevice(eventType));\n capabilities.receiveToDevice?.forEach((eventType) =>\n this.widgetApi.requestCapabilityToReceiveToDevice(eventType),\n );\n if (\n capabilities.sendDelayedEvents &&\n (capabilities.sendEvent?.length ||\n capabilities.sendMessage === true ||\n (Array.isArray(capabilities.sendMessage) && capabilities.sendMessage.length) ||\n capabilities.sendState?.length)\n ) {\n this.widgetApi.requestCapability(MatrixCapabilities.MSC4157SendDelayedEvent);\n }\n if (capabilities.updateDelayedEvents) {\n this.widgetApi.requestCapability(MatrixCapabilities.MSC4157UpdateDelayedEvent);\n }\n if (capabilities.sendSticky) {\n this.widgetApi.requestCapability(MatrixCapabilities.MSC4407SendStickyEvent);\n }\n if (capabilities.receiveSticky) {\n this.widgetApi.requestCapability(MatrixCapabilities.MSC4407ReceiveStickyEvent);\n }\n if (capabilities.turnServers) {\n this.widgetApi.requestCapability(MatrixCapabilities.MSC3846TurnServers);\n }\n if (capabilities.rtcTransports) {\n this.widgetApi.requestCapability(MatrixCapabilities.MSC4515RtcTransports);\n }\n }\n\n public async supportUpdateState(): Promise<boolean> {\n return (await this.widgetApi.getClientVersions()).includes(UnstableApiVersion.MSC2762_UPDATE_STATE);\n }\n\n private readonly syncApiResolver = Promise.withResolvers<void>();\n public async startClient(opts: IStartClientOpts = {}): Promise<void> {\n this.lifecycle = new AbortController();\n\n // Create our own user object artificially (instead of waiting for sync)\n // so it's always available, even if the user is not in any rooms etc.\n const userId = this.getUserId();\n if (userId) {\n this.store.storeUser(new User(userId));\n }\n\n // Even though we have no access token and cannot sync, the sync class\n // still has some valuable helper methods that we make use of, so we\n // instantiate it anyways\n if (opts.slidingSync) {\n this.syncApi = new SlidingSyncSdk(opts.slidingSync, this, opts, this.buildSyncApiOptions());\n } else {\n this.syncApi = new SyncApi(this, opts, this.buildSyncApiOptions());\n }\n this.syncApiResolver.resolve();\n\n this.room = this.syncApi.createRoom(this.roomId);\n this.store.storeRoom(this.room);\n\n await this.widgetApiReady;\n\n // sync room state:\n if (await this.supportUpdateState()) {\n // This will resolve once the client driver has sent us all the allowed room state.\n await this.roomStateSynced;\n } else {\n // Backfill the requested events\n // We only get the most recent event for every type + state key combo,\n // so it doesn't really matter what order we inject them in\n await Promise.all(\n this.capabilities.receiveState?.map(async ({ eventType, stateKey }) => {\n const rawEvents = await this.widgetApi.readStateEvents(eventType, undefined, stateKey, [\n this.roomId,\n ]);\n const events = rawEvents.map((rawEvent) => new MatrixEvent(rawEvent as Partial<IEvent>));\n\n if (this.syncApi instanceof SyncApi) {\n // Passing events as `stateAfterEventList` will update the state.\n await this.syncApi.injectRoomEvents(this.room!, undefined, events);\n } else {\n await this.syncApi!.injectRoomEvents(this.room!, events); // Sliding Sync\n }\n events.forEach((event) => {\n this.emit(ClientEvent.Event, event);\n logger.info(`Backfilled event ${event.getId()} ${event.getType()} ${event.getStateKey()}`);\n });\n }) ?? [],\n );\n }\n\n this.cachedWellKnown.start(\n opts.clientWellKnownPollPeriod !== undefined ? 1000 * opts.clientWellKnownPollPeriod : undefined,\n );\n this.setSyncState(SyncState.Syncing);\n logger.info(\"Finished initial sync\");\n\n this.matrixRTC.start();\n\n // Watch for TURN servers, if requested\n if (this.capabilities.turnServers) this.watchTurnServers();\n }\n\n public stopClient(): void {\n this.widgetApi.off(`action:${WidgetApiToWidgetAction.SendEvent}`, this.onEvent);\n this.widgetApi.off(`action:${WidgetApiToWidgetAction.SendToDevice}`, this.onToDevice);\n this.widgetApi.off(`action:${WidgetApiToWidgetAction.UpdateState}`, this.onStateUpdate);\n\n super.stopClient();\n this.lifecycle!.abort(); // Signal to other async tasks that the client has stopped\n }\n\n public async joinRoom(roomIdOrAlias: string): Promise<Room> {\n if (roomIdOrAlias === this.roomId) return this.room!;\n throw new Error(`Unknown room: ${roomIdOrAlias}`);\n }\n\n protected async encryptAndSendEvent(\n room: Room,\n event: MatrixEvent,\n queryDict?: QueryDict,\n ): Promise<ISendEventResponse>;\n protected async encryptAndSendEvent(\n room: Room,\n event: MatrixEvent,\n delayOpts: SendDelayedEventRequestOpts,\n queryDict?: QueryDict,\n ): Promise<ISendEventResponse>;\n protected async encryptAndSendEvent(\n room: Room,\n event: MatrixEvent,\n delayOptsOrQuery?: SendDelayedEventRequestOpts | QueryDict,\n queryDict?: QueryDict,\n ): Promise<ISendEventResponse | SendDelayedEventResponse> {\n let queryOpts = queryDict;\n let delayOpts: SendDelayedEventRequestOpts | undefined;\n if (delayOptsOrQuery && isSendDelayedEventRequestOpts(delayOptsOrQuery)) {\n delayOpts = delayOptsOrQuery;\n } else if (!queryOpts) {\n queryOpts = delayOptsOrQuery;\n }\n\n const stickyDurationMs = queryOpts?.[\"org.matrix.msc4354.sticky_duration_ms\"];\n if (stickyDurationMs !== undefined && typeof stickyDurationMs !== \"number\") {\n throw new Error(\"Sticky duration must be a number when defined\");\n }\n // This is save since we just checked that above\n // We need the additional as assertion for the EW linter to be happy.\n // It is not capable of implying the type based on the throw if `stickyDurationMs !== undefined && typeof stickyDurationMs !== \"number\"`\n // above\n const stickyDurationMsAsNumber: number | undefined = stickyDurationMs;\n\n // We need to extend the content with the redacts parameter\n // The js sdk uses event.redacts but the widget api uses event.content.redacts\n // This will be converted back to event.redacts in the widget driver.\n const content = event.event.redacts\n ? { ...event.getContent(), redacts: event.event.redacts }\n : event.getContent();\n\n // Delayed event special case.\n if (delayOpts) {\n // TODO: updatePendingEvent for delayed events?\n const response = await this.widgetApi\n .sendRoomEvent(\n event.getType(),\n content,\n room.roomId,\n \"delay\" in delayOpts ? delayOpts.delay : undefined,\n \"parent_delay_id\" in delayOpts ? delayOpts.parent_delay_id : undefined,\n stickyDurationMsAsNumber,\n )\n .catch(timeoutToConnectionError);\n return this.validateSendDelayedEventResponse(response);\n }\n\n const txId = event.getTxnId();\n // Add the txnId to the pending list (still with unknown evID)\n if (txId) this.pendingSendingEventsTxId.push({ type: event.getType(), id: undefined, txId });\n\n let response: ISendEventFromWidgetResponseData;\n try {\n response = await this.widgetApi\n .sendRoomEvent(event.getType(), content, room.roomId, undefined, undefined, stickyDurationMsAsNumber)\n .catch(timeoutToConnectionError);\n } catch (e) {\n this.updatePendingEventStatus(room, event, EventStatus.NOT_SENT);\n throw e;\n }\n // This also checks for an event id on the response\n room.updatePendingEvent(event, EventStatus.SENT, response.event_id);\n\n // Update the pending events list with the eventId\n this.pendingSendingEventsTxId.forEach((p) => {\n if (p.txId === txId) p.id = response.event_id;\n });\n this.eventEmitter.emit(RoomWidgetClientEvent.PendingEventsChanged);\n\n return { event_id: response.event_id! };\n }\n\n public async sendStateEvent(\n roomId: string,\n eventType: string,\n content: any,\n stateKey = \"\",\n ): Promise<ISendEventResponse> {\n const response = await this.widgetApi\n .sendStateEvent(eventType, stateKey, content, roomId)\n .catch(timeoutToConnectionError);\n if (response.event_id === undefined) {\n throw new Error(\"'event_id' absent from response to an event request\");\n }\n return { event_id: response.event_id };\n }\n\n /**\n * @experimental This currently relies on an unstable MSC (MSC4140).\n */\n public async _unstable_sendDelayedStateEvent<K extends keyof StateEvents>(\n roomId: string,\n delayOpts: SendDelayedEventRequestOpts,\n eventType: K,\n content: StateEvents[K],\n stateKey = \"\",\n ): Promise<SendDelayedEventResponse> {\n if (!(await this.doesServerSupportUnstableFeature(UNSTABLE_MSC4140_DELAYED_EVENTS))) {\n throw new UnsupportedDelayedEventsEndpointError(\n \"Server does not support the delayed events API\",\n \"sendDelayedStateEvent\",\n );\n }\n\n const response = await this.widgetApi\n .sendStateEvent(\n eventType,\n stateKey,\n content,\n roomId,\n \"delay\" in delayOpts ? delayOpts.delay : undefined,\n \"parent_delay_id\" in delayOpts ? delayOpts.parent_delay_id : undefined,\n )\n .catch(timeoutToConnectionError);\n return this.validateSendDelayedEventResponse(response);\n }\n\n private validateSendDelayedEventResponse(response: ISendEventFromWidgetResponseData): SendDelayedEventResponse {\n if (response.delay_id === undefined) {\n throw new Error(\"'delay_id' absent from response to a delayed event request\");\n }\n return { delay_id: response.delay_id };\n }\n\n /**\n * @experimental This currently relies on an unstable MSC (MSC4140).\n * @deprecated Instead use one of:\n * - {@link _unstable_cancelScheduledDelayedEvent}\n * - {@link _unstable_restartScheduledDelayedEvent}\n * - {@link _unstable_sendScheduledDelayedEvent}\n */\n public async _unstable_updateDelayedEvent(delayId: string, action: UpdateDelayedEventAction): Promise<EmptyObject> {\n if (!(await this.doesServerSupportUnstableFeature(UNSTABLE_MSC4140_DELAYED_EVENTS))) {\n throw new UnsupportedDelayedEventsEndpointError(\n \"Server does not support the delayed events API\",\n \"updateDelayedEvent\",\n );\n }\n\n switch (action) {\n case UpdateDelayedEventAction.Cancel:\n await this.widgetApi.cancelScheduledDelayedEvent(delayId).catch(timeoutToConnectionError);\n break;\n case UpdateDelayedEventAction.Restart:\n await this.widgetApi.restartScheduledDelayedEvent(delayId).catch(timeoutToConnectionError);\n break;\n case UpdateDelayedEventAction.Send:\n await this.widgetApi.sendScheduledDelayedEvent(delayId).catch(timeoutToConnectionError);\n break;\n }\n return {};\n }\n\n /**\n * @experimental This currently relies on an unstable MSC (MSC4140).\n */\n public async _unstable_cancelScheduledDelayedEvent(delayId: string): Promise<EmptyObject> {\n if (!(await this.doesServerSupportUnstableFeature(UNSTABLE_MSC4140_DELAYED_EVENTS))) {\n throw new UnsupportedDelayedEventsEndpointError(\n \"Server does not support the delayed events API\",\n \"cancelScheduledDelayedEvent\",\n );\n }\n\n await this.widgetApi.cancelScheduledDelayedEvent(delayId).catch(timeoutToConnectionError);\n return {};\n }\n\n /**\n * @experimental This currently relies on an unstable MSC (MSC4140).\n */\n public async _unstable_restartScheduledDelayedEvent(delayId: string): Promise<EmptyObject> {\n if (!(await this.doesServerSupportUnstableFeature(UNSTABLE_MSC4140_DELAYED_EVENTS))) {\n throw new UnsupportedDelayedEventsEndpointError(\n \"Server does not support the delayed events API\",\n \"restartScheduledDelayedEvent\",\n );\n }\n\n await this.widgetApi.restartScheduledDelayedEvent(delayId).catch(timeoutToConnectionError);\n return {};\n }\n\n /**\n * @experimental This currently relies on an unstable MSC (MSC4140).\n */\n public async _unstable_sendScheduledDelayedEvent(delayId: string): Promise<EmptyObject> {\n if (!(await this.doesServerSupportUnstableFeature(UNSTABLE_MSC4140_DELAYED_EVENTS))) {\n throw new UnsupportedDelayedEventsEndpointError(\n \"Server does not support the delayed events API\",\n \"sendScheduledDelayedEvent\",\n );\n }\n\n await this.widgetApi.sendScheduledDelayedEvent(delayId).catch(timeoutToConnectionError);\n return {};\n }\n\n /**\n * by {@link MatrixClient.encryptAndSendToDevice}.\n */\n public async encryptAndSendToDevice(\n eventType: string,\n devices: { userId: string; deviceId: string }[],\n payload: ToDevicePayload,\n ): Promise<void> {\n // map: user Id → device Id → payload\n const contentMap: MapWithDefault<string, Map<string, ToDevicePayload>> = new MapWithDefault(() => new Map());\n for (const { userId, deviceId } of devices) {\n contentMap.getOrCreate(userId).set(deviceId, payload);\n }\n\n await this.widgetApi\n .sendToDevice(eventType, true, recursiveMapToObject(contentMap))\n .catch(timeoutToConnectionError);\n }\n\n public async sendToDevice(eventType: string, contentMap: SendToDeviceContentMap): Promise<EmptyObject> {\n await this.widgetApi\n .sendToDevice(eventType, false, recursiveMapToObject(contentMap))\n .catch(timeoutToConnectionError);\n return {};\n }\n\n public async getOpenIdToken(): Promise<IOpenIDToken> {\n const token = await this.widgetApi.requestOpenIDConnectToken().catch(timeoutToConnectionError);\n // the IOpenIDCredentials from the widget-api and IOpenIDToken form the matrix-js-sdk are compatible.\n // we still recreate the token to make this transparent and catch'able by the linter in case the types change in the future.\n return <IOpenIDToken>{\n access_token: token.access_token,\n expires_in: token.expires_in,\n matrix_server_name: token.matrix_server_name,\n token_type: token.token_type,\n };\n }\n\n /**\n * Returns a set of configured RTC transports supported by the homeserver.\n *\n * Overrides the homeserver-side {@link MatrixClient._unstable_getRTCTransports} (MSC4143):\n * a widget cannot make authenticated homeserver calls itself, so we ask the host over the\n * widget API instead (MSC4515). Requires the `rtcTransports` capability and a host that\n * advertises the `org.matrix.msc4515` API version (otherwise the request throws).\n */\n public override async _unstable_getRTCTransports(): Promise<Transport[]> {\n const { rtc_transports: rtcTransports } = await this.widgetApi\n .getRtcTransports()\n .catch(timeoutToConnectionError);\n return rtcTransports;\n }\n\n public async queueToDevice({ eventType, batch }: ToDeviceBatch): Promise<void> {\n // map: user Id → device Id → payload\n const contentMap: MapWithDefault<string, Map<string, ToDevicePayload>> = new MapWithDefault(() => new Map());\n for (const { userId, deviceId, payload } of batch) {\n contentMap.getOrCreate(userId).set(deviceId, payload);\n }\n\n await this.widgetApi\n .sendToDevice(eventType, false, recursiveMapToObject(contentMap))\n .catch(timeoutToConnectionError);\n }\n\n /**\n * Send an event to a specific list of devices via the widget API. Optionally encrypts the event.\n *\n * If you are using a full MatrixClient you would be calling {@link MatrixClient.getCrypto().encryptToDeviceMessages()} followed\n * by {@link MatrixClient.queueToDevice}.\n *\n * However, this is combined into a single step when running as an embedded widget client. So, we expose this method for those\n * that need it.\n *\n * @param eventType - Type of the event to send.\n * @param encrypted - Whether the event should be encrypted.\n * @param contentMap - The content to send. Map from user_id to device_id to content object.\n */\n public async sendToDeviceViaWidgetApi(\n eventType: string,\n encrypted: boolean,\n contentMap: SendToDeviceContentMap,\n ): Promise<void> {\n await this.widgetApi\n .sendToDevice(eventType, encrypted, recursiveMapToObject(contentMap))\n .catch(timeoutToConnectionError);\n }\n\n // Overridden since we get TURN servers automatically over the widget API,\n // and this method would otherwise complain about missing an access token\n public async checkTurnServers(): Promise<boolean> {\n return this.turnServers.length > 0;\n }\n\n // Overridden since we 'sync' manually without the sync API\n public getSyncState(): SyncState | null {\n return this.syncState;\n }\n\n private setSyncState(state: SyncState): void {\n const oldState = this.syncState;\n this.syncState = state;\n this.emit(ClientEvent.Sync, state, oldState);\n }\n\n private async ack(ev: CustomEvent<IWidgetApiRequest>): Promise<void> {\n this.widgetApi.transport.reply<IWidgetApiAcknowledgeResponseData>(ev.detail, {});\n }\n\n private updateTxId = async (event: MatrixEvent): Promise<void> => {\n // We update the txId for remote echos that originate from this client.\n // This happens with the help of `pendingSendingEventsTxId` where we store all events that are currently sending\n // with their widget txId and once ready the final evId.\n if (\n // This could theoretically be an event send by this device\n // In that case we need to update the txId of the event because the embedded client/widget\n // knows this event with a different transaction Id than what was used by the host client.\n event.getSender() === this.getUserId() &&\n // We optimize by not blocking events from types that we have not send\n // with this client.\n this.pendingSendingEventsTxId.some((p) => event.getType() === p.type)\n ) {\n // Compare by event Id if we have a matching pending event where we know the txId.\n let matchingTxId = this.pendingSendingEventsTxId.find((p) => p.id === event.getId())?.txId;\n // Block any further processing of this event until we have received the sending response.\n // -> until we know the event id.\n // -> until we have not pending events anymore.\n while (!matchingTxId && this.pendingSendingEventsTxId.length > 0) {\n // Recheck whenever the PendingEventsChanged\n await new Promise<void>((resolve) =>\n this.eventEmitter.once(RoomWidgetClientEvent.PendingEventsChanged, () => resolve()),\n );\n matchingTxId = this.pendingSendingEventsTxId.find((p) => p.id === event.getId())?.txId;\n }\n\n // We found the correct txId: we update the event and delete the entry of the pending events.\n if (matchingTxId) {\n event.setTxnId(matchingTxId);\n event.setUnsigned({ ...event.getUnsigned(), transaction_id: matchingTxId });\n }\n this.pendingSendingEventsTxId = this.pendingSendingEventsTxId.filter((p) => p.id !== event.getId());\n\n // Emit once there are no pending events anymore to release all other events that got\n // awaited in the `while (!matchingTxId && this.pendingSendingEventsTxId.length > 0)` loop\n // but are not send by this client.\n if (this.pendingSendingEventsTxId.length === 0) {\n this.eventEmitter.emit(RoomWidgetClientEvent.PendingEventsChanged);\n }\n }\n };\n\n private onEvent = async (ev: CustomEvent<ISendEventToWidgetActionRequest>): Promise<void> => {\n ev.preventDefault();\n\n // Verify the room ID matches, since it's possible for the client to\n // send us events from other rooms if this widget is always on screen\n if (ev.detail.data.room_id === this.roomId) {\n const event = new MatrixEvent(ev.detail.data);\n\n // Only inject once we have update the txId\n await this.updateTxId(event);\n await this.syncApiResolver.promise;\n if (this.syncApi instanceof SyncApi) {\n if (await this.supportUpdateState()) {\n await this.syncApi.injectRoomEvents(this.room!, undefined, [], [event]);\n } else {\n // Passing undefined for `stateAfterEventList` will make `injectRoomEvents` run in legacy mode\n // -> state events in `timelineEventList` will update the state.\n await this.syncApi.injectRoomEvents(this.room!, [], undefined, [event]);\n }\n } else {\n // Sliding Sync\n if (await this.supportUpdateState()) {\n await this.syncApi!.injectRoomEvents(this.room!, [], [event]);\n } else {\n logger.error(\n \"slididng sync cannot be used in widget mode if the client widget driver does not support the version: 'org.matrix.msc2762_update_state'\",\n );\n }\n }\n\n this.emit(ClientEvent.Event, event);\n if (event.unstableStickyInfo !== undefined) this.room!._unstable_addStickyEvents([event]);\n this.setSyncState(SyncState.Syncing);\n logger.info(`Received event ${event.getId()} ${event.getType()}`);\n } else {\n const { event_id: eventId, room_id: roomId } = ev.detail.data;\n logger.info(`Received event ${eventId} for a different room ${roomId}; discarding`);\n }\n\n await this.ack(ev);\n };\n\n private onToDevice = async (ev: CustomEvent<ISendToDeviceToWidgetActionRequest>): Promise<void> => {\n ev.preventDefault();\n\n const event = new MatrixEvent({\n type: ev.detail.data.type,\n sender: ev.detail.data.sender,\n content: ev.detail.data.content,\n });\n // Mark the event as encrypted if it was, using fake contents and keys since those are unknown to us\n if (ev.detail.data.encrypted) event.makeEncrypted(EventType.RoomMessageEncrypted, {}, \"\", \"\");\n\n this.emit(ClientEvent.ToDeviceEvent, event);\n this.setSyncState(SyncState.Syncing);\n await this.ack(ev);\n };\n\n private onStateUpdate = async (ev: CustomEvent<IUpdateStateToWidgetActionRequest>): Promise<void> => {\n ev.preventDefault();\n if (!(await this.supportUpdateState())) {\n logger.warn(\n \"received update_state widget action but the widget driver did not claim to support 'org.matrix.msc2762_update_state'\",\n );\n }\n await this.syncApiResolver.promise;\n for (const rawEvent of ev.detail.data.state) {\n // Verify the room ID matches, since it's possible for the client to\n // send us state updates from other rooms if this widget is always\n // on screen\n if (rawEvent.room_id === this.roomId) {\n const event = new MatrixEvent(rawEvent);\n\n if (this.syncApi instanceof SyncApi) {\n await this.syncApi.injectRoomEvents(this.room!, undefined, [event]);\n } else {\n // Sliding Sync\n await this.syncApi!.injectRoomEvents(this.room!, [event]);\n }\n logger.debug(`Updated state entry ${event.getType()} ${event.getStateKey()} to ${event.getId()}`);\n } else {\n const { event_id: eventId, room_id: roomId } = ev.detail.data;\n logger.info(`Received state entry ${eventId} for a different room ${roomId}; discarding`);\n }\n }\n\n await this.ack(ev);\n };\n\n private async watchTurnServers(): Promise<void> {\n const servers = this.widgetApi.getTurnServers();\n const onClientStopped = (): void => {\n servers.return(undefined);\n };\n this.lifecycle!.signal.addEventListener(\"abort\", onClientStopped);\n\n try {\n for await (const server of servers) {\n this.turnServers = [\n {\n urls: server.uris,\n username: server.username,\n credential: server.password,\n },\n ];\n this.emit(ClientEvent.TurnServers, this.turnServers);\n logger.log(`Received TURN server: ${server.uris}`);\n }\n } catch (e) {\n logger.warn(\"Error watching TURN servers\", e);\n } finally {\n this.lifecycle!.signal.removeEventListener(\"abort\", onClientStopped);\n }\n }\n}\n\nfunction processAndThrow(error: unknown): never {\n if (error instanceof WidgetApiResponseError && error.data.matrix_api_error) {\n throw MatrixError.fromWidgetApiErrorData(error.data.matrix_api_error);\n } else {\n throw error;\n }\n}\n\n/**\n * This converts an \"Request timed out\" error from the PostmessageTransport into a ConnectionError.\n * It either throws the original error or a new ConnectionError.\n **/\nfunction timeoutToConnectionError(error: unknown): never {\n // TODO: this should not check on error.message but instead it should be a specific type\n // error instanceof WidgetTimeoutError\n if (error instanceof Error && error.message === \"Request timed out\") {\n throw new ConnectionError(\"widget api timeout\");\n }\n throw error;\n}\n"],"mappings":"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","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"MatrixRTCSession.js","names":[],"sources":["../../src/matrixrtc/MatrixRTCSession.ts"],"sourcesContent":["/*\nCopyright 2023 - 2026 The Matrix.org Foundation C.I.C.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\nimport { type Logger, logger as rootLogger } from \"../logger.ts\";\nimport { TypedEventEmitter } from \"../models/typed-event-emitter.ts\";\nimport { EventTimeline } from \"../models/event-timeline.ts\";\nimport { type Room } from \"../models/room.ts\";\nimport { type MatrixClient } from \"../client.ts\";\nimport { EventType, RelationType } from \"../@types/event.ts\";\nimport { KnownMembership } from \"../@types/membership.ts\";\nimport { type ISendEventResponse } from \"../@types/requests.ts\";\nimport { CallMembership } from \"./CallMembership.ts\";\nimport { RoomStateEvent } from \"../models/room-state.ts\";\nimport { MembershipManager, StickyEventMembershipManager } from \"./MembershipManager.ts\";\nimport { type CallMembershipIdentityParts, type IEncryptionManager } from \"./EncryptionManager.ts\";\nimport { logDurationSync } from \"../utils.ts\";\nimport type {\n Statistics,\n RTCNotificationType,\n Status,\n IRTCNotificationContent,\n RTCCallIntent,\n Transport,\n SlotDescription,\n RtcSlotEventContent,\n} from \"./types.ts\";\nimport {\n MembershipManagerEvent,\n type MembershipManagerEventHandlerMap,\n type IMembershipManager,\n} from \"./IMembershipManager.ts\";\nimport { RTCEncryptionManager } from \"./RTCEncryptionManager.ts\";\nimport { ToDeviceKeyTransport } from \"./ToDeviceKeyTransport.ts\";\nimport { TypedReEmitter } from \"../ReEmitter.ts\";\nimport { type IContent, type MatrixEvent } from \"../models/event.ts\";\nimport { RoomStickyEventsEvent, type RoomStickyEventsMap } from \"../models/room-sticky-events.ts\";\nimport { computeSlotId } from \"./utils.ts\";\n\n/**\n * Events emitted by MatrixRTCSession\n */\nexport enum MatrixRTCSessionEvent {\n // A member joined, left, or updated a property of their membership.\n MembershipsChanged = \"memberships_changed\",\n // We joined or left the session: our own local idea of whether we are joined,\n // separate from MembershipsChanged, ie. independent of whether our member event\n // has successfully gone through.\n JoinStateChanged = \"join_state_changed\",\n // The key used to encrypt media has changed\n EncryptionKeyChanged = \"encryption_key_changed\",\n /** The membership manager had to shut down caused by an unrecoverable error */\n MembershipManagerError = \"membership_manager_error\",\n /** The RTCSession did send a call notification caused by joining the call as the first member */\n DidSendCallNotification = \"did_send_call_notification\",\n}\n\nexport type MatrixRTCSessionEventHandlerMap = {\n [MatrixRTCSessionEvent.MembershipsChanged]: (\n oldMemberships: CallMembership[],\n newMemberships: CallMembership[],\n ) => void;\n [MatrixRTCSessionEvent.JoinStateChanged]: (isJoined: boolean) => void;\n [MatrixRTCSessionEvent.EncryptionKeyChanged]: (\n key: Uint8Array<ArrayBuffer>,\n encryptionKeyIndex: number,\n membership: CallMembershipIdentityParts,\n rtcBackendIdentity: string,\n ) => void;\n [MatrixRTCSessionEvent.MembershipManagerError]: (error: unknown) => void;\n [MatrixRTCSessionEvent.DidSendCallNotification]: (\n notificationContentNew: { event_id: string } & IRTCNotificationContent,\n ) => void;\n};\n\nexport interface SessionConfig {\n /**\n * What kind of notification to send when starting the session.\n * @default `undefined` (no notification)\n */\n notificationType?: RTCNotificationType;\n\n /**\n * Determines the kind of call this will be.\n */\n callIntent?: RTCCallIntent;\n}\n\n// The names follow these principles:\n// - we use the technical term delay if the option is related to delayed events.\n// - we use delayedLeaveEvent if the option is related to the delayed leave event.\n// - we use membershipEvent if the option is related to the rtc member state event.\n// - we use the technical term expiry if the option is related to the expiry field of the membership state event.\n// - we use a `Ms` postfix if the option is a duration to avoid using words like:\n// `time`, `duration`, `delay`, `timeout`... that might be mistaken/confused with technical terms.\nexport interface MembershipConfig {\n /**\n * The timeout (in milliseconds) after we joined the call, that our membership should expire\n * unless we have explicitly updated it.\n *\n * This is what goes into the m.rtc.member event expiry field and is typically set to a number of hours.\n */\n membershipEventExpiryMs?: number;\n\n /**\n * The time in (in milliseconds) which the manager will prematurely send the updated state event before the membership `expires` time to make sure it\n * sends the updated state event early enough.\n *\n * A headroom of 1000ms and a `membershipExpiryTimeout` of 10000ms would result in the first membership event update after 9s and\n * a membership event that would be considered expired after 10s.\n *\n * This value does not have an effect on the value of `SessionMembershipData.expires`.\n */\n membershipEventExpiryHeadroomMs?: number;\n\n /**\n * The timeout (in milliseconds) with which the deleayed leave event on the server is configured.\n * After this time the server will set the event to the disconnected stat if it has not received a keep-alive from the client.\n */\n delayedLeaveEventDelayMs?: number;\n\n /**\n * The interval (in milliseconds) in which the client will send membership keep-alives to the server.\n */\n delayedLeaveEventRestartMs?: number;\n\n /**\n * The maximum number of retries that the manager will do for delayed event sending/updating and state event sending when a server rate limit has been hit.\n */\n maximumRateLimitRetryCount?: number;\n\n /**\n * The maximum number of retries that the manager will do for delayed event sending/updating and state event sending when a network error occurs.\n */\n maximumNetworkErrorRetryCount?: number;\n\n /**\n * The time (in milliseconds) after which we will retry a http request if it\n * failed to send due to a network error. (send membership event, send delayed event, restart delayed event...)\n */\n networkErrorRetryMs?: number;\n\n /**\n * The time (in milliseconds) after which a we consider a delayed event restart http request to have failed.\n * Setting this to a lower value will result in more frequent retries but also a higher chance of failiour.\n *\n * In the presence of network packet loss (hurting TCP connections), the custom delayedEventRestartLocalTimeoutMs\n * helps by keeping more delayed event reset candidates in flight,\n * improving the chances of a successful reset. (its is equivalent to the js-sdk `localTimeout` configuration,\n * but only applies to calls to the `_unstable_restartScheduledDelayedEvent` endpoint\n * or the `_unstable_updateDelayedEvent` endpoint with a body of `{action:\"restart\"}`.)\n */\n delayedLeaveEventRestartLocalTimeoutMs?: number;\n\n /**\n * Send membership using sticky events rather than state events.\n * This also make the client use the new m.rtc.member MSC4354 event format. (instead of m.call.member)\n *\n * **WARNING**: This is an unstable feature and not all clients will support it.\n */\n unstableSendStickyEvents?: boolean;\n}\n\nexport interface EncryptionConfig {\n /**\n * If true, generate and share a media key for this participant,\n * and emit MatrixRTCSessionEvent.EncryptionKeyChanged when\n * media keys for other participants become available.\n */\n manageMediaKeys?: boolean;\n /**\n * The minimum time (in milliseconds) between each attempt to send encryption key(s).\n * e.g. if this is set to 1000, then we will send at most one key event every second.\n * @deprecated - Not used by the new encryption manager.\n */\n updateEncryptionKeyThrottle?: number;\n\n /**\n * Sometimes it is necessary to rotate the encryption key after a membership update.\n * For performance reasons we might not want to rotate the key immediately but allow future memberships to use the same key.\n * If 5 people join in a row in less than 5 seconds, we don't want to rotate the key for each of them.\n * If 5 people leave in a row in less than 5 seconds, we don't want to rotate the key for each of them.\n * So we do share the key which was already used live for <5s to new joiners.\n * This does result in a potential leak up to the configured time of call media.\n * This has to be considered when choosing a value for this property.\n */\n keyRotationGracePeriodMs?: number;\n\n /**\n * The delay (in milliseconds) after a member leaves before we create and publish a new key, because people\n * tend to leave calls at the same time.\n * @deprecated - Not used by the new encryption manager.\n */\n makeKeyDelay?: number;\n /**\n * The delay (in milliseconds) between sending a new key and starting to encrypt with it. This\n * gives others a chance to receive the new key to minimize the chance they get media they can't decrypt.\n *\n * The higher this value is, the better it is for existing members as they will have a smoother experience.\n * But it impacts new joiners: They will always have to wait `useKeyDelay` before being able to decrypt the media\n * (as it will be encrypted with the new key after the delay only), even if the key has already arrived before the delay.\n */\n useKeyDelay?: number;\n}\nexport type JoinSessionConfig = SessionConfig & MembershipConfig & EncryptionConfig;\n\ninterface SessionMembershipsForSlotOpts {\n /**\n * Listen for incoming sticky member events. If disabled, this session will\n * ignore any incoming sticky events.\n */\n listenForStickyEvents: boolean;\n /**\n * Listen for incoming member state events (legacy). If disabled, this session will\n * ignore any incoming state events.\n */\n listenForMemberStateEvents: boolean;\n}\n\nconst DEFAULT_SESSION_MEMBERSHIPS_FOR_SLOT_OPTS: SessionMembershipsForSlotOpts = {\n listenForStickyEvents: true,\n listenForMemberStateEvents: true,\n};\n\n/**\n * A MatrixRTCSession manages the membership & properties of a MatrixRTC session.\n * This class doesn't deal with media at all, just membership & properties of a session.\n */\nexport class MatrixRTCSession extends TypedEventEmitter<\n MatrixRTCSessionEvent | MembershipManagerEvent,\n MatrixRTCSessionEventHandlerMap & MembershipManagerEventHandlerMap\n> {\n private membershipManager?: IMembershipManager;\n private encryptionManager?: IEncryptionManager;\n private joinConfig?: SessionConfig;\n private logger: Logger;\n\n private pendingNotificationToSend: undefined | RTCNotificationType;\n /**\n * This timeout is responsible to track any expiration. We need to know when we have to start\n * to ignore other call members. There is no callback for this. This timeout will always be configured to\n * emit when the next membership expires.\n */\n private expiryTimeout?: ReturnType<typeof setTimeout>;\n\n public memberships: CallMembership[] = [];\n\n /**\n * Resolves when the session has calculated the initial membership of the session.\n */\n public readonly initialMembershipCalculated: Promise<void>;\n /**\n * Does membership need to be recalculated? This is set to false upon\n * recalculation.\n */\n private membershipNeedsRecalculation = false;\n\n /**\n * The statistics for this session.\n */\n public statistics: Statistics = {\n counters: {\n roomEventEncryptionKeysSent: 0,\n roomEventEncryptionKeysReceived: 0,\n },\n totals: {\n roomEventEncryptionKeysReceivedTotalAge: 0,\n },\n };\n\n public get membershipStatus(): Status | undefined {\n return this.membershipManager?.status;\n }\n public get probablyLeft(): boolean | undefined {\n return this.membershipManager?.probablyLeft;\n }\n public get delayId(): string | undefined {\n return this.membershipManager?.delayId;\n }\n\n /**\n * The callId (sessionId) of the call.\n *\n * It can be undefined since the callId is only known once the first membership joins.\n * The callId is the property that, per definition, groups memberships into one call.\n * @deprecated use `slotId` instead.\n */\n public get callId(): string | undefined {\n return this.slotDescription?.id;\n }\n /**\n * The slotId of the call.\n * `{application}#{appSpecificId}`\n * It can be undefined since the slotId is only known once the first membership joins.\n * The slotId is the property that, per definition, groups memberships into one call.\n */\n public get slotId(): string | undefined {\n return computeSlotId(this.slotDescription);\n }\n\n /**\n * Reads the current slot state event's content for this session.\n *\n * @returns The slot event's content, or `undefined` if no slot event exists for this session.\n */\n public getRtcSlot(): RtcSlotEventContent | undefined {\n return getSlotEventContent(this.roomSubset, this.slotDescription);\n }\n\n /**\n * Whether this session's slot is closed.\n *\n * @returns `true` if the slot is closed, `false` if the slot is open or `undefined`\n * if no slot exists.\n */\n public isSlotClosed(): boolean | undefined {\n return isSlotClosed(this.roomSubset, this.slotDescription);\n }\n\n /**\n * Returns all the call memberships for a room that match the provided `sessionDescription`,\n * oldest first.\n *\n * By default, this will return *both* sticky and member state events.\n */\n public static async sessionMembershipsForSlot(\n room: Pick<Room, \"getLiveTimeline\" | \"roomId\" | \"hasMembershipState\" | \"_unstable_getStickyEvents\">,\n slotDescription: SlotDescription,\n // default both true this implied we combine sticky and state events for the final call state\n // (prefer sticky events in case of a duplicate)\n options: SessionMembershipsForSlotOpts = DEFAULT_SESSION_MEMBERSHIPS_FOR_SLOT_OPTS,\n ): Promise<CallMembership[]> {\n const logger = rootLogger.getChild(\n `[MatrixRTCSession ${room.roomId} ${slotDescription.application}#${slotDescription.id}]`,\n );\n const callMemberEvents = collectMembersEvents(room, slotDescription, options, logger);\n\n const callMemberships = await computeBackendIdentityAndVerifyMemberEvents(\n room,\n callMemberEvents,\n slotDescription,\n logger,\n );\n\n callMemberships.sort((a, b) => a.createdTs() - b.createdTs());\n if (callMemberships.length > 1) {\n logger.debug(\n `Call memberships in room ${room.roomId}, in order: `,\n callMemberships.map((m) => [m.createdTs(), m.userId]),\n );\n }\n\n return callMemberships;\n }\n\n /**\n * Return the MatrixRTC session for the room.\n * This returned session can be used to find out if there are active sessions\n * for the requested room and `slotDescription`.\n */\n public static sessionForSlot(\n client: MatrixClient,\n room: Room,\n slotDescription: SlotDescription,\n opts?: SessionMembershipsForSlotOpts,\n ): MatrixRTCSession {\n return new MatrixRTCSession(client, room, slotDescription, opts);\n }\n\n /**\n * WARN: this can in theory only be a subset of the room with the properties required by\n * this class.\n * Outside of tests this most likely will be a full room, however.\n * @deprecated Relying on a full Room object being available here is an anti-pattern. You should be tracking\n * the room object in your own code and passing it in when needed.\n */\n public get room(): Room {\n return this.roomSubset as Room;\n }\n\n /**\n * This constructs a room session. When using MatrixRTC inside the js-sdk this is expected\n * to be used with the MatrixRTCSessionManager exclusively.\n *\n * In cases where you don't use the js-sdk but build on top of another Matrix stack this class can be used standalone\n * to manage a joined MatrixRTC session.\n *\n * @param client A subset of the {@link MatrixClient} that lets the session interact with the Matrix room.\n * @param roomSubset The room this session is attached to. A subset of a js-sdk Room that the session needs.\n * @param slotDescription The slot description is a virtual address where participants are allowed to meet.\n * This session will only manage memberships that match this slot description.Sessions are distinct if any of\n * those properties are distinct: `roomSubset.roomId`, `slotDescription.application`, `slotDescription.id`.\n * @param calculateMembershipsOpts - Options to configure how memberships are calculated for this session.\n */\n public constructor(\n private readonly client: Pick<\n MatrixClient,\n | \"getUserId\"\n | \"getDeviceId\"\n | \"sendEvent\"\n | \"sendStateEvent\"\n | \"_unstable_sendDelayedStateEvent\"\n | \"_unstable_updateDelayedEvent\"\n | \"_unstable_cancelScheduledDelayedEvent\"\n | \"_unstable_restartScheduledDelayedEvent\"\n | \"_unstable_sendScheduledDelayedEvent\"\n | \"_unstable_sendStickyEvent\"\n | \"_unstable_sendStickyDelayedEvent\"\n | \"cancelPendingEvent\"\n | \"encryptAndSendToDevice\"\n | \"off\"\n | \"on\"\n | \"decryptEventIfNeeded\"\n >,\n private roomSubset: Pick<\n Room,\n | \"getLiveTimeline\"\n | \"roomId\"\n | \"getVersion\"\n | \"hasMembershipState\"\n | \"on\"\n | \"off\"\n | \"_unstable_getStickyEvents\"\n >,\n\n public readonly slotDescription: SlotDescription,\n private readonly calculateMembershipsOpts?: SessionMembershipsForSlotOpts,\n ) {\n super();\n this.logger = rootLogger.getChild(\n `[MatrixRTCSession ${roomSubset.roomId} ${slotDescription.application}#${slotDescription.id}]`,\n );\n\n this.roomSubset.on(RoomStateEvent.Members, this.onRoomMemberUpdate);\n this.roomSubset.on(RoomStateEvent.Events, this.onRoomStateEvent);\n this.roomSubset.on(RoomStickyEventsEvent.Update, this.onStickyEventUpdate);\n\n this.initialMembershipCalculated = this.ensureRecalculateSessionMembers();\n this.setExpiryTimer();\n }\n /*\n * Returns true if we intend to be participating in the MatrixRTC session.\n * This is determined by checking if the relativeExpiry has been set.\n */\n public isJoined(): boolean {\n return this.membershipManager?.isJoined() ?? false;\n }\n\n /**\n * Performs cleanup & removes timers for client shutdown\n */\n public async stop(): Promise<void> {\n await this.membershipManager?.leave(1000);\n if (this.expiryTimeout) {\n clearTimeout(this.expiryTimeout);\n this.expiryTimeout = undefined;\n }\n\n this.roomSubset.off(RoomStateEvent.Members, this.onRoomMemberUpdate);\n this.roomSubset.off(RoomStateEvent.Events, this.onRoomStateEvent);\n this.roomSubset.off(RoomStickyEventsEvent.Update, this.onStickyEventUpdate);\n }\n\n private reEmitter = new TypedReEmitter<\n MatrixRTCSessionEvent | MembershipManagerEvent,\n MatrixRTCSessionEventHandlerMap & MembershipManagerEventHandlerMap\n >(this);\n\n /**\n * Announces this user and device as joined to the MatrixRTC session,\n * and continues to update the membership event to keep it valid until\n * leaveRoomSession() is called\n * This will not subscribe to updates: remember to call subscribe() separately if\n * desired.\n * This method will return immediately and the session will be joined in the background.\n * @param ownMembershipIdentity the identity of the user and device joining the session.\n * This will be put into the content.member.\n * @param fociPreferred the list of preferred foci to use in the joined RTC membership event.\n * If multiSfuFocus is set, this is only needed if this client wants to publish to multiple transports simultaneously.\n * @param multiSfuFocus the active focus to use in the joined RTC membership event. Setting this implies the\n * membership manager will operate in a multi-SFU connection mode. If `undefined`, an `oldest_membership`\n * transport selection will be used instead.\n * @param joinConfig - Additional configuration for the joined session.\n */\n public joinRTCSession(\n ownMembershipIdentity: CallMembershipIdentityParts,\n fociPreferred: Transport[],\n multiSfuFocus?: Transport,\n joinConfig?: JoinSessionConfig,\n ): void {\n if (this.isJoined()) {\n this.logger.info(`Already joined to session in room ${this.roomSubset.roomId}: ignoring join call`);\n return;\n } else {\n // Create MembershipManager and pass the RTCSession logger (with room id info)\n this.membershipManager = joinConfig?.unstableSendStickyEvents\n ? new StickyEventMembershipManager(\n joinConfig,\n this.roomSubset,\n this.client,\n this.slotDescription,\n ownMembershipIdentity.memberId,\n this.logger,\n )\n : new MembershipManager(joinConfig, this.roomSubset, this.client, this.slotDescription, this.logger);\n\n this.reEmitter.reEmit(this.membershipManager!, [\n MembershipManagerEvent.ProbablyLeft,\n MembershipManagerEvent.StatusChanged,\n MembershipManagerEvent.DelayIdChanged,\n ]);\n // Create Encryption manager\n const [room, client, statistics] = [this.roomSubset, this.client, this.statistics];\n const transport = new ToDeviceKeyTransport(ownMembershipIdentity, room.roomId, client, statistics);\n this.encryptionManager = new RTCEncryptionManager(\n ownMembershipIdentity,\n () => this.memberships,\n transport,\n (\n keyBin: Uint8Array<ArrayBuffer>,\n encryptionKeyIndex: number,\n membership: CallMembershipIdentityParts,\n rtcBackendIdentity: string,\n ) => {\n this.emit(\n MatrixRTCSessionEvent.EncryptionKeyChanged,\n keyBin,\n encryptionKeyIndex,\n membership,\n rtcBackendIdentity,\n );\n },\n this.logger,\n );\n }\n\n this.joinConfig = joinConfig;\n this.pendingNotificationToSend = this.joinConfig?.notificationType;\n\n // Join!\n this.membershipManager!.join(fociPreferred, multiSfuFocus, (e) => {\n this.logger.error(\"MembershipManager encountered an unrecoverable error: \", e);\n this.emit(MatrixRTCSessionEvent.MembershipManagerError, e);\n this.emit(MatrixRTCSessionEvent.JoinStateChanged, this.isJoined());\n });\n this.encryptionManager!.join(joinConfig);\n\n this.emit(MatrixRTCSessionEvent.JoinStateChanged, true);\n }\n\n /**\n *\n * @param fociPreferred\n * @param multiSfuFocus\n * @param joinConfig\n * @deprecated use the joinRTCSession method instead\n */\n public joinRoomSession(\n fociPreferred: Transport[],\n multiSfuFocus?: Transport,\n joinConfig?: JoinSessionConfig,\n ): void {\n const [userId, deviceId] = [this.client.getUserId()!, this.client.getDeviceId()!];\n // TODO this wants to become a UUID\n const memberId = `${userId}:${deviceId}`;\n this.joinRTCSession({ userId, deviceId, memberId }, fociPreferred, multiSfuFocus, joinConfig);\n }\n\n /**\n * Announces this user and device as having left the MatrixRTC session\n * and stops scheduled updates.\n * This will not unsubscribe from updates: remember to call unsubscribe() separately if\n * desired.\n * The membership update required to leave the session will retry if it fails.\n * Without network connection the promise will never resolve.\n * A timeout can be provided so that there is a guarantee for the promise to resolve.\n * @returns Whether the membership update was attempted and did not time out.\n */\n public async leaveRoomSession(timeout: number | undefined = undefined): Promise<boolean> {\n if (!this.isJoined()) {\n this.logger.info(`Not joined to session in room ${this.roomSubset.roomId}: ignoring leave call`);\n return false;\n }\n\n this.logger.info(`Leaving call session in room ${this.roomSubset.roomId}`);\n\n this.encryptionManager!.leave();\n\n const leavePromise = this.membershipManager!.leave(timeout);\n this.emit(MatrixRTCSessionEvent.JoinStateChanged, false);\n\n return await leavePromise;\n }\n /**\n * This returns the focus in use by the oldest membership.\n * Do not use since this might be just the focus for the oldest membership. others might use a different focus.\n * @deprecated use `member.getTransport(session.getOldestMembership())` instead for the specific member you want to get the focus for.\n */\n public getFocusInUse(): Transport | undefined {\n const oldestMembership = this.getOldestMembership();\n return oldestMembership?.getTransport(oldestMembership);\n }\n\n public getOldestMembership(): CallMembership | undefined {\n return this.memberships[0];\n }\n\n /**\n * Get the call intent for the current call, based on what members are advertising. If one or more\n * members disagree on the current call intent, or nobody specifies one then `undefined` is returned.\n *\n * If all members that specify a call intent agree, that value is returned.\n * @returns A call intent, or `undefined` if no consensus or not given.\n */\n public getConsensusCallIntent(): RTCCallIntent | undefined {\n const getFirstCallIntent = this.memberships.find((m) => !!m.callIntent)?.callIntent;\n if (!getFirstCallIntent) {\n return undefined;\n }\n if (this.memberships.every((m) => !m.callIntent || m.callIntent === getFirstCallIntent)) {\n return getFirstCallIntent;\n }\n return undefined;\n }\n\n public async updateCallIntent(callIntent: RTCCallIntent): Promise<void> {\n const myMembership = this.membershipManager?.ownMembership;\n if (!myMembership) {\n throw Error(\"Not connected yet\");\n }\n await this.membershipManager?.updateCallIntent(callIntent);\n }\n\n /**\n * Re-emit an EncryptionKeyChanged event for each tracked encryption key. This can be used to export\n * the keys.\n */\n public reemitEncryptionKeys(): void {\n this.encryptionManager?.getEncryptionKeys().forEach((keyRing, key) => {\n keyRing.forEach((keyInfo) => {\n this.emit(\n MatrixRTCSessionEvent.EncryptionKeyChanged,\n keyInfo.key,\n keyInfo.keyIndex,\n keyInfo.membership,\n keyInfo.rtcBackendIdentity,\n );\n });\n });\n }\n\n /**\n * Sets a timer for the soonest membership expiry\n */\n private setExpiryTimer(): void {\n if (this.expiryTimeout) {\n clearTimeout(this.expiryTimeout);\n this.expiryTimeout = undefined;\n }\n\n let soonestExpiry;\n for (const membership of this.memberships) {\n const thisExpiry = membership.getMsUntilExpiry();\n // If getMsUntilExpiry is undefined we have a MSC4143 (MatrixRTC) compliant event - it never expires\n // but will be reliably resent on disconnect.\n if (thisExpiry !== undefined && (soonestExpiry === undefined || thisExpiry < soonestExpiry)) {\n soonestExpiry = thisExpiry;\n }\n }\n\n if (soonestExpiry != undefined) {\n this.expiryTimeout = setTimeout(() => void this.ensureRecalculateSessionMembers(), soonestExpiry);\n }\n }\n\n /**\n * Sends notification events to indiciate the call has started.\n * Note: This does not return a promise, instead scheduling the notification events to be sent.\n * @param parentEventId Event id linking to your RTC call membership event.\n * @param notificationType The type of notification to send\n * @param callIntent The type of call this is (e.g. \"audio\").\n */\n private sendCallNotify(\n parentEventId: string,\n notificationType: RTCNotificationType,\n callIntent?: RTCCallIntent,\n ): void {\n const sendNotificationEvent = async (): Promise<{\n response: ISendEventResponse;\n content: IRTCNotificationContent;\n }> => {\n const content: IRTCNotificationContent = {\n \"m.mentions\": { user_ids: [], room: true },\n \"notification_type\": notificationType,\n \"m.relates_to\": {\n event_id: parentEventId,\n rel_type: RelationType.Reference,\n },\n \"sender_ts\": Date.now(),\n \"lifetime\": 30_000, // 30 seconds\n };\n if (callIntent) {\n content[\"m.call.intent\"] = callIntent;\n }\n const response = await this.client.sendEvent(this.roomSubset.roomId, EventType.RTCNotification, content);\n return { response, content };\n };\n\n void sendNotificationEvent()\n .then((notification) => {\n // Join event_id and origin event content\n const newResult = { ...notification.response, ...notification.content };\n this.emit(MatrixRTCSessionEvent.DidSendCallNotification, newResult);\n })\n .catch(([errorLegacy, errorNew]) =>\n this.logger.error(\"Failed to send call notification\", errorLegacy, errorNew),\n );\n }\n\n /**\n * Call this when the Matrix room members have changed.\n */\n private readonly onRoomMemberUpdate = (): void => {\n void this.ensureRecalculateSessionMembers();\n };\n\n /**\n * Call this when a room state event has been updated.\n */\n private readonly onRoomStateEvent = (event: MatrixEvent): void => {\n if (event.getType() !== EventType.RTCSlot) return;\n if (event.getStateKey() !== computeSlotId(this.slotDescription)) return;\n void this.ensureRecalculateSessionMembers();\n };\n\n /**\n * Call this when a sticky event update has occured.\n */\n private readonly onStickyEventUpdate: RoomStickyEventsMap[RoomStickyEventsEvent.Update] = (\n added,\n updated,\n removed,\n ): void => {\n if (\n [...added, ...removed, ...updated.flatMap((v) => [v.current, v.previous])].some(\n (e) => e.getType() === EventType.RTCMembership,\n )\n ) {\n void this.ensureRecalculateSessionMembers();\n }\n };\n\n /**\n * Call this when something changed that may impacts the current MatrixRTC members in this session.\n */\n // We allow this name schema since this function should only be used for testing purposes.\n public _onRTCSessionMemberUpdate = async (): Promise<void> => {\n await this.recalculateSessionMembers();\n };\n\n // helper variables to make sure we do not have parallel running recalculations.\n private recalculateSessionMembersPromise: Promise<void> = Promise.resolve();\n\n /**\n * Ensures that membership is recalculated when the state of the session may have changed.\n * Also ensures that only one recalculation is made at a time.\n * @returns A promise resolving when the state has been recalculated.\n */\n private ensureRecalculateSessionMembers(): Promise<void> {\n if (this.membershipNeedsRecalculation) {\n // We have already requested recalcuation, don't attempt a new one.\n return this.recalculateSessionMembersPromise;\n }\n this.membershipNeedsRecalculation = true;\n // Chain the recalculation.\n this.recalculateSessionMembersPromise = this.recalculateSessionMembersPromise.then(\n () => this.recalculateSessionMembers(),\n () => this.recalculateSessionMembers(),\n );\n return this.recalculateSessionMembersPromise;\n }\n\n /**\n * Call this when anything that could impact rtc memberships has changed: Room Members or RTC members.\n *\n * Examines the latest call memberships and handles any encryption key sending or rotation that is needed.\n *\n * This function should be called when the room members or call memberships might have changed.\n */\n private readonly recalculateSessionMembers = async (): Promise<void> => {\n // Clear the flag.\n this.membershipNeedsRecalculation = false;\n const oldMemberships = this.memberships;\n\n this.memberships = await MatrixRTCSession.sessionMembershipsForSlot(\n this.room,\n this.slotDescription,\n this.calculateMembershipsOpts,\n );\n\n const changed =\n oldMemberships.length != this.memberships.length ||\n oldMemberships.some((m, i) => !CallMembership.equal(m, this.memberships[i]));\n\n if (changed) {\n this.logger.info(\n `Memberships for call in room ${this.roomSubset.roomId} have changed: emitting (${this.memberships.length} members)`,\n );\n logDurationSync(this.logger, \"emit MatrixRTCSessionEvent.MembershipsChanged\", () => {\n this.emit(MatrixRTCSessionEvent.MembershipsChanged, oldMemberships, this.memberships);\n });\n\n void this.membershipManager?.onRTCSessionMemberUpdate(this.memberships);\n // The `ownMembership` will be set when calling `onRTCSessionMemberUpdate`.\n const ownMembership = this.membershipManager?.ownMembership;\n if (this.pendingNotificationToSend && ownMembership && oldMemberships.length === 0) {\n // If we're the first member in the call, we're responsible for\n // sending the notification event\n if (ownMembership.eventId && this.joinConfig?.notificationType) {\n this.sendCallNotify(\n ownMembership.eventId,\n this.joinConfig.notificationType,\n ownMembership.callIntent,\n );\n } else {\n this.logger.warn(\"Own membership eventId is undefined, cannot send call notification\");\n }\n }\n // If anyone else joins the session it is no longer our responsibility to send the notification.\n // (If we were the joiner we already did sent the notification in the block above.)\n if (this.memberships.length > 0) this.pendingNotificationToSend = undefined;\n } else {\n this.logger.debug(`No membership changes detected for room ${this.roomSubset.roomId}`);\n }\n // This also needs to be done if `changed` = false\n // A member might have updated their fingerprint (created_ts)\n this.encryptionManager?.onMembershipsUpdate(oldMemberships);\n\n this.setExpiryTimer();\n };\n}\n\n/// Private helpers\nasync function computeBackendIdentityAndVerifyMemberEvents(\n room: Pick<Room, \"hasMembershipState\">,\n callMemberEvents: MatrixEvent[],\n slotDescription: SlotDescription,\n logger: Logger,\n): Promise<CallMembership[]> {\n const callMemberships: CallMembership[] = [];\n\n for (const memberEvent of callMemberEvents) {\n const content = memberEvent.getContent();\n\n // Quick filter to avoid unneeded processing of invalid events or left events.\n if (!quickFilterNonRelevantContents(content, logger)) {\n continue;\n }\n\n try {\n const membership = await CallMembership.parseFromEvent(memberEvent);\n\n if (isValidMembership(membership, room, slotDescription, logger)) {\n callMemberships.push(membership);\n }\n } catch (e) {\n logger.warn(\"Couldn't construct call membership: \", e);\n }\n }\n\n return callMemberships;\n}\n\nfunction quickFilterNonRelevantContents(content: IContent, logger: Logger): boolean {\n // Ignore sticky keys for the count\n const eventKeysCount = Object.keys(content).filter((k) => k !== \"msc4354_sticky_key\").length;\n // Don't even bother about empty events (saves us from costly type/\"key in\" checks in bigger rooms)\n if (eventKeysCount === 0) return false;\n\n // We first decide if it's a MSC4143 event (per device state key)\n if (eventKeysCount > 1 && \"application\" in content) {\n // We have a MSC4143 event membership event with a proper joined content\n return true;\n } else if (eventKeysCount === 1 && \"memberships\" in content) {\n // Events used to have this format in the past, but are now deprecated.\n // Given that state events ~cannot be deleted, there can be some remaining events in the room, just ignore them.\n return false;\n } else {\n // Invalid or left content\n return false;\n }\n}\n\nfunction isValidMembership(\n membership: CallMembership,\n room: Pick<Room, \"hasMembershipState\">,\n slotDescription: SlotDescription,\n logger: Logger,\n): boolean {\n if (membership.slotDescription.id !== slotDescription.id) {\n logger.info(\n `Ignoring membership of user ${membership.userId} for a different slot. Theirs: ${JSON.stringify(membership.slotDescription)}, Expected: ${JSON.stringify(slotDescription)}`,\n );\n return false;\n }\n\n if (membership.isExpired()) {\n logger.info(`Ignoring expired device membership ${membership.userId}/${membership.deviceId}`);\n return false;\n }\n\n if (!room.hasMembershipState(membership.userId ?? \"\", KnownMembership.Join)) {\n logger.info(`Ignoring membership of user ${membership.userId} who is not in the room.`);\n return false;\n }\n\n return true;\n}\n\n/**\n * Reads the slot state event's content for the given slot description.\n *\n * @returns The slot event's content, or `undefined` if no slot event exists for the given description.\n */\nfunction getSlotEventContent(\n room: Pick<Room, \"getLiveTimeline\">,\n slotDescription: SlotDescription,\n): RtcSlotEventContent | undefined {\n const slotId = computeSlotId(slotDescription);\n const slotEvent = room\n .getLiveTimeline()\n .getState(EventTimeline.FORWARDS)\n ?.getStateEvents(EventType.RTCSlot, slotId);\n if (!slotEvent) return undefined;\n\n return slotEvent.getContent<RtcSlotEventContent>();\n}\n\n/**\n * Whether the given slot is closed.\n *\n * @returns `true` if the slot is closed, `false` if the slot is open or `undefined`\n * if no slot exists.\n */\nfunction isSlotClosed(room: Pick<Room, \"getLiveTimeline\">, slotDescription: SlotDescription): boolean | undefined {\n const content = getSlotEventContent(room, slotDescription) as Partial<RtcSlotEventContent> | undefined;\n if (content === undefined) return undefined;\n\n return (\n content.status !== \"open\" ||\n typeof content.application !== \"object\" ||\n content.application?.type !== slotDescription.application\n );\n}\n\n/**\n * Collects the raw member events from room state and sticky store.\n */\nfunction collectMembersEvents(\n room: Pick<Room, \"getLiveTimeline\" | \"roomId\" | \"_unstable_getStickyEvents\">,\n slotDescription: SlotDescription,\n options: SessionMembershipsForSlotOpts,\n logger: Logger,\n): MatrixEvent[] {\n const { listenForStickyEvents, listenForMemberStateEvents } = options;\n let callMemberEvents: MatrixEvent[] = [];\n if (listenForStickyEvents && !isSlotClosed(room, slotDescription)) {\n // prefill with sticky events\n callMemberEvents = [...room._unstable_getStickyEvents()].filter((e) => e.getType() === EventType.RTCMembership);\n }\n if (listenForMemberStateEvents) {\n const roomState = room.getLiveTimeline().getState(EventTimeline.FORWARDS);\n if (!roomState) {\n logger.warn(\"Couldn't get state for room \" + room.roomId + \"using empty membership array\");\n return [];\n }\n const callMemberStateEvents = roomState.getStateEvents(EventType.GroupCallMemberPrefix);\n callMemberEvents = callMemberEvents.concat(\n callMemberStateEvents.filter(\n (callMemberStateEvent) =>\n !callMemberEvents.some(\n // only care about state events which have keys which we have not yet seen in the sticky events.\n // TODO: I believe this can discard a joined state event if there is a matching left sticky event.\n (stickyEvent) =>\n stickyEvent.getContent().msc4354_sticky_key === callMemberStateEvent.getStateKey(),\n ),\n ),\n );\n }\n return callMemberEvents;\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"MatrixRTCSession.js","names":[],"sources":["../../src/matrixrtc/MatrixRTCSession.ts"],"sourcesContent":["/*\nCopyright 2023 - 2026 The Matrix.org Foundation C.I.C.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\nimport { type Logger, logger as rootLogger } from \"../logger.ts\";\nimport { TypedEventEmitter } from \"../models/typed-event-emitter.ts\";\nimport { EventTimeline } from \"../models/event-timeline.ts\";\nimport { type Room } from \"../models/room.ts\";\nimport { type MatrixClient } from \"../client.ts\";\nimport { EventType, RelationType } from \"../@types/event.ts\";\nimport { KnownMembership } from \"../@types/membership.ts\";\nimport { type ISendEventResponse } from \"../@types/requests.ts\";\nimport { CallMembership } from \"./CallMembership.ts\";\nimport { RoomStateEvent } from \"../models/room-state.ts\";\nimport { MembershipManager, StickyEventMembershipManager } from \"./MembershipManager.ts\";\nimport { type CallMembershipIdentityParts, type IEncryptionManager } from \"./EncryptionManager.ts\";\nimport { logDurationSync } from \"../utils.ts\";\nimport type {\n Statistics,\n RTCNotificationType,\n Status,\n IRTCNotificationContent,\n RTCCallIntent,\n Transport,\n SlotDescription,\n RtcSlotEventContent,\n} from \"./types.ts\";\nimport {\n MembershipManagerEvent,\n type MembershipManagerEventHandlerMap,\n type IMembershipManager,\n} from \"./IMembershipManager.ts\";\nimport { RTCEncryptionManager } from \"./RTCEncryptionManager.ts\";\nimport { ToDeviceKeyTransport } from \"./ToDeviceKeyTransport.ts\";\nimport { TypedReEmitter } from \"../ReEmitter.ts\";\nimport { type IContent, type MatrixEvent } from \"../models/event.ts\";\nimport { RoomStickyEventsEvent, type RoomStickyEventsMap } from \"../models/room-sticky-events.ts\";\nimport { computeSlotId } from \"./utils.ts\";\n\n/**\n * Events emitted by MatrixRTCSession\n */\nexport enum MatrixRTCSessionEvent {\n // A member joined, left, or updated a property of their membership.\n MembershipsChanged = \"memberships_changed\",\n // We joined or left the session: our own local idea of whether we are joined,\n // separate from MembershipsChanged, ie. independent of whether our member event\n // has successfully gone through.\n JoinStateChanged = \"join_state_changed\",\n // The key used to encrypt media has changed\n EncryptionKeyChanged = \"encryption_key_changed\",\n /** The membership manager had to shut down caused by an unrecoverable error */\n MembershipManagerError = \"membership_manager_error\",\n /** The RTCSession did send a call notification caused by joining the call as the first member */\n DidSendCallNotification = \"did_send_call_notification\",\n}\n\nexport type MatrixRTCSessionEventHandlerMap = {\n [MatrixRTCSessionEvent.MembershipsChanged]: (\n oldMemberships: CallMembership[],\n newMemberships: CallMembership[],\n ) => void;\n [MatrixRTCSessionEvent.JoinStateChanged]: (isJoined: boolean) => void;\n [MatrixRTCSessionEvent.EncryptionKeyChanged]: (\n key: Uint8Array<ArrayBuffer>,\n encryptionKeyIndex: number,\n membership: CallMembershipIdentityParts,\n rtcBackendIdentity: string,\n ) => void;\n [MatrixRTCSessionEvent.MembershipManagerError]: (error: unknown) => void;\n [MatrixRTCSessionEvent.DidSendCallNotification]: (\n notificationContentNew: { event_id: string } & IRTCNotificationContent,\n ) => void;\n};\n\nexport interface SessionConfig {\n /**\n * What kind of notification to send when starting the session.\n * @default `undefined` (no notification)\n */\n notificationType?: RTCNotificationType;\n\n /**\n * Determines the kind of call this will be.\n */\n callIntent?: RTCCallIntent;\n}\n\n// The names follow these principles:\n// - we use the technical term delay if the option is related to delayed events.\n// - we use delayedLeaveEvent if the option is related to the delayed leave event.\n// - we use membershipEvent if the option is related to the rtc member state event.\n// - we use the technical term expiry if the option is related to the expiry field of the membership state event.\n// - we use a `Ms` postfix if the option is a duration to avoid using words like:\n// `time`, `duration`, `delay`, `timeout`... that might be mistaken/confused with technical terms.\nexport interface MembershipConfig {\n /**\n * The timeout (in milliseconds) after we joined the call, that our membership should expire\n * unless we have explicitly updated it.\n *\n * This is what goes into the m.rtc.member event expiry field and is typically set to a number of hours.\n */\n membershipEventExpiryMs?: number;\n\n /**\n * The time in (in milliseconds) which the manager will prematurely send the updated state event before the membership `expires` time to make sure it\n * sends the updated state event early enough.\n *\n * A headroom of 1000ms and a `membershipExpiryTimeout` of 10000ms would result in the first membership event update after 9s and\n * a membership event that would be considered expired after 10s.\n *\n * This value does not have an effect on the value of `SessionMembershipData.expires`.\n */\n membershipEventExpiryHeadroomMs?: number;\n\n /**\n * The timeout (in milliseconds) with which the deleayed leave event on the server is configured.\n * After this time the server will set the event to the disconnected stat if it has not received a keep-alive from the client.\n */\n delayedLeaveEventDelayMs?: number;\n\n /**\n * The interval (in milliseconds) in which the client will send membership keep-alives to the server.\n */\n delayedLeaveEventRestartMs?: number;\n\n /**\n * The maximum number of retries that the manager will do for delayed event sending/updating and state event sending when a server rate limit has been hit.\n */\n maximumRateLimitRetryCount?: number;\n\n /**\n * The maximum number of retries that the manager will do for delayed event sending/updating and state event sending when a network error occurs.\n */\n maximumNetworkErrorRetryCount?: number;\n\n /**\n * The time (in milliseconds) after which we will retry a http request if it\n * failed to send due to a network error. (send membership event, send delayed event, restart delayed event...)\n */\n networkErrorRetryMs?: number;\n\n /**\n * The time (in milliseconds) after which a we consider a delayed event restart http request to have failed.\n * Setting this to a lower value will result in more frequent retries but also a higher chance of failiour.\n *\n * In the presence of network packet loss (hurting TCP connections), the custom delayedEventRestartLocalTimeoutMs\n * helps by keeping more delayed event reset candidates in flight,\n * improving the chances of a successful reset. (its is equivalent to the js-sdk `localTimeout` configuration,\n * but only applies to calls to the `_unstable_restartScheduledDelayedEvent` endpoint\n * or the `_unstable_updateDelayedEvent` endpoint with a body of `{action:\"restart\"}`.)\n */\n delayedLeaveEventRestartLocalTimeoutMs?: number;\n\n /**\n * Send membership using sticky events rather than state events.\n * This also make the client use the new m.rtc.member MSC4354 event format. (instead of m.call.member)\n *\n * **WARNING**: This is an unstable feature and not all clients will support it.\n */\n unstableSendStickyEvents?: boolean;\n}\n\nexport interface EncryptionConfig {\n /**\n * If true, generate and share a media key for this participant,\n * and emit MatrixRTCSessionEvent.EncryptionKeyChanged when\n * media keys for other participants become available.\n */\n manageMediaKeys?: boolean;\n /**\n * The minimum time (in milliseconds) between each attempt to send encryption key(s).\n * e.g. if this is set to 1000, then we will send at most one key event every second.\n * @deprecated - Not used by the new encryption manager.\n */\n updateEncryptionKeyThrottle?: number;\n\n /**\n * Sometimes it is necessary to rotate the encryption key after a membership update.\n * For performance reasons we might not want to rotate the key immediately but allow future memberships to use the same key.\n * If 5 people join in a row in less than 5 seconds, we don't want to rotate the key for each of them.\n * If 5 people leave in a row in less than 5 seconds, we don't want to rotate the key for each of them.\n * So we do share the key which was already used live for <5s to new joiners.\n * This does result in a potential leak up to the configured time of call media.\n * This has to be considered when choosing a value for this property.\n */\n keyRotationGracePeriodMs?: number;\n\n /**\n * The delay (in milliseconds) after a member leaves before we create and publish a new key, because people\n * tend to leave calls at the same time.\n * @deprecated - Not used by the new encryption manager.\n */\n makeKeyDelay?: number;\n /**\n * The delay (in milliseconds) between sending a new key and starting to encrypt with it. This\n * gives others a chance to receive the new key to minimize the chance they get media they can't decrypt.\n *\n * The higher this value is, the better it is for existing members as they will have a smoother experience.\n * But it impacts new joiners: They will always have to wait `useKeyDelay` before being able to decrypt the media\n * (as it will be encrypted with the new key after the delay only), even if the key has already arrived before the delay.\n */\n useKeyDelay?: number;\n}\nexport type JoinSessionConfig = SessionConfig & MembershipConfig & EncryptionConfig;\n\ninterface SessionMembershipsForSlotOpts {\n /**\n * Listen for incoming sticky member events. If disabled, this session will\n * ignore any incoming sticky events.\n */\n listenForStickyEvents: boolean;\n /**\n * Listen for incoming member state events (legacy). If disabled, this session will\n * ignore any incoming state events.\n */\n listenForMemberStateEvents: boolean;\n}\n\nconst DEFAULT_SESSION_MEMBERSHIPS_FOR_SLOT_OPTS: SessionMembershipsForSlotOpts = {\n listenForStickyEvents: true,\n listenForMemberStateEvents: true,\n};\n\n/**\n * A MatrixRTCSession manages the membership & properties of a MatrixRTC session.\n * This class doesn't deal with media at all, just membership & properties of a session.\n */\nexport class MatrixRTCSession extends TypedEventEmitter<\n MatrixRTCSessionEvent | MembershipManagerEvent,\n MatrixRTCSessionEventHandlerMap & MembershipManagerEventHandlerMap\n> {\n private membershipManager?: IMembershipManager;\n private encryptionManager?: IEncryptionManager;\n private joinConfig?: SessionConfig;\n private logger: Logger;\n\n private pendingNotificationToSend: undefined | RTCNotificationType;\n /**\n * This timeout is responsible to track any expiration. We need to know when we have to start\n * to ignore other call members. There is no callback for this. This timeout will always be configured to\n * emit when the next membership expires.\n */\n private expiryTimeout?: ReturnType<typeof setTimeout>;\n\n public memberships: CallMembership[] = [];\n\n /**\n * Resolves when the session has calculated the initial membership of the session.\n */\n public readonly initialMembershipCalculated: Promise<void>;\n /**\n * Does membership need to be recalculated? This is set to false upon\n * recalculation.\n */\n private membershipNeedsRecalculation = false;\n\n /**\n * The statistics for this session.\n */\n public statistics: Statistics = {\n counters: {\n roomEventEncryptionKeysSent: 0,\n roomEventEncryptionKeysReceived: 0,\n },\n totals: {\n roomEventEncryptionKeysReceivedTotalAge: 0,\n },\n };\n\n public get membershipStatus(): Status | undefined {\n return this.membershipManager?.status;\n }\n public get probablyLeft(): boolean | undefined {\n return this.membershipManager?.probablyLeft;\n }\n public get delayId(): string | undefined {\n return this.membershipManager?.delayId;\n }\n\n /**\n * The callId (sessionId) of the call.\n *\n * It can be undefined since the callId is only known once the first membership joins.\n * The callId is the property that, per definition, groups memberships into one call.\n * @deprecated use `slotId` instead.\n */\n public get callId(): string | undefined {\n return this.slotDescription?.id;\n }\n /**\n * The slotId of the call.\n * `{application}#{appSpecificId}`\n * It can be undefined since the slotId is only known once the first membership joins.\n * The slotId is the property that, per definition, groups memberships into one call.\n */\n public get slotId(): string | undefined {\n return computeSlotId(this.slotDescription);\n }\n\n /**\n * Reads the current slot state event's content for this session.\n *\n * @returns The slot event's content, or `undefined` if no slot event exists for this session.\n */\n public getRtcSlot(): RtcSlotEventContent | undefined {\n return getSlotEventContent(this.roomSubset, this.slotDescription);\n }\n\n /**\n * Whether this session's slot is closed.\n *\n * @returns `true` if the slot is closed, `false` if the slot is open or `undefined`\n * if no slot exists.\n */\n public isSlotClosed(): boolean | undefined {\n return isSlotClosed(this.roomSubset, this.slotDescription);\n }\n\n /**\n * Returns all the call memberships for a room that match the provided `sessionDescription`,\n * oldest first.\n *\n * By default, this will return *both* sticky and member state events.\n */\n public static async sessionMembershipsForSlot(\n room: Pick<Room, \"getLiveTimeline\" | \"roomId\" | \"hasMembershipState\" | \"_unstable_getStickyEvents\">,\n slotDescription: SlotDescription,\n // default both true this implied we combine sticky and state events for the final call state\n // (prefer sticky events in case of a duplicate)\n options: SessionMembershipsForSlotOpts = DEFAULT_SESSION_MEMBERSHIPS_FOR_SLOT_OPTS,\n ): Promise<CallMembership[]> {\n const logger = rootLogger.getChild(\n `[MatrixRTCSession ${room.roomId} ${slotDescription.application}#${slotDescription.id}]`,\n );\n const callMemberEvents = collectMembersEvents(room, slotDescription, options, logger);\n\n const callMemberships = await computeBackendIdentityAndVerifyMemberEvents(\n room,\n callMemberEvents,\n slotDescription,\n logger,\n );\n\n callMemberships.sort((a, b) => a.createdTs() - b.createdTs());\n if (callMemberships.length > 1) {\n logger.debug(\n `Call memberships in room ${room.roomId}, in order: `,\n callMemberships.map((m) => [m.createdTs(), m.userId]),\n );\n }\n\n return callMemberships;\n }\n\n /**\n * Return the MatrixRTC session for the room.\n * This returned session can be used to find out if there are active sessions\n * for the requested room and `slotDescription`.\n */\n public static sessionForSlot(\n client: MatrixClient,\n room: Room,\n slotDescription: SlotDescription,\n opts?: SessionMembershipsForSlotOpts,\n ): MatrixRTCSession {\n return new MatrixRTCSession(client, room, slotDescription, opts);\n }\n\n /**\n * WARN: this can in theory only be a subset of the room with the properties required by\n * this class.\n * Outside of tests this most likely will be a full room, however.\n * @deprecated Relying on a full Room object being available here is an anti-pattern. You should be tracking\n * the room object in your own code and passing it in when needed.\n */\n public get room(): Room {\n return this.roomSubset as Room;\n }\n\n /**\n * This constructs a room session. When using MatrixRTC inside the js-sdk this is expected\n * to be used with the MatrixRTCSessionManager exclusively.\n *\n * In cases where you don't use the js-sdk but build on top of another Matrix stack this class can be used standalone\n * to manage a joined MatrixRTC session.\n *\n * @param client A subset of the {@link MatrixClient} that lets the session interact with the Matrix room.\n * @param roomSubset The room this session is attached to. A subset of a js-sdk Room that the session needs.\n * @param slotDescription The slot description is a virtual address where participants are allowed to meet.\n * This session will only manage memberships that match this slot description.Sessions are distinct if any of\n * those properties are distinct: `roomSubset.roomId`, `slotDescription.application`, `slotDescription.id`.\n * @param calculateMembershipsOpts - Options to configure how memberships are calculated for this session.\n */\n public constructor(\n private readonly client: Pick<\n MatrixClient,\n | \"getUserId\"\n | \"getDeviceId\"\n | \"sendEvent\"\n | \"sendStateEvent\"\n | \"_unstable_sendDelayedStateEvent\"\n | \"_unstable_updateDelayedEvent\"\n | \"_unstable_cancelScheduledDelayedEvent\"\n | \"_unstable_restartScheduledDelayedEvent\"\n | \"_unstable_sendScheduledDelayedEvent\"\n | \"_unstable_sendStickyEvent\"\n | \"_unstable_sendStickyDelayedEvent\"\n | \"cancelPendingEvent\"\n | \"encryptAndSendToDevice\"\n | \"off\"\n | \"on\"\n | \"decryptEventIfNeeded\"\n >,\n private roomSubset: Pick<\n Room,\n | \"getLiveTimeline\"\n | \"roomId\"\n | \"getVersion\"\n | \"hasMembershipState\"\n | \"on\"\n | \"off\"\n | \"_unstable_getStickyEvents\"\n >,\n\n public readonly slotDescription: SlotDescription,\n private readonly calculateMembershipsOpts?: SessionMembershipsForSlotOpts,\n ) {\n super();\n this.logger = rootLogger.getChild(\n `[MatrixRTCSession ${roomSubset.roomId} ${slotDescription.application}#${slotDescription.id}]`,\n );\n\n this.roomSubset.on(RoomStateEvent.Members, this.onRoomMemberUpdate);\n this.roomSubset.on(RoomStateEvent.Events, this.onRoomStateEvent);\n this.roomSubset.on(RoomStickyEventsEvent.Update, this.onStickyEventUpdate);\n\n this.initialMembershipCalculated = this.ensureRecalculateSessionMembers();\n this.setExpiryTimer();\n }\n /*\n * Returns true if we intend to be participating in the MatrixRTC session.\n * This is determined by checking if the relativeExpiry has been set.\n */\n public isJoined(): boolean {\n return this.membershipManager?.isJoined() ?? false;\n }\n\n /**\n * Performs cleanup & removes timers for client shutdown\n */\n public async stop(): Promise<void> {\n await this.membershipManager?.leave(1000);\n if (this.expiryTimeout) {\n clearTimeout(this.expiryTimeout);\n this.expiryTimeout = undefined;\n }\n\n this.roomSubset.off(RoomStateEvent.Members, this.onRoomMemberUpdate);\n this.roomSubset.off(RoomStateEvent.Events, this.onRoomStateEvent);\n this.roomSubset.off(RoomStickyEventsEvent.Update, this.onStickyEventUpdate);\n }\n\n private reEmitter = new TypedReEmitter<\n MatrixRTCSessionEvent | MembershipManagerEvent,\n MatrixRTCSessionEventHandlerMap & MembershipManagerEventHandlerMap\n >(this);\n\n /**\n * Announces this user and device as joined to the MatrixRTC session,\n * and continues to update the membership event to keep it valid until\n * leaveRoomSession() is called\n * This will not subscribe to updates: remember to call subscribe() separately if\n * desired.\n * This method will return immediately and the session will be joined in the background.\n * @param ownMembershipIdentity the identity of the user and device joining the session.\n * This will be put into the content.member.\n * @param fociPreferred the list of preferred foci to use in the joined RTC membership event.\n * If multiSfuFocus is set, this is only needed if this client wants to publish to multiple transports simultaneously.\n * @param multiSfuFocus the active focus to use in the joined RTC membership event. Setting this implies the\n * membership manager will operate in a multi-SFU connection mode. If `undefined`, an `oldest_membership`\n * transport selection will be used instead.\n * @param joinConfig - Additional configuration for the joined session.\n */\n public joinRTCSession(\n ownMembershipIdentity: CallMembershipIdentityParts,\n fociPreferred: Transport[],\n multiSfuFocus?: Transport,\n joinConfig?: JoinSessionConfig,\n ): void {\n if (this.isJoined()) {\n this.logger.info(`Already joined to session in room ${this.roomSubset.roomId}: ignoring join call`);\n return;\n } else {\n // Create MembershipManager and pass the RTCSession logger (with room id info)\n this.membershipManager = joinConfig?.unstableSendStickyEvents\n ? new StickyEventMembershipManager(\n joinConfig,\n this.roomSubset,\n this.client,\n this.slotDescription,\n ownMembershipIdentity.memberId,\n this.logger,\n )\n : new MembershipManager(joinConfig, this.roomSubset, this.client, this.slotDescription, this.logger);\n\n this.reEmitter.reEmit(this.membershipManager, [\n MembershipManagerEvent.ProbablyLeft,\n MembershipManagerEvent.StatusChanged,\n MembershipManagerEvent.DelayIdChanged,\n ]);\n // Create Encryption manager\n const [room, client, statistics] = [this.roomSubset, this.client, this.statistics];\n const transport = new ToDeviceKeyTransport(ownMembershipIdentity, room.roomId, client, statistics);\n this.encryptionManager = new RTCEncryptionManager(\n ownMembershipIdentity,\n () => this.memberships,\n transport,\n (\n keyBin: Uint8Array<ArrayBuffer>,\n encryptionKeyIndex: number,\n membership: CallMembershipIdentityParts,\n rtcBackendIdentity: string,\n ) => {\n this.emit(\n MatrixRTCSessionEvent.EncryptionKeyChanged,\n keyBin,\n encryptionKeyIndex,\n membership,\n rtcBackendIdentity,\n );\n },\n this.logger,\n );\n }\n\n this.joinConfig = joinConfig;\n this.pendingNotificationToSend = this.joinConfig?.notificationType;\n\n // Join!\n this.membershipManager.join(fociPreferred, multiSfuFocus, (e) => {\n this.logger.error(\"MembershipManager encountered an unrecoverable error: \", e);\n this.emit(MatrixRTCSessionEvent.MembershipManagerError, e);\n this.emit(MatrixRTCSessionEvent.JoinStateChanged, this.isJoined());\n });\n this.encryptionManager.join(joinConfig);\n\n this.emit(MatrixRTCSessionEvent.JoinStateChanged, true);\n }\n\n /**\n *\n * @param fociPreferred\n * @param multiSfuFocus\n * @param joinConfig\n * @deprecated use the joinRTCSession method instead\n */\n public joinRoomSession(\n fociPreferred: Transport[],\n multiSfuFocus?: Transport,\n joinConfig?: JoinSessionConfig,\n ): void {\n const [userId, deviceId] = [this.client.getUserId()!, this.client.getDeviceId()!];\n // TODO this wants to become a UUID\n const memberId = `${userId}:${deviceId}`;\n this.joinRTCSession({ userId, deviceId, memberId }, fociPreferred, multiSfuFocus, joinConfig);\n }\n\n /**\n * Announces this user and device as having left the MatrixRTC session\n * and stops scheduled updates.\n * This will not unsubscribe from updates: remember to call unsubscribe() separately if\n * desired.\n * The membership update required to leave the session will retry if it fails.\n * Without network connection the promise will never resolve.\n * A timeout can be provided so that there is a guarantee for the promise to resolve.\n * @returns Whether the membership update was attempted and did not time out.\n */\n public async leaveRoomSession(timeout: number | undefined = undefined): Promise<boolean> {\n if (!this.isJoined()) {\n this.logger.info(`Not joined to session in room ${this.roomSubset.roomId}: ignoring leave call`);\n return false;\n }\n\n this.logger.info(`Leaving call session in room ${this.roomSubset.roomId}`);\n\n this.encryptionManager!.leave();\n\n const leavePromise = this.membershipManager!.leave(timeout);\n this.emit(MatrixRTCSessionEvent.JoinStateChanged, false);\n\n return await leavePromise;\n }\n /**\n * This returns the focus in use by the oldest membership.\n * Do not use since this might be just the focus for the oldest membership. others might use a different focus.\n * @deprecated use `member.getTransport(session.getOldestMembership())` instead for the specific member you want to get the focus for.\n */\n public getFocusInUse(): Transport | undefined {\n const oldestMembership = this.getOldestMembership();\n return oldestMembership?.getTransport(oldestMembership);\n }\n\n public getOldestMembership(): CallMembership | undefined {\n return this.memberships[0];\n }\n\n /**\n * Get the call intent for the current call, based on what members are advertising. If one or more\n * members disagree on the current call intent, or nobody specifies one then `undefined` is returned.\n *\n * If all members that specify a call intent agree, that value is returned.\n * @returns A call intent, or `undefined` if no consensus or not given.\n */\n public getConsensusCallIntent(): RTCCallIntent | undefined {\n const getFirstCallIntent = this.memberships.find((m) => !!m.callIntent)?.callIntent;\n if (!getFirstCallIntent) {\n return undefined;\n }\n if (this.memberships.every((m) => !m.callIntent || m.callIntent === getFirstCallIntent)) {\n return getFirstCallIntent;\n }\n return undefined;\n }\n\n public async updateCallIntent(callIntent: RTCCallIntent): Promise<void> {\n const myMembership = this.membershipManager?.ownMembership;\n if (!myMembership) {\n throw Error(\"Not connected yet\");\n }\n await this.membershipManager?.updateCallIntent(callIntent);\n }\n\n /**\n * Re-emit an EncryptionKeyChanged event for each tracked encryption key. This can be used to export\n * the keys.\n */\n public reemitEncryptionKeys(): void {\n this.encryptionManager?.getEncryptionKeys().forEach((keyRing, key) => {\n keyRing.forEach((keyInfo) => {\n this.emit(\n MatrixRTCSessionEvent.EncryptionKeyChanged,\n keyInfo.key,\n keyInfo.keyIndex,\n keyInfo.membership,\n keyInfo.rtcBackendIdentity,\n );\n });\n });\n }\n\n /**\n * Sets a timer for the soonest membership expiry\n */\n private setExpiryTimer(): void {\n if (this.expiryTimeout) {\n clearTimeout(this.expiryTimeout);\n this.expiryTimeout = undefined;\n }\n\n let soonestExpiry;\n for (const membership of this.memberships) {\n const thisExpiry = membership.getMsUntilExpiry();\n // If getMsUntilExpiry is undefined we have a MSC4143 (MatrixRTC) compliant event - it never expires\n // but will be reliably resent on disconnect.\n if (thisExpiry !== undefined && (soonestExpiry === undefined || thisExpiry < soonestExpiry)) {\n soonestExpiry = thisExpiry;\n }\n }\n\n if (soonestExpiry != undefined) {\n this.expiryTimeout = setTimeout(() => void this.ensureRecalculateSessionMembers(), soonestExpiry);\n }\n }\n\n /**\n * Sends notification events to indiciate the call has started.\n * Note: This does not return a promise, instead scheduling the notification events to be sent.\n * @param parentEventId Event id linking to your RTC call membership event.\n * @param notificationType The type of notification to send\n * @param callIntent The type of call this is (e.g. \"audio\").\n */\n private sendCallNotify(\n parentEventId: string,\n notificationType: RTCNotificationType,\n callIntent?: RTCCallIntent,\n ): void {\n const sendNotificationEvent = async (): Promise<{\n response: ISendEventResponse;\n content: IRTCNotificationContent;\n }> => {\n const content: IRTCNotificationContent = {\n \"m.mentions\": { user_ids: [], room: true },\n \"notification_type\": notificationType,\n \"m.relates_to\": {\n event_id: parentEventId,\n rel_type: RelationType.Reference,\n },\n \"sender_ts\": Date.now(),\n \"lifetime\": 30_000, // 30 seconds\n };\n if (callIntent) {\n content[\"m.call.intent\"] = callIntent;\n }\n const response = await this.client.sendEvent(this.roomSubset.roomId, EventType.RTCNotification, content);\n return { response, content };\n };\n\n void sendNotificationEvent()\n .then((notification) => {\n // Join event_id and origin event content\n const newResult = { ...notification.response, ...notification.content };\n this.emit(MatrixRTCSessionEvent.DidSendCallNotification, newResult);\n })\n .catch(([errorLegacy, errorNew]) =>\n this.logger.error(\"Failed to send call notification\", errorLegacy, errorNew),\n );\n }\n\n /**\n * Call this when the Matrix room members have changed.\n */\n private readonly onRoomMemberUpdate = (): void => {\n void this.ensureRecalculateSessionMembers();\n };\n\n /**\n * Call this when a room state event has been updated.\n */\n private readonly onRoomStateEvent = (event: MatrixEvent): void => {\n if (event.getType() !== EventType.RTCSlot) return;\n if (event.getStateKey() !== computeSlotId(this.slotDescription)) return;\n void this.ensureRecalculateSessionMembers();\n };\n\n /**\n * Call this when a sticky event update has occured.\n */\n private readonly onStickyEventUpdate: RoomStickyEventsMap[RoomStickyEventsEvent.Update] = (\n added,\n updated,\n removed,\n ): void => {\n if (\n [...added, ...removed, ...updated.flatMap((v) => [v.current, v.previous])].some(\n (e) => e.getType() === EventType.RTCMembership,\n )\n ) {\n void this.ensureRecalculateSessionMembers();\n }\n };\n\n /**\n * Call this when something changed that may impacts the current MatrixRTC members in this session.\n */\n // We allow this name schema since this function should only be used for testing purposes.\n public _onRTCSessionMemberUpdate = async (): Promise<void> => {\n await this.recalculateSessionMembers();\n };\n\n // helper variables to make sure we do not have parallel running recalculations.\n private recalculateSessionMembersPromise: Promise<void> = Promise.resolve();\n\n /**\n * Ensures that membership is recalculated when the state of the session may have changed.\n * Also ensures that only one recalculation is made at a time.\n * @returns A promise resolving when the state has been recalculated.\n */\n private ensureRecalculateSessionMembers(): Promise<void> {\n if (this.membershipNeedsRecalculation) {\n // We have already requested recalcuation, don't attempt a new one.\n return this.recalculateSessionMembersPromise;\n }\n this.membershipNeedsRecalculation = true;\n // Chain the recalculation.\n this.recalculateSessionMembersPromise = this.recalculateSessionMembersPromise.then(\n () => this.recalculateSessionMembers(),\n () => this.recalculateSessionMembers(),\n );\n return this.recalculateSessionMembersPromise;\n }\n\n /**\n * Call this when anything that could impact rtc memberships has changed: Room Members or RTC members.\n *\n * Examines the latest call memberships and handles any encryption key sending or rotation that is needed.\n *\n * This function should be called when the room members or call memberships might have changed.\n */\n private readonly recalculateSessionMembers = async (): Promise<void> => {\n // Clear the flag.\n this.membershipNeedsRecalculation = false;\n const oldMemberships = this.memberships;\n\n this.memberships = await MatrixRTCSession.sessionMembershipsForSlot(\n this.room,\n this.slotDescription,\n this.calculateMembershipsOpts,\n );\n\n const changed =\n oldMemberships.length != this.memberships.length ||\n oldMemberships.some((m, i) => !CallMembership.equal(m, this.memberships[i]));\n\n if (changed) {\n this.logger.info(\n `Memberships for call in room ${this.roomSubset.roomId} have changed: emitting (${this.memberships.length} members)`,\n );\n logDurationSync(this.logger, \"emit MatrixRTCSessionEvent.MembershipsChanged\", () => {\n this.emit(MatrixRTCSessionEvent.MembershipsChanged, oldMemberships, this.memberships);\n });\n\n void this.membershipManager?.onRTCSessionMemberUpdate(this.memberships);\n // The `ownMembership` will be set when calling `onRTCSessionMemberUpdate`.\n const ownMembership = this.membershipManager?.ownMembership;\n if (this.pendingNotificationToSend && ownMembership && oldMemberships.length === 0) {\n // If we're the first member in the call, we're responsible for\n // sending the notification event\n if (ownMembership.eventId && this.joinConfig?.notificationType) {\n this.sendCallNotify(\n ownMembership.eventId,\n this.joinConfig.notificationType,\n ownMembership.callIntent,\n );\n } else {\n this.logger.warn(\"Own membership eventId is undefined, cannot send call notification\");\n }\n }\n // If anyone else joins the session it is no longer our responsibility to send the notification.\n // (If we were the joiner we already did sent the notification in the block above.)\n if (this.memberships.length > 0) this.pendingNotificationToSend = undefined;\n } else {\n this.logger.debug(`No membership changes detected for room ${this.roomSubset.roomId}`);\n }\n // This also needs to be done if `changed` = false\n // A member might have updated their fingerprint (created_ts)\n this.encryptionManager?.onMembershipsUpdate(oldMemberships);\n\n this.setExpiryTimer();\n };\n}\n\n/// Private helpers\nasync function computeBackendIdentityAndVerifyMemberEvents(\n room: Pick<Room, \"hasMembershipState\">,\n callMemberEvents: MatrixEvent[],\n slotDescription: SlotDescription,\n logger: Logger,\n): Promise<CallMembership[]> {\n const callMemberships: CallMembership[] = [];\n\n for (const memberEvent of callMemberEvents) {\n const content = memberEvent.getContent();\n\n // Quick filter to avoid unneeded processing of invalid events or left events.\n if (!quickFilterNonRelevantContents(content, logger)) {\n continue;\n }\n\n try {\n const membership = await CallMembership.parseFromEvent(memberEvent);\n\n if (isValidMembership(membership, room, slotDescription, logger)) {\n callMemberships.push(membership);\n }\n } catch (e) {\n logger.warn(\"Couldn't construct call membership: \", e);\n }\n }\n\n return callMemberships;\n}\n\nfunction quickFilterNonRelevantContents(content: IContent, logger: Logger): boolean {\n // Ignore sticky keys for the count\n const eventKeysCount = Object.keys(content).filter((k) => k !== \"msc4354_sticky_key\").length;\n // Don't even bother about empty events (saves us from costly type/\"key in\" checks in bigger rooms)\n if (eventKeysCount === 0) return false;\n\n // We first decide if it's a MSC4143 event (per device state key)\n if (eventKeysCount > 1 && \"application\" in content) {\n // We have a MSC4143 event membership event with a proper joined content\n return true;\n } else if (eventKeysCount === 1 && \"memberships\" in content) {\n // Events used to have this format in the past, but are now deprecated.\n // Given that state events ~cannot be deleted, there can be some remaining events in the room, just ignore them.\n return false;\n } else {\n // Invalid or left content\n return false;\n }\n}\n\nfunction isValidMembership(\n membership: CallMembership,\n room: Pick<Room, \"hasMembershipState\">,\n slotDescription: SlotDescription,\n logger: Logger,\n): boolean {\n if (membership.slotDescription.id !== slotDescription.id) {\n logger.info(\n `Ignoring membership of user ${membership.userId} for a different slot. Theirs: ${JSON.stringify(membership.slotDescription)}, Expected: ${JSON.stringify(slotDescription)}`,\n );\n return false;\n }\n\n if (membership.isExpired()) {\n logger.info(`Ignoring expired device membership ${membership.userId}/${membership.deviceId}`);\n return false;\n }\n\n if (!room.hasMembershipState(membership.userId ?? \"\", KnownMembership.Join)) {\n logger.info(`Ignoring membership of user ${membership.userId} who is not in the room.`);\n return false;\n }\n\n return true;\n}\n\n/**\n * Reads the slot state event's content for the given slot description.\n *\n * @returns The slot event's content, or `undefined` if no slot event exists for the given description.\n */\nfunction getSlotEventContent(\n room: Pick<Room, \"getLiveTimeline\">,\n slotDescription: SlotDescription,\n): RtcSlotEventContent | undefined {\n const slotId = computeSlotId(slotDescription);\n const slotEvent = room\n .getLiveTimeline()\n .getState(EventTimeline.FORWARDS)\n ?.getStateEvents(EventType.RTCSlot, slotId);\n if (!slotEvent) return undefined;\n\n return slotEvent.getContent<RtcSlotEventContent>();\n}\n\n/**\n * Whether the given slot is closed.\n *\n * @returns `true` if the slot is closed, `false` if the slot is open or `undefined`\n * if no slot exists.\n */\nfunction isSlotClosed(room: Pick<Room, \"getLiveTimeline\">, slotDescription: SlotDescription): boolean | undefined {\n const content = getSlotEventContent(room, slotDescription) as Partial<RtcSlotEventContent> | undefined;\n if (content === undefined) return undefined;\n\n return (\n content.status !== \"open\" ||\n typeof content.application !== \"object\" ||\n content.application?.type !== slotDescription.application\n );\n}\n\n/**\n * Collects the raw member events from room state and sticky store.\n */\nfunction collectMembersEvents(\n room: Pick<Room, \"getLiveTimeline\" | \"roomId\" | \"_unstable_getStickyEvents\">,\n slotDescription: SlotDescription,\n options: SessionMembershipsForSlotOpts,\n logger: Logger,\n): MatrixEvent[] {\n const { listenForStickyEvents, listenForMemberStateEvents } = options;\n let callMemberEvents: MatrixEvent[] = [];\n if (listenForStickyEvents && !isSlotClosed(room, slotDescription)) {\n // prefill with sticky events\n callMemberEvents = [...room._unstable_getStickyEvents()].filter((e) => e.getType() === EventType.RTCMembership);\n }\n if (listenForMemberStateEvents) {\n const roomState = room.getLiveTimeline().getState(EventTimeline.FORWARDS);\n if (!roomState) {\n logger.warn(\"Couldn't get state for room \" + room.roomId + \"using empty membership array\");\n return [];\n }\n const callMemberStateEvents = roomState.getStateEvents(EventType.GroupCallMemberPrefix);\n callMemberEvents = callMemberEvents.concat(\n callMemberStateEvents.filter(\n (callMemberStateEvent) =>\n !callMemberEvents.some(\n // only care about state events which have keys which we have not yet seen in the sticky events.\n // TODO: I believe this can discard a joined state event if there is a matching left sticky event.\n (stickyEvent) =>\n stickyEvent.getContent().msc4354_sticky_key === callMemberStateEvent.getStateKey(),\n ),\n ),\n );\n }\n return callMemberEvents;\n}\n"],"mappings":"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","ignoreList":[]}