681.js.map (1030407B)
1 {"version":3,"file":"bundles/12c8185ea2689492c07b/681.js","mappings":"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","sources":["webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/@types/membership.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/@types/read_receipts.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/@types/requests.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/@types/search.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/NamespacedValue.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/ReEmitter.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/ToDeviceMessageQueue.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/base64.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/capabilityPoller.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/common-crypto/CryptoBackend.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/content-repo.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/crypto-api/CryptoEvent.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/crypto-api/key-passphrase.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/digest.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/event-mapper.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/feature.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/filter-component.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/http-api/errors.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/http-api/refresh.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/http-api/fetch.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/http-api/interface.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/http-api/method.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/http-api/prefix.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/http-api/utils.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/indexeddb-helpers.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/matrixrtc/EncryptionManager.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/matrixrtc/IKeyTransport.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/matrixrtc/IMembershipManager.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/matrixrtc/types.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/matrixrtc/MembershipManagerActionScheduler.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/matrixrtc/LivekitTransport.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/matrixrtc/MembershipManager.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/matrixrtc/RTCEncryptionManager.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/matrixrtc/ToDeviceKeyTransport.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/matrixrtc/membershipData/common.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/matrixrtc/membershipData/session.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/matrixrtc/membershipData/rtc.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/matrixrtc/utils.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/models/MSC3089Branch.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/models/MSC3089TreeSpace.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/models/compare-event-ordering.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/models/event-context.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/models/event-status.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/models/invites-ignorer-types.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/models/read-receipt.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/models/relations-container.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/models/room-receipts.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/models/room-retention.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/models/room-summary.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/oauth/discover.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/oauth/error.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/pushprocessor.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/realtime-callbacks.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/retentionPolicy.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/rust-crypto/constants.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/service-types.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/sliding-sync-sdk.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/store/indexeddb-local-backend.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/store/stub.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/thread-utils.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/utils/encryptAESSecretStorageItem.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/utils/internal/deriveKeys.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/utils/roomVersion.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/webrtc/audioContext.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/webrtc/callEventHandler.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/webrtc/callEventTypes.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/webrtc/groupCallEventHandler.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/webrtc/stats/callFeedStatsReporter.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/webrtc/stats/connectionStats.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/webrtc/stats/connectionStatsBuilder.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/webrtc/stats/transportStatsBuilder.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/webrtc/stats/media/mediaSsrcHandler.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/webrtc/stats/media/mediaTrackHandler.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/webrtc/stats/media/mediaTrackStats.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/webrtc/stats/media/mediaTrackStatsHandler.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/webrtc/stats/valueFormatter.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/webrtc/stats/trackStatsBuilder.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/webrtc/stats/connectionStatsReportBuilder.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/webrtc/stats/callStatsReportGatherer.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/webrtc/stats/statsReportEmitter.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/webrtc/stats/groupCallStats.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/webrtc/stats/statsReport.ts","webpack://element-web/../node_modules/.pnpm/matrix-js-sdk@42.0.0/node_modules/matrix-js-sdk/src/webrtc/stats/summaryStatsReportGatherer.ts","webpack://element-web/../node_modules/.pnpm/source-map-loader@5.0.0_webpack@5.108.4/node_modules/source-map-loader/dist/node_modules/.pnpm/events@3.3.0/node_modules/events/events.js","webpack://element-web/../node_modules/.pnpm/source-map-loader@5.0.0_webpack@5.108.4/node_modules/source-map-loader/dist/node_modules/.pnpm/matrix-events-sdk@0.0.1/node_modules/matrix-events-sdk/lib/ExtensibleEvents.js","webpack://element-web/../node_modules/.pnpm/source-map-loader@5.0.0_webpack@5.108.4/node_modules/source-map-loader/dist/node_modules/.pnpm/matrix-events-sdk@0.0.1/node_modules/matrix-events-sdk/lib/IPartialEvent.js","webpack://element-web/../node_modules/.pnpm/source-map-loader@5.0.0_webpack@5.108.4/node_modules/source-map-loader/dist/node_modules/.pnpm/matrix-events-sdk@0.0.1/node_modules/matrix-events-sdk/lib/InvalidEventError.js","webpack://element-web/../node_modules/.pnpm/source-map-loader@5.0.0_webpack@5.108.4/node_modules/source-map-loader/dist/node_modules/.pnpm/matrix-events-sdk@0.0.1/node_modules/matrix-events-sdk/lib/NamespacedMap.js","webpack://element-web/../node_modules/.pnpm/source-map-loader@5.0.0_webpack@5.108.4/node_modules/source-map-loader/dist/node_modules/.pnpm/matrix-events-sdk@0.0.1/node_modules/matrix-events-sdk/lib/NamespacedValue.js","webpack://element-web/../node_modules/.pnpm/source-map-loader@5.0.0_webpack@5.108.4/node_modules/source-map-loader/dist/node_modules/.pnpm/matrix-events-sdk@0.0.1/node_modules/matrix-events-sdk/lib/events/EmoteEvent.js","webpack://element-web/../node_modules/.pnpm/source-map-loader@5.0.0_webpack@5.108.4/node_modules/source-map-loader/dist/node_modules/.pnpm/matrix-events-sdk@0.0.1/node_modules/matrix-events-sdk/lib/events/ExtensibleEvent.js","webpack://element-web/../node_modules/.pnpm/source-map-loader@5.0.0_webpack@5.108.4/node_modules/source-map-loader/dist/node_modules/.pnpm/matrix-events-sdk@0.0.1/node_modules/matrix-events-sdk/lib/events/MessageEvent.js","webpack://element-web/../node_modules/.pnpm/source-map-loader@5.0.0_webpack@5.108.4/node_modules/source-map-loader/dist/node_modules/.pnpm/matrix-events-sdk@0.0.1/node_modules/matrix-events-sdk/lib/events/NoticeEvent.js","webpack://element-web/../node_modules/.pnpm/source-map-loader@5.0.0_webpack@5.108.4/node_modules/source-map-loader/dist/node_modules/.pnpm/matrix-events-sdk@0.0.1/node_modules/matrix-events-sdk/lib/events/PollEndEvent.js","webpack://element-web/../node_modules/.pnpm/source-map-loader@5.0.0_webpack@5.108.4/node_modules/source-map-loader/dist/node_modules/.pnpm/matrix-events-sdk@0.0.1/node_modules/matrix-events-sdk/lib/events/PollResponseEvent.js","webpack://element-web/../node_modules/.pnpm/source-map-loader@5.0.0_webpack@5.108.4/node_modules/source-map-loader/dist/node_modules/.pnpm/matrix-events-sdk@0.0.1/node_modules/matrix-events-sdk/lib/events/PollStartEvent.js","webpack://element-web/../node_modules/.pnpm/source-map-loader@5.0.0_webpack@5.108.4/node_modules/source-map-loader/dist/node_modules/.pnpm/matrix-events-sdk@0.0.1/node_modules/matrix-events-sdk/lib/events/message_types.js","webpack://element-web/../node_modules/.pnpm/source-map-loader@5.0.0_webpack@5.108.4/node_modules/source-map-loader/dist/node_modules/.pnpm/matrix-events-sdk@0.0.1/node_modules/matrix-events-sdk/lib/events/poll_types.js","webpack://element-web/../node_modules/.pnpm/source-map-loader@5.0.0_webpack@5.108.4/node_modules/source-map-loader/dist/node_modules/.pnpm/matrix-events-sdk@0.0.1/node_modules/matrix-events-sdk/lib/events/relationship_types.js","webpack://element-web/../node_modules/.pnpm/source-map-loader@5.0.0_webpack@5.108.4/node_modules/source-map-loader/dist/node_modules/.pnpm/matrix-events-sdk@0.0.1/node_modules/matrix-events-sdk/lib/index.js","webpack://element-web/../node_modules/.pnpm/source-map-loader@5.0.0_webpack@5.108.4/node_modules/source-map-loader/dist/node_modules/.pnpm/matrix-events-sdk@0.0.1/node_modules/matrix-events-sdk/lib/interpreters/legacy/MRoomMessage.js","webpack://element-web/../node_modules/.pnpm/source-map-loader@5.0.0_webpack@5.108.4/node_modules/source-map-loader/dist/node_modules/.pnpm/matrix-events-sdk@0.0.1/node_modules/matrix-events-sdk/lib/interpreters/modern/MMessage.js","webpack://element-web/../node_modules/.pnpm/source-map-loader@5.0.0_webpack@5.108.4/node_modules/source-map-loader/dist/node_modules/.pnpm/matrix-events-sdk@0.0.1/node_modules/matrix-events-sdk/lib/interpreters/modern/MPoll.js","webpack://element-web/../node_modules/.pnpm/source-map-loader@5.0.0_webpack@5.108.4/node_modules/source-map-loader/dist/node_modules/.pnpm/matrix-events-sdk@0.0.1/node_modules/matrix-events-sdk/lib/types.js","webpack://element-web/../node_modules/.pnpm/source-map-loader@5.0.0_webpack@5.108.4/node_modules/source-map-loader/dist/node_modules/.pnpm/matrix-events-sdk@0.0.1/node_modules/matrix-events-sdk/lib/utility/MessageMatchers.js","webpack://element-web/../node_modules/.pnpm/source-map-loader@5.0.0_webpack@5.108.4/node_modules/source-map-loader/dist/node_modules/.pnpm/matrix-events-sdk@0.0.1/node_modules/matrix-events-sdk/lib/utility/events.js","webpack://element-web/../node_modules/.pnpm/source-map-loader@5.0.0_webpack@5.108.4/node_modules/source-map-loader/dist/node_modules/.pnpm/sdp-transform@3.0.0/node_modules/sdp-transform/lib/grammar.js","webpack://element-web/../node_modules/.pnpm/source-map-loader@5.0.0_webpack@5.108.4/node_modules/source-map-loader/dist/node_modules/.pnpm/sdp-transform@3.0.0/node_modules/sdp-transform/lib/index.js","webpack://element-web/../node_modules/.pnpm/source-map-loader@5.0.0_webpack@5.108.4/node_modules/source-map-loader/dist/node_modules/.pnpm/sdp-transform@3.0.0/node_modules/sdp-transform/lib/parser.js","webpack://element-web/../node_modules/.pnpm/source-map-loader@5.0.0_webpack@5.108.4/node_modules/source-map-loader/dist/node_modules/.pnpm/sdp-transform@3.0.0/node_modules/sdp-transform/lib/writer.js","webpack://element-web/../node_modules/.pnpm/source-map-loader@5.0.0_webpack@5.108.4/node_modules/source-map-loader/dist/node_modules/.pnpm/unhomoglyph@1.0.6/node_modules/unhomoglyph/index.js","webpack://element-web/../node_modules/.pnpm/content-type@2.0.0/node_modules/content-type/src/index.ts","webpack://element-web/javascript/node_modules/.pnpm/source-map-loader@5.0.0_webpack@5.108.4/node_modules/source-map-loader/dist/node_modules/.pnpm/@babel+runtime@8.0.0/node_modules/@babel/runtime/helpers/esm/objectWithoutProperties.js","webpack://element-web/javascript/node_modules/.pnpm/source-map-loader@5.0.0_webpack@5.108.4/node_modules/source-map-loader/dist/node_modules/.pnpm/@babel+runtime@8.0.0/node_modules/@babel/runtime/helpers/esm/objectWithoutPropertiesLoose.js","webpack://element-web/javascript/node_modules/.pnpm/source-map-loader@5.0.0_webpack@5.108.4/node_modules/source-map-loader/dist/node_modules/.pnpm/base-x@5.0.1/node_modules/base-x/src/esm/index.js","webpack://element-web/javascript/node_modules/.pnpm/source-map-loader@5.0.0_webpack@5.108.4/node_modules/source-map-loader/dist/node_modules/.pnpm/bs58@6.0.0/node_modules/bs58/src/esm/index.js","webpack://element-web/javascript/node_modules/.pnpm/source-map-loader@5.0.0_webpack@5.108.4/node_modules/source-map-loader/dist/node_modules/.pnpm/is-network-error@1.3.2/node_modules/is-network-error/index.js","webpack://element-web/javascript/node_modules/.pnpm/source-map-loader@5.0.0_webpack@5.108.4/node_modules/source-map-loader/dist/node_modules/.pnpm/p-retry@8.0.0/node_modules/p-retry/index.js"],"sourcesContent":["/*\nCopyright 2024 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\n/**\n * Well-known values (from the spec or MSCs) that are allowed in the\n * {@link Membership} type.\n */\nexport enum KnownMembership {\n /**\n * The user has been banned from the room, and is no longer allowed to join\n * it until they are un-banned from the room (by having their membership\n * state set to a value other than ban).\n */\n Ban = \"ban\",\n /**\n * The user has been invited to join a room, but has not yet joined it.\n * They may not participate in the room until they join.\n * */\n Invite = \"invite\",\n /**\n * The user has joined the room (possibly after accepting an invite), and\n * may participate in it.\n */\n Join = \"join\",\n /**\n * The user has knocked on the room, requesting permission to participate.\n * They may not participate in the room until they join.\n */\n Knock = \"knock\",\n /**\n * The user was once joined to the room, but has since left (possibly by\n * choice, or possibly by being kicked).\n */\n Leave = \"leave\",\n}\n\n/**\n * The membership state for a user in a room [1]. A value from\n * {@link KnownMembership} should be used where available, but all string values\n * are allowed to provide flexibility for upcoming spec changes or proposals.\n *\n * [1] https://spec.matrix.org/latest/client-server-api/#mroommember\n */\nexport type Membership = KnownMembership | string;\n","/*\nCopyright 2022 Šimon Brandner <simon.bra.ag@gmail.com>\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\nexport enum ReceiptType {\n Read = \"m.read\",\n FullyRead = \"m.fully_read\",\n ReadPrivate = \"m.read.private\",\n}\n\nexport const MAIN_ROOM_TIMELINE = \"main\";\n\nexport interface Receipt {\n ts: number;\n thread_id?: string;\n}\n\nexport interface WrappedReceipt {\n eventId: string;\n data: Receipt;\n}\n\nexport interface CachedReceipt {\n type: ReceiptType;\n userId: string;\n data: Receipt;\n}\n\nexport type ReceiptCache = Map<string, CachedReceipt[]>;\n\nexport interface ReceiptContent {\n [eventId: string]: {\n [key in ReceiptType | string]: {\n [userId: string]: Receipt;\n };\n };\n}\n\n// We will only hold a synthetic receipt if we do not have a real receipt or the synthetic is newer.\n// map: receipt type → user Id → receipt\nexport type Receipts = Map<string, Map<string, [real: WrappedReceipt | null, synthetic: WrappedReceipt | null]>>;\n\nexport type CachedReceiptStructure = {\n eventId: string;\n receiptType: string | ReceiptType;\n userId: string;\n receipt: Receipt;\n synthetic: boolean;\n};\n","/*\nCopyright 2021 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 IContent, type IEvent } from \"../models/event.ts\";\nimport { type Preset, type Visibility } from \"./partials.ts\";\nimport { type IEventWithRoomId, type SearchKey } from \"./search.ts\";\nimport { type IRoomEventFilter } from \"../filter.ts\";\nimport { type Direction } from \"../models/event-timeline.ts\";\nimport { type PushRuleAction } from \"./PushRules.ts\";\nimport { type MatrixError } from \"../matrix.ts\";\nimport { type IRoomEvent } from \"../sync-accumulator.ts\";\nimport { type EventType, type RelationType, type RoomType } from \"./event.ts\";\n\n// allow camelcase as these are things that go onto the wire\n/* eslint-disable camelcase */\n\nexport interface IJoinRoomOpts {\n /**\n * If the caller has a keypair 3pid invite, the signing URL is passed in this parameter.\n */\n inviteSignUrl?: string;\n\n /**\n * The server names to try and join through in addition to those that are automatically chosen.\n * Only the first 3 are actually used in the request, to avoid HTTP 414 Request-URI Too Long responses.\n */\n viaServers?: string[];\n\n /**\n * Previously, configured whether to accept encrypted history shared by the inviter. This is now always enabled,\n * and the setting is only retained to avoid a breaking change to the API. It has no effect.\n *\n * @deprecated\n */\n acceptSharedHistory?: boolean;\n}\n\n/** Options object for {@link MatrixClient.invite}. */\nexport interface InviteOpts {\n /**\n * The reason for the invite.\n */\n reason?: string;\n\n /**\n * Previously, configured whether to send encrypted history if the visibility settings allow it.\n * This is now always enabled, and the setting is only retained to avoid a breaking change to the API. It has no effect.\n *\n * @deprecated\n */\n shareEncryptedHistory?: boolean;\n}\n\nexport interface KnockRoomOpts {\n /**\n * The reason for the knock.\n */\n reason?: string;\n\n /**\n * The server names to try and knock through in addition to those that are automatically chosen.\n * Only the first 3 are actually used in the request, to avoid HTTP 414 Request-URI Too Long responses.\n */\n viaServers?: string | string[];\n}\n\nexport interface IRedactOpts {\n reason?: string;\n /**\n * If specified, then any events which relate to the event being redacted with\n * any of the relationship types listed will also be redacted.\n * Provide a \"*\" list item to tell the server to redact relations of any type.\n *\n * <b>Raises an Error if the server does not support it.</b>\n * Check for server-side support before using this param with\n * <code>client.canSupport.get(Feature.RelationBasedRedactions)</code>.\n * {@link https://github.com/matrix-org/matrix-spec-proposals/pull/3912}\n */\n with_rel_types?: Array<RelationType | \"*\">;\n}\n\nexport interface ISendEventResponse {\n event_id: string;\n}\n\nexport type SendDelayedEventRequestOpts = { parent_delay_id: string } | { delay: number; parent_delay_id?: string };\n\nexport function isSendDelayedEventRequestOpts(opts: object): opts is SendDelayedEventRequestOpts {\n if (\"parent_delay_id\" in opts && typeof opts.parent_delay_id !== \"string\") {\n // Invalid type, reject\n return false;\n }\n if (\"delay\" in opts && typeof opts.delay !== \"number\") {\n // Invalid type, reject.\n return true;\n }\n // At least one of these fields must be specified.\n return \"delay\" in opts || \"parent_delay_id\" in opts;\n}\nexport type SendDelayedEventResponse = {\n delay_id: string;\n};\n\nexport enum UpdateDelayedEventAction {\n Cancel = \"cancel\",\n Restart = \"restart\",\n Send = \"send\",\n}\n\nexport type UpdateDelayedEventRequestOpts = SendDelayedEventResponse & {\n action: UpdateDelayedEventAction;\n};\n\ntype DelayedPartialTimelineEvent = {\n room_id: string;\n type: string;\n content: IContent;\n};\n\ntype DelayedPartialStateEvent = DelayedPartialTimelineEvent & {\n state_key: string;\n};\n\ntype DelayedPartialEvent = DelayedPartialTimelineEvent | DelayedPartialStateEvent;\n\nexport type DelayedEventInfoItem = DelayedPartialEvent &\n SendDelayedEventResponse &\n SendDelayedEventRequestOpts & {\n running_since: number;\n };\n\nexport type DelayedEventInfo = {\n scheduled?: DelayedEventInfoItem[];\n finalised?: {\n delayed_event: DelayedEventInfoItem;\n outcome: \"send\" | \"cancel\";\n reason: \"error\" | \"action\" | \"delay\";\n error?: MatrixError[\"data\"];\n event_id?: string;\n origin_server_ts?: number;\n }[];\n next_batch?: string;\n};\n\nexport interface IPresenceOpts {\n // One of \"online\", \"offline\" or \"unavailable\"\n presence: \"online\" | \"offline\" | \"unavailable\";\n // The status message to attach.\n status_msg?: string;\n}\n\nexport interface IPaginateOpts {\n // true to fill backwards, false to go forwards\n backwards?: boolean;\n // number of events to request\n limit?: number;\n}\n\nexport interface IGuestAccessOpts {\n /**\n * True to allow guests to join this room. This\n * implicitly gives guests write access. If false or not given, guests are\n * explicitly forbidden from joining the room.\n */\n allowJoin: boolean;\n /**\n * True to set history visibility to\n * be world_readable. This gives guests read access *from this point forward*.\n * If false or not given, history visibility is not modified.\n */\n allowRead: boolean;\n}\n\nexport interface ISearchOpts {\n keys?: SearchKey[];\n query: string;\n}\n\nexport interface IEventSearchOpts {\n // a JSON filter object to pass in the request\n filter?: IRoomEventFilter;\n // the term to search for\n term: string;\n}\n\nexport interface IInvite3PID {\n id_server: string;\n id_access_token?: string; // this gets injected by the js-sdk\n medium: string;\n address: string;\n}\n\nexport interface ICreateRoomStateEvent {\n type: string;\n state_key?: string; // defaults to an empty string\n content: IContent;\n}\n\nexport interface ICreateRoomOpts {\n // The alias localpart to assign to this room.\n room_alias_name?: string;\n // Either 'public' or 'private'.\n visibility?: Visibility;\n // The name to give this room.\n name?: string;\n // The topic to give this room.\n topic?: string;\n preset?: Preset;\n power_level_content_override?: {\n ban?: number;\n events?: Record<EventType | string, number>;\n events_default?: number;\n invite?: number;\n kick?: number;\n notifications?: Record<string, number>;\n redact?: number;\n state_default?: number;\n users?: Record<string, number>;\n users_default?: number;\n };\n creation_content?: object;\n initial_state?: ICreateRoomStateEvent[];\n // A list of user IDs to invite to this room.\n invite?: string[];\n invite_3pid?: IInvite3PID[];\n is_direct?: boolean;\n room_version?: string;\n}\n\nexport interface IRoomDirectoryOptions {\n /**\n * The remote server to query for the room list.\n * Optional. If unspecified, get the local homeserver's public room list.\n */\n server?: string;\n /**\n * Maximum number of entries to return\n */\n limit?: number;\n /**\n * Token to paginate from\n */\n since?: string;\n\n /** Filter parameters */\n filter?: {\n // String to search for\n generic_search_term?: string;\n room_types?: Array<RoomType | null>;\n };\n include_all_networks?: boolean;\n third_party_instance_id?: string;\n}\n\nexport interface IAddThreePidOnlyBody {\n auth?: {\n type: string;\n session?: string;\n };\n client_secret: string;\n sid: string;\n}\n\nexport interface IBindThreePidBody {\n client_secret: string;\n id_server: string;\n // Some older identity servers have no auth enabled\n id_access_token: string | null;\n sid: string;\n}\n\nexport interface IRelationsRequestOpts {\n from?: string;\n to?: string;\n limit?: number;\n dir?: Direction;\n recurse?: boolean; // MSC3981 Relations Recursion https://github.com/matrix-org/matrix-spec-proposals/pull/3981\n}\n\nexport interface IRelationsResponse {\n chunk: IEvent[];\n next_batch?: string;\n prev_batch?: string;\n}\n\nexport interface IContextResponse {\n end?: string;\n start?: string;\n state?: IEventWithRoomId[];\n events_before?: IEventWithRoomId[];\n events_after?: IEventWithRoomId[];\n event?: IEventWithRoomId;\n}\n\nexport interface IEventsResponse {\n chunk: IEventWithRoomId[];\n end: string;\n start: string;\n}\n\nexport interface INotification {\n actions: PushRuleAction[];\n event: IRoomEvent;\n profile_tag?: string;\n read: boolean;\n room_id: string;\n ts: number;\n}\n\nexport interface INotificationsResponse {\n next_token: string;\n notifications: INotification[];\n}\n\nexport interface IFilterResponse {\n filter_id: string;\n}\n\nexport interface ITagsResponse {\n tags: {\n [tagId: string]: {\n order: number;\n };\n };\n}\n\nexport interface IStatusResponse extends IPresenceOpts {\n currently_active?: boolean;\n last_active_ago?: number;\n}\n\n/* eslint-enable camelcase */\n","/*\nCopyright 2021 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\n// Types relating to the /search API\n\nimport { type IRoomEvent, type IStateEvent } from \"../sync-accumulator.ts\";\nimport { type IRoomEventFilter } from \"../filter.ts\";\nimport { type SearchResult } from \"../models/search-result.ts\";\n\n/* eslint-disable camelcase */\nexport interface IEventWithRoomId extends IRoomEvent {\n room_id: string;\n}\n\nexport interface IStateEventWithRoomId extends IStateEvent {\n room_id: string;\n}\n\nexport interface IMatrixProfile {\n avatar_url?: string;\n displayname?: string;\n}\n\nexport interface IResultContext {\n events_before: IEventWithRoomId[];\n events_after: IEventWithRoomId[];\n profile_info: Record<string, IMatrixProfile>;\n start?: string;\n end?: string;\n}\n\nexport interface ISearchResult {\n rank: number;\n result: IEventWithRoomId;\n context: IResultContext;\n}\n\nenum GroupKey {\n RoomId = \"room_id\",\n Sender = \"sender\",\n}\n\nexport interface IResultRoomEvents {\n count?: number;\n highlights?: string[];\n results?: ISearchResult[];\n state?: { [roomId: string]: IStateEventWithRoomId[] };\n groups?: {\n [groupKey in GroupKey]: {\n [value: string]: {\n next_batch?: string;\n order: number;\n results: string[];\n };\n };\n };\n next_batch?: string;\n}\n\ninterface IResultCategories {\n room_events: IResultRoomEvents;\n}\n\nexport type SearchKey = \"content.body\" | \"content.name\" | \"content.topic\";\n\nexport enum SearchOrderBy {\n Recent = \"recent\",\n Rank = \"rank\",\n}\n\nexport interface ISearchRequestBody {\n search_categories: {\n room_events: {\n search_term: string;\n keys?: SearchKey[];\n filter?: IRoomEventFilter;\n order_by?: SearchOrderBy;\n event_context?: {\n before_limit?: number;\n after_limit?: number;\n include_profile?: boolean;\n };\n include_state?: boolean;\n groupings?: {\n group_by: {\n key: GroupKey;\n }[];\n };\n };\n };\n}\n\nexport interface ISearchResponse {\n search_categories: IResultCategories;\n}\n\nexport interface ISearchResults {\n _query?: ISearchRequestBody;\n results: SearchResult[];\n highlights: string[];\n count?: number;\n next_batch?: string;\n pendingRequest?: Promise<ISearchResults>;\n abortSignal?: AbortSignal;\n}\n/* eslint-enable camelcase */\n","/*\nCopyright 2021 - 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\n/**\n * Represents a simple Matrix namespaced value. This will assume that if a stable prefix\n * is provided that the stable prefix should be used when representing the identifier.\n */\nexport class NamespacedValue<S extends string, U extends string> {\n // Stable is optional, but one of the two parameters is required, hence the weird-looking types.\n // Goal is to to have developers explicitly say there is no stable value (if applicable).\n public constructor(stable: S, unstable: U);\n public constructor(stable: S, unstable: U | null);\n public constructor(stable: null, unstable: U);\n public constructor(\n public readonly stable: S | null,\n public readonly unstable: U | null,\n ) {\n if (!this.unstable && !this.stable) {\n throw new Error(\"One of stable or unstable values must be supplied\");\n }\n }\n\n public get name(): U | S {\n if (this.stable) {\n return this.stable;\n }\n return this.unstable!;\n }\n\n public get altName(): U | S | null | undefined {\n if (!this.stable) {\n return null;\n }\n return this.unstable;\n }\n\n public get names(): (U | S)[] {\n const names = [this.name];\n const altName = this.altName;\n if (altName) names.push(altName);\n return names;\n }\n\n public matches(val: string): boolean {\n return this.name === val || this.altName === val;\n }\n\n // this desperately wants https://github.com/microsoft/TypeScript/pull/26349 at the top level of the class\n // so we can instantiate `NamespacedValue<string, _, _>` as a default type for that namespace.\n public findIn<V>(obj: Partial<Record<NonNullable<S | U>, V>>): V | undefined {\n let val: V | undefined = undefined;\n if (this.name) {\n val = obj?.[this.name];\n }\n if (!val && this.altName) {\n val = obj?.[this.altName];\n }\n return val;\n }\n\n public includedIn(arr: any[]): boolean {\n let included = false;\n if (this.name) {\n included = arr.includes(this.name);\n }\n if (!included && this.altName) {\n included = arr.includes(this.altName);\n }\n return included;\n }\n}\n\nexport class ServerControlledNamespacedValue<S extends string, U extends string> extends NamespacedValue<S, U> {\n private preferUnstable = false;\n\n public setPreferUnstable(preferUnstable: boolean): void {\n this.preferUnstable = preferUnstable;\n }\n\n public get name(): U | S {\n if (this.stable && !this.preferUnstable) {\n return this.stable;\n }\n return this.unstable!;\n }\n}\n\n/**\n * Represents a namespaced value which prioritizes the unstable value over the stable\n * value.\n */\nexport class UnstableValue<S extends string, U extends string> extends NamespacedValue<S, U> {\n // Note: Constructor difference is that `unstable` is *required*.\n public constructor(stable: S, unstable: U) {\n super(stable, unstable);\n if (!this.unstable) {\n throw new Error(\"Unstable value must be supplied\");\n }\n }\n\n public get name(): U {\n return this.unstable!;\n }\n\n public get altName(): S {\n return this.stable!;\n }\n}\n","/*\nCopyright 2015, 2016 OpenMarket Ltd\nCopyright 2017 Vector Creations Ltd\nCopyright 2017 New Vector Ltd\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\n// eslint-disable-next-line no-restricted-imports\nimport { type EventEmitter } from \"events\";\n\nimport { type ListenerMap, type TypedEventEmitter } from \"./models/typed-event-emitter.ts\";\n\nexport class ReEmitter {\n public constructor(private readonly target: EventEmitter) {}\n\n // Map from emitter to event name to re-emitter\n private reEmitters = new WeakMap<EventEmitter, Map<string, (...args: any[]) => void>>();\n\n public reEmit(source: EventEmitter, eventNames: string[]): void {\n let reEmittersByEvent = this.reEmitters.get(source);\n if (!reEmittersByEvent) {\n reEmittersByEvent = new Map();\n this.reEmitters.set(source, reEmittersByEvent);\n }\n\n for (const eventName of eventNames) {\n if (reEmittersByEvent.has(eventName)) continue;\n\n // We include the source as the last argument for event handlers which may need it,\n // such as read receipt listeners on the client class which won't have the context\n // of the room.\n const forSource = (...args: any[]): void => {\n // EventEmitter special cases 'error' to make the emit function throw if no\n // handler is attached, which sort of makes sense for making sure that something\n // handles an error, but for re-emitting, there could be a listener on the original\n // source object so the test doesn't really work. We *could* try to replicate the\n // same logic and throw if there is no listener on either the source or the target,\n // but this behaviour is fairly undesireable for us anyway: the main place we throw\n // 'error' events is for calls, where error events are usually emitted some time\n // later by a different part of the code where 'emit' throwing because the app hasn't\n // added an error handler isn't terribly helpful. (A better fix in retrospect may\n // have been to just avoid using the event name 'error', but backwards compat...)\n if (eventName === \"error\" && this.target.listenerCount(\"error\") === 0) return;\n this.target.emit(eventName, ...args, source);\n };\n source.on(eventName, forSource);\n reEmittersByEvent.set(eventName, forSource);\n }\n }\n\n public stopReEmitting(source: EventEmitter, eventNames: string[]): void {\n const reEmittersByEvent = this.reEmitters.get(source);\n if (!reEmittersByEvent) return; // We were never re-emitting these events in the first place\n\n for (const eventName of eventNames) {\n source.off(eventName, reEmittersByEvent.get(eventName)!);\n reEmittersByEvent.delete(eventName);\n }\n\n if (reEmittersByEvent.size === 0) this.reEmitters.delete(source);\n }\n}\n\nexport class TypedReEmitter<Events extends string, Arguments extends ListenerMap<Events>> extends ReEmitter {\n public constructor(target: TypedEventEmitter<Events, Arguments>) {\n super(target);\n }\n\n public reEmit<ReEmittedEvents extends string, T extends Events & ReEmittedEvents>(\n source: TypedEventEmitter<ReEmittedEvents, any>,\n eventNames: T[],\n ): void {\n super.reEmit(source, eventNames);\n }\n\n public stopReEmitting<ReEmittedEvents extends string, T extends Events & ReEmittedEvents>(\n source: TypedEventEmitter<ReEmittedEvents, any>,\n eventNames: T[],\n ): void {\n super.stopReEmitting(source, eventNames);\n }\n}\n","/*\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 { ToDeviceMessageId } from \"./@types/event.ts\";\nimport { type Logger } from \"./logger.ts\";\nimport { type MatrixClient, ClientEvent } from \"./client.ts\";\nimport { type MatrixError } from \"./http-api/index.ts\";\nimport {\n type IndexedToDeviceBatch,\n type ToDeviceBatch,\n type ToDeviceBatchWithTxnId,\n type ToDevicePayload,\n} from \"./models/ToDeviceMessage.ts\";\nimport { MatrixScheduler } from \"./scheduler.ts\";\nimport { SyncState } from \"./sync.ts\";\nimport { MapWithDefault } from \"./utils.ts\";\n\nconst MAX_BATCH_SIZE = 20;\n\n/**\n * Maintains a queue of outgoing to-device messages, sending them\n * as soon as the homeserver is reachable.\n */\nexport class ToDeviceMessageQueue {\n private sending = false;\n private running = true;\n private retryTimeout: ReturnType<typeof setTimeout> | null = null;\n private retryAttempts = 0;\n\n public constructor(\n private client: MatrixClient,\n private readonly logger: Logger,\n ) {}\n\n public start(): void {\n this.running = true;\n this.sendQueue();\n this.client.on(ClientEvent.Sync, this.onResumedSync);\n }\n\n public stop(): void {\n this.running = false;\n if (this.retryTimeout !== null) clearTimeout(this.retryTimeout);\n this.retryTimeout = null;\n this.client.removeListener(ClientEvent.Sync, this.onResumedSync);\n }\n\n public async queueBatch(batch: ToDeviceBatch): Promise<void> {\n const batches: ToDeviceBatchWithTxnId[] = [];\n for (let i = 0; i < batch.batch.length; i += MAX_BATCH_SIZE) {\n const batchWithTxnId = {\n eventType: batch.eventType,\n batch: batch.batch.slice(i, i + MAX_BATCH_SIZE),\n txnId: this.client.makeTxnId(),\n };\n batches.push(batchWithTxnId);\n const msgmap = batchWithTxnId.batch.map(\n (msg) => `${msg.userId}/${msg.deviceId} (msgid ${msg.payload[ToDeviceMessageId]})`,\n );\n this.logger.info(\n `Enqueuing batch of to-device messages. type=${batch.eventType} txnid=${batchWithTxnId.txnId}`,\n msgmap,\n );\n }\n\n await this.client.store.saveToDeviceBatches(batches);\n void this.sendQueue();\n }\n\n public sendQueue = async (): Promise<void> => {\n if (this.retryTimeout !== null) clearTimeout(this.retryTimeout);\n this.retryTimeout = null;\n\n if (this.sending || !this.running) return;\n\n this.logger.debug(\"Attempting to send queued to-device messages\");\n\n this.sending = true;\n let headBatch: IndexedToDeviceBatch | null;\n try {\n while (this.running) {\n headBatch = await this.client.store.getOldestToDeviceBatch();\n if (headBatch === null) break;\n await this.sendBatch(headBatch);\n await this.client.store.removeToDeviceBatch(headBatch.id);\n this.retryAttempts = 0;\n }\n\n // Make sure we're still running after the async tasks: if not, stop.\n if (!this.running) return;\n\n this.logger.debug(\"All queued to-device messages sent\");\n } catch (e) {\n ++this.retryAttempts;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n // eslint-disable-next-line new-cap\n const retryDelay = MatrixScheduler.RETRY_BACKOFF_RATELIMIT(null, this.retryAttempts, <MatrixError>e);\n if (retryDelay === -1) {\n // the scheduler function doesn't differentiate between fatal errors and just getting\n // bored and giving up for now\n if (Math.floor((<MatrixError>e).httpStatus! / 100) === 4) {\n this.logger.error(\"Fatal error when sending to-device message - dropping to-device batch!\", e);\n await this.client.store.removeToDeviceBatch(headBatch!.id);\n } else {\n this.logger.info(\"Automatic retry limit reached for to-device messages.\");\n }\n return;\n }\n\n this.logger.info(`Failed to send batch of to-device messages. Will retry in ${retryDelay}ms`, e);\n this.retryTimeout = setTimeout(this.sendQueue, retryDelay);\n } finally {\n this.sending = false;\n }\n };\n\n /**\n * Attempts to send a batch of to-device messages.\n */\n private async sendBatch(batch: IndexedToDeviceBatch): Promise<void> {\n const contentMap: MapWithDefault<string, Map<string, ToDevicePayload>> = new MapWithDefault(() => new Map());\n for (const item of batch.batch) {\n contentMap.getOrCreate(item.userId).set(item.deviceId, item.payload);\n }\n\n this.logger.info(\n `Sending batch of ${batch.batch.length} to-device messages with ID ${batch.id} and txnId ${batch.txnId}`,\n );\n\n await this.client.sendToDevice(batch.eventType, contentMap, batch.txnId);\n }\n\n /**\n * Listen to sync state changes and automatically resend any pending events\n * once syncing is resumed\n */\n private onResumedSync = (state: SyncState | null, oldState: SyncState | null): void => {\n if (state === SyncState.Syncing && oldState !== SyncState.Syncing) {\n this.logger.info(`Resuming queue after resumed sync`);\n void this.sendQueue();\n }\n };\n}\n","/*\nCopyright 2023 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\n/**\n * Base64 encoding and decoding utilities\n */\n\nfunction toBase64(uint8Array: Uint8Array, options: Uint8ArrayToBase64Options): string {\n if (typeof uint8Array.toBase64 === \"function\") {\n // Currently this is only supported in Firefox,\n // but we match the options in the hope in the future we can rely on it for all environments.\n // https://tc39.es/proposal-arraybuffer-base64/spec/#sec-uint8array.prototype.tobase64\n return uint8Array.toBase64(options);\n }\n\n let base64 = btoa(uint8Array.reduce((acc, current) => acc + String.fromCharCode(current), \"\"));\n if (options.omitPadding) {\n base64 = base64.replace(/={1,2}$/, \"\");\n }\n if (options.alphabet === \"base64url\") {\n base64 = base64.replace(/\\+/g, \"-\").replace(/\\//g, \"_\");\n }\n\n return base64;\n}\n\n/**\n * Encode a typed array of uint8 as base64.\n * @param uint8Array - The data to encode.\n * @returns The base64.\n */\nexport function encodeBase64(uint8Array: Uint8Array): string {\n return toBase64(uint8Array, { alphabet: \"base64\", omitPadding: false });\n}\n\n/**\n * Encode a typed array of uint8 as unpadded base64.\n * @param uint8Array - The data to encode.\n * @returns The unpadded base64.\n */\nexport function encodeUnpaddedBase64(uint8Array: Uint8Array): string {\n return toBase64(uint8Array, { alphabet: \"base64\", omitPadding: true });\n}\n\n/**\n * Encode a typed array of uint8 as unpadded base64 using the URL-safe encoding.\n * @param uint8Array - The data to encode.\n * @returns The unpadded base64.\n */\nexport function encodeUnpaddedBase64Url(uint8Array: Uint8Array): string {\n return toBase64(uint8Array, { alphabet: \"base64url\", omitPadding: true });\n}\n\nfunction fromBase64(base64: string, options: Uint8ArrayFromBase64Options): Uint8Array<ArrayBuffer> {\n if (typeof Uint8Array.fromBase64 === \"function\") {\n // Currently this is only supported in Firefox,\n // but we match the options in the hope in the future we can rely on it for all environments.\n // https://tc39.es/proposal-arraybuffer-base64/spec/#sec-uint8array.frombase64\n return Uint8Array.fromBase64(base64, options);\n }\n\n return Uint8Array.from(atob(base64), (c) => c.charCodeAt(0));\n}\n\n/**\n * Decode a base64 (or base64url) string to a typed array of uint8.\n * @param base64 - The base64 to decode.\n * @returns The decoded data.\n */\nexport function decodeBase64(base64: string): Uint8Array<ArrayBuffer> {\n // The function requires us to select an alphabet, but we don't know if base64url was used so we convert.\n return fromBase64(base64.replace(/-/g, \"+\").replace(/_/g, \"/\"), { alphabet: \"base64\", lastChunkHandling: \"loose\" });\n}\n","/*\nCopyright 2026 Element Creations Ltd.\nCopyright 2024 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 IHttpOpts, type MatrixHttpApi } from \"./http-api/index.ts\";\nimport { type Logger } from \"./logger.ts\";\nimport { TypedEventEmitter } from \"./models/typed-event-emitter.ts\";\nimport { deepCompare } from \"./utils.ts\";\n\n// How often we update the server capabilities.\n// 6 hours - an arbitrary value, but they should change very infrequently.\nconst CAPABILITIES_CACHE_MS = 6 * 60 * 60 * 1000;\n\n// How long we want before retrying if we couldn't fetch\nconst CAPABILITIES_RETRY_MS = 30 * 1000;\n\n/**\n * Manages storing and periodically refreshing the server capabilities.\n */\nexport abstract class CapabilityPoller<ResponseType> extends TypedEventEmitter<\n \"update\",\n { update: (data: ResponseType) => void }\n> {\n protected cached?: ResponseType;\n private retryTimeout?: ReturnType<typeof setTimeout>;\n private refreshTimeout?: ReturnType<typeof setInterval>;\n\n public constructor(\n protected readonly logger: Logger,\n protected readonly http: MatrixHttpApi<IHttpOpts & { onlyData: true }>,\n private readonly name: string,\n ) {\n super();\n }\n\n /**\n * Starts periodically fetching the server capabilities.\n */\n public start(): void {\n this.poll().then();\n }\n\n /**\n * Stops the service\n */\n public stop(): void {\n this.clearTimeouts();\n }\n\n /**\n * Returns the cached capabilities, or undefined if none are cached.\n * @returns the current capabilities, if any.\n */\n public getCached(): ResponseType | undefined {\n return this.cached;\n }\n\n public abstract fetch(): Promise<ResponseType>;\n\n private poll = async (): Promise<void> => {\n this.logger.debug(\"Checking capabilites\");\n try {\n const current = this.cached;\n await this.fetch();\n this.clearTimeouts();\n this.refreshTimeout = globalThis.setTimeout(this.poll, CAPABILITIES_CACHE_MS);\n this.logger.debug(`Fetched new server ${this.name}`);\n if (this.cached && !deepCompare(current, this.cached)) {\n this.emit(\"update\", this.cached);\n }\n } catch (e) {\n this.clearTimeouts();\n const howLong = Math.floor(CAPABILITIES_RETRY_MS + Math.random() * 5000);\n this.retryTimeout = globalThis.setTimeout(this.poll, howLong);\n this.logger.warn(`Failed to refresh ${this.name}: retrying in ${howLong}ms`, e);\n }\n };\n\n private clearTimeouts(): void {\n if (this.refreshTimeout) {\n clearInterval(this.refreshTimeout);\n this.refreshTimeout = undefined;\n }\n if (this.retryTimeout) {\n clearTimeout(this.retryTimeout);\n this.retryTimeout = undefined;\n }\n }\n}\n","/*\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 type { IDeviceLists, IToDeviceEvent, ReceivedToDeviceMessage } from \"../sync-accumulator.ts\";\nimport { type IClearEvent, type MatrixEvent } from \"../models/event.ts\";\nimport { type Room } from \"../models/room.ts\";\nimport { type CryptoApi, type DecryptionFailureCode, type ImportRoomKeysOpts } from \"../crypto-api/index.ts\";\nimport { type KeyBackupInfo, type KeyBackupSession } from \"../crypto-api/keybackup.ts\";\nimport { type IMegolmSessionData } from \"../@types/crypto.ts\";\n\n/**\n * Common interface for the crypto implementations\n *\n * @internal\n */\nexport interface CryptoBackend extends SyncCryptoCallbacks, CryptoApi {\n /**\n * Whether sendMessage in a room with unknown and unverified devices\n * should throw an error and not send the message. This has 'Global' for\n * symmetry with setGlobalBlacklistUnverifiedDevices but there is currently\n * no room-level equivalent for this setting.\n *\n * @remarks This has no effect in Rust Crypto; it exists only for the sake of\n * the accessors in MatrixClient.\n */\n globalErrorOnUnknownDevices: boolean;\n\n /**\n * Shut down any background processes related to crypto\n */\n stop(): void;\n\n /**\n * Encrypt an event according to the configuration of the room.\n *\n * @param event - event to be sent\n *\n * @param room - destination room.\n *\n * @returns Promise which resolves when the event has been\n * encrypted, or null if nothing was needed\n */\n encryptEvent(event: MatrixEvent, room: Room): Promise<void>;\n\n /**\n * Decrypt a received event\n *\n * @returns a promise which resolves once we have finished decrypting.\n * Rejects with an error if there is a problem decrypting the event.\n */\n decryptEvent(event: MatrixEvent): Promise<EventDecryptionResult>;\n\n /**\n * Get a backup decryptor capable of decrypting megolm session data encrypted with the given backup information.\n * @param backupInfo - The backup information\n * @param privKey - The private decryption key.\n */\n getBackupDecryptor(backupInfo: KeyBackupInfo, privKey: Uint8Array): Promise<BackupDecryptor>;\n\n /**\n * Import a list of room keys restored from backup\n *\n * @param keys - a list of session export objects\n * @param backupVersion - the version of the backup these keys came from.\n * @param opts - options object\n * @returns a promise which resolves once the keys have been imported\n */\n importBackedUpRoomKeys(keys: IMegolmSessionData[], backupVersion: string, opts?: ImportRoomKeysOpts): Promise<void>;\n\n ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n //\n // Room key history sharing (MSC4268)\n //\n ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\n /**\n * Share any shareable E2EE history in the given room with the given recipient,\n * as per [MSC4268](https://github.com/matrix-org/matrix-spec-proposals/pull/4268)\n */\n shareRoomHistoryWithUser(roomId: string, userId: string): Promise<void>;\n\n /**\n * Having accepted an invite for the given room from the given user, attempt to\n * find information about a room key bundle and, if found, download the\n * bundle and import the room keys, as per {@link https://github.com/matrix-org/matrix-spec-proposals/pull/4268|MSC4268}.\n *\n * @param roomId - The room we were invited to, for which we want to check if a room\n * key bundle was received.\n *\n * @param inviter - The user who invited us to the room and is expected to have\n * sent the room key bundle.\n *\n * @returns `true` if the key bundle was successfuly downloaded and imported.\n */\n maybeAcceptKeyBundle(roomId: string, inviter: string): Promise<boolean>;\n\n /**\n * Mark a room as pending a key bundle under MSC4268. The backend will listen for room key bundle messages, and if\n * it sees one matching the room specified, it will automatically import it as long as the message author's ID matches\n * the inviter's ID.\n *\n * @param roomId - The room we were invited to, for which we did not receive a key bundle before accepting the invite.\n * @param inviterId - The user who invited us to the room and is expected to send the room key bundle.\n */\n markRoomAsPendingKeyBundle(roomId: string, inviterId: string): Promise<void>;\n}\n\n/** The methods which crypto implementations should expose to the Sync api\n *\n * @internal\n */\nexport interface SyncCryptoCallbacks {\n /**\n * Called by the /sync loop whenever there are incoming to-device messages.\n *\n * The implementation may preprocess the received messages (eg, decrypt them) and return an\n * updated list of messages for dispatch to the rest of the system.\n *\n * Note that, unlike {@link ClientEvent.ToDeviceEvent} events, this is called on the raw to-device\n * messages, rather than the results of any decryption attempts.\n *\n * @param events - the received to-device messages\n * @returns A list of preprocessed to-device messages. This will not map 1:1 to the input list, as some messages may be invalid or\n * failed to decrypt, and so will be omitted from the output list.\n *\n */\n preprocessToDeviceMessages(events: IToDeviceEvent[]): Promise<ReceivedToDeviceMessage[]>;\n\n /**\n * Called by the /sync loop when one time key counts and unused fallback key details are received.\n *\n * @param oneTimeKeysCounts - the received one time key counts\n * @param unusedFallbackKeys - the received unused fallback keys\n */\n processKeyCounts(oneTimeKeysCounts?: Record<string, number>, unusedFallbackKeys?: string[]): Promise<void>;\n\n /**\n * Handle the notification from /sync that device lists have\n * been changed.\n *\n * @param deviceLists - device_lists field from /sync\n */\n processDeviceLists(deviceLists: IDeviceLists): Promise<void>;\n\n /**\n * Called by the /sync loop whenever an m.room.encryption event is received.\n *\n * This is called before RoomStateEvents are emitted for any of the events in the /sync\n * response (even if the other events technically happened first). This works around a problem\n * if the client uses a RoomStateEvent (typically a membership event) as a trigger to send a message\n * in a new room (or one where encryption has been newly enabled): that would otherwise leave the\n * crypto layer confused because it expects crypto to be set up, but it has not yet been.\n *\n * @param room - in which the event was received\n * @param event - encryption event to be processed\n */\n onCryptoEvent(room: Room, event: MatrixEvent): Promise<void>;\n\n /**\n * Called by the /sync loop after each /sync response is processed.\n *\n * Used to complete batch processing, or to initiate background processes\n *\n * @param syncState - information about the completed sync.\n */\n onSyncCompleted(syncState: OnSyncCompletedData): void;\n\n /**\n * Mark all tracked users' device lists as dirty.\n *\n * This method will cause additional `/keys/query` requests on the server, so should be used only\n * when the client has desynced tracking device list deltas from the server.\n * In MSC4186: Simplified Sliding Sync, this can happen when the server expires the connection.\n */\n markAllTrackedUsersAsDirty(): Promise<void>;\n}\n\n/**\n * @internal\n */\nexport interface OnSyncCompletedData {\n /**\n * The 'next_batch' result from /sync, which will become the 'since' token for the next call to /sync.\n */\n nextSyncToken?: string;\n\n /**\n * True if we are working our way through a backlog of events after connecting.\n */\n catchingUp?: boolean;\n}\n\n/**\n * The result of a (successful) call to {@link CryptoBackend.decryptEvent}\n */\nexport interface EventDecryptionResult {\n /**\n * The plaintext payload for the event (typically containing <tt>type</tt> and <tt>content</tt> fields).\n */\n clearEvent: IClearEvent;\n /**\n * No longer used.\n * See {@link MatrixEvent#getForwardingCurve25519KeyChain}.\n * @deprecated\n */\n forwardingCurve25519KeyChain?: string[];\n /**\n * Key owned by the sender of this event. See {@link MatrixEvent#getSenderKey}.\n */\n senderCurve25519Key?: string;\n /**\n * ed25519 key claimed by the sender of this event. See {@link MatrixEvent#getClaimedEd25519Key}.\n */\n claimedEd25519Key?: string;\n\n /**\n * If another user forwarded the key to this message\n * (eg via [MSC4268](https://github.com/matrix-org/matrix-spec-proposals/pull/4268)),\n * the ID of that user.\n */\n keyForwardedBy?: string;\n}\n\n/**\n * Responsible for decrypting megolm session data retrieved from a remote backup.\n * The result of {@link CryptoBackend#getBackupDecryptor}.\n */\nexport interface BackupDecryptor {\n /**\n * Whether keys retrieved from this backup can be trusted.\n *\n * Depending on the backup algorithm, keys retrieved from the backup can be trusted or not.\n * If false, keys retrieved from the backup must be considered unsafe (authenticity cannot be guaranteed).\n * It could be by design (deniability) or for some technical reason (eg asymmetric encryption).\n */\n readonly sourceTrusted: boolean;\n\n /**\n *\n * Decrypt megolm session data retrieved from backup.\n *\n * @param ciphertexts - a Record of sessionId to session data.\n *\n * @returns An array of decrypted `IMegolmSessionData`\n */\n decryptSessions(ciphertexts: Record<string, KeyBackupSession>): Promise<IMegolmSessionData[]>;\n\n /**\n * Free any resources held by this decryptor.\n *\n * Should be called once the decryptor is no longer needed.\n */\n free(): void;\n}\n\n/**\n * Exception thrown when decryption fails\n *\n * @param code - Reason code for the failure.\n *\n * @param msg - user-visible message describing the problem\n *\n * @param details - key/value pairs reported in the logs but not shown\n * to the user.\n */\nexport class DecryptionError extends Error {\n public readonly detailedString: string;\n\n public constructor(\n public readonly code: DecryptionFailureCode,\n msg: string,\n details?: Record<string, string | Error>,\n ) {\n super(msg);\n this.name = \"DecryptionError\";\n this.detailedString = detailedStringForDecryptionError(this, details);\n }\n}\n\nfunction detailedStringForDecryptionError(err: DecryptionError, details?: Record<string, string | Error>): string {\n let result = err.name + \"[msg: \" + err.message;\n\n if (details) {\n result +=\n \", \" +\n Object.keys(details)\n .map((k) => k + \": \" + details[k])\n .join(\", \");\n }\n\n result += \"]\";\n\n return result;\n}\n","/*\nCopyright 2015 - 2024 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\n// Validation based on https://spec.matrix.org/v1.12/appendices/#server-name\n// We do not use the validation described in https://spec.matrix.org/v1.12/client-server-api/#security-considerations-5\n// as it'd wrongly make all MXCs invalid due to not allowing `[].:` in server names.\nconst serverNameRegex =\n /^(?:(?:\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})|(?:\\[[\\dA-Fa-f:.]{2,45}])|(?:[A-Za-z\\d\\-.]{1,255}))(?::\\d{1,5})?$/;\nfunction validateServerName(serverName: string): boolean {\n const matches = serverNameRegex.exec(serverName);\n return matches?.[0] === serverName;\n}\n\n// Validation based on https://spec.matrix.org/v1.12/client-server-api/#security-considerations-5\nconst mediaIdRegex = /^[\\w-]+$/;\nfunction validateMediaId(mediaId: string): boolean {\n const matches = mediaIdRegex.exec(mediaId);\n return matches?.[0] === mediaId;\n}\n\n/**\n * Get the HTTP URL for an MXC URI.\n * @param baseUrl - The base homeserver url which has a content repo.\n * @param mxc - The mxc:// URI.\n * @param width - The desired width of the thumbnail.\n * @param height - The desired height of the thumbnail.\n * @param resizeMethod - The thumbnail resize method to use, either\n * \"crop\" or \"scale\".\n * @param allowDirectLinks - If true, return any non-mxc URLs\n * directly. Fetching such URLs will leak information about the user to\n * anyone they share a room with. If false, will return the emptry string\n * for such URLs.\n * @param allowRedirects - If true, the caller supports the URL being 307 or\n * 308 redirected to another resource upon request. If false, redirects\n * are not expected. Implied `true` when `useAuthentication` is `true`.\n * @param useAuthentication - If true, the caller supports authenticated\n * media and wants an authentication-required URL. Note that server support\n * for authenticated media will *not* be checked - it is the caller's responsibility\n * to do so before calling this function. Note also that `useAuthentication`\n * implies `allowRedirects`. Defaults to false (unauthenticated endpoints).\n * @param animated - Whether the desired thumbnail should be animated.\n * @returns The complete URL to the content, may be an empty string if the provided mxc is not valid.\n */\nexport function getHttpUriForMxc(\n baseUrl: string,\n mxc?: string,\n width?: number,\n height?: number,\n resizeMethod?: string,\n allowDirectLinks = false,\n allowRedirects?: boolean,\n useAuthentication?: boolean,\n animated?: boolean,\n): string {\n if (typeof mxc !== \"string\" || !mxc) {\n return \"\";\n }\n if (!mxc.startsWith(\"mxc://\")) {\n if (allowDirectLinks) {\n return mxc;\n } else {\n return \"\";\n }\n }\n\n const [serverName, mediaId, ...rest] = mxc.slice(6).split(\"/\");\n if (rest.length > 0 || !validateServerName(serverName) || !validateMediaId(mediaId)) {\n return \"\";\n }\n\n if (useAuthentication) {\n allowRedirects = true; // per docs (MSC3916 always expects redirects)\n\n // Dev note: MSC3916 removes `allow_redirect` entirely, but\n // for explicitness we set it here. This makes it slightly more obvious to\n // callers, hopefully.\n }\n\n let prefix: string;\n const isThumbnailRequest = !!width || !!height || !!resizeMethod;\n const verb = isThumbnailRequest ? \"thumbnail\" : \"download\";\n if (useAuthentication) {\n prefix = `/_matrix/client/v1/media/${verb}`;\n } else {\n prefix = `/_matrix/media/v3/${verb}`;\n }\n\n const url = new URL(`${prefix}/${serverName}/${mediaId}`, baseUrl);\n\n if (width) {\n url.searchParams.set(\"width\", Math.round(width).toString());\n }\n if (height) {\n url.searchParams.set(\"height\", Math.round(height).toString());\n }\n if (resizeMethod) {\n url.searchParams.set(\"method\", resizeMethod);\n }\n if (animated !== undefined) {\n url.searchParams.set(\"animated\", String(animated));\n }\n\n if (typeof allowRedirects === \"boolean\") {\n // We add this after, so we don't convert everything to a thumbnail request.\n url.searchParams.set(\"allow_redirect\", JSON.stringify(allowRedirects));\n }\n\n return url.href;\n}\n","/*\n * Copyright 2024 The Matrix.org Foundation C.I.C.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Cryptography-related events emitted by the {@link matrix.MatrixClient}.\n */\nexport enum CryptoEvent {\n /**\n * Fires when the trust status of a user changes.\n * The payload is a pair (userId, userTrustLevel). The trust level is one of the values from UserVerificationStatus.\n */\n UserTrustStatusChanged = \"userTrustStatusChanged\",\n\n /**\n * Fires when the key backup status changes.\n * The payload is a boolean indicating whether the key backup is enabled.\n */\n KeyBackupStatus = \"crypto.keyBackupStatus\",\n\n /**\n * Fires when we failed to back up the keys\n * The payload is the error code of the error that occurred.\n */\n KeyBackupFailed = \"crypto.keyBackupFailed\",\n\n /**\n * Fires when the number of sessions that can be backed up changes.\n * The payload is the remaining number of sessions that can be backed up.\n */\n KeyBackupSessionsRemaining = \"crypto.keyBackupSessionsRemaining\",\n\n /**\n * Fires when a new valid backup decryption key is in cache.\n * This will happen when a secret is received from another session, from secret storage,\n * or when a new backup is created from this session.\n *\n * The payload is the version of the backup for which we have the key for.\n *\n * This event is only fired by the rust crypto backend.\n */\n KeyBackupDecryptionKeyCached = \"crypto.keyBackupDecryptionKeyCached\",\n\n /**\n * Fires when a key verification request is received.\n * The payload is a VerificationRequest object representing the request.\n */\n VerificationRequestReceived = \"crypto.verificationRequestReceived\",\n\n /** @deprecated Use {@link DevicesUpdated} instead when using rust crypto */\n WillUpdateDevices = \"crypto.willUpdateDevices\",\n\n /**\n * Fires whenever the stored devices for a user have been updated\n * The payload is a pair (userIds, initialFetch).\n */\n DevicesUpdated = \"crypto.devicesUpdated\",\n\n /**\n * Fires when the user's cross-signing keys have changed or cross-signing\n * has been enabled/disabled. The client can use getStoredCrossSigningForUser\n * with the user ID of the logged in user to check if cross-signing is\n * enabled on the account. If enabled, it can test whether the current key\n * is trusted using with checkUserTrust with the user ID of the logged\n * in user. The checkOwnCrossSigningTrust function may be used to reconcile\n * the trust in the account key.\n *\n * The cross-signing API is currently UNSTABLE and may change without notice.\n * @experimental\n */\n KeysChanged = \"crossSigning.keysChanged\",\n\n /**\n * Fires when data is being migrated from legacy crypto to rust crypto.\n *\n * The payload is a pair `(progress, total)`, where `progress` is the number of steps completed so far, and\n * `total` is the total number of steps. When migration is complete, a final instance of the event is emitted, with\n * `progress === total === -1`.\n */\n LegacyCryptoStoreMigrationProgress = \"crypto.legacyCryptoStoreMigrationProgress\",\n\n /**\n * Fires when a new dehydrated device is created locally.\n *\n * After the client calls {@link CryptoApi.startDehydration}, this event\n * will be fired every time a new dehydrated device is created. It may fire\n * before `startDehydration` returns.\n */\n DehydratedDeviceCreated = \"dehydration.DehydratedDeviceCreated\",\n\n /**\n * Fires when a new dehydrated device is successfully uploaded to the server.\n *\n * This should fire shortly after {@link DehydratedDeviceCreated} fires. If\n * upload is unsuccessful, this will be reported either by an error thrown\n * by {@link CryptoApi.startDehydration} (for errors that happen before\n * `startDehydration` returns), or by firing {@link DehydratedDeviceRotationError}\n * (for errors that happen during regular rotation of the dehydrated device)\n */\n DehydratedDeviceUploaded = \"dehydration.DehydratedDeviceUploaded\",\n\n /**\n * Fires when rehydration has started.\n *\n * After the client calls {@link CryptoApi.startDehydration}, this event will\n * fire if a dehydrated device is found and we attempt to rehydrate it.\n */\n RehydrationStarted = \"dehydration.RehydrationStarted\",\n\n /**\n * Fires during rehydration, to inform the application of rehydration progress.\n *\n * The payload is a pair `[roomKeyCount: number, toDeviceCount: number]`,\n * where `roomKeyCount` is the number of room keys that have been received\n * so far, and `toDeviceCount` is the number of to-device messages received\n * so far (including the messages containing room keys).\n */\n RehydrationProgress = \"dehydration.RehydrationProgress\",\n\n /** Fires when rehydration has completed successfully. */\n RehydrationCompleted = \"dehydration.RehydrationCompleted\",\n\n /** Fires when there was an error in rehydration.\n *\n * The payload is an error message as a string.\n */\n RehydrationError = \"dehydration.RehydrationError\",\n\n /**\n * Fires when a dehydrated device key has been cached in the local database.\n */\n DehydrationKeyCached = \"dehydration.DehydrationKeyCached\",\n\n /**\n * Fires when an error occurs during periodic rotation of the dehydrated device.\n *\n * The payload is an error message as a string.\n */\n DehydratedDeviceRotationError = \"dehydration.DehydratedDeviceRotationError\",\n}\n","/*\n * Copyright 2024 The Matrix.org Foundation C.I.C.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nconst DEFAULT_BIT_SIZE = 256;\n\n/**\n * Derive a recovery key from a passphrase and salt using PBKDF2.\n * @see https://spec.matrix.org/v1.11/client-server-api/#deriving-keys-from-passphrases\n *\n * @param passphrase - The passphrase to derive the key from\n * @param salt - The salt to use in the derivation\n * @param iterations - The number of iterations to use in the derivation\n * @param numBits - The number of bits to derive\n */\nexport async function deriveRecoveryKeyFromPassphrase(\n passphrase: string,\n salt: string,\n iterations: number,\n numBits = DEFAULT_BIT_SIZE,\n): Promise<Uint8Array<ArrayBuffer>> {\n if (!globalThis.crypto.subtle || !TextEncoder) {\n throw new Error(\"Password-based backup is not available on this platform\");\n }\n\n const key = await globalThis.crypto.subtle.importKey(\n \"raw\",\n new TextEncoder().encode(passphrase),\n { name: \"PBKDF2\" },\n false,\n [\"deriveBits\"],\n );\n\n const keybits = await globalThis.crypto.subtle.deriveBits(\n {\n name: \"PBKDF2\",\n salt: new TextEncoder().encode(salt),\n iterations: iterations,\n hash: \"SHA-512\",\n },\n key,\n numBits,\n );\n\n return new Uint8Array(keybits);\n}\n","/*\nCopyright 2024 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\n/**\n * Computes a SHA-256 hash of a string (after utf-8 encoding) and returns it as an ArrayBuffer.\n *\n * @param plaintext The string to hash\n * @returns An Uint8Array containing the SHA-256 hash of the input string\n * @throws If the subtle crypto API is not available, for example if the code is running\n * in a web page with an insecure context (eg. served over plain HTTP).\n */\nexport async function sha256(plaintext: string): Promise<Uint8Array> {\n if (!globalThis.crypto.subtle) {\n throw new Error(\"Crypto.subtle is not available: insecure context?\");\n }\n const utf8 = new TextEncoder().encode(plaintext);\n\n const digest = await globalThis.crypto.subtle.digest(\"SHA-256\", utf8);\n\n return new Uint8Array(digest);\n}\n","/*\nCopyright 2021 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 MatrixClient } from \"./client.ts\";\nimport { type IEvent, MatrixEvent, MatrixEventEvent } from \"./models/event.ts\";\nimport { RelationType } from \"./@types/event.ts\";\n\nexport type EventMapper = (obj: Partial<IEvent>) => MatrixEvent;\n\nexport interface MapperOpts {\n // don't re-emit events emitted on an event mapped by this mapper on the client\n preventReEmit?: boolean;\n // decrypt event proactively\n decrypt?: boolean;\n}\n\nexport function eventMapperFor(client: MatrixClient, options: MapperOpts): EventMapper {\n let preventReEmit = Boolean(options.preventReEmit);\n const decrypt = options.decrypt !== false;\n\n function mapper(plainOldJsObject: Partial<IEvent>): MatrixEvent {\n const room = client.getRoom(plainOldJsObject.room_id);\n\n let event: MatrixEvent | undefined;\n // If the event is already known to the room, let's re-use the model rather than duplicating.\n // We avoid doing this to state events as they may be forward or backwards looking which tweaks behaviour.\n if (room && plainOldJsObject.state_key === undefined) {\n event = room.findEventById(plainOldJsObject.event_id!);\n }\n\n if (!event || event.status) {\n event = new MatrixEvent(plainOldJsObject);\n } else {\n // merge the latest unsigned data from the server\n event.setUnsigned({ ...event.getUnsigned(), ...plainOldJsObject.unsigned });\n // prevent doubling up re-emitters\n preventReEmit = true;\n }\n\n // if there is a complete edit bundled alongside the event, perform the replacement.\n // (prior to MSC3925, events were automatically replaced on the server-side. MSC3925 proposes that that doesn't\n // happen automatically but the server does provide us with the whole content of the edit event.)\n const bundledEdit = event.getServerAggregatedRelation<Partial<IEvent>>(RelationType.Replace);\n if (bundledEdit?.content) {\n const replacement = mapper(bundledEdit);\n // XXX: it's worth noting that the spec says we should only respect encrypted edits if, once decrypted, the\n // replacement has a `m.new_content` property. The problem is that we haven't yet decrypted the replacement\n // (it should be happening in the background), so we can't enforce this. Possibly we should for decryption\n // to complete, but that sounds a bit racy. For now, we just assume it's ok.\n event.makeReplaced(replacement);\n }\n\n const thread = room?.findThreadForEvent(event);\n if (thread) {\n event.setThread(thread);\n }\n\n if (event.isEncrypted()) {\n if (!preventReEmit) {\n client.reEmitter.reEmit(event, [MatrixEventEvent.Decrypted]);\n }\n if (decrypt) {\n client.decryptEventIfNeeded(event);\n }\n }\n\n if (!preventReEmit) {\n client.reEmitter.reEmit(event, [MatrixEventEvent.Replaced, MatrixEventEvent.VisibilityChange]);\n room?.reEmitter.reEmit(event, [MatrixEventEvent.BeforeRedaction]);\n }\n return event;\n }\n\n return mapper;\n}\n","/*\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 { type IServerVersions } from \"./client.ts\";\n\nexport enum ServerSupport {\n Stable,\n Unstable,\n Unsupported,\n}\n\nexport enum Feature {\n Thread = \"Thread\",\n ThreadUnreadNotifications = \"ThreadUnreadNotifications\",\n /**\n * @deprecated this is now exposed as a capability not a feature\n */\n LoginTokenRequest = \"LoginTokenRequest\",\n RelationBasedRedactions = \"RelationBasedRedactions\",\n AccountDataDeletion = \"AccountDataDeletion\",\n RelationsRecursion = \"RelationsRecursion\",\n IntentionalMentions = \"IntentionalMentions\",\n}\n\ntype FeatureSupportCondition = {\n unstablePrefixes?: string[];\n matrixVersion?: string;\n};\n\nconst featureSupportResolver: Record<string, FeatureSupportCondition> = {\n [Feature.Thread]: {\n unstablePrefixes: [\"org.matrix.msc3440\"],\n matrixVersion: \"v1.3\",\n },\n [Feature.ThreadUnreadNotifications]: {\n unstablePrefixes: [\"org.matrix.msc3771\", \"org.matrix.msc3773\"],\n matrixVersion: \"v1.4\",\n },\n [Feature.LoginTokenRequest]: {\n unstablePrefixes: [\"org.matrix.msc3882\"],\n },\n [Feature.RelationBasedRedactions]: {\n unstablePrefixes: [\"org.matrix.msc3912\"],\n },\n [Feature.AccountDataDeletion]: {\n unstablePrefixes: [\"org.matrix.msc3391\"],\n },\n [Feature.RelationsRecursion]: {\n unstablePrefixes: [\"org.matrix.msc3981\"],\n matrixVersion: \"v1.10\",\n },\n [Feature.IntentionalMentions]: {\n unstablePrefixes: [\"org.matrix.msc3952_intentional_mentions\"],\n matrixVersion: \"v1.7\",\n },\n};\n\nexport async function buildFeatureSupportMap(versions: IServerVersions): Promise<Map<Feature, ServerSupport>> {\n const supportMap = new Map<Feature, ServerSupport>();\n for (const [feature, supportCondition] of Object.entries(featureSupportResolver)) {\n const supportMatrixVersion = versions.versions?.includes(supportCondition.matrixVersion || \"\") ?? false;\n const supportUnstablePrefixes =\n supportCondition.unstablePrefixes?.every((unstablePrefix) => {\n return versions.unstable_features?.[unstablePrefix] === true;\n }) ?? false;\n if (supportMatrixVersion) {\n supportMap.set(feature as Feature, ServerSupport.Stable);\n } else if (supportUnstablePrefixes) {\n supportMap.set(feature as Feature, ServerSupport.Unstable);\n } else {\n supportMap.set(feature as Feature, ServerSupport.Unsupported);\n }\n }\n return supportMap;\n}\n","/*\nCopyright 2016 - 2021 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 RelationType } from \"./@types/event.ts\";\nimport { type MatrixEvent } from \"./models/event.ts\";\nimport { FILTER_RELATED_BY_REL_TYPES, FILTER_RELATED_BY_SENDERS, THREAD_RELATION_TYPE } from \"./models/thread.ts\";\n\n/**\n * Checks if a value matches a given field value, which may be a * terminated\n * wildcard pattern.\n * @param actualValue - The value to be compared\n * @param filterValue - The filter pattern to be compared\n * @returns true if the actualValue matches the filterValue\n */\nfunction matchesWildcard(actualValue: string, filterValue: string): boolean {\n if (filterValue.endsWith(\"*\")) {\n const typePrefix = filterValue.slice(0, -1);\n return actualValue.slice(0, typePrefix.length) === typePrefix;\n } else {\n return actualValue === filterValue;\n }\n}\n\n/* eslint-disable camelcase */\nexport interface IFilterComponent {\n \"types\"?: string[];\n \"not_types\"?: string[];\n \"rooms\"?: string[];\n \"not_rooms\"?: string[];\n \"senders\"?: string[];\n \"not_senders\"?: string[];\n \"contains_url\"?: boolean;\n \"limit\"?: number;\n \"related_by_senders\"?: Array<RelationType | string>;\n \"related_by_rel_types\"?: string[];\n\n // Unstable values\n \"io.element.relation_senders\"?: Array<RelationType | string>;\n \"io.element.relation_types\"?: string[];\n}\n/* eslint-enable camelcase */\n\n/**\n * FilterComponent is a section of a Filter definition which defines the\n * types, rooms, senders filters etc to be applied to a particular type of resource.\n * This is all ported over from synapse's Filter object.\n *\n * N.B. that synapse refers to these as 'Filters', and what js-sdk refers to as\n * 'Filters' are referred to as 'FilterCollections'.\n */\nexport class FilterComponent {\n public constructor(\n private filterJson: IFilterComponent,\n public readonly userId?: string | undefined | null,\n ) {}\n\n /**\n * Checks with the filter component matches the given event\n * @param event - event to be checked against the filter\n * @returns true if the event matches the filter\n */\n public check(event: MatrixEvent): boolean {\n const bundledRelationships = event.getUnsigned()?.[\"m.relations\"] || {};\n const relations: Array<string | RelationType> = Object.keys(bundledRelationships);\n // Relation senders allows in theory a look-up of any senders\n // however clients can only know about the current user participation status\n // as sending a whole list of participants could be proven problematic in terms\n // of performance\n // This should be improved when bundled relationships solve that problem\n const relationSenders: string[] = [];\n if (this.userId && bundledRelationships?.[THREAD_RELATION_TYPE.name]?.current_user_participated) {\n relationSenders.push(this.userId);\n }\n\n return this.checkFields(\n event.getRoomId(),\n event.getSender(),\n event.getType(),\n event.getContent() ? event.getContent().url !== undefined : false,\n relations,\n relationSenders,\n );\n }\n\n /**\n * Converts the filter component into the form expected over the wire\n */\n public toJSON(): object {\n return Object.fromEntries(\n Object.entries({\n types: this.filterJson.types,\n not_types: this.filterJson.not_types,\n rooms: this.filterJson.rooms,\n not_rooms: this.filterJson.not_rooms,\n senders: this.filterJson.senders,\n not_senders: this.filterJson.not_senders,\n contains_url: this.filterJson.contains_url,\n [FILTER_RELATED_BY_SENDERS.name]: this.filterJson[FILTER_RELATED_BY_SENDERS.name],\n [FILTER_RELATED_BY_REL_TYPES.name]: this.filterJson[FILTER_RELATED_BY_REL_TYPES.name],\n }).filter(([_key, value]) => value),\n );\n }\n\n /**\n * Checks whether the filter component matches the given event fields.\n * @param roomId - the roomId for the event being checked\n * @param sender - the sender of the event being checked\n * @param eventType - the type of the event being checked\n * @param containsUrl - whether the event contains a content.url field\n * @param relationTypes - whether has aggregated relation of the given type\n * @param relationSenders - whether one of the relation is sent by the user listed\n * @returns true if the event fields match the filter\n */\n private checkFields(\n roomId: string | undefined,\n sender: string | undefined,\n eventType: string,\n containsUrl: boolean,\n relationTypes: Array<RelationType | string>,\n relationSenders: string[],\n ): boolean {\n const literalKeys = {\n rooms: function (v: string): boolean {\n return roomId === v;\n },\n senders: function (v: string): boolean {\n return sender === v;\n },\n types: function (v: string): boolean {\n return matchesWildcard(eventType, v);\n },\n } as const;\n\n for (const name in literalKeys) {\n const matchFunc = literalKeys[<keyof typeof literalKeys>name];\n const notName = \"not_\" + name;\n const disallowedValues = this.filterJson[<`not_${keyof typeof literalKeys}`>notName];\n if (disallowedValues?.some(matchFunc)) {\n return false;\n }\n\n const allowedValues = this.filterJson[name as keyof typeof literalKeys];\n if (allowedValues && !allowedValues.some(matchFunc)) {\n return false;\n }\n }\n\n const containsUrlFilter = this.filterJson.contains_url;\n if (containsUrlFilter !== undefined && containsUrlFilter !== containsUrl) {\n return false;\n }\n\n const relationTypesFilter = this.filterJson[FILTER_RELATED_BY_REL_TYPES.name];\n if (relationTypesFilter !== undefined) {\n if (!this.arrayMatchesFilter(relationTypesFilter, relationTypes)) {\n return false;\n }\n }\n\n const relationSendersFilter = this.filterJson[FILTER_RELATED_BY_SENDERS.name];\n if (relationSendersFilter !== undefined) {\n if (!this.arrayMatchesFilter(relationSendersFilter, relationSenders)) {\n return false;\n }\n }\n\n return true;\n }\n\n private arrayMatchesFilter(filter: any[], values: any[]): boolean {\n return (\n values.length > 0 &&\n filter.every((value) => {\n return values.includes(value);\n })\n );\n }\n\n /**\n * Filters a list of events down to those which match this filter component\n * @param events - Events to be checked against the filter component\n * @returns events which matched the filter component\n */\n public filter(events: MatrixEvent[]): MatrixEvent[] {\n // oxlint-disable-next-line typescript/unbound-method\n return events.filter(this.check, this);\n }\n\n /**\n * Returns the limit field for a given filter component, providing a default of\n * 10 if none is otherwise specified. Cargo-culted from Synapse.\n * @returns the limit for this filter component.\n */\n public limit(): number {\n return this.filterJson.limit !== undefined ? this.filterJson.limit : 10;\n }\n}\n","/*\nCopyright 2022 - 2024 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 IMatrixApiError as IWidgetMatrixError } from \"matrix-widget-api\";\n\nimport { type IUsageLimit } from \"../@types/partials.ts\";\nimport { type MatrixEvent } from \"../models/event.ts\";\nimport { NamespacedValue } from \"../NamespacedValue.ts\";\n\ninterface IErrorJson extends Partial<IUsageLimit> {\n [key: string]: any; // extensible\n errcode?: string;\n error?: string;\n}\n\n/**\n * Construct a generic HTTP error. This is a JavaScript Error with additional information\n * specific to HTTP responses.\n * @param msg - The error message to include.\n * @param httpStatus - The HTTP response status code.\n * @param httpHeaders - The HTTP response headers.\n */\nexport class HTTPError extends Error {\n public constructor(\n msg: string,\n public readonly httpStatus?: number,\n public readonly httpHeaders?: Headers,\n ) {\n super(msg);\n }\n\n /**\n * Check if this error was due to rate-limiting on the server side (and should therefore be retried after a delay).\n *\n * If this returns `true`, {@link getRetryAfterMs} can be called to retrieve the server-side\n * recommendation for the retry period.\n *\n * @returns Whether this error is due to rate-limiting.\n */\n public isRateLimitError(): boolean {\n return this.httpStatus === 429;\n }\n\n /**\n * @returns The recommended delay in milliseconds to wait before retrying\n * the request that triggered this error, or null if no delay is recommended.\n * @throws Error if the recommended delay is an invalid value.\n * @see {@link safeGetRetryAfterMs} for a version of this check that doesn't throw.\n */\n public getRetryAfterMs(): number | null {\n const retryAfter = this.httpHeaders?.get(\"Retry-After\");\n if (retryAfter != null) {\n if (/^\\d+$/.test(retryAfter)) {\n const ms = Number.parseInt(retryAfter) * 1000;\n if (!Number.isFinite(ms)) {\n throw new Error(\"Retry-After header integer value is too large\");\n }\n return ms;\n }\n const date = new Date(retryAfter);\n if (date.toUTCString() !== retryAfter) {\n throw new Error(\"Retry-After header value is not a valid HTTP-date or non-negative decimal integer\");\n }\n return date.getTime() - Date.now();\n }\n return null;\n }\n}\n\nexport class MatrixError extends HTTPError {\n // The Matrix 'errcode' value, e.g. \"M_FORBIDDEN\".\n public readonly errcode?: string;\n // The Matrix 'error' value.\n public readonly error?: string;\n // The raw Matrix error JSON used to construct this object.\n public data: IErrorJson;\n\n /**\n * Construct a Matrix error. This is a JavaScript Error with additional\n * information specific to the standard Matrix error response.\n * @param errorJson - The Matrix error JSON returned from the homeserver.\n * @param httpStatus - The numeric HTTP status code given\n * @param httpHeaders - The HTTP response headers given\n */\n public constructor(\n errorJson: IErrorJson = {},\n httpStatus?: number,\n public url?: string,\n public event?: MatrixEvent,\n httpHeaders?: Headers,\n ) {\n let message = errorJson.error || \"Unknown message\";\n if (httpStatus) {\n message = `[${httpStatus}] ${message}`;\n }\n if (url) {\n message = `${message} (${url})`;\n }\n super(`MatrixError: ${message}`, httpStatus, httpHeaders);\n this.errcode = errorJson.errcode;\n this.error = errorJson.error;\n this.name = errorJson.errcode || \"Unknown error code\";\n this.data = errorJson;\n }\n\n public isRateLimitError(): boolean {\n return (\n this.errcode === \"M_LIMIT_EXCEEDED\" ||\n ((this.errcode === \"M_UNKNOWN\" || this.errcode === undefined) && super.isRateLimitError())\n );\n }\n\n public getRetryAfterMs(): number | null {\n const headerValue = super.getRetryAfterMs();\n if (headerValue !== null) {\n return headerValue;\n }\n // Note: retry_after_ms is deprecated as of spec version v1.10\n if (this.errcode === \"M_LIMIT_EXCEEDED\" && \"retry_after_ms\" in this.data) {\n if (!Number.isInteger(this.data.retry_after_ms)) {\n throw new Error(\"retry_after_ms is not an integer\");\n }\n return this.data.retry_after_ms;\n }\n return null;\n }\n\n /**\n * @returns this error expressed as a JSON payload\n * for use by Widget API error responses.\n */\n public asWidgetApiErrorData(): IWidgetMatrixError {\n const headers: Record<string, string> = {};\n if (this.httpHeaders) {\n for (const [name, value] of this.httpHeaders) {\n headers[name] = value;\n }\n }\n return {\n http_status: this.httpStatus ?? 400,\n http_headers: headers,\n url: this.url ?? \"\",\n response: {\n errcode: this.errcode ?? \"M_UNKNOWN\",\n error: this.data.error ?? \"Unknown message\",\n ...this.data,\n },\n };\n }\n\n /**\n * @returns a new {@link MatrixError} from a JSON payload\n * received from Widget API error responses.\n */\n public static fromWidgetApiErrorData(data: IWidgetMatrixError): MatrixError {\n return new MatrixError(data.response, data.http_status, data.url, undefined, new Headers(data.http_headers));\n }\n}\n\n/**\n * @returns The recommended delay in milliseconds to wait before retrying the request.\n * @param error - The error to check for a retry delay.\n * @param defaultMs - The delay to use if the error was not due to rate-limiting or if no valid delay is recommended.\n */\nexport function safeGetRetryAfterMs(error: unknown, defaultMs: number): number {\n if (!(error instanceof HTTPError) || !error.isRateLimitError()) {\n return defaultMs;\n }\n try {\n return error.getRetryAfterMs() ?? defaultMs;\n } catch {\n return defaultMs;\n }\n}\n\n/**\n * Construct a ConnectionError. This is a JavaScript Error indicating\n * that a request failed because of some error with the connection, either\n * CORS was not correctly configured on the server, the server didn't response,\n * the request timed out, or the internet connection on the client side went down.\n */\nexport class ConnectionError extends Error {\n public constructor(message: string, cause?: Error) {\n super(message + (cause ? `: ${cause.message}` : \"\"));\n }\n\n public get name(): string {\n return \"ConnectionError\";\n }\n}\n\n/**\n * Construct a TokenRefreshError. This indicates that a request failed due to the token being expired,\n * and attempting to refresh said token also failed but in a way which was not indicative of token invalidation.\n * Assumed to be a temporary failure.\n */\nexport class TokenRefreshError extends Error {\n public constructor(cause?: Error) {\n super(cause?.message ?? \"\");\n }\n\n public get name(): string {\n return \"TokenRefreshError\";\n }\n}\n\n/**\n * Construct a TokenRefreshError. This indicates that a request failed due to the token being expired,\n * and attempting to refresh said token failed in a way indicative of token invalidation.\n */\nexport class TokenRefreshLogoutError extends Error {\n public constructor(cause?: Error) {\n super(cause?.message ?? \"\");\n }\n\n public get name(): string {\n return \"TokenRefreshLogoutError\";\n }\n}\n\nexport const MatrixSafetyErrorCode = new NamespacedValue(null, \"ORG.MATRIX.MSC4387_SAFETY\");\n\n/***\n * This error is thrown when the homeserver refuses to handle an action due to a\n * safety concern.\n * @see https://github.com/matrix-org/matrix-spec-proposals/pull/4387\n */\nexport class MatrixSafetyError extends MatrixError {\n /**\n * The kinds of harms detected by the server.\n * @see https://github.com/matrix-org/matrix-spec-proposals/pull/4387 for a list of spec defined harms.\n */\n public readonly harms: Set<string>;\n /**\n * The date at which a request can be reattempted.\n */\n public readonly expiry?: Date;\n public constructor(...props: ConstructorParameters<typeof MatrixError>) {\n super(...props);\n const body = props[0];\n\n this.harms = new Set(body && \"harms\" in body && Array.isArray(body.harms) ? body.harms : []);\n this.message = `${super.message} (${[...this.harms].join(\", \")})`;\n if (body && \"expiry\" in body && typeof body.expiry === \"number\") {\n this.expiry = new Date(body.expiry);\n }\n }\n}\n","/*\nCopyright 2025 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 { MatrixError, TokenRefreshLogoutError } from \"./errors.ts\";\nimport { type IHttpOpts } from \"./interface.ts\";\nimport { sleep } from \"../utils.ts\";\n\n/**\n * This is an internal module. See {@link MatrixHttpApi} for the public class.\n */\n\nexport const enum TokenRefreshOutcome {\n Success = \"success\",\n Failure = \"failure\",\n Logout = \"logout\",\n}\n\ninterface Snapshot {\n accessToken: string;\n refreshToken?: string;\n expiry?: Date;\n}\n\n// If the token expires in less than this time amount of time, we will eagerly refresh it before making the intended request.\nconst REFRESH_IF_TOKEN_EXPIRES_WITHIN_MS = 500;\n// If we get an unknown token error and the token expires in less than this time amount of time, we will refresh it before making the intended request.\n// Otherwise, we will error as the token should not have expired yet and we need to avoid retrying indefinitely.\nconst REFRESH_ON_ERROR_IF_TOKEN_EXPIRES_WITHIN_MS = 60 * 1000;\n\ntype Opts = Pick<IHttpOpts, \"tokenRefreshFunction\" | \"logger\" | \"refreshToken\" | \"accessToken\">;\n\n/**\n * This class is responsible for managing the access token and refresh token for authenticated requests.\n * It will automatically refresh the access token when it is about to expire, and will handle unknown token errors.\n */\nexport class TokenRefresher {\n public constructor(private readonly opts: Opts) {}\n\n /**\n * Promise used to block authenticated requests during a token refresh to avoid repeated expected errors.\n * @private\n */\n private tokenRefreshPromise?: Promise<TokenRefreshOutcome>;\n\n private latestTokenRefreshExpiry?: Date;\n\n /**\n * This function is called before every request to ensure that the access token is valid.\n * @returns a snapshot containing the access token and other properties which must be passed to the handleUnknownToken\n * handler if an M_UNKNOWN_TOKEN error is encountered.\n */\n public async prepareForRequest(): Promise<Snapshot> {\n // Ensure our token is refreshed before we build the headers/params\n await this.refreshIfNeeded();\n\n return {\n accessToken: this.opts.accessToken!,\n refreshToken: this.opts.refreshToken,\n expiry: this.latestTokenRefreshExpiry,\n };\n }\n\n private async refreshIfNeeded(): Promise<unknown> {\n if (this.tokenRefreshPromise) {\n return this.tokenRefreshPromise;\n }\n // If we don't know the token expiry, we can't eagerly refresh\n if (!this.latestTokenRefreshExpiry) return;\n\n const expiresIn = this.latestTokenRefreshExpiry.getTime() - Date.now();\n if (expiresIn <= REFRESH_IF_TOKEN_EXPIRES_WITHIN_MS) {\n await this._handleUnknownToken();\n }\n }\n\n /**\n * This function is called when an M_UNKNOWN_TOKEN error is encountered.\n * It will attempt to refresh the access token if it is unknown, and will return a TokenRefreshOutcome.\n * @param snapshot - the snapshot returned by prepareForRequest\n * @param attempt - the number of attempts made for this request so far\n * @returns a TokenRefreshOutcome indicating the result of the refresh attempt\n */\n public async handleUnknownToken(snapshot: Snapshot, attempt: number): Promise<TokenRefreshOutcome> {\n return this._handleUnknownToken(snapshot, attempt);\n }\n\n /* eslint-disable @typescript-eslint/naming-convention */\n private async _handleUnknownToken(): Promise<TokenRefreshOutcome>;\n private async _handleUnknownToken(snapshot: Snapshot, attempt: number): Promise<TokenRefreshOutcome>;\n private async _handleUnknownToken(snapshot?: Snapshot, attempt?: number): Promise<TokenRefreshOutcome> {\n if (snapshot?.expiry) {\n // If our token is unknown, but it should not have expired yet, then we should not refresh\n const expiresIn = snapshot.expiry.getTime() - Date.now();\n // If it still has plenty of time left on the clock, we assume something else must be wrong and\n // do not refresh. Otherwise if it's expired, or will soon, we try refreshing.\n if (expiresIn >= REFRESH_ON_ERROR_IF_TOKEN_EXPIRES_WITHIN_MS) {\n return TokenRefreshOutcome.Logout;\n }\n }\n\n if (!snapshot || snapshot?.accessToken === this.opts.accessToken) {\n // If we have a snapshot, but the access token is the same as the current one then a refresh\n // did not happen behind us but one may be ongoing anyway\n this.tokenRefreshPromise ??= this.doTokenRefresh(attempt);\n\n try {\n return await this.tokenRefreshPromise;\n } finally {\n this.tokenRefreshPromise = undefined;\n }\n }\n\n // We may end up here if the token was refreshed in the background due to another request\n return TokenRefreshOutcome.Success;\n }\n\n /**\n * Attempt to refresh access tokens.\n * On success, sets new access and refresh tokens in opts.\n * @returns Promise that resolves to a boolean - true when token was refreshed successfully\n */\n private async doTokenRefresh(attempt?: number): Promise<TokenRefreshOutcome> {\n if (!this.opts.refreshToken || !this.opts.tokenRefreshFunction) {\n this.opts.logger?.error(\"Unable to refresh token - no refresh token or refresh function\");\n return TokenRefreshOutcome.Logout;\n }\n\n if (attempt && attempt > 1) {\n // Exponential backoff to ensure we don't trash the server, up to 2^5 seconds\n await sleep(1000 * Math.min(32, 2 ** attempt));\n }\n\n try {\n this.opts.logger?.debug(\"Attempting to refresh token\");\n const { accessToken, refreshToken, expiry } = await this.opts.tokenRefreshFunction(this.opts.refreshToken);\n this.opts.accessToken = accessToken;\n this.opts.refreshToken = refreshToken;\n this.latestTokenRefreshExpiry = expiry;\n this.opts.logger?.debug(\"... token refresh complete, new token expiry:\", expiry);\n\n // successfully got new tokens\n return TokenRefreshOutcome.Success;\n } catch (error) {\n // If we get a TokenError or MatrixError, we should log out, otherwise assume transient\n if (error instanceof TokenRefreshLogoutError || error instanceof MatrixError) {\n this.opts.logger?.error(\"Failed to refresh token\", error);\n return TokenRefreshOutcome.Logout;\n }\n\n this.opts.logger?.warn(\"Failed to refresh token\", error);\n return TokenRefreshOutcome.Failure;\n }\n }\n}\n","/*\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\n/**\n * This is an internal module. See {@link MatrixHttpApi} for the public class.\n */\n\nimport { checkObjectHasKeys, deepCopy, encodeParams } from \"../utils.ts\";\nimport { type TypedEventEmitter } from \"../models/typed-event-emitter.ts\";\nimport { Method } from \"./method.ts\";\nimport { ConnectionError, MatrixError, TokenRefreshError } from \"./errors.ts\";\nimport {\n type BaseRequestOpts,\n HttpApiEvent,\n type HttpApiEventHandlerMap,\n type IHttpOpts,\n type IRequestOpts,\n type Body,\n} from \"./interface.ts\";\nimport { anySignal, parseErrorResponse, timeoutSignal } from \"./utils.ts\";\nimport { type QueryDict } from \"../utils.ts\";\nimport { TokenRefresher, TokenRefreshOutcome } from \"./refresh.ts\";\n\nexport class FetchHttpApi<O extends IHttpOpts> {\n private abortController = new AbortController();\n private readonly tokenRefresher: TokenRefresher;\n\n public constructor(\n private eventEmitter: TypedEventEmitter<HttpApiEvent, HttpApiEventHandlerMap>,\n public readonly opts: O,\n ) {\n checkObjectHasKeys(opts, [\"baseUrl\", \"prefix\"]);\n if (!opts.onlyData) {\n throw new Error(\"Constructing FetchHttpApi without `onlyData=true` is no longer supported.\");\n }\n opts.useAuthorizationHeader = opts.useAuthorizationHeader ?? true;\n\n this.tokenRefresher = new TokenRefresher(opts);\n }\n\n public abort(): void {\n this.abortController.abort();\n this.abortController = new AbortController();\n }\n\n public fetch(resource: URL | string, options?: RequestInit): ReturnType<typeof globalThis.fetch> {\n if (this.opts.fetchFn) {\n return this.opts.fetchFn(resource, options);\n }\n return globalThis.fetch(resource, options);\n }\n\n /**\n * Sets the base URL for the identity server\n * @param url - The new base url\n */\n public setIdBaseUrl(url?: string): void {\n this.opts.idBaseUrl = url;\n }\n\n public idServerRequest<T extends object = Record<string, unknown>>(\n method: Method,\n path: string,\n params: Record<string, string | string[]> | undefined,\n prefix: string,\n accessToken?: string,\n ): Promise<T> {\n if (!this.opts.idBaseUrl) {\n throw new Error(\"No identity server base URL set\");\n }\n\n let queryParams: QueryDict | undefined = undefined;\n let body: Record<string, string | string[]> | undefined = undefined;\n if (method === Method.Get) {\n queryParams = params;\n } else {\n body = params;\n }\n\n const fullUri = this.getUrl(path, queryParams, prefix, this.opts.idBaseUrl);\n\n const opts: IRequestOpts = {\n json: true,\n headers: {},\n };\n if (accessToken) {\n opts.headers!.Authorization = `Bearer ${accessToken}`;\n }\n\n return this.requestOtherUrl(method, fullUri, body, opts);\n }\n\n /**\n * Perform an authorised request to the homeserver.\n * @param method - The HTTP method e.g. \"GET\".\n * @param path - The HTTP path <b>after</b> the supplied prefix e.g.\n * \"/createRoom\".\n *\n * @param queryParams - A dict of query params (these will NOT be\n * urlencoded). If unspecified, there will be no query params.\n *\n * @param body - The HTTP JSON body.\n *\n * @param paramOpts - additional options.\n * When `paramOpts.doNotAttemptTokenRefresh` is true, token refresh will not be attempted\n * when an expired token is encountered. Used to only attempt token refresh once.\n *\n * @returns The parsed response.\n * @throws Error if a problem occurred. This includes network problems and Matrix-specific error JSON.\n */\n public authedRequest<T>(\n method: Method,\n path: string,\n queryParams: QueryDict = {},\n body?: Body,\n paramOpts: IRequestOpts = {},\n ): Promise<T> {\n return this.doAuthedRequest<T>(1, method, path, queryParams, body, paramOpts);\n }\n\n // Wrapper around public method authedRequest to allow for tracking retry attempt counts\n private async doAuthedRequest<T>(\n attempt: number,\n method: Method,\n path: string,\n queryParams: QueryDict,\n body?: Body,\n paramOpts: IRequestOpts = {},\n ): Promise<T> {\n // avoid mutating paramOpts so they can be used on retry\n const opts = deepCopy(paramOpts);\n // we have to manually copy the abortSignal over as it is not a plain object\n opts.abortSignal = paramOpts.abortSignal;\n\n // Take a snapshot of the current token state before we start the request so we can reference it if we error\n const requestSnapshot = await this.tokenRefresher.prepareForRequest();\n if (requestSnapshot.accessToken) {\n if (this.opts.useAuthorizationHeader) {\n if (!opts.headers) {\n opts.headers = {};\n }\n if (!opts.headers.Authorization) {\n opts.headers.Authorization = `Bearer ${requestSnapshot.accessToken}`;\n }\n if (queryParams.access_token) {\n delete queryParams.access_token;\n }\n } else if (!queryParams.access_token) {\n queryParams.access_token = requestSnapshot.accessToken;\n }\n }\n\n try {\n const response = await this.request<T>(method, path, queryParams, body, opts);\n return response;\n } catch (error) {\n if (!(error instanceof MatrixError)) {\n throw error;\n }\n\n if (error.errcode === \"M_UNKNOWN_TOKEN\") {\n const outcome = await this.tokenRefresher.handleUnknownToken(requestSnapshot, attempt);\n if (outcome === TokenRefreshOutcome.Success) {\n // if we got a new token retry the request\n return this.doAuthedRequest(attempt + 1, method, path, queryParams, body, paramOpts);\n }\n if (outcome === TokenRefreshOutcome.Failure) {\n throw new TokenRefreshError(error);\n }\n\n if (!opts?.inhibitLogoutEmit) {\n this.eventEmitter.emit(HttpApiEvent.SessionLoggedOut, error);\n }\n } else if (error.errcode == \"M_CONSENT_NOT_GIVEN\") {\n this.eventEmitter.emit(HttpApiEvent.NoConsent, error.message, error.data.consent_uri);\n }\n\n throw error;\n }\n }\n\n /**\n * Perform a request to the homeserver without any credentials.\n * @param method - The HTTP method e.g. \"GET\".\n * @param path - The HTTP path <b>after</b> the supplied prefix e.g.\n * \"/createRoom\".\n *\n * @param queryParams - A dict of query params (these will NOT be\n * urlencoded). If unspecified, there will be no query params.\n *\n * @param body - The HTTP JSON body.\n *\n * @param opts - additional options\n *\n * @returns The parsed response.\n * @throws Error if a problem occurred. This includes network problems and Matrix-specific error JSON.\n */\n public request<T = unknown>(\n method: Method,\n path: string,\n queryParams?: QueryDict,\n body?: Body,\n opts?: IRequestOpts,\n ): Promise<T> {\n const fullUri = this.getUrl(path, queryParams, opts?.prefix, opts?.baseUrl);\n return this.requestOtherUrl<T>(method, fullUri, body, opts);\n }\n\n /**\n * Perform a request to an arbitrary URL.\n * @param method - The HTTP method e.g. \"GET\".\n * @param url - The HTTP URL object.\n *\n * @param body - The HTTP JSON body.\n *\n * @param opts - additional options\n *\n * @returns The parsed response.\n * @throws Error if a problem occurred. This includes network problems and Matrix-specific error JSON.\n */\n public async requestOtherUrl<T>(\n method: Method,\n url: URL | string,\n body?: Body,\n opts: BaseRequestOpts = {},\n ): Promise<T> {\n if (opts.json !== undefined && opts.rawResponseBody !== undefined) {\n throw new Error(\"Invalid call to `FetchHttpApi` sets both `opts.json` and `opts.rawResponseBody`\");\n }\n\n const urlForLogs = this.sanitizeUrlForLogs(url);\n\n this.opts.logger?.debug(`FetchHttpApi: --> ${method} ${urlForLogs}`);\n\n const headers = Object.assign({}, opts.headers || {});\n\n const jsonResponse = !opts.rawResponseBody && opts.json !== false;\n if (jsonResponse) {\n if (!headers[\"Accept\"]) {\n headers[\"Accept\"] = \"application/json\";\n }\n }\n\n const timeout = opts.localTimeoutMs ?? this.opts.localTimeoutMs;\n const keepAlive = opts.keepAlive ?? false;\n const signals = [this.abortController.signal];\n if (timeout !== undefined) {\n signals.push(timeoutSignal(timeout));\n }\n if (opts.abortSignal) {\n signals.push(opts.abortSignal);\n }\n\n // If the body is an object, encode it as JSON and set the `Content-Type` header,\n // unless that has been explicitly inhibited by setting `opts.json: false`.\n // We can't use getPrototypeOf here as objects made in other contexts e.g. over postMessage won't have same ref\n let data: BodyInit;\n if (opts.json !== false && body?.constructor?.name === Object.name) {\n data = JSON.stringify(body);\n if (!headers[\"Content-Type\"]) {\n headers[\"Content-Type\"] = \"application/json\";\n }\n } else {\n data = body as BodyInit;\n }\n\n const { signal, cleanup } = anySignal(signals);\n\n // Set cache mode based on presence of Authorization header.\n // Browsers/proxies do not cache responses to requests with Authorization headers.\n // So specifying \"no-cache\" is redundant, and actually prevents caching\n // of preflight requests in CORS scenarios. As such, we only set \"no-cache\"\n // when there is no Authorization header.\n const cacheMode = \"Authorization\" in headers ? undefined : \"no-cache\";\n\n let res: Response;\n const start = Date.now();\n try {\n res = await this.fetch(url, {\n signal,\n method,\n body: data,\n headers,\n mode: \"cors\",\n redirect: \"follow\",\n referrer: \"\",\n referrerPolicy: \"no-referrer\",\n cache: cacheMode,\n credentials: \"omit\", // we send credentials via headers\n keepalive: keepAlive,\n priority: opts.priority,\n });\n\n this.opts.logger?.debug(\n `FetchHttpApi: <-- ${method} ${urlForLogs} [${Date.now() - start}ms ${res.status}]`,\n );\n } catch (e) {\n this.opts.logger?.debug(`FetchHttpApi: <-- ${method} ${urlForLogs} [${Date.now() - start}ms ${e}]`);\n if ((<Error>e).name === \"AbortError\") {\n throw e;\n }\n throw new ConnectionError(\"fetch failed\", <Error>e);\n } finally {\n cleanup();\n }\n\n if (!res.ok) {\n throw parseErrorResponse(res, await res.text());\n }\n\n if (opts.rawResponseBody) {\n return (await res.blob()) as T;\n } else if (jsonResponse) {\n return await res.json();\n } else {\n return (await res.text()) as T;\n }\n }\n\n private sanitizeUrlForLogs(url: URL | string): string {\n try {\n let asUrl: URL;\n if (typeof url === \"string\") {\n asUrl = new URL(url);\n } else {\n asUrl = url;\n }\n // Remove the values of any URL params that could contain potential secrets\n const sanitizedQs = new URLSearchParams();\n for (const key of asUrl.searchParams.keys()) {\n sanitizedQs.append(key, \"xxx\");\n }\n const sanitizedQsString = sanitizedQs.toString();\n const sanitizedQsUrlPiece = sanitizedQsString ? `?${sanitizedQsString}` : \"\";\n\n return asUrl.origin + asUrl.pathname + sanitizedQsUrlPiece;\n } catch {\n // defensive coding for malformed url\n return \"??\";\n }\n }\n /**\n * Form and return a homeserver request URL based on the given path params and prefix.\n * @param path - The HTTP path <b>after</b> the supplied prefix e.g. \"/createRoom\".\n * @param queryParams - A dict of query params (these will NOT be urlencoded).\n * @param prefix - The full prefix to use e.g. \"/_matrix/client/v2_alpha\", defaulting to this.opts.prefix.\n * @param baseUrl - The baseUrl to use e.g. \"https://matrix.org\", defaulting to this.opts.baseUrl.\n * @returns URL\n */\n public getUrl(path: string, queryParams?: QueryDict, prefix?: string, baseUrl?: string): URL {\n const baseUrlWithFallback = baseUrl ?? this.opts.baseUrl;\n const baseUrlWithoutTrailingSlash = baseUrlWithFallback.endsWith(\"/\")\n ? baseUrlWithFallback.slice(0, -1)\n : baseUrlWithFallback;\n const url = new URL(baseUrlWithoutTrailingSlash + (prefix ?? this.opts.prefix) + path);\n // If there are any params, encode and append them to the URL.\n if (this.opts.extraParams || queryParams) {\n const mergedParams = { ...this.opts.extraParams, ...queryParams };\n encodeParams(mergedParams, url.searchParams);\n }\n\n return url;\n }\n}\n","/*\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 { type MatrixError } from \"./errors.ts\";\nimport { type Logger } from \"../logger.ts\";\nimport { type QueryDict } from \"../utils.ts\";\n\nexport type Body = Record<string, any> | BodyInit;\n\n/**\n * Unencrypted access and (optional) refresh token\n */\nexport type AccessTokens = {\n /**\n * The new access token to use for authenticated requests\n */\n accessToken: string;\n /**\n * The new refresh token to use for refreshing tokens, optional\n */\n refreshToken?: string;\n /**\n * Approximate date when the access token will expire, optional\n */\n expiry?: Date;\n};\n\n/**\n * Function that performs token refresh using the given refreshToken.\n * Returns a promise that resolves to the refreshed access and (optional) refresh tokens.\n *\n * Can be passed to HttpApi instance as {@link IHttpOpts.tokenRefreshFunction} during client creation {@link ICreateClientOpts}\n */\nexport type TokenRefreshFunction = (refreshToken: string) => Promise<AccessTokens>;\n\n/** Options object for `FetchHttpApi` and {@link MatrixHttpApi}. */\nexport interface IHttpOpts {\n fetchFn?: typeof globalThis.fetch;\n\n baseUrl: string;\n idBaseUrl?: string;\n prefix: string;\n extraParams?: QueryDict;\n\n accessToken?: string;\n /**\n * Used in conjunction with tokenRefreshFunction to attempt token refresh\n */\n refreshToken?: string;\n /**\n * Function to attempt token refresh when a possibly expired token is encountered\n * Optional, only called when a refreshToken is present\n */\n tokenRefreshFunction?: TokenRefreshFunction;\n\n /**\n * Whether to use the HTTP Authorization header over the `access_token` query parameter\n * @deprecated as of v1.11 in https://spec.matrix.org/v1.17/client-server-api/#using-access-tokens\n */\n useAuthorizationHeader?: boolean; // defaults to true\n\n /** For historical reasons, must be set to `true`. Will eventually be removed. */\n onlyData?: boolean;\n\n localTimeoutMs?: number;\n\n /** Optional logger instance. If provided, requests and responses will be logged. */\n logger?: Logger;\n}\n\n/** Options object for `FetchHttpApi.requestOtherUrl`. */\nexport interface BaseRequestOpts extends Pick<RequestInit, \"priority\"> {\n /**\n * map of additional request headers\n */\n headers?: Record<string, string>;\n abortSignal?: AbortSignal;\n /**\n * The maximum amount of time to wait before\n * timing out the request. If not specified, there is no timeout.\n */\n localTimeoutMs?: number;\n keepAlive?: boolean; // defaults to false\n\n /**\n * By default, we will:\n *\n * * If the `body` is an object, JSON-encode it and set `Content-Type: application/json` in the\n * request headers (unless overridden by {@link headers}).\n *\n * * Set `Accept: application/json` in the request headers (again, unless overridden by {@link headers}).\n *\n * * Parse the response as JSON and return the parsed response.\n *\n * Setting this to `false` inhibits all three behaviors, and the response is instead parsed as a UTF-8 string. It\n * defaults to `true`, unless {@link rawResponseBody} is set.\n *\n * @deprecated Instead of setting this to `false`, set {@link rawResponseBody} to `true`.\n */\n json?: boolean;\n\n /**\n * Setting this to `true` does two things:\n *\n * * Inhibits the automatic addition of `Accept: application/json` in the request headers.\n *\n * * Causes the raw response to be returned as a {@link https://developer.mozilla.org/en-US/docs/Web/API/Blob|Blob}\n * instead of parsing it as JSON.\n */\n rawResponseBody?: boolean;\n}\n\nexport interface IRequestOpts extends BaseRequestOpts {\n /**\n * The alternative base url to use.\n * If not specified, uses this.opts.baseUrl\n */\n baseUrl?: string;\n /**\n * The full prefix to use e.g.\n * \"/_matrix/client/v2_alpha\". If not specified, uses this.opts.prefix.\n */\n prefix?: string;\n\n // Set to true to prevent the request function from emitting a Session.logged_out event.\n // This is intended for use on endpoints where M_UNKNOWN_TOKEN is a valid/notable error response,\n // such as with token refreshes.\n inhibitLogoutEmit?: boolean;\n}\n\nexport enum HttpApiEvent {\n SessionLoggedOut = \"Session.logged_out\",\n NoConsent = \"no_consent\",\n}\n\nexport type HttpApiEventHandlerMap = {\n /**\n * Fires whenever the login session the JS SDK is using is no\n * longer valid and the user must log in again.\n * NB. This only fires when action is required from the user, not\n * when then login session can be renewed by using a refresh token.\n * @example\n * ```\n * matrixClient.on(\"Session.logged_out\", function(errorObj){\n * // show the login screen\n * });\n * ```\n */\n [HttpApiEvent.SessionLoggedOut]: (err: MatrixError) => void;\n /**\n * Fires when the JS SDK receives a M_CONSENT_NOT_GIVEN error in response\n * to a HTTP request.\n * @example\n * ```\n * matrixClient.on(\"no_consent\", function(message, contentUri) {\n * console.info(message + ' Go to ' + contentUri);\n * });\n * ```\n */\n [HttpApiEvent.NoConsent]: (message: string, consentUri: string) => void;\n};\n\nexport interface UploadProgress {\n loaded: number;\n total: number;\n}\n\nexport interface UploadOpts {\n /**\n * Name to give the file on the server. Defaults to <tt>file.name</tt>.\n */\n name?: string;\n /**\n * Content-type for the upload. Defaults to\n * <tt>file.type</tt>, or <tt>applicaton/octet-stream</tt>.\n */\n type?: string;\n /**\n * if false will not send the filename,\n * e.g for encrypted file uploads where filename leaks are undesirable.\n * Defaults to true.\n */\n includeFilename?: boolean;\n /**\n * Optional. Called when a chunk of\n * data has been uploaded, with an object containing the fields `loaded`\n * (number of bytes transferred) and `total` (total size, if known).\n */\n progressHandler?(progress: UploadProgress): void;\n abortController?: AbortController;\n}\n\nexport interface Upload {\n loaded: number;\n total: number;\n promise: Promise<UploadResponse>;\n abortController: AbortController;\n}\n\nexport interface UploadResponse {\n // eslint-disable-next-line camelcase\n content_uri: string;\n}\n\nexport type FileType = XMLHttpRequestBodyInit;\n","/*\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\nexport enum Method {\n Get = \"GET\",\n Put = \"PUT\",\n Post = \"POST\",\n Delete = \"DELETE\",\n Options = \"OPTIONS\",\n Head = \"HEAD\",\n Patch = \"PATCH\",\n}\n","/*\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\nexport enum ClientPrefix {\n /**\n * A constant representing the URI path for Client-Server API endpoints versioned at v1.\n */\n V1 = \"/_matrix/client/v1\",\n /**\n * A constant representing the URI path for Client-Server API endpoints versioned at v3.\n */\n V3 = \"/_matrix/client/v3\",\n /**\n * A constant representing the URI path for as-yet unspecified Client-Server HTTP APIs.\n */\n Unstable = \"/_matrix/client/unstable\",\n}\n\nexport enum IdentityPrefix {\n /**\n * URI path for the v2 identity API\n */\n V2 = \"/_matrix/identity/v2\",\n}\n\nexport enum MediaPrefix {\n /**\n * A constant representing the URI path for Client-Server API Media endpoints versioned at v1.\n */\n V1 = \"/_matrix/media/v1\",\n /**\n * A constant representing the URI path for Client-Server API Media endpoints versioned at v3.\n */\n V3 = \"/_matrix/media/v3\",\n}\n","/*\nCopyright 2022 - 2024 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 { parse as parseContentType, type ContentType } from \"content-type\";\n\nimport { logger } from \"../logger.ts\";\nimport { sleep } from \"../utils.ts\";\nimport {\n ConnectionError,\n HTTPError,\n MatrixError,\n MatrixSafetyError,\n MatrixSafetyErrorCode,\n safeGetRetryAfterMs,\n} from \"./errors.ts\";\n\n// Ponyfill for https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal/timeout\nexport function timeoutSignal(ms: number): AbortSignal {\n const controller = new AbortController();\n setTimeout(() => {\n controller.abort();\n }, ms);\n\n return controller.signal;\n}\n\nexport function anySignal(signals: AbortSignal[]): {\n signal: AbortSignal;\n cleanup(this: void): void;\n} {\n const controller = new AbortController();\n\n function cleanup(): void {\n for (const signal of signals) {\n signal.removeEventListener(\"abort\", onAbort);\n }\n }\n\n function onAbort(): void {\n controller.abort();\n cleanup();\n }\n\n for (const signal of signals) {\n if (signal.aborted) {\n onAbort();\n break;\n }\n signal.addEventListener(\"abort\", onAbort);\n }\n\n return {\n signal: controller.signal,\n cleanup,\n };\n}\n\n/**\n * Attempt to turn an HTTP error response into a Javascript Error.\n *\n * If it is a JSON response, we will parse it into a MatrixError. Otherwise\n * we return a generic Error.\n *\n * @param response - response object\n * @param body - raw body of the response\n * @returns\n */\nexport function parseErrorResponse(response: XMLHttpRequest | Response, body?: string): Error {\n const httpHeaders = isXhr(response)\n ? new Headers(\n response\n .getAllResponseHeaders()\n .trim()\n .split(/[\\r\\n]+/)\n .map((header): [string, string] => {\n const colonIdx = header.indexOf(\":\");\n return [header.substring(0, colonIdx), header.substring(colonIdx + 1)];\n }),\n )\n : response.headers;\n\n let contentType: ContentType | null;\n try {\n contentType = getResponseContentType(httpHeaders);\n } catch (e) {\n return <Error>e;\n }\n if (contentType?.type === \"application/json\" && body) {\n const errorBody = JSON.parse(body);\n if (errorBody.errcode && MatrixSafetyErrorCode.matches(errorBody.errcode)) {\n return new MatrixSafetyError(\n errorBody,\n response.status,\n isXhr(response) ? response.responseURL : response.url,\n undefined,\n httpHeaders,\n );\n }\n return new MatrixError(\n errorBody,\n response.status,\n isXhr(response) ? response.responseURL : response.url,\n undefined,\n httpHeaders,\n );\n }\n if (contentType?.type === \"text/plain\") {\n return new HTTPError(`Server returned ${response.status} error: ${body}`, response.status, httpHeaders);\n }\n return new HTTPError(`Server returned ${response.status} error`, response.status, httpHeaders);\n}\n\nfunction isXhr(response: XMLHttpRequest | Response): response is XMLHttpRequest {\n return \"getResponseHeader\" in response;\n}\n\n/**\n * extract the Content-Type header from response headers, and\n * parse it to a `{type, parameters}` object.\n *\n * returns null if no content-type header could be found.\n *\n * @param response - response object\n * @returns parsed content-type header, or null if not found\n */\nfunction getResponseContentType(headers: Headers): ContentType | null {\n const contentType = headers.get(\"Content-Type\");\n if (contentType === null) return null;\n return parseContentType(contentType);\n}\n\n/**\n * Retries a network operation run in a callback.\n * @param maxAttempts - maximum attempts to try\n * @param callback - callback that returns a promise of the network operation. If rejected with ConnectionError, it will be retried by calling the callback again.\n * @returns the result of the network operation\n * @throws {@link ConnectionError} If after maxAttempts the callback still throws ConnectionError\n */\nexport async function retryNetworkOperation<T>(maxAttempts: number, callback: () => Promise<T>): Promise<T> {\n let attempts = 0;\n let lastConnectionError: ConnectionError | null = null;\n while (attempts < maxAttempts) {\n try {\n if (attempts > 0) {\n const timeout = 1000 * Math.pow(2, attempts);\n logger.log(`network operation failed ${attempts} times, retrying in ${timeout}ms...`);\n await sleep(timeout);\n }\n return await callback();\n } catch (err) {\n if (err instanceof ConnectionError) {\n attempts += 1;\n lastConnectionError = err;\n } else {\n throw err;\n }\n }\n }\n throw lastConnectionError;\n}\n\n/**\n * Calculate the backoff time for a request retry attempt.\n * This produces wait times of 2, 4, 8, and 16 seconds (30s total) after which we give up. If the\n * failure was due to a rate limited request, the time specified in the error is returned.\n *\n * Returns -1 if the error is not retryable, or if we reach the maximum number of attempts.\n *\n * @param err - The error thrown by the http call\n * @param attempts - The number of attempts made so far, including the one that just failed.\n * @param retryConnectionError - Whether to retry on {@link ConnectionError} (CORS, connection is down, etc.)\n */\nexport function calculateRetryBackoff(err: any, attempts: number, retryConnectionError: boolean): number {\n if (attempts > 4) {\n return -1; // give up\n }\n\n if (err instanceof ConnectionError && !retryConnectionError) {\n return -1;\n }\n\n if (err.httpStatus && Math.floor(err.httpStatus / 100) === 4 && err.httpStatus !== 429) {\n // client error; no amount of retrying will save you now (except for rate limiting which is handled below)\n return -1;\n }\n\n if (err.name === \"AbortError\") {\n // this is a client timeout, that is already very high 60s/80s\n // we don't want to retry, as it could do it for very long\n return -1;\n }\n\n // If we are trying to send an event (or similar) that is too large in any way, then retrying won't help\n if (err.name === \"M_TOO_LARGE\") {\n return -1;\n }\n\n return safeGetRetryAfterMs(err, 1000 * Math.pow(2, attempts));\n}\n","/*\nCopyright 2019 New Vector Ltd\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\n/**\n * Check if an IndexedDB database exists. The only way to do so is to try opening it, so\n * we do that and then delete it did not exist before.\n *\n * @param indexedDB - The `indexedDB` interface\n * @param dbName - The database name to test for\n * @returns Whether the database exists\n */\nexport function exists(indexedDB: IDBFactory, dbName: string): Promise<boolean> {\n return new Promise<boolean>((resolve, reject) => {\n let exists = true;\n const req = indexedDB.open(dbName);\n req.onupgradeneeded = (): void => {\n // Since we did not provide an explicit version when opening, this event\n // should only fire if the DB did not exist before at any version.\n exists = false;\n };\n req.onblocked = (): void => reject(req.error);\n req.onsuccess = (): void => {\n const db = req.result;\n db.close();\n if (!exists) {\n // The DB did not exist before, but has been created as part of this\n // existence check. Delete it now to restore previous state. Delete can\n // actually take a while to complete in some browsers, so don't wait for\n // it. This won't block future open calls that a store might issue next to\n // properly set up the DB.\n indexedDB.deleteDatabase(dbName);\n }\n resolve(exists);\n };\n req.onerror = (): void => reject(req.error);\n });\n}\n","import { type EncryptionConfig } from \"./MatrixRTCSession.ts\";\nimport { type CallMembership } from \"./CallMembership.ts\";\nimport { type EncryptionKeyMapKey } from \"./types.ts\";\n\n/**\n * The string used for the keys in the the encryption key map.\n * `@bob:examle.org:DEVICEID(UUIDRANDOM_MEMBERID_RANDOMUUID)`\n */\nexport function getEncryptionKeyMapKey(membership: CallMembershipIdentityParts): EncryptionKeyMapKey {\n return `${membership.userId}:${membership.deviceId}(${membership.memberId})`;\n}\n\n/**\n * This interface is for testing and for making it possible to interchange the encryption manager.\n * @internal\n */\nexport interface IEncryptionManager {\n /**\n * Joins the encryption manager with the provided configuration.\n *\n * @param joinConfig - The configuration for joining encryption, or undefined\n * if no specific configuration is provided.\n */\n join(joinConfig: EncryptionConfig | undefined): void;\n\n /**\n * Leaves the encryption manager, cleaning up any associated resources.\n */\n leave(): void;\n\n /**\n * Called from the MatrixRTCSession when the memberships in this session updated.\n *\n * @param oldMemberships - The previous state of call memberships before the update.\n */\n onMembershipsUpdate(oldMemberships: CallMembership[]): void;\n\n /**\n * Retrieves the encryption keys currently managed by the encryption manager.\n *\n * @returns A map of participant IDs to their encryption keys.\n */\n getEncryptionKeys(): ReadonlyMap<\n EncryptionKeyMapKey,\n ReadonlyArray<{\n key: Uint8Array<ArrayBuffer>;\n keyIndex: number;\n membership: CallMembershipIdentityParts;\n rtcBackendIdentity: string;\n }>\n >;\n}\n\nexport type CallMembershipIdentityParts = Pick<CallMembership, \"userId\" | \"deviceId\" | \"memberId\">;\n","/*\nCopyright 2025 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 CallMembershipIdentityParts } from \"./EncryptionManager.ts\";\nimport { type ParticipantDeviceInfo } from \"./types.ts\";\n\nexport enum KeyTransportEvents {\n ReceivedKeys = \"received_keys\",\n NotSupportedError = \"not_supported_error\",\n}\n\nexport type KeyTransportEventsHandlerMap = {\n [KeyTransportEvents.ReceivedKeys]: KeyTransportEventListener;\n [KeyTransportEvents.NotSupportedError]: () => void;\n};\n\nexport type KeyTransportEventListener = (\n membership: CallMembershipIdentityParts,\n keyBase64Encoded: string,\n index: number,\n timestamp: number,\n) => void;\n\n/**\n * Generic interface for the transport used to share room keys.\n * Keys can be shared using different transports, e.g. to-device messages or room messages.\n */\nexport interface IKeyTransport {\n /**\n * Sends the current user media key to the given members.\n * @param keyBase64Encoded\n * @param index\n * @param members - The participants that should get they key\n */\n sendKey(keyBase64Encoded: string, index: number, members: ParticipantDeviceInfo[]): Promise<void>;\n\n /** Subscribe to keys from this transport. */\n on(event: KeyTransportEvents.ReceivedKeys, listener: KeyTransportEventListener): this;\n /** Unsubscribe from keys from this transport. */\n off(event: KeyTransportEvents.ReceivedKeys, listener: KeyTransportEventListener): this;\n\n /** Once start is called the underlying transport will subscribe to its transport system.\n * Before start is called this transport will not emit any events.\n */\n start(): void;\n /** Once stop is called the underlying transport will unsubscribe from its transport system.\n * After stop is called this transport will not emit any events.\n */\n stop(): void;\n}\n","/*\nCopyright 2025 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 { CallMembership } from \"./CallMembership.ts\";\nimport type { RTCCallIntent, Status, Transport } from \"./types.ts\";\nimport { type TypedEventEmitter } from \"../models/typed-event-emitter.ts\";\n\nexport enum MembershipManagerEvent {\n StatusChanged = \"StatusChanged\",\n /**\n * Emitted when the membership manager has not heard back from the server for the duration\n * of the delayed event and hence failed to restart the delayed event.\n * This means that the user is probably not joined anymore and the leave event was distributed to other session members.\n */\n ProbablyLeft = \"ProbablyLeft\",\n /**\n * Once the membershipManger has aquired the a delay id (after sending the state event)\n * It will emit and share the delay id.\n */\n DelayIdChanged = \"DelayIdChanged\",\n}\n\nexport type MembershipManagerEventHandlerMap = {\n [MembershipManagerEvent.StatusChanged]: (prefStatus: Status, newStatus: Status) => void;\n [MembershipManagerEvent.ProbablyLeft]: (probablyLeft: boolean) => void;\n [MembershipManagerEvent.DelayIdChanged]: (delayId: string | undefined) => void;\n};\n\n/**\n * This interface defines what a MembershipManager uses and exposes.\n * This interface is what we use to write tests and allows changing the actual implementation\n * without breaking tests because of some internal method renaming.\n *\n * @internal\n */\nexport interface IMembershipManager extends TypedEventEmitter<\n MembershipManagerEvent,\n MembershipManagerEventHandlerMap\n> {\n /**\n * If we are trying to join, or have successfully joined the session.\n * It does not reflect if the room state is already configured to represent us being joined.\n * It only means that the Manager should be trying to connect or to disconnect running.\n * The Manager is still running right after isJoined becomes false to send the disconnect events.\n * @returns true if we intend to be participating in the MatrixRTC session\n * @deprecated This name is confusing and replaced by `isActivated()`. (Returns the same as `isActivated()`)\n */\n isJoined(): boolean;\n /**\n * If the manager is activated. This means it tries to do its job to join the call, resend state events...\n * It does not imply that the room state is already configured to represent being joined.\n * It means that the Manager tries to connect or is connected. (\"the manager is still active\")\n * Once `leave()` is called the manager is not activated anymore but still running until `leave()` resolves.\n * @returns `true` if we intend to be participating in the MatrixRTC session\n */\n isActivated(): boolean;\n /**\n * Get the actual connection status of the manager.\n */\n get status(): Status;\n\n /**\n * The Current own state event if the manger is connected.\n * `undefined` if not connected.\n */\n get ownMembership(): CallMembership | undefined;\n\n /**\n * If the membership manager has reason to believe that the hs sent a leave event\n * and as a consequence the current user is perceived as left for other session participants.\n */\n get probablyLeft(): boolean;\n\n /**\n * If the membership manager has reason to believe that the hs sent a leave event\n * and as a consequence the current user is perceived as left for other session participants.\n */\n get delayId(): string | undefined;\n\n /**\n * Start sending all necessary events to make this user participate in the RTC session.\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 * @throws can throw if it exceeds a configured maximum retry.\n */\n join(fociPreferred: Transport[], multiSfuFocus?: Transport, onError?: (error: unknown) => void): void;\n /**\n * Send all necessary events to make this user leave the RTC session.\n * @param timeout the maximum duration in ms until the promise is forced to resolve.\n * @returns It resolves with true in case the leave was sent successfully.\n * It resolves with false in case we hit the timeout before sending successfully.\n */\n leave(timeout?: number): Promise<boolean>;\n /**\n * Call this if the MatrixRTC session members have changed.\n */\n onRTCSessionMemberUpdate(memberships: CallMembership[]): Promise<void>;\n\n /**\n * Update the intent of a membership on the call (e.g. user is now providing a video feed)\n * @param callIntent The new intent to set.\n */\n updateCallIntent(callIntent: RTCCallIntent): Promise<void>;\n}\n","/*\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*/\nimport type { IContent, IMentions } from \"../matrix.ts\";\nimport type { RelationEvent } from \"../types.ts\";\nimport type { CallMembership } from \"./CallMembership.ts\";\nimport { type CallMembershipIdentityParts } from \"./EncryptionManager.ts\";\n\nexport type EncryptionKeyMapKey = string;\n\nexport interface EncryptionKeyEntry {\n index: number;\n key: string;\n}\n\n/**\n * The mxID, deviceId and membership timestamp of a RTC session participant.\n */\nexport type ParticipantDeviceInfo = {\n userId: string;\n deviceId: string;\n membershipTs: number;\n};\n\n/**\n * A type representing the information needed to decrypt video streams.\n */\nexport type InboundEncryptionSession = {\n key: Uint8Array<ArrayBuffer>;\n membership: CallMembershipIdentityParts;\n keyIndex: number;\n creationTS: number;\n};\n\n/**\n * The information about the key used to encrypt video streams.\n */\nexport type OutboundEncryptionSession = {\n key: Uint8Array<ArrayBuffer>;\n creationTS: number;\n // The devices that this key is shared with.\n sharedWith: Array<ParticipantDeviceInfo>;\n // This is an index acting as the id of the key\n keyId: number;\n};\n\nexport interface EncryptionKeysEventContent {\n keys: EncryptionKeyEntry[];\n device_id: string;\n call_id: string;\n sent_ts?: number;\n}\n\n/**\n * THe content of a to-device event that contains encryption keys.\n */\nexport interface EncryptionKeysToDeviceEventContent {\n keys: { index: number; key: string };\n member: {\n id: string;\n // TODO Remove that it is claimed, need to get the sealed sender from decryption info\n // Or add some validation on it based on the encryption info\n claimed_device_id: string;\n };\n room_id: string;\n session: {\n application: string;\n call_id: string;\n scope: string;\n };\n // Why is this needed?\n sent_ts?: number;\n}\n/**\n * @deprecated Use `RTCNotificationType` instead.\n */\nexport type CallNotifyType = \"ring\" | \"notify\";\n/**\n * @deprecated Use `IRTCNotificationContent` instead.\n */\nexport interface ICallNotifyContent {\n \"application\": string;\n \"m.mentions\": IMentions;\n \"notify_type\": CallNotifyType;\n \"call_id\": string;\n}\n\nexport type RTCNotificationType = \"ring\" | \"notification\";\n\n/**\n * Represents the intention of the call from the perspective of the sending user.\n * May be any string, although `\"audio\"` and `\"video\"` are commonly accepted values.\n */\nexport type RTCCallIntent = \"audio\" | \"video\" | string;\n\n/**\n * This will check if the content has all the expected fields to be a valid IRTCNotificationContent.\n * It will also cap the lifetime to 90000ms (1.5 min) if a higher value is provided.\n * @param content\n * @throws if the content is invalid\n * @returns a parsed IRTCNotificationContent\n */\nexport function parseCallNotificationContent(content: IContent): IRTCNotificationContent {\n if (content[\"m.mentions\"] && typeof content[\"m.mentions\"] !== \"object\") {\n throw new Error(\"malformed m.mentions\");\n }\n if (typeof content[\"notification_type\"] !== \"string\") {\n throw new Error(\"Missing or invalid notification_type\");\n }\n if (typeof content[\"sender_ts\"] !== \"number\") {\n throw new Error(\"Missing or invalid sender_ts\");\n }\n if (typeof content[\"lifetime\"] !== \"number\") {\n throw new Error(\"Missing or invalid lifetime\");\n }\n\n if (content[\"relation\"] && content[\"relation\"][\"rel_type\"] !== \"m.reference\") {\n throw new Error(\"Invalid relation\");\n }\n if (content[\"m.call.intent\"] && typeof content[\"m.call.intent\"] !== \"string\") {\n throw new Error(\"Invalid m.call.intent\");\n }\n\n const cappedLifetime = content[\"lifetime\"] >= 90000 ? 90000 : content[\"lifetime\"];\n return { ...content, lifetime: cappedLifetime } as IRTCNotificationContent;\n}\n\n/**\n * Interface for `org.matrix.msc4075.rtc.notification` events.\n * Don't cast event content to this directly. Use `parseCallNotificationContent` instead to validate the content first.\n */\nexport interface IRTCNotificationContent extends RelationEvent {\n \"m.mentions\"?: IMentions;\n \"notification_type\": RTCNotificationType;\n /**\n * The initial intent of the calling user.\n */\n \"m.call.intent\"?: RTCCallIntent;\n \"sender_ts\": number;\n \"lifetime\": number;\n}\n\n/**\n * MSC4310 decline event content for `org.matrix.msc4310.rtc.decline`.\n * Sent as a standard m.reference relation to an `org.matrix.msc4075.rtc.notification` event.\n */\nexport interface IRTCDeclineContent extends RelationEvent {}\n\nexport enum Status {\n Disconnected = \"Disconnected\",\n Connecting = \"Connecting\",\n Connected = \"Connected\",\n Disconnecting = \"Disconnecting\",\n Unknown = \"Unknown\",\n}\n\n/**\n * A type collecting call encryption statistics for a session.\n */\nexport type Statistics = {\n counters: {\n /**\n * The number of times we have sent a room event containing encryption keys.\n */\n roomEventEncryptionKeysSent: number;\n /**\n * The number of times we have received a room event containing encryption keys.\n */\n roomEventEncryptionKeysReceived: number;\n };\n totals: {\n /**\n * The total age (in milliseconds) of all room events containing encryption keys that we have received.\n * We track the total age so that we can later calculate the average age of all keys received.\n */\n roomEventEncryptionKeysReceivedTotalAge: number;\n };\n};\n\nexport const isMyMembership = (m: CallMembership, userId: string, deviceId: string): boolean =>\n m.sender === userId && m.deviceId === deviceId;\n\n/**\n * A RTC transport is a JSON object that describes how to connect to a RTC member.\n */\nexport interface Transport {\n type: string;\n [key: string]: unknown;\n}\n\n/**\n * Event content for a `m.rtc.slot` state event.\n */\nexport interface RtcSlotEventContent<T extends string = string> {\n application: {\n type: T;\n // other application specific keys\n [key: string]: unknown;\n };\n slot_id: string;\n}\n\n/**\n * The session description is used to identify a session. Used in the state event.\n */\nexport interface SlotDescription {\n /**\n * The application type. e.g. \"m.call\".\n */\n application: string;\n /**\n * The application-specific slot ID. e.g. \"ROOM\".\n */\n id: string;\n}\n","import { type Logger, logger as rootLogger } from \"../logger.ts\";\nimport { type EmptyObject } from \"../matrix.ts\";\nimport { sleep } from \"../utils.ts\";\nimport { MembershipActionType } from \"./MembershipManager.ts\";\n\n/** @internal */\nexport interface Action {\n /**\n * When this action should be executed\n */\n ts: number;\n /**\n * The state of the different loops\n * can also be thought of as the type of the action\n */\n type: MembershipActionType;\n}\n\n/** @internal */\nexport type ActionUpdate =\n | {\n /** Replace all existing scheduled actions with this new array */\n replace: Action[];\n }\n | {\n /** Add these actions to the existing scheduled actions */\n insert: Action[];\n }\n | EmptyObject;\n\n/**\n * This scheduler tracks the state of the current membership participation\n * and runs one central timer that wakes up a handler callback with the correct action + state\n * whenever necessary.\n *\n * It can also be awakened whenever a new action is added which is\n * earlier then the current \"next awake\".\n * @internal\n */\nexport class ActionScheduler {\n private logger: Logger;\n /**\n * This is tracking the state of the scheduler loop.\n * Only used to prevent starting the loop twice.\n */\n public running = false;\n\n public constructor(\n /** This is the callback called for each scheduled action (`this.addAction()`) */\n private membershipLoopHandler: (type: MembershipActionType) => Promise<ActionUpdate>,\n parentLogger?: Logger,\n ) {\n this.logger = (parentLogger ?? rootLogger).getChild(`[NewMembershipActionScheduler]`);\n }\n\n // function for the wakeup mechanism (in case we add an action externally and need to leave the current sleep)\n private wakeup: (update: ActionUpdate) => void = (update: ActionUpdate): void => {\n this.logger.error(\"Cannot call wakeup before calling `startWithJoin()`\");\n };\n private _actions: Action[] = [];\n public get actions(): Action[] {\n return this._actions;\n }\n\n /**\n * This starts the main loop of the membership manager that handles event sending, delayed event sending and delayed event restarting.\n * @param initialActions The initial actions the manager will start with. It should be enough to pass: DelayedLeaveActionType.Initial\n * @returns Promise that resolves once all actions have run and no more are scheduled.\n * @throws This throws an error if one of the actions throws.\n * In most other error cases the manager will try to handle any server errors by itself.\n */\n public async startWithJoin(): Promise<void> {\n if (this.running) {\n this.logger.error(\"Cannot call startWithJoin() on NewMembershipActionScheduler while already running\");\n return;\n }\n this.running = true;\n this._actions = [{ ts: Date.now(), type: MembershipActionType.SendDelayedEvent }];\n try {\n while (this._actions.length > 0) {\n // Sort so next (smallest ts) action is at the beginning\n this._actions.sort((a, b) => a.ts - b.ts);\n const nextAction = this._actions[0];\n let wakeupUpdate: ActionUpdate | undefined = undefined;\n\n // while we await for the next action, wakeup has to resolve the wakeupPromise\n const wakeupPromise = new Promise<void>((resolve) => {\n this.wakeup = (update: ActionUpdate): void => {\n wakeupUpdate = update;\n resolve();\n };\n });\n if (nextAction.ts > Date.now()) await Promise.race([wakeupPromise, sleep(nextAction.ts - Date.now())]);\n\n let handlerResult: ActionUpdate = {};\n if (!wakeupUpdate) {\n this.logger.debug(\n `Current MembershipManager processing: ${nextAction.type}\\nQueue:`,\n this._actions,\n `\\nDate.now: \"${Date.now()}`,\n );\n try {\n // `this.wakeup` can also be called and sets the `wakeupUpdate` object while we are in the handler.\n handlerResult = await this.membershipLoopHandler(nextAction.type as MembershipActionType);\n } catch (e) {\n // Preserve the original error as `cause`.\n throw new Error(`The MembershipManager shut down because of the end condition: ${e}`, {\n cause: e,\n });\n }\n }\n // remove the processed action only after we are done processing\n this._actions.splice(0, 1);\n // The wakeupUpdate always wins since that is a direct external update.\n const actionUpdate = wakeupUpdate ?? handlerResult;\n\n if (\"replace\" in actionUpdate) {\n this._actions = actionUpdate.replace;\n } else if (\"insert\" in actionUpdate) {\n this._actions.push(...actionUpdate.insert);\n }\n }\n } finally {\n // Set the rtc session running state since we cannot recover from here and the consumer user of the\n // MatrixRTCSession class needs to manually rejoin.\n this.running = false;\n }\n\n this.logger.debug(\"Leave MembershipManager ActionScheduler loop (no more actions)\");\n }\n\n public initiateJoin(): void {\n this.wakeup?.({ replace: [{ ts: Date.now(), type: MembershipActionType.SendDelayedEvent }] });\n }\n public initiateLeave(): void {\n this.wakeup?.({ replace: [{ ts: Date.now(), type: MembershipActionType.SendScheduledDelayedLeaveEvent }] });\n }\n}\n","/*\nCopyright 2025 New Vector Ltd\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 Transport } from \"./types.ts\";\n\nexport interface LivekitTransportConfig extends Transport {\n type: \"livekit\";\n livekit_service_url: string;\n}\n\nexport const isLivekitTransportConfig = (object: any): object is LivekitTransportConfig =>\n object.type === \"livekit\" && \"livekit_service_url\" in object;\n\nexport interface LivekitTransport extends LivekitTransportConfig {\n livekit_alias: string;\n}\n\nexport const isLivekitTransport = (object: any): object is LivekitTransport =>\n isLivekitTransportConfig(object) && \"livekit_alias\" in object;\n\n/**\n * @deprecated this is just needed for the old focus active / focus fields of a call membership.\n * Not needed for new implementations.\n */\nexport interface LivekitFocusSelection extends Transport {\n type: \"livekit\";\n focus_selection: \"oldest_membership\" | \"multi_sfu\";\n}\n/**\n * @deprecated see LivekitFocusSelection\n */\nexport const isLivekitFocusSelection = (object: any): object is LivekitFocusSelection =>\n object.type === \"livekit\" && \"focus_selection\" in object;\n","/*\nCopyright 2025-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*/\nimport { AbortError } from \"p-retry\";\n\nimport { EventType, RelationType } from \"../@types/event.ts\";\nimport { type ISendEventResponse, type SendDelayedEventResponse } from \"../@types/requests.ts\";\nimport { type EmptyObject } from \"../@types/common.ts\";\nimport type { MatrixClient } from \"../client.ts\";\nimport { ConnectionError, HTTPError, MatrixError } from \"../http-api/errors.ts\";\nimport { type Logger, logger as rootLogger } from \"../logger.ts\";\nimport { type Room } from \"../models/room.ts\";\nimport { type CallMembership, DEFAULT_EXPIRE_DURATION } from \"./CallMembership.ts\";\nimport { type Transport, isMyMembership, type RTCCallIntent, Status, type SlotDescription } from \"./types.ts\";\nimport { type MembershipConfig, type SessionConfig } from \"./MatrixRTCSession.ts\";\nimport { ActionScheduler, type ActionUpdate } from \"./MembershipManagerActionScheduler.ts\";\nimport { TypedEventEmitter } from \"../models/typed-event-emitter.ts\";\nimport { UnsupportedDelayedEventsEndpointError } from \"../errors.ts\";\nimport {\n MembershipManagerEvent,\n type IMembershipManager,\n type MembershipManagerEventHandlerMap,\n} from \"./IMembershipManager.ts\";\nimport { type RtcMembershipData, type SessionMembershipData } from \"./membershipData/index.ts\";\nimport { computeSlotId } from \"./utils.ts\";\nimport { isLivekitTransportConfig } from \"./LivekitTransport.ts\";\n\n/* MembershipActionTypes:\nOn Join: ───────────────┐ ┌───────────────(1)───────────┐\n ▼ ▼ │\n ┌────────────────┐ │\n │SendDelayedEvent│ ──────(2)───┐ │\n └────────────────┘ │ │\n │(3) │ │\n ▼ │ │\n ┌─────────────┐ │ │\n ┌──────(4)───│SendJoinEvent│────(4)─────┐ │ │\n │ └─────────────┘ │ │ │\n │ ┌─────┐ ┌──────┐ │ │ │\n ▼ ▼ │ │ ▼ ▼ ▼ │\n┌────────────┐ │ │ ┌───────────────────┐ │\n│UpdateExpiry│ (s) (s)|RestartDelayedEvent│ │\n└────────────┘ │ │ └───────────────────┘ │\n │ │ │ │ │ │\n └─────┘ └──────┘ └───────┘\n\nOn Leave: ───────── STOP ALL ABOVE\n ▼\n ┌────────────────────────────────┐\n │ SendScheduledDelayedLeaveEvent │\n └────────────────────────────────┘\n │(5)\n ▼\n ┌──────────────┐\n │SendLeaveEvent│\n └──────────────┘\n(1) [Not found error] results in resending the delayed event\n(2) [hasMemberEvent = true] Sending the delayed event if we\n already have a call member event results jumping to the\n RestartDelayedEvent loop directly\n(3) [hasMemberEvent = false] if there is not call member event\n sending it is the next step\n(4) Both (UpdateExpiry and RestartDelayedEvent) actions are\n scheduled when successfully sending the state event\n(5) Only if delayed event sending failed (fallback)\n(s) Successful restart/resend\n*/\n\n/**\n * Call membership should always remain sticky for this amount\n * of time.\n */\nconst MEMBERSHIP_STICKY_DURATION_MS = 60 * 60 * 1000; // 60 minutes\n\n/**\n * The different types of actions the MembershipManager can take.\n * @internal\n */\nexport enum MembershipActionType {\n SendDelayedEvent = \"SendDelayedEvent\",\n // -> MembershipActionType.SendJoinEvent if successful\n // -> DelayedLeaveActionType.SendDelayedEvent on error, retry sending the first delayed event.\n // -> DelayedLeaveActionType.RestartDelayedEvent on success start updating the delayed event\n\n SendJoinEvent = \"SendJoinEvent\",\n // -> MembershipActionType.SendJoinEvent if we run into a rate limit and need to retry\n // -> MembershipActionType.Update if we successfully send the join event then schedule the expire event update\n // -> DelayedLeaveActionType.RestartDelayedEvent to recheck the delayed event\n\n RestartDelayedEvent = \"RestartDelayedEvent\",\n // -> DelayedLeaveActionType.SendMainDelayedEvent on missing delay id but there is a rtc state event\n // -> DelayedLeaveActionType.SendDelayedEvent on missing delay id and there is no state event\n // -> DelayedLeaveActionType.RestartDelayedEvent on success we schedule the next restart\n\n UpdateExpiry = \"UpdateExpiry\",\n // -> MembershipActionType.Update if the timeout has passed so the next update is required.\n\n SendScheduledDelayedLeaveEvent = \"SendScheduledDelayedLeaveEvent\",\n // -> MembershipActionType.SendLeaveEvent on failure (not found) we need to send the leave manually and cannot use the scheduled delayed event\n // -> DelayedLeaveActionType.SendScheduledDelayedLeaveEvent on error we try again.\n\n SendLeaveEvent = \"SendLeaveEvent\",\n // -> MembershipActionType.SendLeaveEvent\n}\n\n/**\n * @internal\n */\nexport interface MembershipManagerState {\n /** The delayId we got when successfully sending the delayed leave event.\n * Gets set to undefined if the server claims it cannot find the delayed event anymore. */\n delayId?: string;\n /** Stores how often we have update the `expires` field.\n * `expireUpdateIterations` * `membershipEventExpiryTimeout` resolves to the value the expires field should contain next */\n expireUpdateIterations: number;\n /** The time at which we send the first state event. The time the call started from the DAG point of view.\n * This is used to compute the local sleep timestamps when to next update the member event with a new expires value. */\n startTime: number;\n /** The manager is in the state where its actually connected to the session. */\n hasMemberStateEvent: boolean;\n // There can be multiple retries at once so we need to store counters per action\n // e.g. the send update membership and the restart delayed could be rate limited at the same time.\n /** Retry counter for rate limits */\n rateLimitRetries: Map<MembershipActionType, number>;\n /** Retry counter for other errors */\n networkErrorRetries: Map<MembershipActionType, number>;\n /** The time at which we expect the server to send the delayed leave event. */\n expectedServerDelayLeaveTs?: number;\n /** This is used to track if the client expects the scheduled delayed leave event to have\n * been sent because restarting failed during the available time.\n * Once we resend the delayed event or successfully restarted it will get unset. */\n probablyLeft: boolean;\n}\n\nfunction createInsertActionUpdate(type: MembershipActionType, offset?: number): ActionUpdate {\n return {\n insert: [{ ts: Date.now() + (offset ?? 0), type }],\n };\n}\n\nfunction createReplaceActionUpdate(type: MembershipActionType, offset?: number): ActionUpdate {\n return {\n replace: [{ ts: Date.now() + (offset ?? 0), type }],\n };\n}\n\ntype MembershipManagerClient = Pick<\n MatrixClient,\n | \"getUserId\"\n | \"getDeviceId\"\n | \"sendStateEvent\"\n | \"_unstable_sendDelayedStateEvent\"\n | \"_unstable_updateDelayedEvent\"\n | \"_unstable_cancelScheduledDelayedEvent\"\n | \"_unstable_restartScheduledDelayedEvent\"\n | \"_unstable_sendScheduledDelayedEvent\"\n>;\n\n/**\n * This class is responsible for sending all events relating to the own membership of a matrixRTC call.\n * It has the following tasks:\n * - Send the users leave delayed event before sending the membership\n * - Send the users membership if the state machine is started\n * - Check if the delayed event was canceled due to sending the membership\n * - update the delayed event (`restart`)\n * - Update the state event every ~5h = `DEFAULT_EXPIRE_DURATION` (so it does not get treated as expired)\n * - When the state machine is stopped:\n * - Disconnect the member\n * - Stop the timer for the delay refresh\n * - Stop the timer for updating the state event\n */\nexport class MembershipManager\n extends TypedEventEmitter<MembershipManagerEvent, MembershipManagerEventHandlerMap>\n implements IMembershipManager\n{\n private activated = false;\n private readonly logger: Logger;\n protected callIntent: RTCCallIntent | undefined;\n\n public isActivated(): boolean {\n return this.activated;\n }\n // DEPRECATED use isActivated\n public isJoined(): boolean {\n return this.isActivated();\n }\n\n /**\n * Puts the MembershipManager in a state where it tries to be joined.\n * It will send delayed events and membership events\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 onError This will be called once the membership manager encounters an unrecoverable error.\n * This should bubble up the the frontend to communicate that the call does not work in the current environment.\n * The original underlying error is preserved as `error.cause`, so consumers can `instanceof`-check the typed\n * cause.\n */\n public join(fociPreferred: Transport[], multiSfuFocus?: Transport, onError?: (error: unknown) => void): void {\n if (this.scheduler.running) {\n this.logger.error(\"MembershipManager is already running. Ignoring join request.\");\n return;\n }\n this.fociPreferred = fociPreferred;\n this.rtcTransport = multiSfuFocus;\n this.leavePromiseResolvers = undefined;\n this.activated = true;\n this.oldStatus = this.status;\n this.state = MembershipManager.defaultState;\n\n this.scheduler\n .startWithJoin()\n .catch((e) => {\n this.logger.error(\"MembershipManager stopped because: \", e);\n onError?.(e);\n })\n .finally(() => {\n // Should already be set to false when calling `leave` in non error cases.\n this.activated = false;\n // Here the scheduler is not running anymore so we the `membershipLoopHandler` is not called to emit.\n if (this.oldStatus && this.oldStatus !== this.status) {\n this.emit(MembershipManagerEvent.StatusChanged, this.oldStatus, this.status);\n }\n if (!this.scheduler.running) {\n this.leavePromiseResolvers?.resolve(true);\n this.leavePromiseResolvers = undefined;\n }\n });\n }\n\n /**\n * Leave from the call (Send an rtc session event with content: `{}`)\n * @param timeout the maximum duration this promise will take to resolve\n * @returns true if it managed to leave and false if the timeout condition happened.\n */\n public leave(timeout?: number): Promise<boolean> {\n if (!this.scheduler.running) {\n this.logger.warn(\"Called MembershipManager.leave() even though the MembershipManager is not running\");\n return Promise.resolve(true);\n }\n\n // We use the promise to track if we already scheduled a leave event\n // So we do not check scheduler.actions/scheduler.insertions\n if (!this.leavePromiseResolvers) {\n // reset scheduled actions so we will not do any new actions.\n this.leavePromiseResolvers = Promise.withResolvers<boolean>();\n this.activated = false;\n this.scheduler.initiateLeave();\n if (timeout) setTimeout(() => this.leavePromiseResolvers?.resolve(false), timeout);\n }\n return this.leavePromiseResolvers.promise;\n }\n\n private leavePromiseResolvers?: PromiseWithResolvers<boolean>;\n\n public onRTCSessionMemberUpdate(memberships: CallMembership[]): Promise<void> {\n if (!this.isActivated()) {\n return Promise.resolve();\n }\n\n this._ownMembership = memberships.find((m) => isMyMembership(m, this.userId, this.deviceId));\n\n if (!this._ownMembership) {\n // If one of these actions are scheduled or are getting inserted in the next iteration, we should already\n // take care of our missing membership.\n const sendingMembershipActions = [\n MembershipActionType.SendDelayedEvent,\n MembershipActionType.SendJoinEvent,\n ];\n this.logger.warn(\"Missing own membership: force re-join\");\n this.state.hasMemberStateEvent = false;\n\n if (this.scheduler.actions.some((a) => sendingMembershipActions.includes(a.type as MembershipActionType))) {\n this.logger.error(\n \"tried adding another `SendDelayedEvent` actions even though we already have one in the Queue\\nActionQueueOnMemberUpdate:\",\n this.scheduler.actions,\n );\n } else {\n // Only react to our own membership missing if we have not already scheduled sending a new membership DirectMembershipManagerAction.Join\n this.scheduler.initiateJoin();\n }\n }\n return Promise.resolve();\n }\n\n public async updateCallIntent(callIntent: RTCCallIntent): Promise<void> {\n if (!this.activated || !this.ownMembership) {\n throw Error(\"You cannot update your intent before joining the call\");\n }\n if (this.ownMembership.callIntent === callIntent) {\n return; // No-op\n }\n this.callIntent = callIntent;\n // Kick off a new membership event as a result.\n await this.sendJoinEvent();\n }\n\n /**\n * @throws if the client does not return user or device id.\n * @param joinConfig\n * @param room\n * @param client\n */\n public constructor(\n private readonly joinConfig: (SessionConfig & MembershipConfig) | undefined,\n protected readonly room: Pick<Room, \"roomId\" | \"getVersion\">,\n protected readonly client: MembershipManagerClient,\n public readonly slotDescription: SlotDescription,\n parentLogger?: Logger,\n ) {\n super();\n this.logger = (parentLogger ?? rootLogger).getChild(`[MembershipManager]`);\n const [userId, deviceId] = [this.client.getUserId(), this.client.getDeviceId()];\n if (userId === null) throw Error(\"Missing userId in client\");\n if (deviceId === null) throw Error(\"Missing deviceId in client\");\n this.deviceId = deviceId;\n this.userId = userId;\n // this needs to become a uuid so that consecutive join/leaves result in a key rotation.\n // we keep it as a string for now for backwards compatibility.\n this.stateKey = this.makeMembershipStateKey(userId, deviceId);\n this.state = MembershipManager.defaultState;\n this.callIntent = joinConfig?.callIntent;\n this.scheduler = new ActionScheduler((type): Promise<ActionUpdate> => {\n if (this.oldStatus) {\n // we put this at the beginning of the actions scheduler loop handle callback since it is a loop this\n // is equivalent to running it at the end of the loop. (just after applying the status/action list changes)\n // This order is required because this method needs to return the action updates.\n this.logger.debug(\n `MembershipManager applied action changes. Status: ${this.oldStatus} -> ${this.status}`,\n );\n if (this.oldStatus !== this.status) {\n this.emit(MembershipManagerEvent.StatusChanged, this.oldStatus, this.status);\n }\n }\n this.oldStatus = this.status;\n this.logger.debug(`MembershipManager before processing action. status=${this.oldStatus}`);\n return this.membershipLoopHandler(type);\n }, this.logger);\n }\n\n private _ownMembership?: CallMembership;\n public get ownMembership(): CallMembership | undefined {\n return this._ownMembership;\n }\n\n // scheduler\n private oldStatus?: Status;\n private scheduler: ActionScheduler;\n\n // MembershipManager mutable state.\n private state: MembershipManagerState;\n private static get defaultState(): MembershipManagerState {\n return {\n hasMemberStateEvent: false,\n delayId: undefined,\n\n startTime: 0,\n rateLimitRetries: new Map(),\n networkErrorRetries: new Map(),\n expireUpdateIterations: 1,\n probablyLeft: false,\n };\n }\n // Membership Event static parameters:\n protected deviceId: string;\n protected userId: string;\n protected stateKey: string;\n protected rtcTransport?: Transport;\n /** @deprecated This will be removed in favor or rtcTransport becoming a list of actively used transports */\n private fociPreferred?: Transport[];\n\n // Config:\n private delayedLeaveEventDelayMsOverride?: number;\n\n private get networkErrorRetryMs(): number {\n return this.joinConfig?.networkErrorRetryMs ?? 3_000;\n }\n private get membershipEventExpiryMs(): number {\n return this.joinConfig?.membershipEventExpiryMs ?? DEFAULT_EXPIRE_DURATION;\n }\n private get membershipEventExpiryHeadroomMs(): number {\n return this.joinConfig?.membershipEventExpiryHeadroomMs ?? 5_000;\n }\n private computeNextExpiryActionTs(iteration: number): number {\n return (\n this.state.startTime +\n Math.min(this.membershipEventExpiryMs, MEMBERSHIP_STICKY_DURATION_MS) * iteration -\n this.membershipEventExpiryHeadroomMs\n );\n }\n protected get delayedLeaveEventDelayMs(): number {\n return this.delayedLeaveEventDelayMsOverride ?? this.joinConfig?.delayedLeaveEventDelayMs ?? 8_000;\n }\n private get delayedLeaveEventRestartMs(): number {\n return this.joinConfig?.delayedLeaveEventRestartMs ?? 5_000;\n }\n private get maximumRateLimitRetryCount(): number {\n return this.joinConfig?.maximumRateLimitRetryCount ?? 10;\n }\n private get maximumNetworkErrorRetryCount(): number {\n return this.joinConfig?.maximumNetworkErrorRetryCount ?? 10;\n }\n private get delayedLeaveEventRestartLocalTimeoutMs(): number {\n return this.joinConfig?.delayedLeaveEventRestartLocalTimeoutMs ?? 2000;\n }\n\n // LOOP HANDLER:\n private async membershipLoopHandler(type: MembershipActionType): Promise<ActionUpdate> {\n switch (type) {\n case MembershipActionType.SendDelayedEvent: {\n // Before we start we check if we come from a state where we have a delay id.\n if (!this.state.delayId) {\n return this.sendOrResendDelayedLeaveEvent(); // Normal case without any previous delayed id.\n } else {\n // This can happen if someone else (or another client) removes our own membership event.\n // It will trigger `onRTCSessionMemberUpdate` queue `MembershipActionType.SendDelayedEvent`.\n // We might still have our delayed event from the previous participation and dependent on the server this might not\n // get removed automatically if the state changes. Hence, it would remove our membership unexpectedly shortly after the rejoin.\n //\n // In this block we will try to cancel this delayed event before setting up a new one.\n\n return this.cancelKnownDelayIdBeforeSendDelayedEvent(this.state.delayId);\n }\n }\n case MembershipActionType.RestartDelayedEvent: {\n if (!this.state.delayId) {\n // Delay id got reset. This action was used to check if the hs canceled the delayed event when the join state got sent.\n return createInsertActionUpdate(MembershipActionType.SendDelayedEvent);\n }\n return this.restartDelayedEvent(this.state.delayId);\n }\n case MembershipActionType.SendScheduledDelayedLeaveEvent: {\n // We are already good\n if (!this.state.hasMemberStateEvent) {\n return { replace: [] };\n }\n if (this.state.delayId) {\n return this.sendScheduledDelayedLeaveEventOrFallbackToSendLeaveEvent(this.state.delayId);\n } else {\n return createInsertActionUpdate(MembershipActionType.SendLeaveEvent);\n }\n }\n case MembershipActionType.SendJoinEvent: {\n return this.sendJoinEvent();\n }\n case MembershipActionType.UpdateExpiry: {\n return this.updateExpiryOnJoinedEvent();\n }\n case MembershipActionType.SendLeaveEvent: {\n // We are good already\n if (!this.state.hasMemberStateEvent) {\n return { replace: [] };\n }\n // This is only a fallback in case we do not have working delayed events support.\n // first we should try to just send the scheduled leave event\n return this.sendFallbackLeaveEvent();\n }\n }\n }\n\n // an abstraction to switch between sending state or a sticky event\n protected clientSendDelayedDisconnectMembership: () => Promise<SendDelayedEventResponse> = () =>\n this.client._unstable_sendDelayedStateEvent(\n this.room.roomId,\n { delay: this.delayedLeaveEventDelayMs },\n EventType.GroupCallMemberPrefix,\n {},\n this.stateKey,\n );\n\n // HANDLERS (used in the membershipLoopHandler)\n private async sendOrResendDelayedLeaveEvent(): Promise<ActionUpdate> {\n // We can reach this at the start of a call (where we do not yet have a membership: state.hasMemberStateEvent=false)\n // or during a call if the state event canceled our delayed event or caused by an unexpected error that removed our delayed event.\n // (Another client could have canceled it, the homeserver might have removed/lost it due to a restart, ...)\n // In the `then` and `catch` block we treat both cases differently. \"if (this.state.hasMemberStateEvent) {} else {}\"\n return await this.clientSendDelayedDisconnectMembership()\n .then((response) => {\n this.state.expectedServerDelayLeaveTs = Date.now() + this.delayedLeaveEventDelayMs;\n this.setAndEmitProbablyLeft(false);\n // On success we reset retries and set delayId.\n this.resetRateLimitCounter(MembershipActionType.SendDelayedEvent);\n this.setAndEmitDelayId(response.delay_id);\n if (this.state.hasMemberStateEvent) {\n // This action was scheduled because the previous delayed event was cancelled\n // due to lack of https://github.com/element-hq/synapse/pull/17810\n return createInsertActionUpdate(\n MembershipActionType.RestartDelayedEvent,\n this.delayedLeaveEventRestartMs,\n );\n } else {\n // This action was scheduled because we are in the process of joining\n return createInsertActionUpdate(MembershipActionType.SendJoinEvent);\n }\n })\n .catch((e) => {\n const repeatActionType = MembershipActionType.SendDelayedEvent;\n if (this.manageMaxDelayExceededSituation(e)) {\n return createInsertActionUpdate(repeatActionType);\n }\n const update = this.actionUpdateFromErrors(e, repeatActionType, \"_unstable_sendDelayedStateEvent\");\n if (update) return update;\n\n if (this.state.hasMemberStateEvent) {\n // This action was scheduled because the previous delayed event was cancelled\n // due to lack of https://github.com/element-hq/synapse/pull/17810\n\n // Don't do any other delayed event work if its not supported.\n if (this.isUnsupportedDelayedEndpoint(e)) return {};\n throw Error(\"Could not send delayed event, even though delayed events are supported. \" + e);\n } else {\n // This action was scheduled because we are in the process of joining\n // log and fall through\n if (this.isUnsupportedDelayedEndpoint(e)) {\n this.logger.info(\"Not using delayed event because the endpoint is not supported\");\n } else {\n this.logger.info(\"Not using delayed event because: \" + e);\n }\n // On any other error we fall back to not using delayed events and send the join state event immediately\n return createInsertActionUpdate(MembershipActionType.SendJoinEvent);\n }\n });\n }\n\n private async cancelKnownDelayIdBeforeSendDelayedEvent(delayId: string): Promise<ActionUpdate> {\n // Remove all running updates and restarts\n return await this.client\n ._unstable_cancelScheduledDelayedEvent(delayId)\n .then(() => {\n this.setAndEmitDelayId(undefined);\n this.resetRateLimitCounter(MembershipActionType.SendDelayedEvent);\n return createReplaceActionUpdate(MembershipActionType.SendDelayedEvent);\n })\n .catch((e) => {\n const repeatActionType = MembershipActionType.SendDelayedEvent;\n const update = this.actionUpdateFromErrors(e, repeatActionType, \"cancelScheduledDelayedEvent\");\n if (update) return update;\n\n if (this.isNotFoundError(e)) {\n // If we get a M_NOT_FOUND we know that the delayed event got already removed.\n // This means we are good and can set it to undefined and run this again.\n this.setAndEmitDelayId(undefined);\n return createReplaceActionUpdate(repeatActionType);\n }\n if (this.isUnsupportedDelayedEndpoint(e)) {\n return createReplaceActionUpdate(MembershipActionType.SendJoinEvent);\n }\n // We do not just ignore and log this error since we would also need to reset the delayId.\n\n // This becomes an unrecoverable error case since something is significantly off if we don't hit any of the above cases\n // when state.delayId !== undefined\n // We do not just ignore and log this error since we would also need to reset the delayId.\n // It is cleaner if we, the frontend, rejoins instead of resetting the delayId here and behaving like in the success case.\n throw Error(\n \"We failed to cancel a delayed event where we already had a delay id with an error we cannot automatically handle\",\n );\n });\n }\n\n private setAndEmitProbablyLeft(probablyLeft: boolean): void {\n if (this.state.probablyLeft === probablyLeft) {\n return;\n }\n this.state.probablyLeft = probablyLeft;\n this.emit(MembershipManagerEvent.ProbablyLeft, this.state.probablyLeft);\n }\n\n private setAndEmitDelayId(delayId: string | undefined): void {\n if (this.state.delayId === delayId) return;\n\n this.state.delayId = delayId;\n this.emit(MembershipManagerEvent.DelayIdChanged, this.state.delayId);\n }\n\n private async restartDelayedEvent(delayId: string): Promise<ActionUpdate> {\n // Compute the duration until we expect the server to send the delayed leave event.\n const durationUntilServerDelayedLeave = this.state.expectedServerDelayLeaveTs\n ? this.state.expectedServerDelayLeaveTs - Date.now()\n : undefined;\n const abortPromise = new Promise((_, reject) => {\n setTimeout(\n () => {\n reject(new AbortError(\"Restart delayed event timed out before the HS responded\"));\n },\n // We abort immediately at the time where we expect the server to send the delayed leave event.\n // At this point we want the catch block to run and set the `probablyLeft` state.\n //\n // While we are already in probablyLeft state, we use the unaltered delayedLeaveEventRestartLocalTimeoutMs.\n durationUntilServerDelayedLeave !== undefined && !this.state.probablyLeft\n ? Math.min(this.delayedLeaveEventRestartLocalTimeoutMs, durationUntilServerDelayedLeave)\n : this.delayedLeaveEventRestartLocalTimeoutMs,\n );\n });\n\n // The obvious choice here would be to use the `IRequestOpts` to set the timeout. Since this call might be forwarded\n // to the widget driver this information would get lost. That is why we mimic the AbortError using the race.\n return await Promise.race([this.client._unstable_restartScheduledDelayedEvent(delayId), abortPromise])\n .then(() => {\n // Whenever we successfully restart the delayed event we update the `state.expectedServerDelayLeaveTs`\n // which stores the predicted timestamp at which the server will send the delayed leave event if there wont be any further\n // successful restart requests.\n this.state.expectedServerDelayLeaveTs = Date.now() + this.delayedLeaveEventDelayMs;\n this.resetRateLimitCounter(MembershipActionType.RestartDelayedEvent);\n this.setAndEmitProbablyLeft(false);\n return createInsertActionUpdate(\n MembershipActionType.RestartDelayedEvent,\n this.delayedLeaveEventRestartMs,\n );\n })\n .catch((e) => {\n if (this.state.expectedServerDelayLeaveTs && this.state.expectedServerDelayLeaveTs <= Date.now()) {\n // Once we reach this point it's likely that the server is sending the delayed leave event so we emit `probablyLeft = true`.\n // It will emit `probablyLeft = false` once we notice about our leave through sync and successfully setup a new state event.\n this.setAndEmitProbablyLeft(true);\n }\n const repeatActionType = MembershipActionType.RestartDelayedEvent;\n if (this.isNotFoundError(e)) {\n this.setAndEmitDelayId(undefined);\n return createInsertActionUpdate(MembershipActionType.SendDelayedEvent);\n }\n // If the HS does not support delayed events we wont reschedule.\n if (this.isUnsupportedDelayedEndpoint(e)) return {};\n\n // TODO this also needs a test: get rate limit while checking id delayed event is scheduled\n const update = this.actionUpdateFromErrors(e, repeatActionType, \"restartScheduledDelayedEvent\");\n if (update) return update;\n\n // In other error cases we have no idea what is happening\n throw Error(\"Could not restart delayed event, even though delayed events are supported. \" + e);\n });\n }\n\n private async sendScheduledDelayedLeaveEventOrFallbackToSendLeaveEvent(delayId: string): Promise<ActionUpdate> {\n return await this.client\n ._unstable_sendScheduledDelayedEvent(delayId)\n .then(() => {\n this.state.hasMemberStateEvent = false;\n this.setAndEmitDelayId(undefined);\n this.resetRateLimitCounter(MembershipActionType.SendScheduledDelayedLeaveEvent);\n\n return { replace: [] };\n })\n .catch((e) => {\n const repeatActionType = MembershipActionType.SendLeaveEvent;\n if (this.isUnsupportedDelayedEndpoint(e)) return {};\n if (this.isNotFoundError(e)) {\n this.setAndEmitDelayId(undefined);\n return createInsertActionUpdate(repeatActionType);\n }\n const update = this.actionUpdateFromErrors(e, repeatActionType, \"sendScheduledDelayedEvent\");\n if (update) return update;\n\n // On any other error we fall back to SendLeaveEvent (this includes hard errors from rate limiting)\n this.logger.warn(\n \"Encountered unexpected error during SendScheduledDelayedLeaveEvent. Falling back to SendLeaveEvent\",\n e,\n );\n return createInsertActionUpdate(repeatActionType);\n });\n }\n\n protected clientSendMembership: (\n myMembership: RtcMembershipData | SessionMembershipData | EmptyObject,\n ) => Promise<ISendEventResponse> = (myMembership) => {\n return this.client.sendStateEvent(\n this.room.roomId,\n EventType.GroupCallMemberPrefix,\n myMembership as EmptyObject | SessionMembershipData,\n this.stateKey,\n );\n };\n\n private async sendJoinEvent(): Promise<ActionUpdate> {\n return await this.clientSendMembership(this.makeMyMembership(this.membershipEventExpiryMs))\n .then(() => {\n this.setAndEmitProbablyLeft(false);\n this.state.startTime = Date.now();\n // The next update should already use twice the membershipEventExpiryTimeout\n this.state.expireUpdateIterations = 1;\n this.state.hasMemberStateEvent = true;\n this.resetRateLimitCounter(MembershipActionType.SendJoinEvent);\n // An UpdateExpiry action might be left over from a previous join event.\n // We can reach sendJoinEvent when the delayed leave event gets send by the HS.\n // The branch where we might have a leftover UpdateExpiry action is:\n // RestartDelayedEvent (cannot find it, server removed it)\n // -> SendDelayedEvent (send new delayed event)\n // -> SendJoinEvent (here with a still scheduled UpdateExpiry action)\n const actionsWithoutUpdateExpiry = this.scheduler.actions.filter(\n (a) =>\n a.type !== MembershipActionType.UpdateExpiry && // A new UpdateExpiry action with an updated will be scheduled,\n a.type !== MembershipActionType.SendJoinEvent, // Manually remove the SendJoinEvent action,\n );\n return {\n replace: [\n ...actionsWithoutUpdateExpiry,\n // To check if the delayed event is still there or got removed by inserting the stateEvent, we need to restart it.\n { ts: Date.now(), type: MembershipActionType.RestartDelayedEvent },\n {\n ts: this.computeNextExpiryActionTs(this.state.expireUpdateIterations),\n type: MembershipActionType.UpdateExpiry,\n },\n ],\n };\n })\n .catch((e) => {\n const update = this.actionUpdateFromErrors(e, MembershipActionType.SendJoinEvent, \"sendStateEvent\");\n if (update) return update;\n throw e;\n });\n }\n\n private async updateExpiryOnJoinedEvent(): Promise<ActionUpdate> {\n const nextExpireUpdateIteration = this.state.expireUpdateIterations + 1;\n return await this.clientSendMembership(\n this.makeMyMembership(this.membershipEventExpiryMs * nextExpireUpdateIteration),\n )\n .then(() => {\n // Success, we reset retries and schedule update.\n this.resetRateLimitCounter(MembershipActionType.UpdateExpiry);\n this.state.expireUpdateIterations = nextExpireUpdateIteration;\n return {\n insert: [\n {\n ts: this.computeNextExpiryActionTs(nextExpireUpdateIteration),\n type: MembershipActionType.UpdateExpiry,\n },\n ],\n };\n })\n .catch((e) => {\n const update = this.actionUpdateFromErrors(e, MembershipActionType.UpdateExpiry, \"sendStateEvent\");\n if (update) return update;\n\n throw e;\n });\n }\n private async sendFallbackLeaveEvent(): Promise<ActionUpdate> {\n return await this.clientSendMembership({})\n .then(() => {\n this.resetRateLimitCounter(MembershipActionType.SendLeaveEvent);\n this.state.hasMemberStateEvent = false;\n return { replace: [] };\n })\n .catch((e) => {\n const update = this.actionUpdateFromErrors(e, MembershipActionType.SendLeaveEvent, \"sendStateEvent\");\n if (update) return update;\n throw e;\n });\n }\n\n // HELPERS\n /**\n * this creates `${localUserId}_${localDeviceId}_${this.slotDescription.application}${this.slotDescription.id}`\n * which is not compatible with membershipID of session type member events. They have to be `${localUserId}:${localDeviceId}`\n */\n private makeMembershipStateKey(localUserId: string, localDeviceId: string): string {\n // INFO_SLOT_ID_LEGACY_CASE (search for all occurances of this INFO to get the full picture)\n // Revert back to \"\" just for the state key (state keys are always legacy. we use sticky events for non legacy events)\n const application = this.slotDescription.application;\n const needsEmptyStringRoomFix = application === \"m.call\" && this.slotDescription.id === \"ROOM\";\n const slotId = needsEmptyStringRoomFix ? \"\" : this.slotDescription.id;\n const stateKey = `${localUserId}_${localDeviceId}_${application}${slotId}`;\n if (/^org\\.matrix\\.msc(3757|3779)\\b/.exec(this.room.getVersion())) {\n return stateKey;\n } else {\n return `_${stateKey}`;\n }\n }\n\n /**\n * Constructs our own membership\n * @returns Only returns `SessionMembershipData`\n */\n protected makeMyMembership(expires: number): SessionMembershipData | RtcMembershipData {\n const ownMembership = this.ownMembership;\n const needsEmptyStringRoomFix =\n this.slotDescription.application === \"m.call\" && this.slotDescription.id === \"ROOM\";\n\n const focusObjects: Pick<SessionMembershipData, \"foci_preferred\" | \"focus_active\"> =\n this.rtcTransport === undefined\n ? {\n focus_active: { type: \"livekit\", focus_selection: \"oldest_membership\" } as const,\n foci_preferred: this.fociPreferred ?? [],\n }\n : {\n focus_active: { type: \"livekit\", focus_selection: \"multi_sfu\" } as const,\n foci_preferred: [this.rtcTransport, ...(this.fociPreferred ?? [])],\n };\n return {\n \"application\": this.slotDescription.application,\n // INFO_SLOT_ID_LEGACY_CASE (search for all occurances of this INFO to get the full picture)\n // Revert back to \"\" just for the sending the event.\n \"call_id\": needsEmptyStringRoomFix ? \"\" : this.slotDescription.id,\n \"scope\": \"m.room\",\n \"device_id\": this.deviceId,\n // DO NOT use this.memberId here since that is the state key (using application...)\n // But for session events we use the colon seperated userId and deviceId. The SFU will automatically\n // assign those values to the media participant for those versions.\n \"membershipID\": `${this.userId}:${this.deviceId}`,\n expires,\n \"m.call.intent\": this.callIntent,\n ...focusObjects,\n ...(ownMembership !== undefined ? { created_ts: ownMembership.createdTs() } : undefined),\n };\n }\n\n // Error checks and handlers\n\n /**\n * Check if its a NOT_FOUND error\n * @param error the error causing this handler check/execution\n * @returns true if its a not found error\n */\n private isNotFoundError(error: unknown): boolean {\n return error instanceof MatrixError && error.errcode === \"M_NOT_FOUND\";\n }\n\n /**\n * Check if this is a DelayExceeded timeout and update the TimeoutOverride for the next try\n * @param error the error causing this handler check/execution\n * @returns true if its a delay exceeded error and we updated the local TimeoutOverride\n */\n private manageMaxDelayExceededSituation(error: unknown): boolean {\n if (\n error instanceof MatrixError &&\n error.errcode === \"M_UNKNOWN\" &&\n error.data[\"org.matrix.msc4140.errcode\"] === \"M_MAX_DELAY_EXCEEDED\"\n ) {\n const maxDelayAllowed = error.data[\"org.matrix.msc4140.max_delay\"];\n if (typeof maxDelayAllowed === \"number\" && this.delayedLeaveEventDelayMs > maxDelayAllowed) {\n this.delayedLeaveEventDelayMsOverride = maxDelayAllowed;\n }\n this.logger.warn(\"Retry sending delayed disconnection event due to server timeout limitations:\", error);\n return true;\n }\n return false;\n }\n\n protected actionUpdateFromErrors(\n error: unknown,\n type: MembershipActionType,\n method: string,\n ): ActionUpdate | undefined {\n const updateLimit = this.actionUpdateFromRateLimitError(error, method, type);\n if (updateLimit) return updateLimit;\n const updateNetwork = this.actionUpdateFromNetworkErrorRetry(error, type);\n if (updateNetwork) return updateNetwork;\n }\n /**\n * Check if we have a rate limit error and schedule the same action again if we dont exceed the rate limit retry count yet.\n * @param error the error causing this handler check/execution\n * @param method the method used for the throw message\n * @param type which MembershipActionType we reschedule because of a rate limit.\n * @throws If it is a rate limit error and the retry count got exceeded\n * @returns Returns true if we handled the error by rescheduling the correct next action.\n * Returns false if it is not a network error.\n */\n private actionUpdateFromRateLimitError(\n error: unknown,\n method: string,\n type: MembershipActionType,\n ): ActionUpdate | undefined {\n // \"Is rate limit\"-boundary\n if (!((error instanceof HTTPError || error instanceof MatrixError) && error.isRateLimitError())) {\n return undefined;\n }\n\n // retry boundary\n const rateLimitRetries = this.state.rateLimitRetries.get(type) ?? 0;\n if (rateLimitRetries < this.maximumRateLimitRetryCount) {\n let resendDelay: number;\n const defaultMs = 5000;\n try {\n resendDelay = error.getRetryAfterMs() ?? defaultMs;\n this.logger.info(`Rate limited by server, retrying in ${resendDelay}ms`);\n } catch (e) {\n this.logger.warn(\n `Error while retrieving a rate-limit retry delay, retrying after default delay of ${defaultMs}`,\n e,\n );\n resendDelay = defaultMs;\n }\n this.state.rateLimitRetries.set(type, rateLimitRetries + 1);\n return createInsertActionUpdate(type, resendDelay);\n }\n\n throw Error(\"Exceeded maximum retries for \" + type + \" attempts (client.\" + method + \")\", { cause: error });\n }\n\n /**\n * FIXME Don't Check the error and retry the same MembershipAction again in the configured time and for the configured retry count.\n * @param error the error causing this handler check/execution\n * @param type the action type that we need to repeat because of the error\n * @throws If it is a network error and the retry count got exceeded\n * @returns\n * Returns true if we handled the error by rescheduling the correct next action.\n * Returns false if it is not a network error.\n */\n private actionUpdateFromNetworkErrorRetry(error: unknown, type: MembershipActionType): ActionUpdate | undefined {\n // \"Is a network error\"-boundary\n const retries = this.state.networkErrorRetries.get(type) ?? 0;\n\n // Strings for error logging\n const retryDurationString = this.networkErrorRetryMs / 1000 + \"s\";\n const retryCounterString = \"(\" + retries + \"/\" + this.maximumNetworkErrorRetryCount + \")\";\n\n // Variables for scheduling the new event\n let retryDuration = this.networkErrorRetryMs;\n\n if (error instanceof Error && error.name === \"AbortError\") {\n // We do not wait for the timeout on local timeouts.\n retryDuration = 0;\n this.logger.warn(\n \"Network local timeout error while sending event, immediate retry (\" + retryCounterString + \")\",\n error,\n );\n } else if (error instanceof Error && error.message.includes(\"updating delayed event\")) {\n // TODO: We do not want error message matching here but instead the error should be a typed HTTPError\n // and be handled below automatically (the same as in the SPA case).\n //\n // The error originates because of https://github.com/matrix-org/matrix-widget-api/blob/5d81d4a26ff69e4bd3ddc79a884c9527999fb2f4/src/ClientWidgetApi.ts#L698-L701\n // uses `e` instance of HttpError (and not MatrixError)\n // The element web widget driver (only checks for MatrixError) is then failing to process (`processError`) it as a typed error: https://github.com/element-hq/element-web/blob/471712cbf06a067e5499bd5d2d7a75f693d9a12d/src/stores/widgets/StopGapWidgetDriver.ts#L711-L715\n // So it will not call: `error.asWidgetApiErrorData()` which is also missing for `HttpError`\n //\n // A proper fix would be to either find a place to convert the `HttpError` into a `MatrixError` and the `processError`\n // method to handle it as expected or to adjust `processError` to also process `HttpError`'s.\n this.logger.warn(\n \"delayed event update timeout error, retrying in \" + retryDurationString + \" \" + retryCounterString,\n error,\n );\n } else if (error instanceof ConnectionError) {\n this.logger.warn(\n \"Network connection error while sending event, retrying in \" +\n retryDurationString +\n \" \" +\n retryCounterString,\n error,\n );\n } else if (\n (error instanceof HTTPError || error instanceof MatrixError) &&\n typeof error.httpStatus === \"number\" &&\n error.httpStatus >= 500 &&\n error.httpStatus < 600\n ) {\n this.logger.warn(\n \"Server error while sending event, retrying in \" + retryDurationString + \" \" + retryCounterString,\n error,\n );\n } else {\n return undefined;\n }\n\n // retry boundary\n if (retries < this.maximumNetworkErrorRetryCount) {\n this.state.networkErrorRetries.set(type, retries + 1);\n return createInsertActionUpdate(type, retryDuration);\n }\n\n // Failure\n throw Error(\n \"Reached maximum (\" + this.maximumNetworkErrorRetryCount + \") retries cause by: \" + (error as Error),\n );\n }\n\n /**\n * Check if its an UnsupportedDelayedEventsEndpointError and which implies that we cannot do any delayed event logic\n * @param error The error to check\n * @returns true it its an UnsupportedDelayedEventsEndpointError\n */\n private isUnsupportedDelayedEndpoint(error: unknown): boolean {\n return error instanceof UnsupportedDelayedEventsEndpointError;\n }\n\n private resetRateLimitCounter(type: MembershipActionType): void {\n this.state.rateLimitRetries.set(type, 0);\n this.state.networkErrorRetries.set(type, 0);\n }\n\n public get status(): Status {\n const actions = this.scheduler.actions;\n if (actions.length === 1) {\n const { type } = actions[0];\n switch (type) {\n case MembershipActionType.SendDelayedEvent:\n case MembershipActionType.SendJoinEvent:\n return Status.Connecting;\n case MembershipActionType.UpdateExpiry: // where no delayed events\n return Status.Connected;\n case MembershipActionType.SendScheduledDelayedLeaveEvent:\n case MembershipActionType.SendLeaveEvent:\n return Status.Disconnecting;\n default:\n // pass through as not expected\n }\n } else if (actions.length === 2) {\n const types = actions.map((a) => a.type);\n // normal state for connected with delayed events\n if (\n (types.includes(MembershipActionType.RestartDelayedEvent) ||\n (types.includes(MembershipActionType.SendDelayedEvent) && this.state.hasMemberStateEvent)) &&\n types.includes(MembershipActionType.UpdateExpiry)\n ) {\n return Status.Connected;\n }\n } else if (actions.length === 3) {\n const types = actions.map((a) => a.type);\n // It is a correct connected state if we already schedule the next Restart but have not yet cleaned up\n // the current restart.\n if (\n types.filter((t) => t === MembershipActionType.RestartDelayedEvent).length === 2 &&\n types.includes(MembershipActionType.UpdateExpiry)\n ) {\n return Status.Connected;\n }\n }\n\n if (!this.scheduler.running) {\n return Status.Disconnected;\n }\n\n this.logger.error(\"MembershipManager has an unknown state. Actions: \", actions);\n return Status.Unknown;\n }\n\n public get probablyLeft(): boolean {\n return this.state.probablyLeft;\n }\n public get delayId(): string | undefined {\n return this.state.delayId;\n }\n}\n\n/**\n * Implementation of the Membership manager that uses sticky events\n * rather than state events.\n */\nexport class StickyEventMembershipManager extends MembershipManager {\n public constructor(\n joinConfig: (SessionConfig & MembershipConfig) | undefined,\n room: Pick<Room, \"getLiveTimeline\" | \"roomId\" | \"getVersion\">,\n private readonly clientWithSticky: MembershipManagerClient &\n Pick<MatrixClient, \"_unstable_sendStickyEvent\" | \"_unstable_sendStickyDelayedEvent\">,\n sessionDescription: SlotDescription,\n // this needs to become a uuid so that consecutive join/leaves result in a key rotation.\n // we keep it as a string for now for backwards compatibility.\n private readonly memberId: string,\n parentLogger?: Logger,\n ) {\n super(joinConfig, room, clientWithSticky, sessionDescription, parentLogger);\n }\n\n protected clientSendDelayedDisconnectMembership: () => Promise<SendDelayedEventResponse> = () =>\n this.clientWithSticky._unstable_sendStickyDelayedEvent(\n this.room.roomId,\n MEMBERSHIP_STICKY_DURATION_MS,\n { delay: this.delayedLeaveEventDelayMs },\n null,\n EventType.RTCMembership,\n { msc4354_sticky_key: this.memberId },\n );\n\n protected clientSendMembership: (\n myMembership: RtcMembershipData | SessionMembershipData | EmptyObject,\n ) => Promise<ISendEventResponse> = (myMembership) => {\n return this.clientWithSticky._unstable_sendStickyEvent(\n this.room.roomId,\n MEMBERSHIP_STICKY_DURATION_MS,\n null,\n EventType.RTCMembership,\n { ...myMembership, msc4354_sticky_key: this.memberId },\n );\n };\n\n private static nameMap = new Map([\n [\"sendStateEvent\", \"_unstable_sendStickyEvent\"],\n [\"sendDelayedStateEvent\", \"_unstable_sendStickyDelayedEvent\"],\n ]);\n protected actionUpdateFromErrors(e: unknown, t: MembershipActionType, m: string): ActionUpdate | undefined {\n return super.actionUpdateFromErrors(e, t, StickyEventMembershipManager.nameMap.get(m) ?? \"unknown\");\n }\n\n /**\n *\n * @returns Only returns `RtcMembershipData`\n */\n protected makeMyMembership(): RtcMembershipData {\n const ownMembership = this.ownMembership;\n\n const livekitTransport = isLivekitTransportConfig(this.rtcTransport) ? this.rtcTransport : undefined;\n const relationObject = ownMembership?.eventId\n ? { \"m.relation\": { rel_type: RelationType.Reference, event_id: ownMembership?.eventId } }\n : {};\n return {\n application: {\n type: this.slotDescription.application,\n ...(this.callIntent ? { \"m.call.intent\": this.callIntent } : {}),\n },\n slot_id: computeSlotId(this.slotDescription),\n // Make sure we do not add the alias to the transport.\n // It is not needed in matrix2.0. The additional session information will be used to find the right alias on the sfu.\n rtc_transports: livekitTransport\n ? [{ type: livekitTransport.type, livekit_service_url: livekitTransport.livekit_service_url }]\n : [],\n member: { device_id: this.deviceId, user_id: this.userId, id: this.memberId },\n versions: [],\n ...relationObject,\n };\n }\n}\n","/*\nCopyright 2025-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 {\n type CallMembershipIdentityParts,\n getEncryptionKeyMapKey,\n type IEncryptionManager,\n} from \"./EncryptionManager.ts\";\nimport { type EncryptionConfig, type MembershipConfig } from \"./MatrixRTCSession.ts\";\nimport type { CallMembership } from \"./CallMembership.ts\";\nimport { decodeBase64, encodeBase64 } from \"../base64.ts\";\nimport { type IKeyTransport, type KeyTransportEventListener, KeyTransportEvents } from \"./IKeyTransport.ts\";\nimport { type Logger } from \"../logger.ts\";\nimport { sleep } from \"../utils.ts\";\nimport {\n type EncryptionKeyMapKey,\n type InboundEncryptionSession,\n type OutboundEncryptionSession,\n type ParticipantDeviceInfo,\n} from \"./types.ts\";\nimport { OutdatedKeyFilter } from \"./utils.ts\";\nimport { computeRtcIdentityRaw } from \"./membershipData/rtc.ts\";\n\n/**\n * RTCEncryptionManager is used to manage the encryption keys for a call.\n *\n * It is responsible for distributing the keys to the other participants and rotating the keys if needed.\n *\n * This manager when used with to-device transport will share the existing key only to new joiners, and rotate\n * if there is a leaver.\n *\n * XXX In the future we want to distribute a ratcheted key not the current one for new joiners.\n */\nexport class RTCEncryptionManager implements IEncryptionManager {\n // This is a stop-gap solution for now. The preferred way to handle this case would be instead\n // to create a NoOpEncryptionManager that does nothing and use it for the session.\n // This will be done when removing the legacy EncryptionManager.\n private manageMediaKeys = false;\n\n private useHashedRtcBackendIdentity = false;\n private ownRtcBackendIdentityCache: string | undefined;\n\n /**\n * Store the key rings for each participant.\n * The encryption manager stores the keys because the application layer might not be ready yet to handle the keys.\n * The keys are stored and can be retrieved later when the application layer is ready {@link RTCEncryptionManager#getEncryptionKeys}.\n */\n private readonly participantKeyRings = new Map<\n EncryptionKeyMapKey,\n Array<{\n key: Uint8Array<ArrayBuffer>;\n keyIndex: number;\n membership: CallMembershipIdentityParts;\n rtcBackendIdentity: string;\n }>\n >();\n\n // The current per-sender media key for this device\n private outboundSession: OutboundEncryptionSession | null = null;\n\n /**\n * Ensures that there is only one distribute operation at a time for that call.\n */\n private currentKeyDistributionPromise: Promise<void> | null = null;\n\n /**\n * The time to wait before using the outbound session after it has been distributed.\n * This is to ensure that the key is delivered to all participants before it is used.\n * When creating the first key, this is set to 0 so that the key can be used immediately.\n */\n private useKeyDelay = 5000;\n\n /**\n * We want to avoid rolling out a new outbound key when the previous one was created less than `keyRotationGracePeriodMs` milliseconds ago.\n * This is to avoid expensive key rotations when users quickly join the call in a row.\n *\n * This must be higher than `useKeyDelay` to have an effect.\n * If it is lower, the current key will always be older than the grace period.\n * @private\n */\n private keyRotationGracePeriodMs = 10_000;\n\n /**\n * If a new key distribution is being requested while one is going on, we will set this flag to true.\n * This will ensure that a new round is started after the current one.\n * @private\n */\n private needToEnsureKeyAgain = false;\n\n /**\n * There is a possibility that keys arrive in the wrong order.\n * For example, after a quick join/leave/join, there will be 2 keys of index 0 distributed, and\n * if they are received in the wrong order, the stream won't be decryptable.\n * For that reason we keep a small buffer of keys for a limited time to disambiguate.\n * @private\n */\n private keyBuffer = new OutdatedKeyFilter();\n\n private logger: Logger | undefined = undefined;\n\n private readonly rtcIdentityProvider: (userId: string, deviceId: string, memberId: string) => Promise<string>;\n\n /**\n *\n * @param ownMembership - our own membership info\n * @param getMemberships - function to get current memberships\n * @param transport - key transport (room or to-device)\n * @param statistics - statistics collector\n * @param onEncryptionKeysChanged - callback to notify the media layer of new keys\n * @param parentLogger - optional parent logger\n * @param rtcBackendIdProvider - A function to compute the rtc backend identity, exposed for testing purposes\n */\n public constructor(\n private readonly ownMembership: CallMembershipIdentityParts,\n private getMemberships: () => CallMembership[],\n private transport: IKeyTransport,\n // Callback to notify the media layer of new keys\n private onEncryptionKeysChanged: (\n keyBin: Uint8Array<ArrayBuffer>,\n encryptionKeyIndex: number,\n membership: CallMembershipIdentityParts,\n rtcBackendIdentity: string,\n ) => void,\n parentLogger?: Logger,\n rtcBackendIdProvider?: (userId: string, deviceId: string, memberId: string) => Promise<string>,\n ) {\n this.logger = parentLogger?.getChild(`[EncryptionManager]`);\n this.rtcIdentityProvider = rtcBackendIdProvider ?? computeRtcIdentityRaw;\n }\n\n private async getOwnRtcBackendIdentity(): Promise<string> {\n if (this.ownRtcBackendIdentityCache) return this.ownRtcBackendIdentityCache;\n\n if (this.useHashedRtcBackendIdentity) {\n const { userId, deviceId, memberId } = this.ownMembership;\n this.logger?.info(\n // If we see this log multiple times, we need to reconsider the precompute call of getOwnRtcBackendIdentity\n `Computing RTC backend identity for ${userId}:${deviceId}:${memberId} (SHOULD ONLY BE CALLED ONCE)`,\n );\n this.ownRtcBackendIdentityCache = await this.rtcIdentityProvider(userId, deviceId, memberId);\n } else {\n this.ownRtcBackendIdentityCache = `${this.ownMembership.userId}:${this.ownMembership.deviceId}`;\n }\n return this.ownRtcBackendIdentityCache;\n }\n\n public getEncryptionKeys(): ReadonlyMap<\n EncryptionKeyMapKey,\n ReadonlyArray<{\n key: Uint8Array<ArrayBuffer>;\n keyIndex: number;\n membership: CallMembershipIdentityParts;\n rtcBackendIdentity: string;\n }>\n > {\n return new Map(this.participantKeyRings);\n }\n\n private keysWithoutMatchingRTCMembership: Array<{\n key: Uint8Array<ArrayBuffer>;\n keyIndex: number;\n membership: CallMembershipIdentityParts;\n }> = [];\n\n private checkKeysWithoutMatchingRTCMembership(): void {\n const keyInfoTemp = this.keysWithoutMatchingRTCMembership;\n this.keysWithoutMatchingRTCMembership = [];\n keyInfoTemp.forEach((keyInfo) => {\n this.addKeyToParticipant(keyInfo.key, keyInfo.keyIndex, keyInfo.membership);\n });\n }\n\n private addKeyToParticipant(\n key: Uint8Array<ArrayBuffer>,\n keyIndex: number,\n membership: CallMembershipIdentityParts,\n ): void {\n const knownRtcMembership = this.getMemberships();\n const fullMembership = knownRtcMembership.find(\n (member) => member.userId === membership.userId && member.deviceId === membership.deviceId,\n );\n if (!fullMembership) {\n this.logger?.info(\n `No matching RTC membership for key from ${membership.userId}:${membership.deviceId}, delaying key addition`,\n );\n this.keysWithoutMatchingRTCMembership.push({ key, keyIndex, membership });\n return;\n }\n this.addKeyToParticipantWithBackendIdentity(key, keyIndex, membership, fullMembership.rtcBackendIdentity);\n }\n\n private addKeyToParticipantWithBackendIdentity(\n key: Uint8Array<ArrayBuffer>,\n keyIndex: number,\n membership: CallMembershipIdentityParts,\n rtcBackendIdentity: string,\n ): void {\n const mapKey = getEncryptionKeyMapKey(membership);\n if (!this.participantKeyRings.has(mapKey)) {\n this.participantKeyRings.set(mapKey, []);\n }\n this.participantKeyRings.get(mapKey)!.push({ key, keyIndex, membership, rtcBackendIdentity });\n this.onEncryptionKeysChanged(key, keyIndex, membership, rtcBackendIdentity);\n }\n\n public join(joinConfig: (EncryptionConfig & MembershipConfig) | undefined): void {\n this.manageMediaKeys = joinConfig?.manageMediaKeys ?? true; // default to true\n this.useHashedRtcBackendIdentity = joinConfig?.unstableSendStickyEvents ?? false;\n this.useKeyDelay = joinConfig?.useKeyDelay ?? 1000;\n this.keyRotationGracePeriodMs = joinConfig?.keyRotationGracePeriodMs ?? 10_000;\n\n this.transport.on(KeyTransportEvents.ReceivedKeys, this.onNewKeyReceived);\n void this.getOwnRtcBackendIdentity(); // precompute own identity\n\n this.logger?.info(`Joining room`);\n this.transport.start();\n }\n\n public leave(): void {\n this.transport.off(KeyTransportEvents.ReceivedKeys, this.onNewKeyReceived);\n this.transport.stop();\n this.participantKeyRings.clear();\n }\n\n /**\n * Will ensure that a new key is distributed and used to encrypt our media.\n * If there is already a key distribution in progress, it will schedule a new distribution round just after the current one is completed.\n * If this function is called repeatedly while a distribution is in progress,\n * the calls will be coalesced to a single new distribution (that will start just after the current one has completed).\n */\n private ensureKeyDistribution(): void {\n // `manageMediaKeys` is a stop-gap solution for now. The preferred way to handle this case would be instead\n // to create a NoOpEncryptionManager that does nothing and use it for the session.\n // This will be done when removing the legacy EncryptionManager.\n if (!this.manageMediaKeys) return;\n if (this.currentKeyDistributionPromise == null) {\n this.logger?.debug(`No active rollout, start a new one`);\n // start a rollout\n this.currentKeyDistributionPromise = this.rolloutOutboundKey().then(() => {\n this.logger?.debug(`Rollout completed`);\n this.currentKeyDistributionPromise = null;\n if (this.needToEnsureKeyAgain) {\n this.logger?.debug(`New Rollout needed`);\n this.needToEnsureKeyAgain = false;\n // rollout a new one\n this.ensureKeyDistribution();\n }\n });\n } else {\n // There is a rollout in progress, but a key rotation is requested (could be caused by a ownMembership change)\n // Remember that a new rotation is needed after the current one.\n this.logger?.debug(`Rollout in progress, a new rollout will be started after the current one`);\n this.needToEnsureKeyAgain = true;\n }\n }\n\n public onNewKeyReceived: KeyTransportEventListener = (membership, keyBase64Encoded, index, timestamp) => {\n // `manageMediaKeys` is a stop-gap solution for now. The preferred way to handle this case would be instead\n // to create a NoOpEncryptionManager that does nothing and use it for the session.\n // This will be done when removing the legacy EncryptionManager.\n if (!this.manageMediaKeys) {\n this.logger?.warn(\n `Received key over transport ${membership.userId}:${membership.deviceId} at index ${index} but media keys are disabled`,\n );\n return;\n }\n this.logger?.debug(`Received key over transport ${membership.userId}:${membership.deviceId} at index ${index}`);\n\n // We received a new key, notify the video layer of this new key so that it can decrypt the frames properly.\n const keyBin = decodeBase64(keyBase64Encoded);\n const candidateInboundSession: InboundEncryptionSession = {\n key: keyBin,\n membership,\n keyIndex: index,\n creationTS: timestamp,\n };\n\n const outdated = this.keyBuffer.isOutdated(membership, candidateInboundSession);\n if (!outdated) {\n this.addKeyToParticipant(\n candidateInboundSession.key,\n candidateInboundSession.keyIndex,\n candidateInboundSession.membership,\n );\n } else {\n this.logger?.info(\n `Received an out of order key for ${membership.userId}:${membership.deviceId}, dropping it`,\n );\n }\n };\n\n /**\n * Called when the ownMembership of the call changes.\n * This encryption manager is very basic, it will rotate the key everytime this is called.\n * @param oldMemberships - This parameter is not used here, but it is kept for compatibility with the interface.\n */\n public onMembershipsUpdate(oldMemberships: CallMembership[] = []): void {\n this.logger?.trace(`onMembershipsUpdate`);\n\n // Ensure the key is distributed. This will be no-op if the key is already being distributed to everyone.\n // If there is an ongoing distribution, it will be completed before a new one is started.\n this.ensureKeyDistribution();\n // ensure key emission to the rtc backend\n this.checkKeysWithoutMatchingRTCMembership();\n }\n\n private async rolloutOutboundKey(): Promise<void> {\n const isFirstKey = this.outboundSession == null;\n if (isFirstKey) {\n // create the first key\n const firstKey = {\n key: this.generateRandomKey(),\n creationTS: Date.now(),\n sharedWith: [],\n keyId: 0,\n };\n this.outboundSession = firstKey;\n this.addKeyToParticipantWithBackendIdentity(\n firstKey.key,\n firstKey.keyId,\n this.ownMembership,\n await this.getOwnRtcBackendIdentity(),\n );\n }\n // get current memberships\n const toShareWith: ParticipantDeviceInfo[] = this.getMemberships()\n .filter((membership) => {\n return membership.sender != undefined;\n })\n .map((membership) => {\n return {\n userId: membership.sender!,\n deviceId: membership.deviceId,\n membershipTs: membership.createdTs(),\n };\n });\n\n let alreadySharedWith = this.outboundSession?.sharedWith ?? [];\n\n // Some users might have rotate their ownMembership event (formally called fingerprint) meaning they might have\n // clear their key. Reset the `alreadySharedWith` flag for them.\n alreadySharedWith = alreadySharedWith.filter(\n (x) =>\n // If there was a member with same userId and deviceId but different membershipTs, we need to clear it\n !toShareWith.some(\n (o) => x.userId == o.userId && x.deviceId == o.deviceId && x.membershipTs != o.membershipTs,\n ),\n );\n\n const anyLeft = alreadySharedWith.filter(\n (x) =>\n !toShareWith.some(\n (o) => x.userId == o.userId && x.deviceId == o.deviceId && x.membershipTs == o.membershipTs,\n ),\n );\n const anyJoined = toShareWith.filter(\n (x) =>\n !alreadySharedWith.some(\n (o) => x.userId == o.userId && x.deviceId == o.deviceId && x.membershipTs == o.membershipTs,\n ),\n );\n\n let toDistributeTo: ParticipantDeviceInfo[] = [];\n let outboundKey: OutboundEncryptionSession;\n let hasKeyChanged = false;\n if (anyLeft.length > 0) {\n // We need to rotate the key\n const newOutboundKey = this.createNewOutboundSession();\n hasKeyChanged = true;\n toDistributeTo = toShareWith;\n outboundKey = newOutboundKey;\n } else if (anyJoined.length > 0) {\n const now = Date.now();\n const keyAge = now - this.outboundSession!.creationTS;\n // If the current key is recently created (less than `keyRotationGracePeriodMs`), we can keep it and just distribute it to the new joiners.\n if (keyAge < this.keyRotationGracePeriodMs) {\n // keep the same key\n // XXX In the future we want to distribute a ratcheted key, not the current one\n this.logger?.debug(`New joiners detected, but the key is recent enough (age:${keyAge}), keeping it`);\n toDistributeTo = anyJoined;\n outboundKey = this.outboundSession!;\n } else {\n // We need to rotate the key\n this.logger?.debug(`New joiners detected, rotating the key`);\n const newOutboundKey = this.createNewOutboundSession();\n hasKeyChanged = true;\n toDistributeTo = toShareWith;\n outboundKey = newOutboundKey;\n }\n } else {\n // no changes\n return;\n }\n\n try {\n this.logger?.trace(`Sending key...`);\n await this.transport.sendKey(encodeBase64(outboundKey.key), outboundKey.keyId, toDistributeTo);\n outboundKey.sharedWith.push(...toDistributeTo);\n this.logger?.trace(\n `key index:${outboundKey.keyId} sent to ${outboundKey.sharedWith.map((m) => `${m.userId}:${m.deviceId}`).join(\",\")}`,\n );\n if (hasKeyChanged) {\n // Delay a bit before using this key\n // It is recommended not to start using a key immediately but instead wait for a short time to make sure it is delivered.\n this.logger?.trace(`Delay Rollout for key:${outboundKey.keyId}...`);\n await sleep(this.useKeyDelay);\n this.logger?.trace(`...Delayed rollout of index:${outboundKey.keyId} `);\n this.addKeyToParticipantWithBackendIdentity(\n outboundKey.key,\n outboundKey.keyId,\n this.ownMembership,\n await this.getOwnRtcBackendIdentity(),\n );\n }\n } catch (err) {\n this.logger?.error(`Failed to rollout key`, err);\n }\n }\n\n private createNewOutboundSession(): OutboundEncryptionSession {\n const newOutboundKey: OutboundEncryptionSession = {\n key: this.generateRandomKey(),\n creationTS: Date.now(),\n sharedWith: [],\n keyId: this.nextKeyIndex(),\n };\n\n this.logger?.info(`creating new outbound key index:${newOutboundKey.keyId}`);\n // Set this new key as the current one\n this.outboundSession = newOutboundKey;\n return newOutboundKey;\n }\n\n private nextKeyIndex(): number {\n if (this.outboundSession) {\n return (this.outboundSession!.keyId + 1) % 256;\n }\n return 0;\n }\n\n private generateRandomKey(): Uint8Array<ArrayBuffer> {\n const key = new Uint8Array(16);\n globalThis.crypto.getRandomValues(key);\n return key;\n }\n}\n","/*\nCopyright 2025 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 WidgetApiResponseError } from \"matrix-widget-api\";\n\nimport { TypedEventEmitter } from \"../models/typed-event-emitter.ts\";\nimport { type IKeyTransport, KeyTransportEvents, type KeyTransportEventsHandlerMap } from \"./IKeyTransport.ts\";\nimport { type Logger, logger as rootLogger } from \"../logger.ts\";\nimport { type EncryptionKeysToDeviceEventContent, type ParticipantDeviceInfo, type Statistics } from \"./types.ts\";\nimport { ClientEvent, type MatrixClient } from \"../client.ts\";\nimport type { MatrixEvent } from \"../models/event.ts\";\nimport { EventType } from \"../@types/event.ts\";\nimport { type CallMembershipIdentityParts } from \"./EncryptionManager.ts\";\n\nexport class NotSupportedError extends Error {\n public constructor(message?: string) {\n super(message);\n }\n public get name(): string {\n return \"NotSupportedError\";\n }\n}\n/**\n * ToDeviceKeyTransport is used to send MatrixRTC keys to other devices using the\n * to-device CS-API.\n */\nexport class ToDeviceKeyTransport\n extends TypedEventEmitter<KeyTransportEvents, KeyTransportEventsHandlerMap>\n implements IKeyTransport\n{\n private logger: Logger = rootLogger;\n\n public setParentLogger(parentLogger: Logger): void {\n this.logger = parentLogger.getChild(`[ToDeviceKeyTransport]`);\n }\n\n public constructor(\n private membership: CallMembershipIdentityParts,\n private roomId: string,\n private client: Pick<MatrixClient, \"encryptAndSendToDevice\" | \"on\" | \"off\">,\n private statistics: Statistics,\n parentLogger?: Logger,\n ) {\n super();\n this.setParentLogger(parentLogger ?? rootLogger);\n }\n\n public start(): void {\n this.client.on(ClientEvent.ToDeviceEvent, this.onToDeviceEvent);\n }\n\n public stop(): void {\n this.client.off(ClientEvent.ToDeviceEvent, this.onToDeviceEvent);\n }\n\n public async sendKey(keyBase64Encoded: string, index: number, members: ParticipantDeviceInfo[]): Promise<void> {\n const content: EncryptionKeysToDeviceEventContent = {\n keys: {\n index: index,\n key: keyBase64Encoded,\n },\n room_id: this.roomId,\n member: {\n claimed_device_id: this.membership.deviceId,\n id: this.membership.memberId,\n },\n session: {\n call_id: \"\",\n application: \"m.call\",\n scope: \"m.room\",\n },\n sent_ts: Date.now(),\n };\n\n const targets = members\n .map((member) => {\n return {\n userId: member.userId!,\n deviceId: member.deviceId!,\n };\n })\n // filter out me\n .filter(\n (member) => !(member.userId == this.membership.userId && member.deviceId == this.membership.deviceId),\n );\n\n if (targets.length > 0) {\n await this.client\n .encryptAndSendToDevice(EventType.CallEncryptionKeysPrefix, targets, content)\n .catch((error: WidgetApiResponseError) => {\n const msg: string = error.message;\n // This is not ideal. We would want to have a custom error type for unsupported actions.\n // This is not part of the widget API spec. Since as of now there are only two implementations:\n // Rust SDK + JS-SDK, and the JS-SDK does support to-device sending, we can assume that\n // this is a widget driver issue error message.\n if (\n (msg.includes(\"unknown variant\") && msg.includes(\"send_to_device\")) ||\n msg.includes(\"not supported\")\n ) {\n throw new NotSupportedError(\"The widget driver does not support to-device encryption\");\n }\n });\n this.statistics.counters.roomEventEncryptionKeysSent += 1;\n } else {\n this.logger.warn(\"No targets found for sending key\");\n }\n }\n\n private receiveCallKeyEvent(fromUser: string, content: EncryptionKeysToDeviceEventContent): void {\n // The event has already been validated at this point.\n\n this.statistics.counters.roomEventEncryptionKeysReceived += 1;\n\n // What is this, and why is it needed?\n // Also to device events do not have an origin server ts\n const now = Date.now();\n const age = now - (typeof content.sent_ts === \"number\" ? content.sent_ts : now);\n this.statistics.totals.roomEventEncryptionKeysReceivedTotalAge += age;\n\n const hardcodedMemberIdAlternative = `${fromUser}:${content.member.claimed_device_id}`;\n\n this.emit(\n KeyTransportEvents.ReceivedKeys,\n // TODO userId this is claimed information, deviceId is claimed information\n {\n userId: fromUser,\n deviceId: content.member.claimed_device_id!,\n memberId: content.member.id ?? hardcodedMemberIdAlternative,\n },\n content.keys.key,\n content.keys.index,\n now,\n );\n }\n\n private onToDeviceEvent = (event: MatrixEvent): void => {\n if (event.getType() !== EventType.CallEncryptionKeysPrefix) {\n // Ignore this is not a call encryption event\n return;\n }\n\n // TODO: Not possible to check if the event is encrypted or not\n // see https://github.com/matrix-org/matrix-rust-sdk/issues/4883\n // if (evnt.getWireType() != EventType.RoomMessageEncrypted) {\n // // WARN: The call keys were sent in clear. Ignore them\n // logger.warn(`Call encryption keys sent in clear from: ${event.getSender()}`);\n // return;\n // }\n\n const content = this.getValidEventContent(event);\n if (!content) return;\n\n if (!event.getSender()) return;\n\n this.receiveCallKeyEvent(event.getSender()!, content);\n };\n\n private getValidEventContent(event: MatrixEvent): EncryptionKeysToDeviceEventContent | undefined {\n const content = event.getContent();\n const roomId = content.room_id;\n if (!roomId) {\n // Invalid event\n this.logger.warn(\"Malformed Event: invalid call encryption keys event, no roomId\");\n return;\n }\n if (roomId !== this.roomId) {\n this.logger.warn(\"Malformed Event: Mismatch roomId\");\n return;\n }\n\n if (!content.keys || !content.keys.key || typeof content.keys.index !== \"number\") {\n this.logger.warn(\"Malformed Event: Missing keys field\");\n return;\n }\n\n if (!content.member || !content.member.claimed_device_id) {\n this.logger.warn(\"Malformed Event: Missing claimed_device_id\");\n return;\n }\n\n // TODO check for session related fields once the to-device encryption uses the new format.\n return content as EncryptionKeysToDeviceEventContent;\n }\n}\n","/*\nCopyright 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\n/**\n * Thrown when an event is not valid for use with MatrixRTC.\n */\nexport class MatrixRTCMembershipParseError extends AggregateError {\n public constructor(\n public readonly type: string,\n errors: string[],\n ) {\n super(errors, `Does not match ${type}:\\n${errors.join(\"\\n\")}`);\n }\n}\n","/*\nCopyright 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 IContent } from \"../../matrix.ts\";\nimport { type RTCCallIntent, type Transport } from \"../types.ts\";\nimport { MatrixRTCMembershipParseError } from \"./common.ts\";\n\n/**\n * (MatrixRTC) session membership data.\n * This represents the *OLD* form of MSC4143, which uses state events to store membership.\n * Represents the `session` in the memberships section of an m.call.member event as it is on the wire.\n **/\nexport type SessionMembershipData = {\n /**\n * The RTC application defines the type of the RTC session.\n */\n \"application\": string;\n\n /**\n * The id of this session.\n * A session can never span over multiple rooms so this id is to distinguish between\n * multiple session in one room. A room wide session that is not associated with a user,\n * and therefore immune to creation race conflicts, uses the `call_id: \"\"`.\n */\n \"call_id\": string;\n\n /**\n * The Matrix device ID of this session. A single user can have multiple sessions on different devices.\n */\n \"device_id\": string;\n\n /**\n * The focus selection system this user/membership is using.\n * NOTE: This is still included for legacy reasons, but not consumed by the SDK.\n */\n \"focus_active\": {\n type: \"livekit\" | string;\n focus_selection: \"oldest_membership\" | \"multi_sfu\" | string;\n };\n\n /**\n * A list of possible foci this user knows about. One of them might be used based on the focus_active\n * selection system.\n */\n \"foci_preferred\": Transport[];\n\n /**\n * Optional field that contains the creation of the session. If it is undefined the creation\n * is the `origin_server_ts` of the event itself. For updates to the event this property tracks\n * the `origin_server_ts` of the initial join event.\n * - If it is undefined it can be interpreted as a \"Join\".\n * - If it is defined it can be interpreted as an \"Update\"\n */\n \"created_ts\"?: number;\n\n // Application specific data\n\n /**\n * If the `application` = `\"m.call\"` this defines if it is a room or user owned call.\n * There can always be one room scoped call but multiple user owned calls (breakout sessions)\n */\n \"scope\"?: \"m.room\" | \"m.user\";\n\n /**\n * Optionally we allow to define a delta to the `created_ts` that defines when the event is expired/invalid.\n * This should be set to multiple hours. The only reason it exist is to deal with failed delayed events.\n * (for example caused by a homeserver crashes)\n **/\n \"expires\"?: number;\n\n /**\n * The intent of the call from the perspective of this user. This may be an audio call, video call or\n * something else.\n */\n \"m.call.intent\"?: RTCCallIntent;\n\n /**\n * The id used on the media backend.\n * (With livekit this is the participant identity on the LK SFU)\n * This can be a UUID but right now it is `${this.matrixEventData.sender}:${data.device_id}`.\n *\n * It is compleatly valid to not set this field. Other clients will treat `undefined` as `${this.matrixEventData.sender}:${data.device_id}`\n */\n \"membershipID\"?: string;\n};\n\n/**\n * Validates that `data` matches the format expected by the legacy form of MSC4143.\n * @param data The event content.\n * @returns true if `data` is valid SessionMembershipData\n * @throws {MatrixRTCMembershipParseError} if the content is not valid\n */\nexport const checkSessionsMembershipData = (data: IContent): data is SessionMembershipData => {\n const prefix = \" - \";\n const errors: string[] = [];\n if (typeof data.device_id !== \"string\") errors.push(prefix + \"device_id must be string\");\n if (typeof data.call_id !== \"string\") errors.push(prefix + \"call_id must be string\");\n if (typeof data.application !== \"string\") errors.push(prefix + \"application must be a string\");\n if (data.focus_active === undefined) {\n errors.push(prefix + \"focus_active has an invalid type\");\n }\n if (typeof data.focus_active?.type !== \"string\") {\n errors.push(prefix + \"focus_active.type must be a string\");\n }\n if (\n data.foci_preferred !== undefined &&\n !(\n Array.isArray(data.foci_preferred) &&\n data.foci_preferred.every(\n (f: Transport) => typeof f === \"object\" && f !== null && typeof f.type === \"string\",\n )\n )\n ) {\n errors.push(prefix + \"foci_preferred must be an array of transport objects\");\n }\n // optional parameters\n if (data.created_ts !== undefined && typeof data.created_ts !== \"number\") {\n errors.push(prefix + \"created_ts must be number\");\n }\n\n // application specific data (we first need to check if they exist)\n if (data.scope !== undefined && typeof data.scope !== \"string\") errors.push(prefix + \"scope must be string\");\n\n if (data[\"m.call.intent\"] !== undefined && typeof data[\"m.call.intent\"] !== \"string\") {\n errors.push(prefix + \"m.call.intent must be a string\");\n }\n\n if (errors.length) {\n throw new MatrixRTCMembershipParseError(\"SessionMembership\", errors);\n }\n\n return true;\n};\n","/*\nCopyright 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 { MXID_PATTERN } from \"../../models/room-member.ts\";\nimport type { IContent } from \"../../models/event.ts\";\nimport type { RelationType } from \"../../types.ts\";\nimport { type RtcSlotEventContent, type Transport } from \"../types.ts\";\nimport { MatrixRTCMembershipParseError } from \"./common.ts\";\nimport { sha256 } from \"../../digest.ts\";\nimport { encodeUnpaddedBase64 } from \"../../base64.ts\";\nimport { slotIdToDescription } from \"../utils.ts\";\n\n/**\n * Represents the current form of MSC4143, which uses sticky events to store membership.\n */\nexport interface RtcMembershipData {\n \"slot_id\": string;\n \"member\": {\n user_id: string;\n device_id: string;\n id: string;\n };\n \"m.relates_to\"?: {\n event_id: string;\n rel_type: RelationType.Reference;\n };\n \"application\": RtcSlotEventContent[\"application\"];\n \"rtc_transports\": Transport[];\n \"versions\": string[];\n \"msc4354_sticky_key\"?: string;\n \"sticky_key\"?: string;\n}\n\n/**\n * Validates that `data` matches the format expected by MSC4143.\n * @param data The event content.\n * @param sender The sender of the event.\n * @returns true if `data` is valid RtcMembershipData\n * @throws {MatrixRTCMembershipParseError} if the content is not valid\n */\nexport const checkRtcMembershipData = (data: IContent, sender: string): data is RtcMembershipData => {\n const errors: string[] = [];\n const prefix = \" - \";\n const expectedSlotPrefix = `${data?.application?.type}#`;\n\n // required fields\n if (typeof data.slot_id !== \"string\") {\n errors.push(prefix + \"slot_id must be string\");\n } else if (!data.slot_id.startsWith(expectedSlotPrefix)) {\n errors.push(prefix + `slot_id must start with ${expectedSlotPrefix}`);\n } else {\n try {\n slotIdToDescription(data.slot_id);\n } catch (ex) {\n errors.push(prefix + `slot_id was badly formed${ex instanceof Error ? `: ${ex.message}` : \"\"}`);\n }\n }\n\n if (typeof data.member !== \"object\" || data.member === null) {\n errors.push(prefix + \"member must be an object\");\n } else {\n if (typeof data.member.user_id !== \"string\") {\n errors.push(prefix + \"member.user_id must be string\");\n } else if (!MXID_PATTERN.test(data.member.user_id)) {\n errors.push(prefix + \"member.user_id must be a valid mxid\");\n }\n // This is not what the spec enforces but there currently are no rules what power levels are required to\n // send a m.rtc.member event for a other user. So we add this check for simplicity and to avoid possible attacks until there\n // is a proper definition when this is allowed.\n else if (data.member.user_id !== sender) {\n errors.push(prefix + \"member.user_id must match the sender\");\n }\n if (typeof data.member.device_id !== \"string\") {\n errors.push(prefix + \"member.device_id must be string\");\n }\n if (typeof data.member.id !== \"string\") errors.push(prefix + \"member.id must be string\");\n }\n if (typeof data.application !== \"object\" || data.application === null) {\n errors.push(prefix + \"application must be an object\");\n } else {\n if (typeof data.application.type !== \"string\") {\n errors.push(prefix + \"application.type must be a string\");\n } else {\n if (data.application.type.includes(\"#\")) errors.push(prefix + 'application.type must not include \"#\"');\n }\n }\n if (data.rtc_transports === undefined || !Array.isArray(data.rtc_transports)) {\n errors.push(prefix + \"rtc_transports must be an array\");\n } else {\n // validate that each transport has at least a string 'type'\n for (const t of data.rtc_transports) {\n if (typeof t !== \"object\" || t === null || typeof (t as any).type !== \"string\") {\n errors.push(prefix + \"rtc_transports entries must be objects with a string type\");\n break;\n }\n }\n }\n if (data.versions === undefined || !Array.isArray(data.versions)) {\n errors.push(prefix + \"versions must be an array\");\n } else if (!data.versions.every((v) => typeof v === \"string\")) {\n errors.push(prefix + \"versions must be an array of strings\");\n }\n\n // optional fields\n if ((data.sticky_key ?? data.msc4354_sticky_key) === undefined) {\n errors.push(prefix + \"sticky_key or msc4354_sticky_key must be a defined\");\n }\n if (data.sticky_key !== undefined && typeof data.sticky_key !== \"string\") {\n errors.push(prefix + \"sticky_key must be a string\");\n }\n if (data.msc4354_sticky_key !== undefined && typeof data.msc4354_sticky_key !== \"string\") {\n errors.push(prefix + \"msc4354_sticky_key must be a string\");\n }\n if (\n data.sticky_key !== undefined &&\n data.msc4354_sticky_key !== undefined &&\n data.sticky_key !== data.msc4354_sticky_key\n ) {\n errors.push(prefix + \"sticky_key and msc4354_sticky_key must be equal if both are defined\");\n }\n if (data[\"m.relates_to\"] !== undefined) {\n const rel = data[\"m.relates_to\"] as RtcMembershipData[\"m.relates_to\"];\n if (typeof rel !== \"object\" || rel === null) {\n errors.push(prefix + \"m.relates_to must be an object if provided\");\n } else {\n if (typeof rel.event_id !== \"string\") errors.push(prefix + \"m.relates_to.event_id must be a string\");\n if (rel.rel_type !== \"m.reference\") errors.push(prefix + \"m.relates_to.rel_type must be m.reference\");\n }\n }\n\n if (errors.length) {\n throw new MatrixRTCMembershipParseError(\"RtcMembership\", errors);\n }\n\n return true;\n};\n\nexport async function computeRtcIdentityRaw(userId: string, deviceId: string, memberId: string): Promise<string> {\n // canonical JSON serialization (Matrix canonical JSON for arrays)\n const jsonStr = JSON.stringify([userId, deviceId, memberId]);\n const hashBuffer = await sha256(jsonStr);\n const hashedString = encodeUnpaddedBase64(hashBuffer);\n return hashedString;\n}\n","/*\nCopyright 2025-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 { getEncryptionKeyMapKey, type CallMembershipIdentityParts } from \"./EncryptionManager.ts\";\nimport type { InboundEncryptionSession, EncryptionKeyMapKey, SlotDescription } from \"./types.ts\";\n\n/**\n * Detects when a key for a given index is outdated.\n */\nexport class OutdatedKeyFilter {\n // Map of participantId -> keyIndex -> timestamp\n private tsBuffer: Map<EncryptionKeyMapKey, Map<number, number>> = new Map();\n\n public constructor() {}\n\n /**\n * Check if there is a recent key with the same keyId (index) and then use the creationTS to decide what to\n * do with the key. If the key received is older than the one already in the buffer, it is ignored.\n * @param participantId\n * @param item\n */\n public isOutdated(membership: CallMembershipIdentityParts, item: InboundEncryptionSession): boolean {\n const mapKey = getEncryptionKeyMapKey(membership);\n if (!this.tsBuffer.has(mapKey)) {\n this.tsBuffer.set(mapKey, new Map<number, number>());\n }\n\n const latestTimestamp = this.tsBuffer.get(mapKey)?.get(item.keyIndex);\n if (latestTimestamp && latestTimestamp > item.creationTS) {\n // The existing key is more recent, ignore this one\n return true;\n }\n this.tsBuffer.get(mapKey)!.set(item.keyIndex, item.creationTS);\n return false;\n }\n}\n\n/**\n * Converts a slot ID into it's component application and ID portions.\n * @param slotId e.g. `m.call#call_id`\n * @throws If the format of `slotId` is invalid.\n */\nexport function slotIdToDescription(slotId: string): SlotDescription {\n const [application, id, ...unexpectedAdditionalValues] = slotId.split(\"#\");\n if (unexpectedAdditionalValues.length) {\n throw Error(\n \"MatrixRTC Slot IDs *must* only contain two components seperated by one '#'. Additional '#' characters detected.\",\n );\n }\n return { application, id };\n}\n\n/**\n * Converts a SlotDescription into it's slot ID format.\n */\nexport function computeSlotId(slotDescription: SlotDescription): string {\n return `${slotDescription.application}#${slotDescription.id}`;\n}\n","/*\nCopyright 2021 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 MatrixClient } from \"../client.ts\";\nimport { RelationType, UNSTABLE_MSC3089_BRANCH } from \"../@types/event.ts\";\nimport { type IContent, type MatrixEvent } from \"./event.ts\";\nimport { type MSC3089TreeSpace } from \"./MSC3089TreeSpace.ts\";\nimport { EventTimeline } from \"./event-timeline.ts\";\nimport { type FileType } from \"../http-api/index.ts\";\nimport type { ISendEventResponse } from \"../@types/requests.ts\";\nimport { type EncryptedFile } from \"../@types/media.ts\";\n\nexport interface MSC3089EventContent {\n active?: boolean;\n name?: string;\n locked?: boolean;\n version?: number;\n}\n\nexport interface MSC3089EventContent {\n active?: boolean;\n name?: string;\n locked?: boolean;\n version?: number;\n}\n\n/**\n * Represents a [MSC3089](https://github.com/matrix-org/matrix-doc/pull/3089) branch - a reference\n * to a file (leaf) in the tree. Note that this is UNSTABLE and subject to breaking changes\n * without notice.\n */\nexport class MSC3089Branch {\n public constructor(\n private client: MatrixClient,\n public readonly indexEvent: MatrixEvent,\n public readonly directory: MSC3089TreeSpace,\n ) {\n // Nothing to do\n }\n\n /**\n * The file ID.\n */\n public get id(): string {\n const stateKey = this.indexEvent.getStateKey();\n if (!stateKey) {\n throw new Error(\"State key not found for branch\");\n }\n return stateKey;\n }\n\n /**\n * Whether this branch is active/valid.\n */\n public get isActive(): boolean {\n return this.indexEvent.getContent()[\"active\"] === true;\n }\n\n /**\n * Version for the file, one-indexed.\n */\n public get version(): number {\n return this.indexEvent.getContent()[\"version\"] ?? 1;\n }\n\n private get roomId(): string {\n return this.indexEvent.getRoomId()!;\n }\n\n /**\n * Deletes the file from the tree, including all prior edits/versions.\n * @returns Promise which resolves when complete.\n */\n public async delete(): Promise<void> {\n await this.client.sendStateEvent(this.roomId, UNSTABLE_MSC3089_BRANCH.name, {}, this.id);\n await this.client.redactEvent(this.roomId, this.id);\n\n const nextVersion = (await this.getVersionHistory())[1]; // [0] will be us\n if (nextVersion) await nextVersion.delete(); // implicit recursion\n }\n\n /**\n * Gets the name for this file.\n * @returns The name, or \"Unnamed File\" if unknown.\n */\n public getName(): string {\n return this.indexEvent.getContent()[\"name\"] || \"Unnamed File\";\n }\n\n /**\n * Sets the name for this file.\n * @param name - The new name for this file.\n * @returns Promise which resolves when complete.\n */\n public async setName(name: string): Promise<void> {\n await this.client.sendStateEvent(\n this.roomId,\n UNSTABLE_MSC3089_BRANCH.name,\n {\n ...this.indexEvent.getContent(),\n name: name,\n },\n this.id,\n );\n }\n\n /**\n * Gets whether or not a file is locked.\n * @returns True if locked, false otherwise.\n */\n public isLocked(): boolean {\n return this.indexEvent.getContent()[\"locked\"] || false;\n }\n\n /**\n * Sets a file as locked or unlocked.\n * @param locked - True to lock the file, false otherwise.\n * @returns Promise which resolves when complete.\n */\n public async setLocked(locked: boolean): Promise<void> {\n await this.client.sendStateEvent(\n this.roomId,\n UNSTABLE_MSC3089_BRANCH.name,\n {\n ...this.indexEvent.getContent(),\n locked: locked,\n },\n this.id,\n );\n }\n\n /**\n * Gets information about the file needed to download it.\n * @returns Information about the file.\n */\n public async getFileInfo(): Promise<{ info: EncryptedFile; httpUrl: string }> {\n const event = await this.getFileEvent();\n\n const file = event.getOriginalContent()[\"file\"];\n const httpUrl = this.client.mxcUrlToHttp(file[\"url\"]);\n\n if (!httpUrl) {\n throw new Error(`No HTTP URL available for ${file[\"url\"]}`);\n }\n\n return { info: file, httpUrl: httpUrl };\n }\n\n /**\n * Gets the event the file points to.\n * @returns Promise which resolves to the file's event.\n */\n public async getFileEvent(): Promise<MatrixEvent> {\n const room = this.client.getRoom(this.roomId);\n if (!room) throw new Error(\"Unknown room\");\n\n let event: MatrixEvent | undefined = room.getUnfilteredTimelineSet().findEventById(this.id);\n\n // keep scrolling back if needed until we find the event or reach the start of the room:\n while (!event && room.getLiveTimeline().getState(EventTimeline.BACKWARDS)!.paginationToken) {\n await this.client.scrollback(room, 100);\n event = room.getUnfilteredTimelineSet().findEventById(this.id);\n }\n\n if (!event) throw new Error(\"Failed to find event\");\n\n // Sometimes the event isn't decrypted for us, so do that.\n await this.client.decryptEventIfNeeded(event);\n\n return event;\n }\n\n /**\n * Creates a new version of this file with contents in a type that is compatible with MatrixClient.uploadContent().\n * @param name - The name of the file.\n * @param encryptedContents - The encrypted contents.\n * @param info - The encrypted file information.\n * @param additionalContent - Optional event content fields to include in the message.\n * @returns Promise which resolves to the file event's sent response.\n */\n public async createNewVersion(\n name: string,\n encryptedContents: FileType,\n info: EncryptedFile,\n additionalContent?: IContent,\n ): Promise<ISendEventResponse> {\n const fileEventResponse = await this.directory.createFile(name, encryptedContents, info, {\n ...additionalContent,\n \"m.new_content\": true,\n \"m.relates_to\": {\n rel_type: RelationType.Replace,\n event_id: this.id,\n },\n });\n\n // Update the version of the new event\n await this.client.sendStateEvent(\n this.roomId,\n UNSTABLE_MSC3089_BRANCH.name,\n {\n active: true,\n name: name,\n version: this.version + 1,\n },\n fileEventResponse[\"event_id\"],\n );\n\n // Deprecate ourselves\n await this.client.sendStateEvent(\n this.roomId,\n UNSTABLE_MSC3089_BRANCH.name,\n {\n ...this.indexEvent.getContent(),\n active: false,\n },\n this.id,\n );\n\n return fileEventResponse;\n }\n\n /**\n * Gets the file's version history, starting at this file.\n * @returns Promise which resolves to the file's version history, with the\n * first element being the current version and the last element being the first version.\n */\n public async getVersionHistory(): Promise<MSC3089Branch[]> {\n const fileHistory: MSC3089Branch[] = [];\n fileHistory.push(this); // start with ourselves\n\n const room = this.client.getRoom(this.roomId);\n if (!room) throw new Error(\"Invalid or unknown room\");\n\n // Clone the timeline to reverse it, getting most-recent-first ordering, hopefully\n // shortening the awful loop below. Without the clone, we can unintentionally mutate\n // the timeline.\n const timelineEvents = [...room.getLiveTimeline().getEvents()].reverse();\n\n // XXX: This is a very inefficient search, but it's the best we can do with the\n // relations structure we have in the SDK. As of writing, it is not worth the\n // investment in improving the structure.\n let childEvent: MatrixEvent | undefined;\n let parentEvent = await this.getFileEvent();\n do {\n childEvent = timelineEvents.find((e) => e.replacingEventId() === parentEvent.getId());\n if (childEvent) {\n const branch = this.directory.getFile(childEvent.getId()!);\n if (branch) {\n fileHistory.push(branch);\n parentEvent = childEvent;\n } else {\n break; // prevent infinite loop\n }\n }\n } while (childEvent);\n\n return fileHistory;\n }\n}\n","/*\nCopyright 2021 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 MatrixClient } from \"../client.ts\";\nimport { EventType, MsgType, UNSTABLE_MSC3089_BRANCH, UNSTABLE_MSC3089_LEAF } from \"../@types/event.ts\";\nimport { type Room } from \"./room.ts\";\nimport { logger } from \"../logger.ts\";\nimport { type IContent, type MatrixEvent } from \"./event.ts\";\nimport {\n averageBetweenStrings,\n DEFAULT_ALPHABET,\n lexicographicCompare,\n nextString,\n prevString,\n simpleRetryOperation,\n} from \"../utils.ts\";\nimport { MSC3089Branch } from \"./MSC3089Branch.ts\";\nimport { type ISendEventResponse } from \"../@types/requests.ts\";\nimport { type FileType, MatrixError } from \"../http-api/index.ts\";\nimport { KnownMembership } from \"../@types/membership.ts\";\nimport { type RoomPowerLevelsEventContent, type SpaceChildEventContent } from \"../@types/state_events.ts\";\nimport type { EncryptedFile, FileContent } from \"../@types/media.ts\";\nimport { type EmptyObject } from \"../@types/common.ts\";\n\n/**\n * The recommended defaults for a tree space's power levels. Note that this\n * is UNSTABLE and subject to breaking changes without notice.\n */\nexport const DEFAULT_TREE_POWER_LEVELS_TEMPLATE = {\n // Owner\n invite: 100,\n kick: 100,\n ban: 100,\n\n // Editor\n redact: 50,\n state_default: 50,\n events_default: 50,\n\n // Viewer\n users_default: 0,\n\n // Mixed\n events: {\n [EventType.RoomPowerLevels]: 100,\n [EventType.RoomHistoryVisibility]: 100,\n [EventType.RoomTombstone]: 100,\n [EventType.RoomEncryption]: 100,\n [EventType.RoomName]: 50,\n [EventType.RoomMessage]: 50,\n [EventType.RoomMessageEncrypted]: 50,\n [EventType.Sticker]: 50,\n },\n\n users: {}, // defined by calling code\n};\n\n/**\n * Ease-of-use representation for power levels represented as simple roles.\n * Note that this is UNSTABLE and subject to breaking changes without notice.\n */\nexport enum TreePermissions {\n Viewer = \"viewer\", // Default\n Editor = \"editor\", // \"Moderator\" or ~PL50\n Owner = \"owner\", // \"Admin\" or PL100\n}\n\ndeclare module \"../@types/media\" {\n interface FileContent {\n [UNSTABLE_MSC3089_LEAF.name]?: EmptyObject;\n }\n}\n\n/**\n * Represents a [MSC3089](https://github.com/matrix-org/matrix-doc/pull/3089)\n * file tree Space. Note that this is UNSTABLE and subject to breaking changes\n * without notice.\n */\nexport class MSC3089TreeSpace {\n public readonly room: Room;\n\n public constructor(\n private client: MatrixClient,\n public readonly roomId: string,\n ) {\n this.room = this.client.getRoom(this.roomId)!;\n\n if (!this.room) throw new Error(\"Unknown room\");\n }\n\n /**\n * Syntactic sugar for room ID of the Space.\n */\n public get id(): string {\n return this.roomId;\n }\n\n /**\n * Whether or not this is a top level space.\n */\n public get isTopLevel(): boolean {\n // XXX: This is absolutely not how you find out if the space is top level\n // but is safe for a managed usecase like we offer in the SDK.\n const parentEvents = this.room.currentState.getStateEvents(EventType.SpaceParent);\n if (!parentEvents?.length) return true;\n return parentEvents.every((e) => !e.getContent()?.[\"via\"]);\n }\n\n /**\n * Sets the name of the tree space.\n * @param name - The new name for the space.\n * @returns Promise which resolves when complete.\n */\n public async setName(name: string): Promise<void> {\n await this.client.sendStateEvent(this.roomId, EventType.RoomName, { name }, \"\");\n }\n\n /**\n * Invites a user to the tree space. They will be given the default Viewer\n * permission level unless specified elsewhere.\n * @param userId - The user ID to invite.\n * @param andSubspaces - True (default) to invite the user to all\n * directories/subspaces too, recursively.\n * @returns Promise which resolves when complete.\n */\n public async invite(userId: string, andSubspaces = true): Promise<void> {\n const promises: Promise<void>[] = [this.retryInvite(userId)];\n if (andSubspaces) {\n promises.push(...this.getDirectories().map((d) => d.invite(userId, andSubspaces)));\n }\n await Promise.all(promises);\n }\n\n private async retryInvite(userId: string): Promise<void> {\n await simpleRetryOperation(\n () => this.client.invite(this.roomId, userId),\n (e) => {\n // We don't want to retry permission errors forever...\n if (e instanceof MatrixError && e.errcode === \"M_FORBIDDEN\") {\n return false;\n }\n return true;\n },\n );\n }\n\n /**\n * Sets the permissions of a user to the given role. Note that if setting a user\n * to Owner then they will NOT be able to be demoted. If the user does not have\n * permission to change the power level of the target, an error will be thrown.\n * @param userId - The user ID to change the role of.\n * @param role - The role to assign.\n * @returns Promise which resolves when complete.\n */\n public async setPermissions(userId: string, role: TreePermissions): Promise<void> {\n const currentPls = this.room.currentState.getStateEvents(EventType.RoomPowerLevels, \"\");\n if (Array.isArray(currentPls)) throw new Error(\"Unexpected return type for power levels\");\n\n const pls = currentPls?.getContent<RoomPowerLevelsEventContent>() || {};\n const viewLevel = pls[\"users_default\"] || 0;\n const editLevel = pls[\"events_default\"] || 50;\n const adminLevel = pls[\"events\"]?.[EventType.RoomPowerLevels] || 100;\n\n const users = pls[\"users\"] || {};\n switch (role) {\n case TreePermissions.Viewer:\n users[userId] = viewLevel;\n break;\n case TreePermissions.Editor:\n users[userId] = editLevel;\n break;\n case TreePermissions.Owner:\n users[userId] = adminLevel;\n break;\n default:\n throw new Error(\"Invalid role: \" + role);\n }\n pls[\"users\"] = users;\n\n await this.client.sendStateEvent(this.roomId, EventType.RoomPowerLevels, pls, \"\");\n }\n\n /**\n * Gets the current permissions of a user. Note that any users missing explicit permissions (or not\n * in the space) will be considered Viewers. Appropriate membership checks need to be performed\n * elsewhere.\n * @param userId - The user ID to check permissions of.\n * @returns The permissions for the user, defaulting to Viewer.\n */\n public getPermissions(userId: string): TreePermissions {\n const currentPls = this.room.currentState.getStateEvents(EventType.RoomPowerLevels, \"\");\n if (Array.isArray(currentPls)) throw new Error(\"Unexpected return type for power levels\");\n\n const pls = currentPls?.getContent() || {};\n const viewLevel = pls[\"users_default\"] || 0;\n const editLevel = pls[\"events_default\"] || 50;\n const adminLevel = pls[\"events\"]?.[EventType.RoomPowerLevels] || 100;\n\n const userLevel = pls[\"users\"]?.[userId] || viewLevel;\n if (userLevel >= adminLevel) return TreePermissions.Owner;\n if (userLevel >= editLevel) return TreePermissions.Editor;\n return TreePermissions.Viewer;\n }\n\n /**\n * Creates a directory under this tree space, represented as another tree space.\n * @param name - The name for the directory.\n * @returns Promise which resolves to the created directory.\n */\n public async createDirectory(name: string): Promise<MSC3089TreeSpace> {\n const directory = await this.client.unstableCreateFileTree(name);\n\n await this.client.sendStateEvent(\n this.roomId,\n EventType.SpaceChild,\n {\n via: [this.client.getDomain()!],\n },\n directory.roomId,\n );\n\n await this.client.sendStateEvent(\n directory.roomId,\n EventType.SpaceParent,\n {\n via: [this.client.getDomain()!],\n },\n this.roomId,\n );\n\n return directory;\n }\n\n /**\n * Gets a list of all known immediate subdirectories to this tree space.\n * @returns The tree spaces (directories). May be empty, but not null.\n */\n public getDirectories(): MSC3089TreeSpace[] {\n const trees: MSC3089TreeSpace[] = [];\n const children = this.room.currentState.getStateEvents(EventType.SpaceChild);\n for (const child of children) {\n try {\n const stateKey = child.getStateKey();\n if (stateKey) {\n const tree = this.client.unstableGetFileTreeSpace(stateKey);\n if (tree) trees.push(tree);\n }\n } catch (e) {\n logger.warn(\"Unable to create tree space instance for listing. Are we joined?\", e);\n }\n }\n return trees;\n }\n\n /**\n * Gets a subdirectory of a given ID under this tree space. Note that this will not recurse\n * into children and instead only look one level deep.\n * @param roomId - The room ID (directory ID) to find.\n * @returns The directory, or undefined if not found.\n */\n public getDirectory(roomId: string): MSC3089TreeSpace | undefined {\n return this.getDirectories().find((r) => r.roomId === roomId);\n }\n\n /**\n * Deletes the tree, kicking all members and deleting **all subdirectories**.\n * @returns Promise which resolves when complete.\n */\n public async delete(): Promise<void> {\n const subdirectories = this.getDirectories();\n for (const dir of subdirectories) {\n await dir.delete();\n }\n\n const kickMemberships = [KnownMembership.Invite, KnownMembership.Knock, KnownMembership.Join];\n const members = this.room.currentState.getStateEvents(EventType.RoomMember);\n for (const member of members) {\n const isNotUs = member.getStateKey() !== this.client.getUserId();\n if (isNotUs && kickMemberships.includes(member.getContent().membership! as KnownMembership)) {\n const stateKey = member.getStateKey();\n if (!stateKey) {\n throw new Error(\"State key not found for branch\");\n }\n await this.client.kick(this.roomId, stateKey, \"Room deleted\");\n }\n }\n\n await this.client.leave(this.roomId);\n }\n\n private getOrderedChildren(children: MatrixEvent[]): { roomId: string; order: string }[] {\n const ordered: { roomId: string; order: string }[] = children\n .map((c) => ({ roomId: c.getStateKey(), order: c.getContent()[\"order\"] }))\n .filter((c) => c.roomId) as { roomId: string; order: string }[];\n ordered.sort((a, b) => {\n if (a.order && !b.order) {\n return -1;\n } else if (!a.order && b.order) {\n return 1;\n } else if (!a.order && !b.order) {\n const roomA = this.client.getRoom(a.roomId);\n const roomB = this.client.getRoom(b.roomId);\n if (!roomA || !roomB) {\n // just don't bother trying to do more partial sorting\n return lexicographicCompare(a.roomId, b.roomId);\n }\n\n const createTsA = roomA.currentState.getStateEvents(EventType.RoomCreate, \"\")?.getTs() ?? 0;\n const createTsB = roomB.currentState.getStateEvents(EventType.RoomCreate, \"\")?.getTs() ?? 0;\n if (createTsA === createTsB) {\n return lexicographicCompare(a.roomId, b.roomId);\n }\n return createTsA - createTsB;\n } else {\n // both not-null orders\n return lexicographicCompare(a.order, b.order);\n }\n });\n return ordered;\n }\n\n private getParentRoom(): Room {\n const parents = this.room.currentState.getStateEvents(EventType.SpaceParent);\n const parent = parents[0]; // XXX: Wild assumption\n if (!parent) throw new Error(\"Expected to have a parent in a non-top level space\");\n\n // XXX: We are assuming the parent is a valid tree space.\n // We probably don't need to validate the parent room state for this usecase though.\n const stateKey = parent.getStateKey();\n if (!stateKey) throw new Error(\"No state key found for parent\");\n const parentRoom = this.client.getRoom(stateKey);\n if (!parentRoom) throw new Error(\"Unable to locate room for parent\");\n\n return parentRoom;\n }\n\n /**\n * Gets the current order index for this directory. Note that if this is the top level space\n * then -1 will be returned.\n * @returns The order index of this space.\n */\n public getOrder(): number {\n if (this.isTopLevel) return -1;\n\n const parentRoom = this.getParentRoom();\n const children = parentRoom.currentState.getStateEvents(EventType.SpaceChild);\n const ordered = this.getOrderedChildren(children);\n\n return ordered.findIndex((c) => c.roomId === this.roomId);\n }\n\n /**\n * Sets the order index for this directory within its parent. Note that if this is a top level\n * space then an error will be thrown. -1 can be used to move the child to the start, and numbers\n * larger than the number of children can be used to move the child to the end.\n * @param index - The new order index for this space.\n * @returns Promise which resolves when complete.\n * @throws Throws if this is a top level space.\n */\n public async setOrder(index: number): Promise<void> {\n if (this.isTopLevel) throw new Error(\"Cannot set order of top level spaces currently\");\n\n const parentRoom = this.getParentRoom();\n const children = parentRoom.currentState.getStateEvents(EventType.SpaceChild);\n const ordered = this.getOrderedChildren(children);\n index = Math.max(Math.min(index, ordered.length - 1), 0);\n\n const currentIndex = this.getOrder();\n const movingUp = currentIndex < index;\n if (movingUp && index === ordered.length - 1) {\n index--;\n } else if (!movingUp && index === 0) {\n index++;\n }\n\n const prev = ordered[movingUp ? index : index - 1];\n const next = ordered[movingUp ? index + 1 : index];\n\n let newOrder = DEFAULT_ALPHABET[0];\n let ensureBeforeIsSane = false;\n if (!prev) {\n // Move to front\n if (next?.order) {\n newOrder = prevString(next.order);\n }\n } else if (index === ordered.length - 1) {\n // Move to back\n if (next?.order) {\n newOrder = nextString(next.order);\n }\n } else {\n // Move somewhere in the middle\n const startOrder = prev?.order;\n const endOrder = next?.order;\n if (startOrder && endOrder) {\n if (startOrder === endOrder) {\n // Error case: just move +1 to break out of awful math\n newOrder = nextString(startOrder);\n } else {\n newOrder = averageBetweenStrings(startOrder, endOrder);\n }\n } else {\n if (startOrder) {\n // We're at the end (endOrder is null, so no explicit order)\n newOrder = nextString(startOrder);\n } else if (endOrder) {\n // We're at the start (startOrder is null, so nothing before us)\n newOrder = prevString(endOrder);\n } else {\n // Both points are unknown. We're likely in a range where all the children\n // don't have particular order values, so we may need to update them too.\n // The other possibility is there's only us as a child, but we should have\n // shown up in the other states.\n ensureBeforeIsSane = true;\n }\n }\n }\n\n if (ensureBeforeIsSane) {\n // We were asked by the order algorithm to prepare the moving space for a landing\n // in the undefined order part of the order array, which means we need to update the\n // spaces that come before it with a stable order value.\n let lastOrder: string | undefined;\n for (let i = 0; i <= index; i++) {\n const target = ordered[i];\n if (i === 0) {\n lastOrder = target.order;\n }\n if (!target.order) {\n // XXX: We should be creating gaps to avoid conflicts\n lastOrder = lastOrder ? nextString(lastOrder) : DEFAULT_ALPHABET[0];\n const currentChild = parentRoom.currentState.getStateEvents(EventType.SpaceChild, target.roomId);\n const content = currentChild?.getContent<SpaceChildEventContent>() ?? {\n via: [this.client.getDomain()!],\n };\n await this.client.sendStateEvent(\n parentRoom.roomId,\n EventType.SpaceChild,\n {\n ...content,\n order: lastOrder,\n },\n target.roomId,\n );\n } else {\n lastOrder = target.order;\n }\n }\n if (lastOrder) {\n newOrder = nextString(lastOrder);\n }\n }\n\n // TODO: Deal with order conflicts by reordering\n\n // Now we can finally update our own order state\n const currentChild = parentRoom.currentState.getStateEvents(EventType.SpaceChild, this.roomId);\n const content = currentChild?.getContent<SpaceChildEventContent>() ?? { via: [this.client.getDomain()!] };\n await this.client.sendStateEvent(\n parentRoom.roomId,\n EventType.SpaceChild,\n {\n ...content,\n\n // TODO: Safely constrain to 50 character limit required by spaces.\n order: newOrder,\n },\n this.roomId,\n );\n }\n\n /**\n * Creates (uploads) a new file to this tree. The file must have already been encrypted for the room.\n * The file contents are in a type that is compatible with MatrixClient.uploadContent().\n * @param name - The name of the file.\n * @param encryptedContents - The encrypted contents.\n * @param info - The encrypted file information.\n * @param additionalContent - Optional event content fields to include in the message.\n * @returns Promise which resolves to the file event's sent response.\n */\n public async createFile(\n name: string,\n encryptedContents: FileType,\n info: EncryptedFile,\n additionalContent?: IContent,\n ): Promise<ISendEventResponse> {\n const { content_uri: mxc } = await this.client.uploadContent(encryptedContents, {\n includeFilename: false,\n });\n info.url = mxc;\n\n const fileContent: FileContent = {\n msgtype: MsgType.File,\n body: name,\n url: mxc,\n file: info,\n };\n\n additionalContent = additionalContent ?? {};\n if (additionalContent[\"m.new_content\"]) {\n // We do the right thing according to the spec, but due to how relations are\n // handled we also end up duplicating this information to the regular `content`\n // as well.\n additionalContent[\"m.new_content\"] = fileContent;\n }\n\n const res = await this.client.sendMessage(this.roomId, {\n ...additionalContent,\n ...fileContent,\n [UNSTABLE_MSC3089_LEAF.name]: {},\n } as FileContent);\n\n await this.client.sendStateEvent(\n this.roomId,\n UNSTABLE_MSC3089_BRANCH.name,\n {\n active: true,\n name: name,\n },\n res[\"event_id\"],\n );\n\n return res;\n }\n\n /**\n * Retrieves a file from the tree.\n * @param fileEventId - The event ID of the file.\n * @returns The file, or null if not found.\n */\n public getFile(fileEventId: string): MSC3089Branch | null {\n const branch = this.room.currentState.getStateEvents(UNSTABLE_MSC3089_BRANCH.name, fileEventId);\n return branch ? new MSC3089Branch(this.client, branch, this) : null;\n }\n\n /**\n * Gets an array of all known files for the tree.\n * @returns The known files. May be empty, but not null.\n */\n public listFiles(): MSC3089Branch[] {\n return this.listAllFiles().filter((b) => b.isActive);\n }\n\n /**\n * Gets an array of all known files for the tree, including inactive/invalid ones.\n * @returns The known files. May be empty, but not null.\n */\n public listAllFiles(): MSC3089Branch[] {\n const branches = this.room.currentState.getStateEvents(UNSTABLE_MSC3089_BRANCH.name) ?? [];\n return branches.map((e) => new MSC3089Branch(this.client, e, this));\n }\n}\n","/*\nCopyright 2023 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 MatrixEvent } from \"./event.ts\";\nimport { type Room } from \"./room.ts\";\nimport { inMainTimelineForReceipt, threadIdForReceipt } from \"../client.ts\";\n\n/**\n * Determine the order of two events in a room.\n *\n * In principle this should use the same order as the server, but in practice\n * this is difficult for events that were not received over the Sync API. See\n * MSC4033 for details.\n *\n * This implementation leans on the order of events within their timelines, and\n * falls back to comparing event timestamps when they are in different\n * timelines.\n *\n * See https://github.com/matrix-org/matrix-js-sdk/issues/3325 for where we are\n * tracking the work to fix this.\n *\n * @param room - the room we are looking in\n * @param leftEventId - the id of the first event\n * @param rightEventId - the id of the second event\n\n * @returns -1 if left \\< right, 1 if left \\> right, 0 if left == right, null if\n * we can't tell (because we can't find the events).\n */\nexport function compareEventOrdering(room: Room, leftEventId: string, rightEventId: string): number | null {\n const leftEvent = room.findEventById(leftEventId);\n const rightEvent = room.findEventById(rightEventId);\n\n if (!leftEvent || !rightEvent) {\n // Without the events themselves, we can't find their thread or\n // timeline, or guess based on timestamp, so we just don't know.\n return null;\n }\n\n // Check whether the events are in the main timeline\n const isLeftEventInMainTimeline = inMainTimelineForReceipt(leftEvent);\n const isRightEventInMainTimeline = inMainTimelineForReceipt(rightEvent);\n\n if (isLeftEventInMainTimeline && isRightEventInMainTimeline) {\n return compareEventsInMainTimeline(room, leftEventId, rightEventId, leftEvent, rightEvent);\n } else {\n // At least one event is not in the timeline, so we can't use the room's\n // unfiltered timeline set.\n return compareEventsInThreads(leftEventId, rightEventId, leftEvent, rightEvent);\n }\n}\n\nfunction compareEventsInMainTimeline(\n room: Room,\n leftEventId: string,\n rightEventId: string,\n leftEvent: MatrixEvent,\n rightEvent: MatrixEvent,\n): number | null {\n // Get the timeline set that contains all the events.\n const timelineSet = room.getUnfilteredTimelineSet();\n\n // If they are in the same timeline, compareEventOrdering does what we need\n const compareSameTimeline = timelineSet.compareEventOrdering(leftEventId, rightEventId);\n if (compareSameTimeline !== null) {\n return compareSameTimeline;\n }\n\n // Find which timeline each event is in. Refuse to provide an ordering if we\n // can't find either of the events.\n\n const leftTimeline = timelineSet.getTimelineForEvent(leftEventId);\n if (leftTimeline === timelineSet.getLiveTimeline()) {\n // The left event is part of the live timeline, so it must be after the\n // right event (since they are not in the same timeline or we would have\n // returned after compareEventOrdering.\n return 1;\n }\n\n const rightTimeline = timelineSet.getTimelineForEvent(rightEventId);\n if (rightTimeline === timelineSet.getLiveTimeline()) {\n // The right event is part of the live timeline, so it must be after the\n // left event.\n return -1;\n }\n\n // They are in older timeline sets (because they were fetched by paging up).\n return guessOrderBasedOnTimestamp(leftEvent, rightEvent);\n}\n\nfunction compareEventsInThreads(\n leftEventId: string,\n rightEventId: string,\n leftEvent: MatrixEvent,\n rightEvent: MatrixEvent,\n): number | null {\n const leftEventThreadId = threadIdForReceipt(leftEvent);\n const rightEventThreadId = threadIdForReceipt(rightEvent);\n\n const leftThread = leftEvent.getThread();\n\n if (leftThread && leftEventThreadId === rightEventThreadId) {\n // They are in the same thread, so we can ask the thread's timeline to\n // figure it out for us\n return leftThread.timelineSet.compareEventOrdering(leftEventId, rightEventId);\n } else {\n return guessOrderBasedOnTimestamp(leftEvent, rightEvent);\n }\n}\n\n/**\n * Guess the order of events based on server timestamp. This is not good, but\n * difficult to avoid without MSC4033.\n *\n * See https://github.com/matrix-org/matrix-js-sdk/issues/3325\n */\nfunction guessOrderBasedOnTimestamp(leftEvent: MatrixEvent, rightEvent: MatrixEvent): number {\n const leftTs = leftEvent.getTs();\n const rightTs = rightEvent.getTs();\n if (leftTs < rightTs) {\n return -1;\n } else if (leftTs > rightTs) {\n return 1;\n } else {\n return 0;\n }\n}\n","/*\nCopyright 2015 - 2021 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 MatrixEvent } from \"./event.ts\";\nimport { Direction } from \"./event-timeline.ts\";\n\nexport class EventContext {\n private timeline: MatrixEvent[];\n private ourEventIndex = 0;\n private paginateTokens: Record<Direction, string | null> = {\n [Direction.Backward]: null,\n [Direction.Forward]: null,\n };\n\n /**\n * Construct a new EventContext\n *\n * An eventcontext is used for circumstances such as search results, when we\n * have a particular event of interest, and a bunch of events before and after\n * it.\n *\n * It also stores pagination tokens for going backwards and forwards in the\n * timeline.\n *\n * @param ourEvent - the event at the centre of this context\n */\n public constructor(public readonly ourEvent: MatrixEvent) {\n this.timeline = [ourEvent];\n }\n\n /**\n * Get the main event of interest\n *\n * This is a convenience function for getTimeline()[getOurEventIndex()].\n *\n * @returns The event at the centre of this context.\n */\n public getEvent(): MatrixEvent {\n return this.timeline[this.ourEventIndex];\n }\n\n /**\n * Get the list of events in this context\n *\n * @returns An array of MatrixEvents\n */\n public getTimeline(): MatrixEvent[] {\n return this.timeline;\n }\n\n /**\n * Get the index in the timeline of our event\n */\n public getOurEventIndex(): number {\n return this.ourEventIndex;\n }\n\n /**\n * Get a pagination token.\n *\n * @param backwards - true to get the pagination token for going\n */\n public getPaginateToken(backwards = false): string | null {\n return this.paginateTokens[backwards ? Direction.Backward : Direction.Forward];\n }\n\n /**\n * Set a pagination token.\n *\n * Generally this will be used only by the matrix js sdk.\n *\n * @param token - pagination token\n * @param backwards - true to set the pagination token for going\n * backwards in time\n */\n public setPaginateToken(token?: string, backwards = false): void {\n this.paginateTokens[backwards ? Direction.Backward : Direction.Forward] = token ?? null;\n }\n\n /**\n * Add more events to the timeline\n *\n * @param events - new events, in timeline order\n * @param atStart - true to insert new events at the start\n */\n public addEvents(events: MatrixEvent[], atStart = false): void {\n // TODO: should we share logic with Room.addEventsToTimeline?\n // Should Room even use EventContext?\n\n if (atStart) {\n this.timeline = events.concat(this.timeline);\n this.ourEventIndex += events.length;\n } else {\n this.timeline = this.timeline.concat(events);\n }\n }\n}\n","/*\nCopyright 2015 - 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\n/**\n * Enum for event statuses.\n * @readonly\n */\nexport enum EventStatus {\n /** The event was not sent and will no longer be retried. */\n NOT_SENT = \"not_sent\",\n\n /** The message is being encrypted */\n ENCRYPTING = \"encrypting\",\n\n /** The event is in the process of being sent. */\n SENDING = \"sending\",\n\n /** The event is in a queue waiting to be sent. */\n QUEUED = \"queued\",\n\n /** The event has been sent to the server, but we have not yet received the echo. */\n SENT = \"sent\",\n\n /** The event was cancelled before it was successfully sent. */\n CANCELLED = \"cancelled\",\n}\n","/*\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 { UnstableValue } from \"matrix-events-sdk\";\n\n/// The event type storing the user's individual policies.\n///\n/// Exported for testing purposes.\nexport const POLICIES_ACCOUNT_EVENT_TYPE = new UnstableValue(\"m.policies\", \"org.matrix.msc3847.policies\");\n\n/// The key within the user's individual policies storing the user's ignored invites.\n///\n/// Exported for testing purposes.\nexport const IGNORE_INVITES_ACCOUNT_EVENT_KEY = new UnstableValue(\n \"m.ignore.invites\",\n \"org.matrix.msc3847.ignore.invites\",\n);\n\n/// The types of recommendations understood.\nexport enum PolicyRecommendation {\n Ban = \"m.ban\",\n}\n\n/**\n * The various scopes for policies.\n */\nexport enum PolicyScope {\n /**\n * The policy deals with an individual user, e.g. reject invites\n * from this user.\n */\n User = \"m.policy.user\",\n\n /**\n * The policy deals with a room, e.g. reject invites towards\n * a specific room.\n */\n Room = \"m.policy.room\",\n\n /**\n * The policy deals with a server, e.g. reject invites from\n * this server.\n */\n Server = \"m.policy.server\",\n}\n","/*\nCopyright 2022 The Matrix.org Foundation C.I.C.\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 http://www.apache.org/licenses/LICENSE-2.0\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 CachedReceipt,\n MAIN_ROOM_TIMELINE,\n type Receipt,\n type ReceiptCache,\n ReceiptType,\n type WrappedReceipt,\n} from \"../@types/read_receipts.ts\";\nimport { type ListenerMap, TypedEventEmitter } from \"./typed-event-emitter.ts\";\nimport { isSupportedReceiptType } from \"../utils.ts\";\nimport { MatrixEvent } from \"./event.ts\";\nimport { EventType } from \"../@types/event.ts\";\nimport { type EventTimelineSet } from \"./event-timeline-set.ts\";\nimport { MapWithDefault } from \"../utils.ts\";\nimport { NotificationCountType } from \"./room.ts\";\nimport { logger } from \"../logger.ts\";\nimport { inMainTimelineForReceipt, threadIdForReceipt } from \"../client.ts\";\n\n/**\n * Create a synthetic receipt for the given event\n * @param userId - The user ID if the receipt sender\n * @param event - The event that is to be acknowledged\n * @param receiptType - The type of receipt\n * @param unthreaded - the receipt is unthreaded\n * @returns a new event with the synthetic receipt in it\n */\nexport function synthesizeReceipt(\n userId: string,\n event: MatrixEvent,\n receiptType: ReceiptType,\n unthreaded = false,\n): MatrixEvent {\n return new MatrixEvent({\n content: {\n [event.getId()!]: {\n [receiptType]: {\n [userId]: {\n ts: event.getTs(),\n ...(!unthreaded && { thread_id: threadIdForReceipt(event) }),\n },\n },\n },\n },\n type: EventType.Receipt,\n room_id: event.getRoomId(),\n });\n}\n\nconst ReceiptPairRealIndex = 0;\nconst ReceiptPairSyntheticIndex = 1;\n\nexport abstract class ReadReceipt<\n Events extends string,\n Arguments extends ListenerMap<Events>,\n SuperclassArguments extends ListenerMap<any> = Arguments,\n> extends TypedEventEmitter<Events, Arguments, SuperclassArguments> {\n // receipts should clobber based on receipt_type and user_id pairs hence\n // the form of this structure. This is sub-optimal for the exposed APIs\n // which pass in an event ID and get back some receipts, so we also store\n // a pre-cached list for this purpose.\n // Map: receipt type → user Id → receipt\n private receipts = new MapWithDefault<\n string,\n Map<string, [realReceipt: WrappedReceipt | null, syntheticReceipt: WrappedReceipt | null]>\n >(() => new Map());\n private receiptCacheByEventId: ReceiptCache = new Map();\n\n public abstract getUnfilteredTimelineSet(): EventTimelineSet;\n public abstract get timeline(): MatrixEvent[];\n\n /**\n * Gets the latest receipt for a given user in the room\n * @param userId - The id of the user for which we want the receipt\n * @param ignoreSynthesized - Whether to ignore synthesized receipts or not\n * @param receiptType - Optional. The type of the receipt we want to get\n * @returns the latest receipts of the chosen type for the chosen user\n */\n public getReadReceiptForUserId(\n userId: string,\n ignoreSynthesized = false,\n receiptType = ReceiptType.Read,\n ): WrappedReceipt | null {\n const [realReceipt, syntheticReceipt] = this.receipts.get(receiptType)?.get(userId) ?? [null, null];\n if (ignoreSynthesized) {\n return realReceipt;\n }\n\n return syntheticReceipt ?? realReceipt;\n }\n\n private compareReceipts(a: WrappedReceipt, b: WrappedReceipt): number {\n // Try compare them in our unfiltered timeline set order, falling back to receipt timestamp which should be\n // relatively sane as receipts are set only by the originating homeserver so as long as its clock doesn't\n // jump around then it should be valid.\n return this.getUnfilteredTimelineSet().compareEventOrdering(a.eventId, b.eventId) ?? a.data.ts - b.data.ts;\n }\n\n /**\n * Get the ID of the event that a given user has read up to, or null if:\n * - we have received no read receipts for them, or\n * - the receipt we have points at an event we don't have, or\n * - the thread ID in the receipt does not match the thread root of the\n * referenced event.\n *\n * (The event might not exist if it is not loaded, and the thread ID might\n * not match if the event has moved thread because it was redacted.)\n *\n * @param userId - The user ID to get read receipt event ID for\n * @param ignoreSynthesized - If true, return only receipts that have been\n * sent by the server, not implicit ones generated\n * by the JS SDK.\n * @returns ID of the latest existing event that the given user has read, or null.\n */\n public getEventReadUpTo(userId: string, ignoreSynthesized = false): string | null {\n // Find what the latest receipt says is the latest event we have read\n const latestReceipt = this.getLatestReceipt(userId, ignoreSynthesized);\n\n if (!latestReceipt) {\n return null;\n }\n\n return this.receiptPointsAtConsistentEvent(latestReceipt) ? latestReceipt.eventId : null;\n }\n\n /**\n * Returns true if the event pointed at by this receipt exists, and its\n * threadRootId is consistent with the thread information in the receipt.\n */\n private receiptPointsAtConsistentEvent(receipt: WrappedReceipt): boolean {\n const event = this.findEventById(receipt.eventId);\n if (!event) {\n // If the receipt points at a non-existent event, we have multiple\n // possibilities:\n //\n // 1. We don't have the event because it's not loaded yet - probably\n // it's old and we're best off ignoring the receipt - we can just\n // send a new one when we read a new event.\n //\n // 2. We have a bug e.g. we misclassified this event into the wrong\n // thread.\n //\n // 3. The referenced event moved out of this thread (e.g. because it\n // was deleted.)\n //\n // 4. The receipt had the incorrect thread ID (due to a bug in a\n // client, or malicious behaviour).\n\n // This receipt is not \"valid\" because it doesn't point at an event\n // we have. We want to pretend it doesn't exist.\n return false;\n }\n\n if (!receipt.data?.thread_id) {\n // If this is an unthreaded receipt, it could point at any event, so\n // there is no need to validate further - this receipt is valid.\n return true;\n }\n // Otherwise it is a threaded receipt...\n\n if (receipt.data.thread_id === MAIN_ROOM_TIMELINE) {\n // The receipt is for the main timeline: we check that the event is\n // in the main timeline.\n\n // Check if the event is in the main timeline\n const eventIsInMainTimeline = inMainTimelineForReceipt(event);\n\n if (eventIsInMainTimeline) {\n // The receipt is for the main timeline, and so is the event, so\n // the receipt is valid.\n return true;\n }\n } else {\n // The receipt is for a different thread (not the main timeline)\n\n if (event.threadRootId === receipt.data.thread_id) {\n // If the receipt and event agree on the thread ID, the receipt\n // is valid.\n return true;\n }\n }\n\n // The receipt thread ID disagrees with the event thread ID. There are 2\n // possibilities:\n //\n // 1. The event moved to a different thread after the receipt was\n // created. This can happen if the event was redacted because that\n // moves it to the main timeline.\n //\n // 2. There is a bug somewhere - either we put the event into the wrong\n // thread, or someone sent an incorrect receipt.\n //\n // In many cases, we won't get here because the call to findEventById\n // would have already returned null. We include this check to cover\n // cases when `this` is a room, meaning findEventById will find events\n // in any thread, and to be defensive against unforeseen code paths.\n logger.warn(\n `Ignoring receipt because its thread_id (${receipt.data.thread_id}) disagrees ` +\n `with the thread root (${event.threadRootId}) of the referenced event ` +\n `(event ID = ${receipt.eventId})`,\n );\n\n // This receipt is not \"valid\" because it disagrees with us about what\n // thread the event is in. We want to pretend it doesn't exist.\n return false;\n }\n\n private getLatestReceipt(userId: string, ignoreSynthesized: boolean): WrappedReceipt | null {\n // XXX: This is very very ugly and I hope I won't have to ever add a new\n // receipt type here again. IMHO this should be done by the server in\n // some more intelligent manner or the client should just use timestamps\n\n const publicReadReceipt = this.getReadReceiptForUserId(userId, ignoreSynthesized, ReceiptType.Read);\n const privateReadReceipt = this.getReadReceiptForUserId(userId, ignoreSynthesized, ReceiptType.ReadPrivate);\n\n // If we have both, compare them\n let comparison: number | null | undefined;\n if (publicReadReceipt?.eventId && privateReadReceipt?.eventId) {\n comparison = this.compareReceipts(publicReadReceipt, privateReadReceipt);\n }\n\n // The public receipt is more likely to drift out of date so the private\n // one has precedence\n if (!comparison) return privateReadReceipt ?? publicReadReceipt ?? null;\n\n // If public read receipt is older, return the private one\n return (comparison < 0 ? privateReadReceipt : publicReadReceipt) ?? null;\n }\n\n public addReceiptToStructure(\n eventId: string,\n receiptType: ReceiptType,\n userId: string,\n receipt: Receipt,\n synthetic: boolean,\n ): void {\n const receiptTypesMap = this.receipts.getOrCreate(receiptType);\n let pair = receiptTypesMap.get(userId);\n\n if (!pair) {\n pair = [null, null];\n receiptTypesMap.set(userId, pair);\n }\n\n let existingReceipt = pair[ReceiptPairRealIndex];\n if (synthetic) {\n existingReceipt = pair[ReceiptPairSyntheticIndex] ?? pair[ReceiptPairRealIndex];\n }\n\n const wrappedReceipt: WrappedReceipt = {\n eventId,\n data: receipt,\n };\n\n if (existingReceipt) {\n // We only want to add this receipt if we think it is later than the one we already have.\n // This is managed server-side, but because we synthesize RRs locally we have to do it here too.\n const ordering = this.compareReceipts(existingReceipt, wrappedReceipt);\n if (ordering >= 0) {\n return;\n }\n }\n\n const realReceipt = synthetic ? pair[ReceiptPairRealIndex] : wrappedReceipt;\n const syntheticReceipt = synthetic ? wrappedReceipt : pair[ReceiptPairSyntheticIndex];\n\n let ordering: number | null = null;\n if (realReceipt && syntheticReceipt) {\n ordering = this.getUnfilteredTimelineSet().compareEventOrdering(\n realReceipt.eventId,\n syntheticReceipt.eventId,\n );\n }\n\n const preferSynthetic = ordering === null || ordering < 0;\n\n // we don't bother caching just real receipts by event ID as there's nothing that would read it.\n // Take the current cached receipt before we overwrite the pair elements.\n const cachedReceipt = pair[ReceiptPairSyntheticIndex] ?? pair[ReceiptPairRealIndex];\n\n if (synthetic && preferSynthetic) {\n pair[ReceiptPairSyntheticIndex] = wrappedReceipt;\n } else if (!synthetic) {\n pair[ReceiptPairRealIndex] = wrappedReceipt;\n\n if (!preferSynthetic) {\n pair[ReceiptPairSyntheticIndex] = null;\n }\n }\n\n const newCachedReceipt = pair[ReceiptPairSyntheticIndex] ?? pair[ReceiptPairRealIndex];\n if (cachedReceipt === newCachedReceipt) return;\n\n // clean up any previous cache entry\n if (cachedReceipt && this.receiptCacheByEventId.get(cachedReceipt.eventId)) {\n const previousEventId = cachedReceipt.eventId;\n // Remove the receipt we're about to clobber out of existence from the cache\n this.receiptCacheByEventId.set(\n previousEventId,\n this.receiptCacheByEventId.get(previousEventId)!.filter((r) => {\n return r.type !== receiptType || r.userId !== userId;\n }),\n );\n\n if (this.receiptCacheByEventId.get(previousEventId)!.length < 1) {\n this.receiptCacheByEventId.delete(previousEventId); // clean up the cache keys\n }\n }\n\n // cache the new one\n if (!this.receiptCacheByEventId.get(eventId)) {\n this.receiptCacheByEventId.set(eventId, []);\n }\n this.receiptCacheByEventId.get(eventId)!.push({\n userId: userId,\n type: receiptType as ReceiptType,\n data: receipt,\n });\n }\n\n /**\n * Get a list of receipts for the given event.\n * @param event - the event to get receipts for\n * @returns A list of receipts with a userId, type and data keys or\n * an empty list.\n */\n public getReceiptsForEvent(event: MatrixEvent): CachedReceipt[] {\n return this.receiptCacheByEventId.get(event.getId()!) || [];\n }\n\n public abstract addReceipt(event: MatrixEvent, synthetic: boolean): void;\n\n public abstract setUnread(type: NotificationCountType, count: number): void;\n\n /**\n * Look in this room/thread's timeline to find an event. If `this` is a\n * room, we look in all threads, but if `this` is a thread, we look only\n * inside this thread.\n */\n public abstract findEventById(eventId: string): MatrixEvent | undefined;\n\n /**\n * This issue should also be addressed on synapse's side and is tracked as part\n * of https://github.com/matrix-org/synapse/issues/14837\n *\n * Retrieves the read receipt for the logged in user and checks if it matches\n * the last event in the room and whether that event originated from the logged\n * in user.\n * Under those conditions we can consider the context as read. This is useful\n * because we never send read receipts against our own events\n * @param userId - the logged in user\n */\n public fixupNotifications(userId: string): void {\n const receipt = this.getReadReceiptForUserId(userId, false);\n\n const lastEvent = this.timeline[this.timeline.length - 1];\n if (lastEvent && receipt?.eventId === lastEvent.getId() && userId === lastEvent.getSender()) {\n this.setUnread(NotificationCountType.Total, 0);\n this.setUnread(NotificationCountType.Highlight, 0);\n }\n }\n\n /**\n * Add a temporary local-echo receipt to the room to reflect in the\n * client the fact that we've sent one.\n * @param userId - The user ID if the receipt sender\n * @param e - The event that is to be acknowledged\n * @param receiptType - The type of receipt\n * @param unthreaded - the receipt is unthreaded\n */\n public addLocalEchoReceipt(userId: string, e: MatrixEvent, receiptType: ReceiptType, unthreaded = false): void {\n this.addReceipt(synthesizeReceipt(userId, e, receiptType, unthreaded), true);\n }\n\n /**\n * Get a list of user IDs who have <b>read up to</b> the given event.\n * @param event - the event to get read receipts for.\n * @returns A list of user IDs.\n */\n public getUsersReadUpTo(event: MatrixEvent): string[] {\n return this.getReceiptsForEvent(event)\n .filter(function (receipt) {\n return isSupportedReceiptType(receipt.type);\n })\n .map(function (receipt) {\n return receipt.userId;\n });\n }\n\n /**\n * Determines if the given user has read a particular event ID with the known\n * history of the room. This is not a definitive check as it relies only on\n * what is available to the room at the time of execution.\n * @param userId - The user ID to check the read state of.\n * @param eventId - The event ID to check if the user read.\n * @returns True if the user has read the event, false otherwise.\n */\n public abstract hasUserReadEvent(userId: string, eventId: string): boolean;\n\n /**\n * Returns the most recent unthreaded receipt for a given user\n * @param userId - the MxID of the User\n * @returns an unthreaded Receipt. Can be undefined if receipts have been disabled\n * or a user chooses to use private read receipts (or we have simply not received\n * a receipt from this user yet).\n *\n * @deprecated use `hasUserReadEvent` or `getEventReadUpTo` instead\n */\n public abstract getLastUnthreadedReceiptFor(userId: string): Receipt | undefined;\n}\n","/*\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 { Relations } from \"./relations.ts\";\nimport { type EventType, type RelationType } from \"../@types/event.ts\";\nimport { EventStatus, type MatrixEvent, MatrixEventEvent } from \"./event.ts\";\nimport { type EventTimelineSet } from \"./event-timeline-set.ts\";\nimport { type MatrixClient } from \"../client.ts\";\nimport { type Room } from \"./room.ts\";\n\nexport class RelationsContainer {\n // A tree of objects to access a set of related children for an event, as in:\n // this.relations.get(parentEventId).get(relationType).get(relationEventType)\n private relations = new Map<string, Map<RelationType | string, Map<EventType | string, Relations>>>();\n\n public constructor(\n private readonly client: MatrixClient,\n private readonly room?: Room,\n ) {}\n\n /**\n * Get a collection of child events to a given event in this timeline set.\n *\n * @param eventId - The ID of the event that you'd like to access child events for.\n * For example, with annotations, this would be the ID of the event being annotated.\n * @param relationType - The type of relationship involved, such as \"m.annotation\", \"m.reference\", \"m.replace\", etc.\n * @param eventType - The relation event's type, such as \"m.reaction\", etc.\n * @throws If `eventId</code>, <code>relationType</code> or <code>eventType`\n * are not valid.\n *\n * @returns\n * A container for relation events or undefined if there are no relation events for\n * the relationType.\n */\n public getChildEventsForEvent(\n eventId: string,\n relationType: RelationType | string,\n eventType: EventType | string,\n ): Relations | undefined {\n return this.relations.get(eventId)?.get(relationType)?.get(eventType);\n }\n\n public getAllChildEventsForEvent(parentEventId: string): MatrixEvent[] {\n const relationsForEvent =\n this.relations.get(parentEventId) ?? new Map<RelationType | string, Map<EventType | string, Relations>>();\n const events: MatrixEvent[] = [];\n for (const relationsRecord of relationsForEvent.values()) {\n for (const relations of relationsRecord.values()) {\n events.push(...relations.getRelations());\n }\n }\n return events;\n }\n\n /**\n * Set an event as the target event if any Relations exist for it already.\n * Child events can point to other child events as their parent, so this method may be\n * called for events which are also logically child events.\n *\n * @param event - The event to check as relation target.\n */\n public aggregateParentEvent(event: MatrixEvent): void {\n const relationsForEvent = this.relations.get(event.getId()!);\n if (!relationsForEvent) return;\n\n for (const relationsWithRelType of relationsForEvent.values()) {\n for (const relationsWithEventType of relationsWithRelType.values()) {\n relationsWithEventType.setTargetEvent(event);\n }\n }\n }\n\n /**\n * Add relation events to the relevant relation collection.\n *\n * @param event - The new child event to be aggregated.\n * @param timelineSet - The event timeline set within which to search for the related event if any.\n */\n public aggregateChildEvent(event: MatrixEvent, timelineSet?: EventTimelineSet): void {\n if (event.isRedacted() || event.status === EventStatus.CANCELLED) {\n return;\n }\n\n const relation = event.getRelation();\n if (!relation) return;\n\n const onEventDecrypted = (): void => {\n if (event.isDecryptionFailure()) {\n // This could for example happen if the encryption keys are not yet available.\n // The event may still be decrypted later. Register the listener again.\n event.once(MatrixEventEvent.Decrypted, onEventDecrypted);\n return;\n }\n\n this.aggregateChildEvent(event, timelineSet);\n };\n\n // If the event is currently encrypted, wait until it has been decrypted.\n if (event.isBeingDecrypted() || event.shouldAttemptDecryption()) {\n event.once(MatrixEventEvent.Decrypted, onEventDecrypted);\n return;\n }\n\n const { event_id: relatesToEventId, rel_type: relationType } = relation;\n const eventType = event.getType();\n\n let relationsForEvent = this.relations.get(relatesToEventId!);\n if (!relationsForEvent) {\n relationsForEvent = new Map<RelationType | string, Map<EventType | string, Relations>>();\n this.relations.set(relatesToEventId!, relationsForEvent);\n }\n\n let relationsWithRelType = relationsForEvent.get(relationType!);\n if (!relationsWithRelType) {\n relationsWithRelType = new Map<EventType | string, Relations>();\n relationsForEvent.set(relationType!, relationsWithRelType);\n }\n\n let relationsWithEventType = relationsWithRelType.get(eventType);\n if (!relationsWithEventType) {\n relationsWithEventType = new Relations(relationType!, eventType, this.client);\n relationsWithRelType.set(eventType, relationsWithEventType);\n\n const room = this.room ?? timelineSet?.room;\n const relatesToEvent =\n timelineSet?.findEventById(relatesToEventId!) ??\n room?.findEventById(relatesToEventId!) ??\n room?.getPendingEvent(relatesToEventId!);\n if (relatesToEvent) {\n relationsWithEventType.setTargetEvent(relatesToEvent);\n }\n }\n\n relationsWithEventType.addEvent(event);\n }\n}\n","/*\nCopyright 2023 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 { MAIN_ROOM_TIMELINE, type Receipt, type ReceiptContent } from \"../@types/read_receipts.ts\";\nimport { threadIdForReceipt } from \"../client.ts\";\nimport { type Room, RoomEvent } from \"./room.ts\";\nimport { type MatrixEvent } from \"./event.ts\";\nimport { logger } from \"../logger.ts\";\n\n/**\n * The latest receipts we have for a room.\n */\nexport class RoomReceipts {\n private room: Room;\n private threadedReceipts: ThreadedReceipts;\n private unthreadedReceipts: ReceiptsByUser;\n private danglingReceipts: DanglingReceipts;\n\n public constructor(room: Room) {\n this.room = room;\n this.threadedReceipts = new ThreadedReceipts(room);\n this.unthreadedReceipts = new ReceiptsByUser(room);\n this.danglingReceipts = new DanglingReceipts();\n // We listen for timeline events so we can process dangling receipts\n room.on(RoomEvent.Timeline, this.onTimelineEvent);\n }\n\n /**\n * Remember the receipt information supplied. For each receipt:\n *\n * If we don't have the event for this receipt, store it as \"dangling\" so we\n * can process it later.\n *\n * Otherwise store it per-user in either the threaded store for its\n * thread_id, or the unthreaded store if there is no thread_id.\n *\n * Ignores any receipt that is before an existing receipt for the same user\n * (in the same thread, if applicable). \"Before\" is defined by the\n * unfilteredTimelineSet of the room.\n */\n public add(receiptContent: ReceiptContent, synthetic: boolean): void {\n /*\n Transform this structure:\n {\n \"$EVENTID\": {\n \"m.read|m.read.private\": {\n \"@user:example.org\": {\n \"ts\": 1661,\n \"thread_id\": \"main|$THREAD_ROOT_ID\" // or missing/undefined for an unthreaded receipt\n }\n }\n },\n ...\n }\n into maps of:\n threaded :: threadid :: userId :: ReceiptInfo\n unthreaded :: userId :: ReceiptInfo\n dangling :: eventId :: DanglingReceipt\n */\n for (const [eventId, eventReceipt] of Object.entries(receiptContent)) {\n for (const [receiptType, receiptsByUser] of Object.entries(eventReceipt)) {\n for (const [userId, receipt] of Object.entries(receiptsByUser)) {\n const referencedEvent = this.room.findEventById(eventId);\n if (!referencedEvent) {\n this.danglingReceipts.add(\n new DanglingReceipt(eventId, receiptType, userId, receipt, synthetic),\n );\n } else if (receipt.thread_id) {\n this.threadedReceipts.set(\n receipt.thread_id,\n eventId,\n receiptType,\n userId,\n receipt.ts,\n synthetic,\n );\n } else {\n this.unthreadedReceipts.set(eventId, receiptType, userId, receipt.ts, synthetic);\n }\n }\n }\n }\n }\n\n /**\n * Look for dangling receipts for the given event ID,\n * and add them to the thread of unthread receipts if found.\n * @param event - the event to look for\n */\n private onTimelineEvent = (event: MatrixEvent): void => {\n const eventId = event.getId();\n if (!eventId) return;\n\n const danglingReceipts = this.danglingReceipts.remove(eventId);\n\n danglingReceipts?.forEach((danglingReceipt) => {\n // The receipt is a thread receipt\n if (danglingReceipt.receipt.thread_id) {\n this.threadedReceipts.set(\n danglingReceipt.receipt.thread_id,\n danglingReceipt.eventId,\n danglingReceipt.receiptType,\n danglingReceipt.userId,\n danglingReceipt.receipt.ts,\n danglingReceipt.synthetic,\n );\n } else {\n this.unthreadedReceipts.set(\n eventId,\n danglingReceipt.receiptType,\n danglingReceipt.userId,\n danglingReceipt.receipt.ts,\n danglingReceipt.synthetic,\n );\n }\n });\n };\n\n public hasUserReadEvent(userId: string, eventId: string): boolean {\n const unthreaded = this.unthreadedReceipts.get(userId);\n if (unthreaded) {\n if (isAfterOrSame(unthreaded.eventId, eventId, this.room)) {\n // The unthreaded receipt is after this event, so we have read it.\n return true;\n }\n }\n\n const event = this.room.findEventById(eventId);\n if (!event) {\n // We don't know whether the user has read it - default to caution and say no.\n // This shouldn't really happen and feels like it ought to be an exception: let's\n // log a warn for now.\n logger.warn(\n `hasUserReadEvent event ID ${eventId} not found in room ${this.room.roomId}: this shouldn't happen!`,\n );\n return false;\n }\n\n const threadId = threadIdForReceipt(event);\n const threaded = this.threadedReceipts.get(threadId, userId);\n if (threaded) {\n if (isAfterOrSame(threaded.eventId, eventId, this.room)) {\n // The threaded receipt is after this event, so we have read it.\n return true;\n }\n }\n\n // TODO: what if they sent the second-last event in the thread?\n if (this.userSentLatestEventInThread(threadId, userId)) {\n // The user sent the latest message in this event's thread, so we\n // consider everything in the thread to be read.\n //\n // Note: maybe we don't need this because synthetic receipts should\n // do this job for us?\n return true;\n }\n\n // Neither of the receipts were after the event, so it's unread.\n return false;\n }\n\n /**\n * @returns true if the thread with this ID can be found, and the supplied\n * user sent the latest message in it.\n */\n private userSentLatestEventInThread(threadId: string, userId: string): boolean {\n const timeline =\n threadId === MAIN_ROOM_TIMELINE\n ? this.room.getLiveTimeline().getEvents()\n : this.room.getThread(threadId)?.timeline;\n\n return !!(timeline && timeline.length > 0 && timeline[timeline.length - 1].getSender() === userId);\n }\n}\n\n// --- implementation details ---\n\n/**\n * The information \"inside\" a receipt once it has been stored inside\n * RoomReceipts - what eventId it refers to, its type, and its ts.\n *\n * Does not contain userId or threadId since these are stored as keys of the\n * maps in RoomReceipts.\n */\nclass ReceiptInfo {\n public constructor(\n public eventId: string,\n public receiptType: string,\n public ts: number,\n ) {}\n}\n\n/**\n * Everything we know about a receipt that is \"dangling\" because we can't find\n * the event to which it refers.\n */\nclass DanglingReceipt {\n public constructor(\n public eventId: string,\n public receiptType: string,\n public userId: string,\n public receipt: Receipt,\n public synthetic: boolean,\n ) {}\n}\n\nclass UserReceipts {\n private room: Room;\n\n /**\n * The real receipt for this user.\n */\n private real: ReceiptInfo | undefined;\n\n /**\n * The synthetic receipt for this user. If this is defined, it is later than real.\n */\n private synthetic: ReceiptInfo | undefined;\n\n public constructor(room: Room) {\n this.room = room;\n this.real = undefined;\n this.synthetic = undefined;\n }\n\n public set(synthetic: boolean, receiptInfo: ReceiptInfo): void {\n if (synthetic) {\n this.synthetic = receiptInfo;\n } else {\n this.real = receiptInfo;\n }\n\n // Preserve the invariant: synthetic is only defined if it's later than real\n if (this.synthetic && this.real) {\n if (isAfterOrSame(this.real.eventId, this.synthetic.eventId, this.room)) {\n this.synthetic = undefined;\n }\n }\n }\n\n /**\n * Return the latest receipt we have - synthetic if we have one (and it's\n * later), otherwise real.\n */\n public get(): ReceiptInfo | undefined {\n // Relies on the invariant that synthetic is only defined if it's later than real.\n return this.synthetic ?? this.real;\n }\n\n /**\n * Return the latest receipt we have of the specified type (synthetic or not).\n */\n public getByType(synthetic: boolean): ReceiptInfo | undefined {\n return synthetic ? this.synthetic : this.real;\n }\n}\n\n/**\n * The latest receipt info we have, either for a single thread, or all the\n * unthreaded receipts for a room.\n *\n * userId: ReceiptInfo\n */\nclass ReceiptsByUser {\n private room: Room;\n\n /** map of userId: UserReceipts */\n private data: Map<string, UserReceipts>;\n\n public constructor(room: Room) {\n this.room = room;\n this.data = new Map<string, UserReceipts>();\n }\n\n /**\n * Add the supplied receipt to our structure, if it is not earlier than the\n * one we already hold for this user.\n */\n public set(eventId: string, receiptType: string, userId: string, ts: number, synthetic: boolean): void {\n const userReceipts = getOrCreate(this.data, userId, () => new UserReceipts(this.room));\n\n const existingReceipt = userReceipts.getByType(synthetic);\n if (existingReceipt && isAfter(existingReceipt.eventId, eventId, this.room)) {\n // The new receipt is before the existing one - don't store it.\n return;\n }\n\n // Possibilities:\n //\n // 1. there was no existing receipt, or\n // 2. the existing receipt was before this one, or\n // 3. we were unable to compare the receipts.\n //\n // In the case of 3 it's difficult to decide what to do, so the\n // most-recently-received receipt wins.\n //\n // Case 3 can only happen if the events for these receipts have\n // disappeared, which is quite unlikely since the new one has just been\n // checked, and the old one was checked before it was inserted here.\n //\n // We go ahead and store this receipt (replacing the other if it exists)\n userReceipts.set(synthetic, new ReceiptInfo(eventId, receiptType, ts));\n }\n\n /**\n * Find the latest receipt we have for this user. (Note - there is only one\n * receipt per user, because we are already inside a specific thread or\n * unthreaded list.)\n *\n * If there is a later synthetic receipt for this user, return that.\n * Otherwise, return the real receipt.\n *\n * @returns the found receipt info, or undefined if we have no receipt for this user.\n */\n public get(userId: string): ReceiptInfo | undefined {\n return this.data.get(userId)?.get();\n }\n}\n\n/**\n * The latest threaded receipts we have for a room.\n */\nclass ThreadedReceipts {\n private room: Room;\n\n /** map of threadId: ReceiptsByUser */\n private data: Map<string, ReceiptsByUser>;\n\n public constructor(room: Room) {\n this.room = room;\n this.data = new Map<string, ReceiptsByUser>();\n }\n\n /**\n * Add the supplied receipt to our structure, if it is not earlier than one\n * we already hold for this user in this thread.\n */\n public set(\n threadId: string,\n eventId: string,\n receiptType: string,\n userId: string,\n ts: number,\n synthetic: boolean,\n ): void {\n const receiptsByUser = getOrCreate(this.data, threadId, () => new ReceiptsByUser(this.room));\n receiptsByUser.set(eventId, receiptType, userId, ts, synthetic);\n }\n\n /**\n * Find the latest threaded receipt for the supplied user in the supplied thread.\n *\n * @returns the found receipt info or undefined if we don't have one.\n */\n public get(threadId: string, userId: string): ReceiptInfo | undefined {\n return this.data.get(threadId)?.get(userId);\n }\n}\n\n/**\n * All the receipts that we have received but can't process because we can't\n * find the event they refer to.\n *\n * We hold on to them so we can process them if their event arrives later.\n */\nclass DanglingReceipts {\n /**\n * eventId: DanglingReceipt[]\n */\n private data = new Map<string, Array<DanglingReceipt>>();\n\n /**\n * Remember the supplied dangling receipt.\n */\n public add(danglingReceipt: DanglingReceipt): void {\n const danglingReceipts = getOrCreate(this.data, danglingReceipt.eventId, () => []);\n danglingReceipts.push(danglingReceipt);\n }\n\n /**\n * Remove and return the dangling receipts for the given event ID.\n * @param eventId - the event ID to look for\n * @returns the found dangling receipts, or undefined if we don't have one.\n */\n public remove(eventId: string): Array<DanglingReceipt> | undefined {\n const danglingReceipts = this.data.get(eventId);\n this.data.delete(eventId);\n return danglingReceipts;\n }\n}\n\nfunction getOrCreate<K, V>(m: Map<K, V>, key: K, createFn: () => V): V {\n const found = m.get(key);\n if (found) {\n return found;\n } else {\n const created = createFn();\n m.set(key, created);\n return created;\n }\n}\n\n/**\n * Is left after right (or the same)?\n *\n * Only returns true if both events can be found, and left is after or the same\n * as right.\n *\n * @returns left \\>= right\n */\nfunction isAfterOrSame(leftEventId: string, rightEventId: string, room: Room): boolean {\n const comparison = room.compareEventOrdering(leftEventId, rightEventId);\n return comparison !== null && comparison >= 0;\n}\n\n/**\n * Is left strictly after right?\n *\n * Only returns true if both events can be found, and left is strictly after right.\n *\n * @returns left \\> right\n */\nfunction isAfter(leftEventId: string, rightEventId: string, room: Room): boolean {\n const comparison = room.compareEventOrdering(leftEventId, rightEventId);\n return comparison !== null && comparison > 0;\n}\n","/*\nCopyright 2026 Element Creations Ltd.\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 { MatrixEvent } from \"../models/event.ts\";\nimport { RoomEvent, type Room } from \"./room.ts\";\nimport { RoomStateEvent, type RoomState } from \"./room-state.ts\";\nimport { type Logger, logger as rootLogger } from \"../logger.ts\";\nimport { EventType } from \"../@types/event.ts\";\nimport type { RetentionPolicyService } from \"../retentionPolicy.ts\";\nimport type { IStore } from \"../store/index.ts\";\nimport { ROOM_RETENTION_TYPE, type RoomRetentionContent } from \"../@types/retention.ts\";\n\n/**\n * Applies https://github.com/matrix-org/matrix-spec-proposals/pull/1763 by checking the current\n * state of the room and applying the *latest* retention policy to all preceeding events.\n * Currently does not:\n * - Apply global server policies (requires Synapse work)\n * - React at all to `min_retention` configs.\n * - Loop\n */\nexport class RoomRetentionPolicy {\n // minRetention is not implemented.\n private maxRetention: number | null = null;\n private retentionTimeout?: ReturnType<typeof setTimeout>;\n private readonly logger: Logger;\n\n public constructor(\n private readonly room: Room,\n private readonly retentionService: RetentionPolicyService,\n private readonly store: IStore,\n ) {\n this.logger = rootLogger.getChild(`RetentionPolicy ${room.roomId}`);\n\n // Recalculate on room state update.\n room.on(RoomStateEvent.Events, (event) => {\n if (\n event.getStateKey() !== \"\" ||\n (event.getType() !== \"org.matrix.msc1763.retention\" && event.getType() !== \"m.room.retention\")\n ) {\n return;\n }\n void this.handleRetentionUpdate();\n });\n\n // Recalculate our retention whenever the global policy changes.\n this.retentionService.on(\"update\", () => {\n this.logger.info(\"Got global retention policy update!\");\n void this.handleRetentionUpdate();\n });\n // Do an initial check on construction.\n void this.handleRetentionUpdate();\n\n // Only bind RoomEvent.Timeline once we know we have a retention policy.\n }\n\n public shouldEventBeRetained(ev: MatrixEvent): boolean {\n if (!this.maxRetention) {\n return true;\n }\n const expireBefore = Date.now() - this.maxRetention;\n return ev.getTs() > expireBefore;\n }\n\n private readonly handleRetentionUpdate = async (): Promise<void> => {\n // First store if we currently have a retention period.\n const hadRetentionPeriod = this.maxRetention !== null;\n\n try {\n await this.recalculateRetention(this.room.currentState);\n } catch (err) {\n this.logger.warn(\"Failed to recalculate retention policy\", err);\n return;\n }\n\n // Bind/unbind the Timeline event handler based on whether we should be running retention.\n if (hadRetentionPeriod !== (this.maxRetention !== null)) {\n this.logger.info(\"retention recalculated to be\", this.maxRetention);\n // We've changed\n if (this.maxRetention) {\n this.room.on(RoomEvent.Timeline, this.timelineUpdated);\n } else {\n this.room.off(RoomEvent.Timeline, this.timelineUpdated);\n }\n }\n };\n\n private readonly recalculateRetention = async (roomState: RoomState): Promise<void> => {\n const unstableEvent = roomState.getStateEvents(ROOM_RETENTION_TYPE.name).find((e) => e.getStateKey() === \"\");\n const stableEvent = roomState.getStateEvents(ROOM_RETENTION_TYPE.altName).find((e) => e.getStateKey() === \"\");\n\n const serverPolicy = this.retentionService.getCached();\n\n const serverRoomPolicy = serverPolicy?.policies?.[this.room.roomId];\n const roomStatePolicy =\n unstableEvent?.getContent<RoomRetentionContent>() ?? stableEvent?.getContent<RoomRetentionContent>();\n\n const content =\n // * if the homeserver defines a specific retention policy for this room, then use this policy as the effective retention policy of the room.\n serverRoomPolicy ??\n // * otherwise, if the state of the room includes a `m.room.retention` event with an empty state key:\n roomStatePolicy ??\n // * otherwise, if the state of the room does not include a m.room.retention event with an empty state key:\n serverPolicy?.policies?.[\"*\"];\n\n if (!content) {\n // * otherwise, don't apply a retention policy in this room.\n this.maxRetention = null;\n return;\n }\n\n const validatePolicy = !serverRoomPolicy && roomStatePolicy;\n\n // Parse it\n let { max_lifetime: maxLifetime } = content;\n\n if (!maxLifetime && validatePolicy) {\n // if there is no value specified in the room's state, use the limit's min value for the effective retention policy of the room (which can be null or absent).\n maxLifetime = serverPolicy?.limits?.max_lifetime?.min;\n if (!maxLifetime) {\n this.maxRetention = null;\n return;\n }\n }\n\n if (typeof maxLifetime !== \"number\") {\n throw Error(`max_lifetime must be a number, got \"${maxLifetime}\"`);\n }\n if (maxLifetime < 0 || !Number.isInteger(maxLifetime)) {\n throw Error(`max_lifetime must be >= 0, got ${maxLifetime}`);\n }\n this.maxRetention = maxLifetime;\n\n if (validatePolicy && serverPolicy?.limits?.max_lifetime) {\n // We're using room state so we need to validate this policy matches the server.\n /**\n if the value specified in the room's state complies with the limit, use this value for the effective retention policy of the room.\n if the value specified in the room's state is lower than the limit's min value, use the min value for the effective retention policy of the room.\n if the value specified in the room's state is greater than the limit's max value, use the max value for the effective retention policy of the room.\n */\n this.maxRetention = Math.max(this.maxRetention, serverPolicy.limits.max_lifetime.min ?? 0);\n this.maxRetention = Math.min(\n this.maxRetention,\n serverPolicy.limits.max_lifetime.max ?? Number.MAX_SAFE_INTEGER,\n );\n }\n\n this.processTimeline();\n };\n\n private readonly timelineUpdated = (): void => {\n this.logger.info(\"timelineUpdated\");\n this.scheduleTimelineCheck(200);\n };\n\n private readonly scheduleTimelineCheck = (nextTs: number): void => {\n if (this.retentionTimeout) {\n clearTimeout(this.retentionTimeout);\n }\n this.retentionTimeout = setTimeout(() => {\n this.processTimeline();\n this.retentionTimeout = undefined;\n }, nextTs);\n };\n\n private processTimeline(): void {\n if (!this.maxRetention) {\n return; // No policy, skip.\n }\n this.logger.info(`Running processTimeline`);\n const expireBefore = Date.now() - this.maxRetention;\n const events = this.room\n .getLiveTimeline()\n .getEvents()\n .filter((ev) => ev.getStateKey() === undefined && !ev.isRedacted() && ev.getType() !== \"m.room.redaction\");\n\n const expiredEvents = events.filter((ev) => ev.getTs() < expireBefore);\n const [earliestExpiringEvent] = events\n .filter((ev) => ev.getTs() >= expireBefore)\n .sort((a, b) => a.getTs() - b.getTs());\n\n if (earliestExpiringEvent) {\n const nextTs = earliestExpiringEvent.getTs() + this.maxRetention - Date.now();\n this.logger.info(`Next expiry scheduled for ${nextTs}`);\n this.scheduleTimelineCheck(nextTs);\n }\n\n if (expiredEvents.length === 0) {\n this.logger.info(\"Found no expired events\");\n return;\n }\n this.logger.info(`Found ${expiredEvents.length} expired events`);\n for (const event of expiredEvents) {\n this.room.tryApplyRedaction(\n new MatrixEvent({\n type: EventType.RoomRedaction,\n sender: event.getSender(),\n event_id: \"$synthetic_redaction\",\n room_id: this.room.roomId,\n redacts: event.getId(),\n content: {\n reason: \"Retention policy\",\n },\n origin_server_ts: Date.now(),\n unsigned: {},\n }),\n );\n }\n void this.store\n .removeEventsFromRoom(\n this.room.roomId,\n expiredEvents.map((e) => e.getId()!),\n )\n .catch((ex) => {\n this.logger.warn(`Failed to remove events from store`, ex);\n });\n }\n}\n","/*\nCopyright 2015 - 2021 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\n/**\n * A stripped m.room.member event which contains the key renderable fields from the event,\n * sent only in simplified sliding sync (not `/v3/sync`).\n * This is very similar to MSC4186Hero from sliding-sync.ts but an internal format with\n * camelCase rather than underscores.\n */\nexport type Hero = {\n userId: string;\n displayName?: string;\n avatarUrl?: string;\n /**\n * If true, the hero is from an MSC4186 summary, in which case `displayName` and `avatarUrl` will\n * have been set by the server if available. If false, the `Hero` has been constructed from a `/v3/sync` response,\n * so these fields will always be undefined.\n */\n fromMSC4186: boolean;\n};\n\n/**\n * High level summary information for a room, as returned by `/v3/sync`.\n */\nexport interface IRoomSummary {\n /**\n * The room heroes: a selected set of members that can be used when summarising or\n * generating a name for a room. List of user IDs.\n */\n \"m.heroes\": string[];\n /**\n * The number of joined members in the room.\n */\n \"m.joined_member_count\"?: number;\n /**\n * The number of invited members in the room.\n */\n \"m.invited_member_count\"?: number;\n}\n\ninterface IInfo {\n /** The title of the room (e.g. `m.room.name`) */\n title: string;\n /** The description of the room (e.g. `m.room.topic`) */\n desc?: string;\n /** The number of joined users. */\n numMembers?: number;\n /** The list of aliases for this room. */\n aliases?: string[];\n /** The timestamp for this room. */\n timestamp?: number;\n}\n\n/**\n * Construct a new Room Summary. A summary can be used for display on a recent\n * list, without having to load the entire room list into memory.\n * @param roomId - Required. The ID of this room.\n * @param info - Optional. The summary info. Additional keys are supported.\n */\nexport class RoomSummary {\n public constructor(\n public readonly roomId: string,\n info?: IInfo,\n ) {}\n}\n","/*\nCopyright 2023 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 hasOptionalStringProperty,\n hasRequiredStringProperty,\n isRecord,\n optionalStringArrayProperty,\n requiredArrayValue,\n} from \"../@types/type-guards.ts\";\nimport { OAuthGrantType } from \"./index.ts\";\n\n/**\n * Metadata from OAuth 2.0 client authentication API as per\n * https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv1auth_metadata\n * With validated properties required in type\n */\nexport interface ValidatedAuthMetadata {\n /** List of actions that the account management URL supports. */\n account_management_actions_supported?: string[];\n /** The URL where the user is able to access the account management capabilities of the homeserver. */\n account_management_uri?: string;\n /** URL of the authorization endpoint, necessary to use the authorization code grant. */\n authorization_endpoint: string;\n /**\n * List of OAuth 2.0 Proof Key for Code Exchange (PKCE) code challenge methods that the server supports at the authorization endpoint.\n *\n * This array MUST contain at least the S256 value, for improved security in the authorization code grant.\n */\n code_challenge_methods_supported: string[];\n /** URL of the device authorization endpoint, as defined in RFC 8628, necessary to use the device authorization grant. */\n device_authorization_endpoint?: string;\n /**\n * List of OAuth 2.0 grant type strings that the server supports at the token endpoint.\n *\n * This array MUST contain at least the authorization_code and refresh_token values,\n * for clients to be able to use the authorization code grant and refresh token grant, respectively.\n */\n grant_types_supported: string[];\n /** The authorization server’s issuer identifier, which is a URL that uses the https scheme and has no query or fragment components. */\n issuer: string;\n /** List of OpenID Connect prompt values that the server supports at the authorization endpoint. */\n prompt_values_supported?: string[];\n /** URL of the client registration endpoint, necessary to perform dynamic registration of a client. */\n registration_endpoint: string;\n /**\n * List of OAuth 2.0 response mode strings that the server supports at the authorization endpoint.\n *\n * This array MUST contain at least the query and fragment values, for improved security in the authorization code grant.\n */\n response_modes_supported: string[];\n /**\n * List of OAuth 2.0 response type strings that the server supports at the authorization endpoint.\n *\n * This array MUST contain at least the code value, for clients to be able to use the authorization code grant.\n */\n response_types_supported: string[];\n /** URL of the revocation endpoint, necessary to log out a client by invalidating its access and refresh tokens. */\n revocation_endpoint: string;\n /** URL of the token endpoint, used by the grants. */\n token_endpoint: string;\n}\n\n/**\n * Validates OAuth 2.0 auth metadata as defined by\n * https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv1auth_metadata\n * @param authMetadata - json object\n * @returns boolean of whether the input is valid\n */\nexport const isValidAuthMetadata = (authMetadata: unknown): authMetadata is ValidatedAuthMetadata => {\n return (\n isRecord(authMetadata) &&\n hasRequiredStringProperty(authMetadata, \"issuer\") &&\n hasRequiredStringProperty(authMetadata, \"authorization_endpoint\") &&\n hasRequiredStringProperty(authMetadata, \"token_endpoint\") &&\n hasRequiredStringProperty(authMetadata, \"revocation_endpoint\") &&\n hasRequiredStringProperty(authMetadata, \"registration_endpoint\") &&\n hasOptionalStringProperty(authMetadata, \"account_management_uri\") &&\n hasOptionalStringProperty(authMetadata, \"device_authorization_endpoint\") &&\n optionalStringArrayProperty(authMetadata, \"account_management_actions_supported\") &&\n optionalStringArrayProperty(authMetadata, \"prompt_values_supported\") &&\n requiredArrayValue(authMetadata, \"response_modes_supported\", \"query\") &&\n requiredArrayValue(authMetadata, \"response_modes_supported\", \"fragment\") &&\n requiredArrayValue(authMetadata, \"response_types_supported\", \"code\") &&\n requiredArrayValue(authMetadata, \"grant_types_supported\", OAuthGrantType.AuthorizationCode) &&\n requiredArrayValue(authMetadata, \"grant_types_supported\", OAuthGrantType.RefreshToken) &&\n requiredArrayValue(authMetadata, \"code_challenge_methods_supported\", \"S256\")\n );\n};\n","/*\nCopyright 2023 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\n/**\n * Errors expected to be encountered during OAuth2 discovery, client registration, and authentication.\n * Not intended to be displayed directly to the user.\n */\nexport enum OAuth2Error {\n General = \"Something went wrong with OAuth2 discovery\",\n OpSupport = \"Configured OAuth2 OP does not support required functions\",\n DynamicRegistrationNotSupported = \"Dynamic registration not supported\",\n DynamicRegistrationFailed = \"Dynamic registration failed\",\n DynamicRegistrationInvalid = \"Dynamic registration invalid response\",\n CodeExchangeFailed = \"Failed to exchange code for token\",\n InvalidBearerTokenResponse = \"Invalid bearer token response\",\n InvalidDeviceAuthorizationResponse = \"Invalid device authorization response\",\n MissingOrInvalidStoredState = \"State required to finish logging in is not found in storage.\",\n RefreshTokenFailed = \"Failed to refresh token\",\n RevokeTokenFailed = \"Failed to revoke token\",\n DeviceAuthorizationGrantFailed = \"Failed to perform device authorization grant\",\n}\n","/*\nCopyright 2015 - 2021 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 { deepCompare, escapeRegExp, globToRegexp, isNullOrUndefined } from \"./utils.ts\";\nimport { type Logger } from \"./logger.ts\";\nimport { type MatrixClient } from \"./client.ts\";\nimport { type MatrixEvent } from \"./models/event.ts\";\nimport {\n ConditionKind,\n type IAnnotatedPushRule,\n type ICallStartedCondition,\n type ICallStartedPrefixCondition,\n type IContainsDisplayNameCondition,\n type IEventMatchCondition,\n type IEventPropertyContainsCondition,\n type IEventPropertyIsCondition,\n type IPushRule,\n type IPushRules,\n type IRoomMemberCountCondition,\n type ISenderNotificationPermissionCondition,\n type PushRuleAction,\n PushRuleActionName,\n type PushRuleCondition,\n PushRuleKind,\n type PushRuleSet,\n RuleId,\n TweakName,\n} from \"./@types/PushRules.ts\";\nimport { EventType } from \"./@types/event.ts\";\n\nconst RULEKINDS_IN_ORDER = [\n PushRuleKind.Override,\n PushRuleKind.ContentSpecific,\n PushRuleKind.RoomSpecific,\n PushRuleKind.SenderSpecific,\n PushRuleKind.Underride,\n];\n\n// The default override rules to apply to the push rules that arrive from the server.\n// We do this for two reasons:\n// 1. Synapse is unlikely to send us the push rule in an incremental sync - see\n// https://github.com/matrix-org/synapse/pull/4867#issuecomment-481446072 for\n// more details.\n// 2. We often want to start using push rules ahead of the server supporting them,\n// and so we can put them here.\nconst DEFAULT_OVERRIDE_RULES: Record<string, IPushRule> = {\n \".m.rule.is_room_mention\": {\n // Matrix v1.7\n rule_id: \".m.rule.is_room_mention\",\n default: true,\n enabled: true,\n conditions: [\n {\n kind: ConditionKind.EventPropertyIs,\n key: \"content.m\\\\.mentions.room\",\n value: true,\n },\n {\n kind: ConditionKind.SenderNotificationPermission,\n key: \"room\",\n },\n ],\n actions: [\n PushRuleActionName.Notify,\n {\n set_tweak: TweakName.Highlight,\n },\n ],\n },\n \".m.rule.reaction\": {\n // For homeservers which don't support MSC2153 yet\n rule_id: \".m.rule.reaction\",\n default: true,\n enabled: true,\n conditions: [\n {\n kind: ConditionKind.EventMatch,\n key: \"type\",\n pattern: \"m.reaction\",\n },\n ],\n actions: [PushRuleActionName.DontNotify],\n },\n \".org.matrix.msc3786.rule.room.server_acl\": {\n // For homeservers which don't support MSC3786 yet\n rule_id: \".org.matrix.msc3786.rule.room.server_acl\",\n default: true,\n enabled: true,\n conditions: [\n {\n kind: ConditionKind.EventMatch,\n key: \"type\",\n pattern: EventType.RoomServerAcl,\n },\n {\n kind: ConditionKind.EventMatch,\n key: \"state_key\",\n pattern: \"\",\n },\n ],\n actions: [],\n },\n};\n\n// A special rule id for `EXPECTED_DEFAULT_OVERRIDE_RULE_IDS` and friends which denotes where user-defined rules live in the order.\nconst UserDefinedRules = Symbol(\"UserDefinedRules\");\n\ntype OrderedRules = Array<string | typeof UserDefinedRules>;\n\nconst EXPECTED_DEFAULT_OVERRIDE_RULE_IDS: OrderedRules = [\n RuleId.Master,\n UserDefinedRules,\n RuleId.SuppressNotices,\n RuleId.InviteToSelf,\n RuleId.MemberEvent,\n RuleId.IsUserMention,\n RuleId.ContainsDisplayName,\n RuleId.IsRoomMention,\n RuleId.AtRoomNotification,\n RuleId.Tombstone,\n \".m.rule.reaction\",\n \".m.rule.room.server_acl\",\n \".org.matrix.msc3786.rule.room.server_acl\",\n \".m.rule.suppress_edits\",\n];\n\nconst DEFAULT_UNDERRIDE_RULES: Record<string, IPushRule> = {\n \".org.matrix.msc3914.rule.room.call\": {\n // For homeservers which don't support MSC3914 yet\n rule_id: \".org.matrix.msc3914.rule.room.call\",\n default: true,\n enabled: true,\n conditions: [\n {\n kind: ConditionKind.EventMatch,\n key: \"type\",\n pattern: \"org.matrix.msc3401.call\",\n },\n {\n kind: ConditionKind.CallStarted,\n },\n ],\n actions: [PushRuleActionName.Notify, { set_tweak: TweakName.Sound, value: \"default\" }],\n },\n};\n\nconst EXPECTED_DEFAULT_UNDERRIDE_RULE_IDS: OrderedRules = [\n UserDefinedRules,\n RuleId.IncomingCall,\n \".org.matrix.msc3914.rule.room.call\",\n RuleId.EncryptedDM,\n RuleId.DM,\n RuleId.Message,\n RuleId.EncryptedMessage,\n];\n\n/**\n * Make sure that each of the rules listed in `defaultRuleIds` is listed in the given set of push rules.\n *\n * @param logger - A `Logger` to write log messages to.\n * @param kind - the kind of push rule set being merged.\n * @param incomingRules - the existing set of known push rules for the user.\n * @param defaultRules - a lookup table for the default definitions of push rules.\n * @param orderedRuleIds - the IDs of the expected push rules, in order.\n *\n * @returns A copy of `incomingRules`, with any missing default rules inserted in the right place.\n */\nfunction mergeRulesWithDefaults(\n logger: Logger,\n kind: PushRuleKind,\n incomingRules: IPushRule[],\n defaultRules: Record<string, IPushRule>,\n orderedRuleIds: OrderedRules,\n): IPushRule[] {\n // Split the incomingRules into defaults and custom\n const incomingDefaultRules = incomingRules.filter((rule) => rule.default);\n const incomingCustomRules = incomingRules.filter((rule) => !rule.default);\n\n function insertDefaultPushRule(ruleId: OrderedRules[number]): void {\n if (ruleId === UserDefinedRules) {\n // Re-insert any user-defined rules that were in `incomingRules`\n newRules.push(...incomingCustomRules);\n } else if (ruleId in defaultRules) {\n logger.warn(`Adding default global ${kind} push rule ${ruleId}`);\n newRules.push(defaultRules[ruleId]);\n } else {\n logger.warn(`Missing default global ${kind} push rule ${ruleId}`);\n }\n }\n\n let nextExpectedRuleIdIndex = 0;\n const newRules: IPushRule[] = [];\n // Merge our expected rules (including the incoming custom rules) into the incoming default rules.\n for (const rule of incomingDefaultRules) {\n const ruleIndex = orderedRuleIds.indexOf(rule.rule_id);\n if (ruleIndex === -1) {\n // an unrecognised rule; copy it over\n newRules.push(rule);\n continue;\n }\n while (ruleIndex > nextExpectedRuleIdIndex) {\n // insert new rules\n const defaultRuleId = orderedRuleIds[nextExpectedRuleIdIndex];\n insertDefaultPushRule(defaultRuleId);\n nextExpectedRuleIdIndex += 1;\n }\n // copy over the existing rule\n newRules.push(rule);\n nextExpectedRuleIdIndex += 1;\n }\n\n // Now copy over any remaining default rules\n for (const ruleId of orderedRuleIds.slice(nextExpectedRuleIdIndex)) {\n insertDefaultPushRule(ruleId);\n }\n\n return newRules;\n}\n\nexport interface IActionsObject {\n /** Whether this event should notify the user or not. */\n notify: boolean;\n /** How this event should be notified. */\n tweaks: Partial<Record<TweakName, any>>;\n}\n\nexport class PushProcessor {\n /**\n * Construct a Push Processor.\n * @param client - The Matrix client object to use\n */\n public constructor(private readonly client: MatrixClient) {}\n\n /**\n * Maps the original key from the push rules to a list of property names\n * after unescaping.\n */\n private readonly parsedKeys = new Map<string, string[]>();\n\n /**\n * Convert a list of actions into a object with the actions as keys and their values\n * @example\n * eg. `[ 'notify', { set_tweak: 'sound', value: 'default' } ]`\n * becomes `{ notify: true, tweaks: { sound: 'default' } }`\n * @param actionList - The actions list\n *\n * @returns A object with key 'notify' (true or false) and an object of actions\n */\n public static actionListToActionsObject(actionList: PushRuleAction[]): IActionsObject {\n const actionObj: IActionsObject = { notify: false, tweaks: {} };\n for (const action of actionList) {\n if (action === PushRuleActionName.Notify) {\n actionObj.notify = true;\n } else if (typeof action === \"object\") {\n if (action.value === undefined) {\n action.value = true;\n }\n actionObj.tweaks[action.set_tweak] = action.value;\n }\n }\n return actionObj;\n }\n\n /**\n * Rewrites conditions on a client's push rules to match the defaults\n * where applicable. Useful for upgrading push rules to more strict\n * conditions when the server is falling behind on defaults.\n *\n * @param logger - A `Logger` to write log messages to.\n * @param incomingRules - The client's existing push rules\n * @param userId - The Matrix ID of the client.\n * @returns The rewritten rules\n */\n public static rewriteDefaultRules(\n logger: Logger,\n incomingRules: IPushRules,\n userId: string | undefined = undefined,\n ): IPushRules {\n let newRules: IPushRules = JSON.parse(JSON.stringify(incomingRules)); // deep clone\n\n // These lines are mostly to make the tests happy. We shouldn't run into these\n // properties missing in practice.\n if (!newRules) newRules = {} as IPushRules;\n if (!newRules.global) newRules.global = {} as PushRuleSet;\n if (!newRules.global.override) newRules.global.override = [];\n if (!newRules.global.underride) newRules.global.underride = [];\n\n // Merge the client-level defaults with the ones from the server\n newRules.global.override = mergeRulesWithDefaults(\n logger,\n PushRuleKind.Override,\n newRules.global.override,\n DEFAULT_OVERRIDE_RULES,\n EXPECTED_DEFAULT_OVERRIDE_RULE_IDS,\n );\n\n newRules.global.underride = mergeRulesWithDefaults(\n logger,\n PushRuleKind.Underride,\n newRules.global.underride,\n DEFAULT_UNDERRIDE_RULES,\n EXPECTED_DEFAULT_UNDERRIDE_RULE_IDS,\n );\n\n return newRules;\n }\n\n /**\n * Create a RegExp object for the given glob pattern with a single capture group around the pattern itself, caching the result.\n * No cache invalidation is present currently,\n * as this will be inherently bounded to the size of the user's own push rules.\n * @param pattern - the glob pattern to convert to a RegExp\n * @param alignToWordBoundary - whether to align the pattern to word boundaries,\n * as specified for `content.body` matches, will use lookaround assertions to ensure the match only includes the pattern\n * @param flags - the flags to pass to the RegExp constructor, defaults to case-insensitive\n */\n public static getPushRuleGlobRegex(pattern: string, alignToWordBoundary = false, flags = \"i\"): RegExp {\n const [prefix, suffix] = alignToWordBoundary ? [\"(?<=^|\\\\W)\", \"(?=\\\\W|$)\"] : [\"^\", \"$\"];\n const cacheKey = `${alignToWordBoundary}-${flags}-${pattern}`;\n\n if (!PushProcessor.cachedGlobToRegex[cacheKey]) {\n PushProcessor.cachedGlobToRegex[cacheKey] = new RegExp(\n prefix + \"(\" + globToRegexp(pattern) + \")\" + suffix,\n flags,\n );\n }\n return PushProcessor.cachedGlobToRegex[cacheKey];\n }\n\n /**\n * Pre-caches the parsed keys for push rules and cleans out any obsolete cache\n * entries. Should be called after push rules are updated.\n * @param newRules - The new push rules.\n */\n public updateCachedPushRuleKeys(newRules: IPushRules): void {\n // These lines are mostly to make the tests happy. We shouldn't run into these\n // properties missing in practice.\n if (!newRules) newRules = {} as IPushRules;\n if (!newRules.global) newRules.global = {} as PushRuleSet;\n if (!newRules.global.override) newRules.global.override = [];\n if (!newRules.global.room) newRules.global.room = [];\n if (!newRules.global.sender) newRules.global.sender = [];\n if (!newRules.global.underride) newRules.global.underride = [];\n\n // Process the 'key' property on event_match conditions pre-cache the\n // values and clean-out any unused values.\n const toRemoveKeys = new Set(this.parsedKeys.keys());\n for (const ruleset of [\n newRules.global.override,\n newRules.global.room,\n newRules.global.sender,\n newRules.global.underride,\n ]) {\n for (const rule of ruleset) {\n if (!rule.conditions) {\n continue;\n }\n\n for (const condition of rule.conditions) {\n if (condition.kind !== ConditionKind.EventMatch) {\n continue;\n }\n\n // Ensure we keep this key.\n toRemoveKeys.delete(condition.key);\n\n // Pre-process the key.\n this.parsedKeys.set(condition.key, PushProcessor.partsForDottedKey(condition.key));\n }\n }\n }\n // Any keys that were previously cached, but are no longer needed should\n // be removed.\n toRemoveKeys.forEach((k) => this.parsedKeys.delete(k));\n }\n\n private static cachedGlobToRegex: Record<string, RegExp> = {}; // $glob: RegExp\n\n private matchingRuleFromKindSet(ev: MatrixEvent, kindset: PushRuleSet): IAnnotatedPushRule | null {\n for (const kind of RULEKINDS_IN_ORDER) {\n const ruleset = kindset[kind];\n if (!ruleset) {\n continue;\n }\n\n for (const rule of ruleset) {\n if (!rule.enabled) {\n continue;\n }\n\n const rawrule = this.templateRuleToRaw(kind, rule);\n if (!rawrule) {\n continue;\n }\n\n if (this.ruleMatchesEvent(rawrule, ev)) {\n return {\n ...rule,\n kind,\n };\n }\n }\n }\n return null;\n }\n\n private templateRuleToRaw(\n kind: PushRuleKind,\n tprule: IPushRule,\n ): Pick<IPushRule, \"rule_id\" | \"actions\" | \"conditions\"> | null {\n const rawrule: Pick<IPushRule, \"rule_id\" | \"actions\" | \"conditions\"> = {\n rule_id: tprule.rule_id,\n actions: tprule.actions,\n conditions: [],\n };\n switch (kind) {\n case PushRuleKind.Underride:\n case PushRuleKind.Override:\n rawrule.conditions = tprule.conditions;\n break;\n case PushRuleKind.RoomSpecific:\n if (!tprule.rule_id) {\n return null;\n }\n rawrule.conditions!.push({\n kind: ConditionKind.EventMatch,\n key: \"room_id\",\n value: tprule.rule_id,\n });\n break;\n case PushRuleKind.SenderSpecific:\n if (!tprule.rule_id) {\n return null;\n }\n rawrule.conditions!.push({\n kind: ConditionKind.EventMatch,\n key: \"user_id\",\n value: tprule.rule_id,\n });\n break;\n case PushRuleKind.ContentSpecific:\n if (!tprule.pattern) {\n return null;\n }\n rawrule.conditions!.push({\n kind: ConditionKind.EventMatch,\n key: \"content.body\",\n pattern: tprule.pattern,\n });\n break;\n }\n return rawrule;\n }\n\n private eventFulfillsCondition(cond: PushRuleCondition, ev: MatrixEvent): boolean {\n switch (cond.kind) {\n case ConditionKind.EventMatch:\n return this.eventFulfillsEventMatchCondition(cond, ev);\n case ConditionKind.EventPropertyIs:\n return this.eventFulfillsEventPropertyIsCondition(cond, ev);\n case ConditionKind.EventPropertyContains:\n return this.eventFulfillsEventPropertyContains(cond, ev);\n case ConditionKind.ContainsDisplayName:\n return this.eventFulfillsDisplayNameCondition(cond, ev);\n case ConditionKind.RoomMemberCount:\n return this.eventFulfillsRoomMemberCountCondition(cond, ev);\n case ConditionKind.SenderNotificationPermission:\n return this.eventFulfillsSenderNotifPermCondition(cond, ev);\n case ConditionKind.CallStarted:\n case ConditionKind.CallStartedPrefix:\n return this.eventFulfillsCallStartedCondition(cond, ev);\n }\n\n // unknown conditions: we previously matched all unknown conditions,\n // but given that rules can be added to the base rules on a server,\n // it's probably better to not match unknown conditions.\n return false;\n }\n\n private eventFulfillsSenderNotifPermCondition(\n cond: ISenderNotificationPermissionCondition,\n ev: MatrixEvent,\n ): boolean {\n const notifLevelKey = cond[\"key\"];\n if (!notifLevelKey) {\n return false;\n }\n\n const room = this.client.getRoom(ev.getRoomId());\n if (!room?.currentState) {\n return false;\n }\n\n // Note that this should not be the current state of the room but the state at\n // the point the event is in the DAG. Unfortunately the js-sdk does not store\n // this.\n return room.currentState.mayTriggerNotifOfType(notifLevelKey, ev.getSender()!);\n }\n\n private eventFulfillsRoomMemberCountCondition(cond: IRoomMemberCountCondition, ev: MatrixEvent): boolean {\n if (!cond.is) {\n return false;\n }\n\n const room = this.client.getRoom(ev.getRoomId());\n if (!room || !room.currentState || !room.currentState.members) {\n return false;\n }\n\n const memberCount = room.currentState.getJoinedMemberCount();\n\n const m = cond.is.match(/^([=<>]*)(\\d*)$/);\n if (!m) {\n return false;\n }\n const ineq = m[1];\n const rhs = parseInt(m[2]);\n if (isNaN(rhs)) {\n return false;\n }\n switch (ineq) {\n case \"\":\n case \"==\":\n return memberCount == rhs;\n case \"<\":\n return memberCount < rhs;\n case \">\":\n return memberCount > rhs;\n case \"<=\":\n return memberCount <= rhs;\n case \">=\":\n return memberCount >= rhs;\n default:\n return false;\n }\n }\n\n private eventFulfillsDisplayNameCondition(cond: IContainsDisplayNameCondition, ev: MatrixEvent): boolean {\n let content = ev.getContent();\n if (ev.isEncrypted() && ev.getClearContent()) {\n content = ev.getClearContent()!;\n }\n if (!content || !content.body || typeof content.body != \"string\") {\n return false;\n }\n\n const room = this.client.getRoom(ev.getRoomId());\n const member = room?.currentState?.getMember(this.client.credentials.userId!);\n if (!member) {\n return false;\n }\n\n const displayName = member.name;\n\n // N.B. we can't use \\b as it chokes on unicode. however \\W seems to be okay\n // as shorthand for [^0-9A-Za-z_].\n const pat = new RegExp(\"(^|\\\\W)\" + escapeRegExp(displayName) + \"(\\\\W|$)\", \"i\");\n return content.body.search(pat) > -1;\n }\n\n /**\n * Check whether the given event matches the push rule condition by fetching\n * the property from the event and comparing against the condition's glob-based\n * pattern.\n * @param cond - The push rule condition to check for a match.\n * @param ev - The event to check for a match.\n */\n private eventFulfillsEventMatchCondition(cond: IEventMatchCondition, ev: MatrixEvent): boolean {\n if (!cond.key) {\n return false;\n }\n\n const val = this.valueForDottedKey(cond.key, ev);\n if (typeof val !== \"string\") {\n return false;\n }\n\n // XXX This does not match in a case-insensitive manner.\n //\n // See https://spec.matrix.org/v1.5/client-server-api/#conditions-1\n if (cond.value) {\n return cond.value === val;\n }\n\n if (typeof cond.pattern !== \"string\") {\n return false;\n }\n\n // Align to word boundary on `content.body` matches, whole string otherwise\n // https://spec.matrix.org/v1.13/client-server-api/#conditions-1\n const regex = PushProcessor.getPushRuleGlobRegex(cond.pattern, cond.key === \"content.body\");\n return !!val.match(regex);\n }\n\n /**\n * Check whether the given event matches the push rule condition by fetching\n * the property from the event and comparing exactly against the condition's\n * value.\n * @param cond - The push rule condition to check for a match.\n * @param ev - The event to check for a match.\n */\n private eventFulfillsEventPropertyIsCondition(cond: IEventPropertyIsCondition, ev: MatrixEvent): boolean {\n if (!cond.key || cond.value === undefined) {\n return false;\n }\n return cond.value === this.valueForDottedKey(cond.key, ev);\n }\n\n /**\n * Check whether the given event matches the push rule condition by fetching\n * the property from the event and comparing exactly against the condition's\n * value.\n * @param cond - The push rule condition to check for a match.\n * @param ev - The event to check for a match.\n */\n private eventFulfillsEventPropertyContains(cond: IEventPropertyContainsCondition, ev: MatrixEvent): boolean {\n if (!cond.key || cond.value === undefined) {\n return false;\n }\n const val = this.valueForDottedKey(cond.key, ev);\n if (!Array.isArray(val)) {\n return false;\n }\n return val.includes(cond.value);\n }\n\n private eventFulfillsCallStartedCondition(\n _cond: ICallStartedCondition | ICallStartedPrefixCondition,\n ev: MatrixEvent,\n ): boolean {\n // Since servers don't support properly sending push notification\n // about MSC3401 call events, we do the handling ourselves\n return (\n [\"m.ring\", \"m.prompt\"].includes(ev.getContent()[\"m.intent\"]) &&\n !(\"m.terminated\" in ev.getContent()) &&\n (ev.getPrevContent()[\"m.terminated\"] !== ev.getContent()[\"m.terminated\"] ||\n deepCompare(ev.getPrevContent(), {}))\n );\n }\n\n /**\n * Parse the key into the separate fields to search by splitting on\n * unescaped \".\", and then removing any escape characters.\n *\n * @param str - The key of the push rule condition: a dotted field.\n * @returns The unescaped parts to fetch.\n * @internal\n */\n public static partsForDottedKey(str: string): string[] {\n const result: string[] = [];\n\n // The current field and whether the previous character was the escape\n // character (a backslash).\n let part = \"\";\n let escaped = false;\n\n // Iterate over each character, and decide whether to append to the current\n // part (following the escape rules) or to start a new part (based on the\n // field separator).\n for (const c of str) {\n // If the previous character was the escape character (a backslash)\n // then decide what to append to the current part.\n if (escaped) {\n if (c === \"\\\\\" || c === \".\") {\n // An escaped backslash or dot just gets added.\n part += c;\n } else {\n // A character that shouldn't be escaped gets the backslash prepended.\n part += \"\\\\\" + c;\n }\n // This always resets being escaped.\n escaped = false;\n continue;\n }\n\n if (c == \".\") {\n // The field separator creates a new part.\n result.push(part);\n part = \"\";\n } else if (c == \"\\\\\") {\n // A backslash adds no characters, but starts an escape sequence.\n escaped = true;\n } else {\n // Otherwise, just add the current character.\n part += c;\n }\n }\n\n // Ensure the final part is included. If there's an open escape sequence\n // it should be included.\n if (escaped) {\n part += \"\\\\\";\n }\n result.push(part);\n\n return result;\n }\n\n /**\n * For a dotted field and event, fetch the value at that position, if one\n * exists.\n *\n * @param key - The key of the push rule condition: a dotted field to fetch.\n * @param ev - The matrix event to fetch the field from.\n * @returns The value at the dotted path given by key.\n */\n private valueForDottedKey(key: string, ev: MatrixEvent): any {\n // The key should already have been parsed via updateCachedPushRuleKeys,\n // but if it hasn't (maybe via an old consumer of the SDK which hasn't\n // been updated?) then lazily calculate it here.\n let parts = this.parsedKeys.get(key);\n if (parts === undefined) {\n parts = PushProcessor.partsForDottedKey(key);\n this.parsedKeys.set(key, parts);\n }\n let val: any;\n\n // special-case the first component to deal with encrypted messages\n const firstPart = parts[0];\n let currentIndex = 0;\n if (firstPart === \"content\") {\n val = ev.getContent();\n ++currentIndex;\n } else if (firstPart === \"type\") {\n val = ev.getType();\n ++currentIndex;\n } else {\n // use the raw event for any other fields\n val = ev.event;\n }\n\n for (; currentIndex < parts.length; ++currentIndex) {\n // The previous iteration resulted in null or undefined, bail (and\n // avoid the type error of attempting to retrieve a property).\n if (isNullOrUndefined(val)) {\n return undefined;\n }\n\n const thisPart = parts[currentIndex];\n val = val[thisPart];\n }\n return val;\n }\n\n private matchingRuleForEventWithRulesets(ev: MatrixEvent, rulesets?: IPushRules): IAnnotatedPushRule | null {\n if (!rulesets) {\n return null;\n }\n\n if (ev.getSender() === this.client.getSafeUserId()) {\n return null;\n }\n\n return this.matchingRuleFromKindSet(ev, rulesets.global);\n }\n\n private pushActionsForEventAndRulesets(\n ev: MatrixEvent,\n rulesets?: IPushRules,\n ): {\n actions?: IActionsObject;\n rule?: IAnnotatedPushRule;\n } {\n const rule = this.matchingRuleForEventWithRulesets(ev, rulesets);\n if (!rule) {\n return {};\n }\n\n const actionObj = PushProcessor.actionListToActionsObject(rule.actions);\n\n // Some actions are implicit in some situations: we add those here\n if (actionObj.tweaks.highlight === undefined) {\n // if it isn't specified, highlight if it's a content\n // rule but otherwise not\n actionObj.tweaks.highlight = rule.kind == PushRuleKind.ContentSpecific;\n }\n\n return { actions: actionObj, rule };\n }\n\n public ruleMatchesEvent(rule: Partial<IPushRule> & Pick<IPushRule, \"conditions\">, ev: MatrixEvent): boolean {\n // Disable the deprecated mentions push rules if the new mentions property exists.\n if (\n this.client.supportsIntentionalMentions() &&\n ev.getContent()[\"m.mentions\"] !== undefined &&\n (rule.rule_id === RuleId.ContainsUserName ||\n rule.rule_id === RuleId.ContainsDisplayName ||\n rule.rule_id === RuleId.AtRoomNotification)\n ) {\n return false;\n }\n\n return !rule.conditions?.some((cond) => !this.eventFulfillsCondition(cond, ev));\n }\n\n /**\n * Get the user's push actions for the given event\n */\n public actionsForEvent(ev: MatrixEvent): IActionsObject {\n const { actions } = this.pushActionsForEventAndRulesets(ev, this.client.pushRules);\n return actions || ({} as IActionsObject);\n }\n\n public actionsAndRuleForEvent(ev: MatrixEvent): {\n actions?: IActionsObject;\n rule?: IAnnotatedPushRule;\n } {\n return this.pushActionsForEventAndRulesets(ev, this.client.pushRules);\n }\n\n /**\n * Get one of the users push rules by its ID\n *\n * @param ruleId - The ID of the rule to search for\n * @returns The push rule, or null if no such rule was found\n */\n public getPushRuleById(ruleId: string): IPushRule | null {\n const result = this.getPushRuleAndKindById(ruleId);\n return result?.rule ?? null;\n }\n\n /**\n * Get one of the users push rules by its ID\n *\n * @param ruleId - The ID of the rule to search for\n * @returns rule The push rule, or null if no such rule was found\n * @returns kind - The PushRuleKind of the rule to search for\n */\n public getPushRuleAndKindById(ruleId: string): { rule: IPushRule; kind: PushRuleKind } | null {\n for (const scope of [\"global\"] as const) {\n if (this.client.pushRules?.[scope] === undefined) continue;\n\n for (const kind of RULEKINDS_IN_ORDER) {\n if (this.client.pushRules[scope][kind] === undefined) continue;\n\n for (const rule of this.client.pushRules[scope][kind]!) {\n if (rule.rule_id === ruleId) return { rule, kind };\n }\n }\n }\n return null;\n }\n}\n","/*\nCopyright 2016 OpenMarket Ltd\nCopyright 2019 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\n/* A re-implementation of the javascript callback functions (setTimeout,\n * clearTimeout; setInterval and clearInterval are not yet implemented) which\n * try to improve handling of large clock jumps (as seen when\n * suspending/resuming the system).\n *\n * In particular, if a timeout would have fired while the system was suspended,\n * it will instead fire as soon as possible after resume.\n */\n\nimport { logger } from \"./logger.ts\";\n\n// we schedule a callback at least this often, to check if we've missed out on\n// some wall-clock time due to being suspended.\nconst TIMER_CHECK_PERIOD_MS = 1000;\n\n// counter, for making up ids to return from setTimeout\nlet count = 0;\n\n// the key for our callback with the real globalThis.setTimeout\nlet realCallbackKey: NodeJS.Timeout | number;\n\ntype Callback = {\n runAt: number;\n func: (...params: any[]) => void;\n params: any[];\n key: number;\n};\n\n// a sorted list of the callbacks to be run.\n// each is an object with keys [runAt, func, params, key].\nconst callbackList: Callback[] = [];\n\n// var debuglog = logger.log.bind(logger);\n/* istanbul ignore next */\nconst debuglog = function (...params: any[]): void {};\n\n/**\n * reimplementation of window.setTimeout, which will call the callback if\n * the wallclock time goes past the deadline.\n *\n * @param func - callback to be called after a delay\n * @param delayMs - number of milliseconds to delay by\n *\n * @returns an identifier for this callback, which may be passed into\n * clearTimeout later.\n */\nexport function setTimeout(func: (...params: any[]) => void, delayMs: number, ...params: any[]): number {\n delayMs = delayMs || 0;\n if (delayMs < 0) {\n delayMs = 0;\n }\n\n const runAt = Date.now() + delayMs;\n const key = count++;\n debuglog(\"setTimeout: scheduling cb\", key, \"at\", runAt, \"(delay\", delayMs, \")\");\n const data = {\n runAt: runAt,\n func: func,\n params: params,\n key: key,\n };\n\n // figure out where it goes in the list\n const idx = binarySearch(callbackList, function (el) {\n return el.runAt - runAt;\n });\n\n callbackList.splice(idx, 0, data);\n scheduleRealCallback();\n\n return key;\n}\n\n/**\n * reimplementation of window.clearTimeout, which mirrors setTimeout\n *\n * @param key - result from an earlier setTimeout call\n */\nexport function clearTimeout(key: number): void {\n if (callbackList.length === 0) {\n return;\n }\n\n // remove the element from the list\n let i: number;\n for (i = 0; i < callbackList.length; i++) {\n const cb = callbackList[i];\n if (cb.key == key) {\n callbackList.splice(i, 1);\n break;\n }\n }\n\n // iff it was the first one in the list, reschedule our callback.\n if (i === 0) {\n scheduleRealCallback();\n }\n}\n\n// use the real globalThis.setTimeout to schedule a callback to runCallbacks.\nfunction scheduleRealCallback(): void {\n if (realCallbackKey) {\n globalThis.clearTimeout(realCallbackKey as NodeJS.Timeout);\n }\n\n const first = callbackList[0];\n\n if (!first) {\n debuglog(\"scheduleRealCallback: no more callbacks, not rescheduling\");\n return;\n }\n\n const timestamp = Date.now();\n const delayMs = Math.min(first.runAt - timestamp, TIMER_CHECK_PERIOD_MS);\n\n debuglog(\"scheduleRealCallback: now:\", timestamp, \"delay:\", delayMs);\n realCallbackKey = globalThis.setTimeout(runCallbacks, delayMs);\n}\n\nfunction runCallbacks(): void {\n const timestamp = Date.now();\n debuglog(\"runCallbacks: now:\", timestamp);\n\n // get the list of things to call\n const callbacksToRun: Callback[] = [];\n // eslint-disable-next-line\n while (true) {\n const first = callbackList[0];\n if (!first || first.runAt > timestamp) {\n break;\n }\n const cb = callbackList.shift()!;\n debuglog(\"runCallbacks: popping\", cb.key);\n callbacksToRun.push(cb);\n }\n\n // reschedule the real callback before running our functions, to\n // keep the codepaths the same whether or not our functions\n // register their own setTimeouts.\n scheduleRealCallback();\n\n for (const cb of callbacksToRun) {\n try {\n cb.func.apply(globalThis, cb.params);\n } catch (e) {\n logger.error(\"Uncaught exception in callback function\", e);\n }\n }\n}\n\n/* search in a sorted array.\n *\n * returns the index of the last element for which func returns\n * greater than zero, or array.length if no such element exists.\n */\nfunction binarySearch<T>(array: T[], func: (v: T) => number): number {\n // min is inclusive, max exclusive.\n let min = 0;\n let max = array.length;\n\n while (min < max) {\n const mid = (min + max) >> 1;\n const res = func(array[mid]);\n if (res > 0) {\n // the element at 'mid' is too big; set it as the new max.\n max = mid;\n } else {\n // the element at 'mid' is too small. 'min' is inclusive, so +1.\n min = mid + 1;\n }\n }\n // presumably, min==max now.\n return min;\n}\n","/*\nCopyright 2024 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 { CapabilityPoller } from \"./capabilityPoller.ts\";\nimport { ClientPrefix, type IHttpOpts, type MatrixHttpApi, Method } from \"./http-api/index.ts\";\nimport type { Logger } from \"./logger.ts\";\n\nexport interface RetentionConfigurationResponse {\n policies?: Record<\n string,\n {\n max_lifetime?: number;\n min_lifetime?: number;\n }\n >;\n limits?: {\n min_lifetime?: {\n min?: number;\n max?: number;\n };\n max_lifetime?: {\n min?: number;\n max?: number;\n };\n };\n}\n\n/**\n * Manages storing and periodically refreshing the server capabilities.\n */\nexport class RetentionPolicyService extends CapabilityPoller<RetentionConfigurationResponse> {\n public constructor(logger: Logger, http: MatrixHttpApi<IHttpOpts & { onlyData: true }>) {\n super(logger, http, \"retention policy\");\n }\n /**\n * Fetches the latest server capabilities from the homeserver and returns them, or rejects\n * on failure.\n */\n public fetch = async (): Promise<RetentionConfigurationResponse> => {\n const resp = await this.http.authedRequest<RetentionConfigurationResponse>(\n Method.Get,\n \"/retention/configuration\",\n undefined,\n undefined,\n {\n prefix: `${ClientPrefix.Unstable}/org.matrix.msc1763`,\n },\n );\n this.cached = resp;\n return this.cached;\n };\n}\n","/*\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\n/** The prefix used on indexeddbs created by rust-crypto */\nexport const RUST_SDK_STORE_PREFIX = \"matrix-js-sdk\";\n","/*\nCopyright 2019 - 2021 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\nexport enum SERVICE_TYPES {\n IS = \"SERVICE_TYPE_IS\", // An identity server\n IM = \"SERVICE_TYPE_IM\", // An integration manager\n}\n","/*\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 type { SyncCryptoCallbacks } from \"./common-crypto/CryptoBackend.ts\";\nimport { NotificationCountType, Room, RoomEvent } from \"./models/room.ts\";\nimport { logger } from \"./logger.ts\";\nimport { promiseMapSeries } from \"./utils.ts\";\nimport { EventTimeline } from \"./models/event-timeline.ts\";\nimport { ClientEvent, type IStoredClientOpts, type MatrixClient } from \"./client.ts\";\nimport {\n type ISyncStateData,\n SyncState,\n _createAndReEmitRoom,\n type SyncApiOptions,\n defaultClientOpts,\n defaultSyncApiOpts,\n type SetPresence,\n processToDeviceMessages,\n} from \"./sync.ts\";\nimport { type MatrixEvent } from \"./models/event.ts\";\nimport {\n type IMinimalEvent,\n type IRoomEvent,\n type IStateEvent,\n type IStrippedState,\n type ISyncResponse,\n type ReceivedToDeviceMessage,\n} from \"./sync-accumulator.ts\";\nimport { MatrixError } from \"./http-api/index.ts\";\nimport {\n type Extension,\n ExtensionState,\n type MSC3575RoomData,\n type MSC3575SlidingSyncResponse,\n type SlidingSync,\n SlidingSyncEvent,\n SlidingSyncState,\n} from \"./sliding-sync.ts\";\nimport { EventType } from \"./@types/event.ts\";\nimport { type IPushRules } from \"./@types/PushRules.ts\";\nimport { RoomStateEvent } from \"./models/room-state.ts\";\nimport { RoomMemberEvent } from \"./models/room-member.ts\";\nimport { KnownMembership } from \"./@types/membership.ts\";\n\n// Number of consecutive failed syncs that will lead to a syncState of ERROR as opposed\n// to RECONNECTING. This is needed to inform the client of server issues when the\n// keepAlive is successful but the server /sync fails.\nconst FAILED_SYNC_ERROR_THRESHOLD = 3;\n\ntype ExtensionE2EERequest = {\n enabled: boolean;\n};\n\ntype ExtensionE2EEResponse = Pick<\n ISyncResponse,\n | \"device_lists\"\n | \"device_one_time_keys_count\"\n | \"device_unused_fallback_key_types\"\n | \"org.matrix.msc2732.device_unused_fallback_key_types\"\n>;\n\nclass ExtensionE2EE implements Extension<ExtensionE2EERequest, ExtensionE2EEResponse> {\n public constructor(private readonly crypto: SyncCryptoCallbacks) {}\n\n public name(): string {\n return \"e2ee\";\n }\n\n public when(): ExtensionState {\n return ExtensionState.PreProcess;\n }\n\n public async onRequest(isInitial: boolean): Promise<ExtensionE2EERequest> {\n if (isInitial) {\n // In SSS, the `?pos=` contains the stream position for device list updates.\n // If we do not have a `?pos=` (e.g because we forgot it, or because the server\n // invalidated our connection) then we MUST invlaidate all device lists because\n // the server will not tell us the delta. This will then cause UTDs as we will fail\n // to encrypt for new devices. This is an expensive call, so we should\n // really really remember `?pos=` wherever possible.\n logger.log(\"ExtensionE2EE: invalidating all device lists due to missing 'pos'\");\n await this.crypto.markAllTrackedUsersAsDirty();\n }\n return {\n enabled: true, // this is sticky so only send it on the initial request\n };\n }\n\n public async onResponse(data: ExtensionE2EEResponse): Promise<void> {\n // Handle device list updates\n if (data.device_lists) {\n await this.crypto.processDeviceLists(data.device_lists);\n }\n\n // Handle one_time_keys_count and unused_fallback_key_types\n await this.crypto.processKeyCounts(\n data.device_one_time_keys_count,\n data[\"device_unused_fallback_key_types\"] || data[\"org.matrix.msc2732.device_unused_fallback_key_types\"],\n );\n\n this.crypto.onSyncCompleted({});\n }\n}\n\ntype ExtensionToDeviceRequest = {\n since?: string;\n limit?: number;\n enabled?: boolean;\n};\n\ntype ExtensionToDeviceResponse = {\n events: Required<ISyncResponse>[\"to_device\"][\"events\"];\n next_batch: string | null;\n};\n\nclass ExtensionToDevice implements Extension<ExtensionToDeviceRequest, ExtensionToDeviceResponse> {\n private nextBatch: string | null = null;\n\n public constructor(\n private readonly client: MatrixClient,\n private readonly cryptoCallbacks?: SyncCryptoCallbacks,\n ) {}\n\n public name(): string {\n return \"to_device\";\n }\n\n public when(): ExtensionState {\n return ExtensionState.PreProcess;\n }\n\n public async onRequest(isInitial: boolean): Promise<ExtensionToDeviceRequest> {\n return {\n since: this.nextBatch !== null ? this.nextBatch : undefined,\n limit: 100,\n enabled: true,\n };\n }\n\n public async onResponse(data: ExtensionToDeviceResponse): Promise<void> {\n const events = data[\"events\"] || [];\n let receivedToDeviceMessages: ReceivedToDeviceMessage[];\n if (this.cryptoCallbacks) {\n receivedToDeviceMessages = await this.cryptoCallbacks.preprocessToDeviceMessages(events);\n } else {\n // Crypto is not enabled, so we just return the events.\n receivedToDeviceMessages = events.map((rawEvent) => ({\n message: rawEvent,\n encryptionInfo: null,\n }));\n }\n processToDeviceMessages(receivedToDeviceMessages, this.client);\n\n this.nextBatch = data.next_batch;\n }\n}\n\ntype ExtensionAccountDataRequest = {\n enabled: boolean;\n};\n\ntype ExtensionAccountDataResponse = {\n global: IMinimalEvent[];\n rooms: Record<string, IMinimalEvent[]>;\n};\n\nclass ExtensionAccountData implements Extension<ExtensionAccountDataRequest, ExtensionAccountDataResponse> {\n public constructor(private readonly client: MatrixClient) {}\n\n public name(): string {\n return \"account_data\";\n }\n\n public when(): ExtensionState {\n return ExtensionState.PostProcess;\n }\n\n public async onRequest(isInitial: boolean): Promise<ExtensionAccountDataRequest> {\n return {\n enabled: true,\n };\n }\n\n public async onResponse(data: ExtensionAccountDataResponse): Promise<void> {\n if (data.global && data.global.length > 0) {\n this.processGlobalAccountData(data.global);\n }\n\n for (const roomId in data.rooms) {\n const accountDataEvents = mapEvents(this.client, roomId, data.rooms[roomId]);\n const room = this.client.getRoom(roomId);\n if (!room) {\n logger.warn(\"got account data for room but room doesn't exist on client:\", roomId);\n continue;\n }\n room.addAccountData(accountDataEvents);\n accountDataEvents.forEach((e) => {\n this.client.emit(ClientEvent.Event, e);\n });\n }\n }\n\n private processGlobalAccountData(globalAccountData: IMinimalEvent[]): void {\n const events = mapEvents(this.client, undefined, globalAccountData);\n const prevEventsMap = events.reduce<Record<string, MatrixEvent | undefined>>((m, c) => {\n m[c.getType()] = this.client.store.getAccountData(c.getType());\n return m;\n }, {});\n this.client.store.storeAccountDataEvents(events);\n events.forEach((accountDataEvent) => {\n // Honour push rules that come down the sync stream but also\n // honour push rules that were previously cached. Base rules\n // will be updated when we receive push rules via getPushRules\n // (see sync) before syncing over the network.\n if (accountDataEvent.getType() === EventType.PushRules) {\n const rules = accountDataEvent.getContent<IPushRules>();\n this.client.setPushRules(rules);\n }\n const prevEvent = prevEventsMap[accountDataEvent.getType()];\n this.client.emit(ClientEvent.AccountData, accountDataEvent, prevEvent);\n return accountDataEvent;\n });\n }\n}\n\ntype ExtensionTypingRequest = {\n enabled: boolean;\n};\n\ntype ExtensionTypingResponse = {\n rooms: Record<string, IMinimalEvent>;\n};\n\nclass ExtensionTyping implements Extension<ExtensionTypingRequest, ExtensionTypingResponse> {\n public constructor(private readonly client: MatrixClient) {}\n\n public name(): string {\n return \"typing\";\n }\n\n public when(): ExtensionState {\n return ExtensionState.PostProcess;\n }\n\n public async onRequest(isInitial: boolean): Promise<ExtensionTypingRequest> {\n return {\n enabled: true,\n };\n }\n\n public async onResponse(data: ExtensionTypingResponse): Promise<void> {\n if (!data?.rooms) {\n return;\n }\n\n for (const roomId in data.rooms) {\n processEphemeralEvents(this.client, roomId, [data.rooms[roomId]]);\n }\n }\n}\n\ntype ExtensionReceiptsRequest = {\n enabled: boolean;\n};\n\ntype ExtensionReceiptsResponse = {\n rooms: Record<string, IMinimalEvent>;\n};\n\nclass ExtensionReceipts implements Extension<ExtensionReceiptsRequest, ExtensionReceiptsResponse> {\n public constructor(private readonly client: MatrixClient) {}\n\n public name(): string {\n return \"receipts\";\n }\n\n public when(): ExtensionState {\n return ExtensionState.PostProcess;\n }\n\n public async onRequest(isInitial: boolean): Promise<ExtensionReceiptsRequest> {\n return {\n enabled: true,\n };\n }\n\n public async onResponse(data: ExtensionReceiptsResponse): Promise<void> {\n if (!data?.rooms) {\n return;\n }\n\n for (const roomId in data.rooms) {\n processEphemeralEvents(this.client, roomId, [data.rooms[roomId]]);\n }\n }\n}\n\n/**\n * A copy of SyncApi such that it can be used as a drop-in replacement for sync v2. For the actual\n * sliding sync API, see sliding-sync.ts or the class SlidingSync.\n */\nexport class SlidingSyncSdk {\n private readonly opts: IStoredClientOpts;\n private readonly syncOpts: SyncApiOptions;\n private syncState: SyncState | null = null;\n private syncStateData?: ISyncStateData;\n private lastPos: string | null = null;\n private failCount = 0;\n private notifEvents: MatrixEvent[] = []; // accumulator of sync events in the current sync response\n\n public constructor(\n private readonly slidingSync: SlidingSync,\n private readonly client: MatrixClient,\n opts: IStoredClientOpts | undefined,\n syncOpts: SyncApiOptions,\n ) {\n this.opts = defaultClientOpts(opts);\n this.syncOpts = defaultSyncApiOpts(syncOpts);\n\n if (client.getNotifTimelineSet()) {\n client.reEmitter.reEmit(client.getNotifTimelineSet()!, [RoomEvent.Timeline, RoomEvent.TimelineReset]);\n }\n\n this.slidingSync.on(SlidingSyncEvent.Lifecycle, this.onLifecycle.bind(this));\n this.slidingSync.on(SlidingSyncEvent.RoomData, this.onRoomData.bind(this));\n const extensions: Extension<any, any>[] = [\n new ExtensionToDevice(this.client, this.syncOpts.cryptoCallbacks),\n new ExtensionAccountData(this.client),\n new ExtensionTyping(this.client),\n new ExtensionReceipts(this.client),\n ];\n if (this.syncOpts.cryptoCallbacks) {\n extensions.push(new ExtensionE2EE(this.syncOpts.cryptoCallbacks));\n }\n extensions.forEach((ext) => {\n this.slidingSync.registerExtension(ext);\n });\n }\n\n private async onRoomData(roomId: string, roomData: MSC3575RoomData): Promise<void> {\n let room = this.client.store.getRoom(roomId);\n if (!room) {\n if (!roomData.initial) {\n this.syncOpts.logger.debug(\n \"initial flag not set but no stored room exists for room \",\n roomId,\n roomData,\n );\n return;\n }\n room = _createAndReEmitRoom(this.client, roomId, this.opts);\n }\n await this.processRoomData(this.client, room!, roomData);\n }\n\n private onLifecycle(state: SlidingSyncState, resp: MSC3575SlidingSyncResponse | null, err?: Error): void {\n if (err) {\n this.syncOpts.logger.debug(\"onLifecycle\", state, err);\n }\n switch (state) {\n case SlidingSyncState.Complete:\n this.purgeNotifications();\n if (!resp) {\n break;\n }\n // Element won't stop showing the initial loading spinner unless we fire SyncState.Prepared\n if (!this.lastPos) {\n this.updateSyncState(SyncState.Prepared, {\n oldSyncToken: undefined,\n nextSyncToken: resp.pos,\n catchingUp: false,\n fromCache: false,\n });\n }\n // Conversely, Element won't show the room list unless there is at least 1x SyncState.Syncing\n // so hence for the very first sync we will fire prepared then immediately syncing.\n this.updateSyncState(SyncState.Syncing, {\n oldSyncToken: this.lastPos!,\n nextSyncToken: resp.pos,\n catchingUp: false,\n fromCache: false,\n });\n this.lastPos = resp.pos;\n break;\n case SlidingSyncState.RequestFinished:\n if (err) {\n this.failCount += 1;\n this.updateSyncState(\n this.failCount > FAILED_SYNC_ERROR_THRESHOLD ? SyncState.Error : SyncState.Reconnecting,\n {\n error: new MatrixError(err),\n },\n );\n if (this.shouldAbortSync(new MatrixError(err))) {\n return; // shouldAbortSync actually stops syncing too so we don't need to do anything.\n }\n } else {\n this.failCount = 0;\n this.syncOpts.logger.debug(\n `SlidingSyncState.RequestFinished with ${Object.keys(resp?.rooms || []).length} rooms`,\n );\n }\n break;\n }\n }\n\n /**\n * Sync rooms the user has left.\n * @returns Resolved when they've been added to the store.\n */\n public async syncLeftRooms(): Promise<Room[]> {\n return []; // TODO\n }\n\n /**\n * Peek into a room. This will result in the room in question being synced so it\n * is accessible via getRooms(). Live updates for the room will be provided.\n * @param roomId - The room ID to peek into.\n * @returns A promise which resolves once the room has been added to the\n * store.\n */\n public async peek(roomId: string): Promise<Room> {\n return null!; // TODO\n }\n\n /**\n * Stop polling for updates in the peeked room. NOPs if there is no room being\n * peeked.\n */\n public stopPeeking(): void {\n // TODO\n }\n\n /**\n * Specify the set_presence value to be used for subsequent calls to the Sync API.\n * @param presence - the presence to specify to set_presence of sync calls\n */\n public setPresence(presence?: SetPresence): void {\n // TODO not possible in sliding sync yet\n }\n\n /**\n * Returns the current state of this sync object\n * @see MatrixClient#event:\"sync\"\n */\n public getSyncState(): SyncState | null {\n return this.syncState;\n }\n\n /**\n * Returns the additional data object associated with\n * the current sync state, or null if there is no\n * such data.\n * Sync errors, if available, are put in the 'error' key of\n * this object.\n */\n public getSyncStateData(): ISyncStateData | null {\n return this.syncStateData ?? null;\n }\n\n // Helper functions which set up JS SDK structs are below and are identical to the sync v2 counterparts\n\n public createRoom(roomId: string): Room {\n // XXX cargoculted from sync.ts\n const { timelineSupport } = this.client;\n const room = new Room(roomId, this.client, this.client.getUserId()!, {\n lazyLoadMembers: this.opts.lazyLoadMembers,\n pendingEventOrdering: this.opts.pendingEventOrdering,\n timelineSupport,\n });\n this.client.reEmitter.reEmit(room, [\n RoomEvent.Name,\n RoomEvent.Redaction,\n RoomEvent.RedactionCancelled,\n RoomEvent.Receipt,\n RoomEvent.Tags,\n RoomEvent.LocalEchoUpdated,\n RoomEvent.AccountData,\n RoomEvent.MyMembership,\n RoomEvent.Timeline,\n RoomEvent.TimelineReset,\n ]);\n this.registerStateListeners(room);\n return room;\n }\n\n private registerStateListeners(room: Room): void {\n // XXX cargoculted from sync.ts\n // we need to also re-emit room state and room member events, so hook it up\n // to the client now. We need to add a listener for RoomState.members in\n // order to hook them correctly.\n this.client.reEmitter.reEmit(room.currentState, [\n RoomStateEvent.Events,\n RoomStateEvent.Members,\n RoomStateEvent.NewMember,\n RoomStateEvent.Update,\n ]);\n room.currentState.on(RoomStateEvent.NewMember, (event, state, member) => {\n member.user = this.client.getUser(member.userId) ?? undefined;\n this.client.reEmitter.reEmit(member, [\n RoomMemberEvent.Name,\n RoomMemberEvent.Typing,\n RoomMemberEvent.PowerLevel,\n RoomMemberEvent.Membership,\n ]);\n });\n }\n\n /*\n private deregisterStateListeners(room: Room): void { // XXX cargoculted from sync.ts\n // could do with a better way of achieving this.\n room.currentState.removeAllListeners(RoomStateEvent.Events);\n room.currentState.removeAllListeners(RoomStateEvent.Members);\n room.currentState.removeAllListeners(RoomStateEvent.NewMember);\n } */\n\n private shouldAbortSync(error: MatrixError): boolean {\n if (error.errcode === \"M_UNKNOWN_TOKEN\") {\n // The logout already happened, we just need to stop.\n this.syncOpts.logger.warn(\"Token no longer valid - assuming logout\");\n this.stop();\n this.updateSyncState(SyncState.Error, { error });\n return true;\n }\n return false;\n }\n\n private async processRoomData(client: MatrixClient, room: Room, roomData: MSC3575RoomData): Promise<void> {\n roomData = ensureNameEvent(client, room.roomId, roomData);\n const stateEvents = mapEvents(this.client, room.roomId, roomData.required_state);\n // Prevent events from being decrypted ahead of time\n // this helps large account to speed up faster\n // room::decryptCriticalEvent is in charge of decrypting all the events\n // required for a client to function properly\n let timelineEvents = mapEvents(this.client, room.roomId, roomData.timeline, false);\n const ephemeralEvents: MatrixEvent[] = []; // TODO this.mapSyncEventsFormat(joinObj.ephemeral);\n\n // TODO: handle threaded / beacon events\n\n if (roomData.limited || roomData.initial) {\n // we should not know about any of these timeline entries if this is a genuinely new room.\n // If we do, then we've effectively done scrollback (e.g requesting timeline_limit: 1 for\n // this room, then timeline_limit: 50).\n const knownEvents = new Set<string>();\n room.getLiveTimeline()\n .getEvents()\n .forEach((e) => {\n knownEvents.add(e.getId()!);\n });\n // all unknown events BEFORE a known event must be scrollback e.g:\n // D E <-- what we know\n // A B C D E F <-- what we just received\n // means:\n // A B C <-- scrollback\n // D E <-- dupes\n // F <-- new event\n // We bucket events based on if we have seen a known event yet.\n const oldEvents: MatrixEvent[] = [];\n const newEvents: MatrixEvent[] = [];\n let seenKnownEvent = false;\n for (let i = timelineEvents.length - 1; i >= 0; i--) {\n const recvEvent = timelineEvents[i];\n if (knownEvents.has(recvEvent.getId()!)) {\n seenKnownEvent = true;\n continue; // don't include this event, it's a dupe\n }\n if (seenKnownEvent) {\n // old -> new\n oldEvents.push(recvEvent);\n } else {\n // old -> new\n newEvents.unshift(recvEvent);\n }\n }\n timelineEvents = newEvents;\n if (oldEvents.length > 0) {\n // old events are scrollback, insert them now\n room.addEventsToTimeline(oldEvents, true, false, room.getLiveTimeline(), roomData.prev_batch);\n }\n }\n\n const encrypted = room.hasEncryptionStateEvent();\n // we do this first so it's correct when any of the events fire\n if (roomData.notification_count != null) {\n room.setUnreadNotificationCount(NotificationCountType.Total, roomData.notification_count);\n }\n\n if (roomData.highlight_count != null) {\n // We track unread notifications ourselves in encrypted rooms, so don't\n // bother setting it here. We trust our calculations better than the\n // server's for this case, and therefore will assume that our non-zero\n // count is accurate.\n if (!encrypted || (encrypted && room.getUnreadNotificationCount(NotificationCountType.Highlight) <= 0)) {\n room.setUnreadNotificationCount(NotificationCountType.Highlight, roomData.highlight_count);\n }\n }\n if (roomData.bump_stamp) {\n room.setBumpStamp(roomData.bump_stamp);\n }\n\n if (Number.isInteger(roomData.invited_count)) {\n room.currentState.setInvitedMemberCount(roomData.invited_count!);\n }\n if (Number.isInteger(roomData.joined_count)) {\n room.currentState.setJoinedMemberCount(roomData.joined_count!);\n }\n\n if (roomData.invite_state) {\n const inviteStateEvents = mapEvents(this.client, room.roomId, roomData.invite_state);\n await this.injectRoomEvents(room, inviteStateEvents);\n if (roomData.initial) {\n room.recalculate();\n this.client.store.storeRoom(room);\n this.client.emit(ClientEvent.Room, room);\n }\n inviteStateEvents.forEach((e) => {\n this.client.emit(ClientEvent.Event, e);\n });\n return;\n }\n\n if (roomData.limited) {\n // set the back-pagination token. Do this *before* adding any\n // events so that clients can start back-paginating.\n room.getLiveTimeline().setPaginationToken(roomData.prev_batch ?? null, EventTimeline.BACKWARDS);\n }\n\n /* TODO\n else if (roomData.limited) {\n\n let limited = true;\n\n // we've got a limited sync, so we *probably* have a gap in the\n // timeline, so should reset. But we might have been peeking or\n // paginating and already have some of the events, in which\n // case we just want to append any subsequent events to the end\n // of the existing timeline.\n //\n // This is particularly important in the case that we already have\n // *all* of the events in the timeline - in that case, if we reset\n // the timeline, we'll end up with an entirely empty timeline,\n // which we'll try to paginate but not get any new events (which\n // will stop us linking the empty timeline into the chain).\n //\n for (let i = timelineEvents.length - 1; i >= 0; i--) {\n const eventId = timelineEvents[i].getId();\n if (room.getTimelineForEvent(eventId)) {\n this.syncOpts.logger.debug(\"Already have event \" + eventId + \" in limited \" +\n \"sync - not resetting\");\n limited = false;\n\n // we might still be missing some of the events before i;\n // we don't want to be adding them to the end of the\n // timeline because that would put them out of order.\n timelineEvents.splice(0, i);\n\n // XXX: there's a problem here if the skipped part of the\n // timeline modifies the state set in stateEvents, because\n // we'll end up using the state from stateEvents rather\n // than the later state from timelineEvents. We probably\n // need to wind stateEvents forward over the events we're\n // skipping.\n break;\n }\n }\n\n if (limited) {\n room.resetLiveTimeline(\n roomData.prev_batch,\n null, // TODO this.syncOpts.canResetEntireTimeline(room.roomId) ? null : syncEventData.oldSyncToken,\n );\n\n // We have to assume any gap in any timeline is\n // reason to stop incrementally tracking notifications and\n // reset the timeline.\n this.client.resetNotifTimelineSet();\n this.registerStateListeners(room);\n }\n } */\n\n await this.injectRoomEvents(room, stateEvents, timelineEvents, roomData.num_live);\n\n // we deliberately don't add ephemeral events to the timeline\n room.addEphemeralEvents(ephemeralEvents);\n\n // local fields must be set before any async calls because call site assumes\n // synchronous execution prior to emitting SlidingSyncState.Complete\n room.updateMyMembership(KnownMembership.Join);\n\n room.setMSC4186SummaryData(roomData.heroes, roomData.joined_count, roomData.invited_count);\n\n room.recalculate();\n if (roomData.initial) {\n client.store.storeRoom(room);\n client.emit(ClientEvent.Room, room);\n }\n\n // check if any timeline events should bing and add them to the notifEvents array:\n // we'll purge this once we've fully processed the sync response\n this.addNotifications(timelineEvents);\n\n const processRoomEvent = async (e: MatrixEvent): Promise<void> => {\n client.emit(ClientEvent.Event, e);\n if (e.isState() && e.getType() == EventType.RoomEncryption && this.syncOpts.cryptoCallbacks) {\n await this.syncOpts.cryptoCallbacks.onCryptoEvent(room, e);\n }\n };\n\n await promiseMapSeries(stateEvents, processRoomEvent);\n await promiseMapSeries(timelineEvents, processRoomEvent);\n ephemeralEvents.forEach(function (e) {\n client.emit(ClientEvent.Event, e);\n });\n\n // Decrypt only the last message in all rooms to make sure we can generate a preview\n // And decrypt all events after the recorded read receipt to ensure an accurate\n // notification count\n room.decryptCriticalEvents();\n }\n\n /**\n * Injects events into a room's model.\n * @param stateEventList - A list of state events. This is the state\n * at the *END* of the timeline list if it is supplied.\n * @param timelineEventList - A list of timeline events. Lower index\n * is earlier in time. Higher index is later.\n * @param numLive - the number of events in timelineEventList which just happened,\n * supplied from the server.\n */\n public async injectRoomEvents(\n room: Room,\n stateEventList: MatrixEvent[],\n timelineEventList: MatrixEvent[] = [],\n numLive: number = 0,\n ): Promise<void> {\n // If there are no events in the timeline yet, initialise it with\n // the given state events\n const liveTimeline = room.getLiveTimeline();\n const timelineWasEmpty = liveTimeline.getEvents().length == 0;\n if (timelineWasEmpty) {\n // Passing these events into initialiseState will freeze them, so we need\n // to compute and cache the push actions for them now, otherwise sync dies\n // with an attempt to assign to read only property.\n // XXX: This is pretty horrible and is assuming all sorts of behaviour from\n // these functions that it shouldn't be. We should probably either store the\n // push actions cache elsewhere so we can freeze MatrixEvents, or otherwise\n // find some solution where MatrixEvents are immutable but allow for a cache\n // field.\n for (const ev of stateEventList) {\n this.client.getPushActionsForEvent(ev);\n }\n liveTimeline.initialiseState(stateEventList);\n }\n\n // If the timeline wasn't empty, we process the state events here: they're\n // defined as updates to the state before the start of the timeline, so this\n // starts to roll the state forward.\n // XXX: That's what we *should* do, but this can happen if we were previously\n // peeking in a room, in which case we obviously do *not* want to add the\n // state events here onto the end of the timeline. Historically, the js-sdk\n // has just set these new state events on the old and new state. This seems\n // very wrong because there could be events in the timeline that diverge the\n // state, in which case this is going to leave things out of sync. However,\n // for now I think it;s best to behave the same as the code has done previously.\n if (!timelineWasEmpty) {\n // XXX: As above, don't do this...\n //room.addLiveEvents(stateEventList || []);\n // Do this instead...\n room.oldState.setStateEvents(stateEventList);\n room.currentState.setStateEvents(stateEventList);\n }\n\n // the timeline is broken into 'live' events which just happened and normal timeline events\n // which are still to be appended to the end of the live timeline but happened a while ago.\n // The live events are marked as fromCache=false to ensure that downstream components know\n // this is a live event, not historical (from a remote server cache).\n\n let liveTimelineEvents: MatrixEvent[] = [];\n if (numLive > 0) {\n // last numLive events are live\n liveTimelineEvents = timelineEventList.slice(-1 * numLive);\n // everything else is not live\n timelineEventList = timelineEventList.slice(0, -1 * liveTimelineEvents.length);\n }\n\n // Execute the timeline events.\n // This also needs to be done before running push rules on the events as they need\n // to be decorated with sender etc.\n await room.addLiveEvents(timelineEventList, {\n fromCache: true,\n addToState: false,\n });\n if (liveTimelineEvents.length > 0) {\n await room.addLiveEvents(liveTimelineEvents, {\n fromCache: false,\n addToState: false,\n });\n }\n\n room.recalculate();\n\n // resolve invites now we have set the latest state\n this.resolveInvites(room);\n }\n\n private resolveInvites(room: Room): void {\n if (!room || !this.opts.resolveInvitesToProfiles) {\n return;\n }\n const client = this.client;\n // For each invited room member we want to give them a displayname/avatar url\n // if they have one (the m.room.member invites don't contain this).\n room.getMembersWithMembership(KnownMembership.Invite).forEach(function (member) {\n if (member.requestedProfileInfo) return;\n member.requestedProfileInfo = true;\n // try to get a cached copy first.\n const user = client.getUser(member.userId);\n let promise: ReturnType<MatrixClient[\"getProfileInfo\"]>;\n if (user) {\n promise = Promise.resolve({\n avatar_url: user.avatarUrl,\n displayname: user.displayName,\n });\n } else {\n promise = client.getProfileInfo(member.userId);\n }\n promise.then(\n function (info) {\n // slightly naughty by doctoring the invite event but this means all\n // the code paths remain the same between invite/join display name stuff\n // which is a worthy trade-off for some minor pollution.\n const inviteEvent = member.events.member!;\n if (inviteEvent.getContent().membership !== KnownMembership.Invite) {\n // between resolving and now they have since joined, so don't clobber\n return;\n }\n inviteEvent.getContent().avatar_url = info.avatar_url;\n inviteEvent.getContent().displayname = info.displayname;\n // fire listeners\n member.setMembershipEvent(inviteEvent, room.currentState);\n },\n function (_err) {\n // OH WELL.\n },\n );\n });\n }\n\n public retryImmediately(): boolean {\n return true;\n }\n\n /**\n * Main entry point. Blocks until stop() is called.\n */\n public async sync(): Promise<void> {\n this.syncOpts.logger.debug(\"Sliding sync init loop\");\n\n // 1) We need to get push rules so we can check if events should bing as we get\n // them from /sync.\n while (!this.client.isGuest()) {\n try {\n this.syncOpts.logger.debug(\"Getting push rules...\");\n const result = await this.client.getPushRules();\n this.syncOpts.logger.debug(\"Got push rules\");\n this.client.pushRules = result;\n break;\n } catch (err) {\n this.syncOpts.logger.error(\"Getting push rules failed\", err);\n if (this.shouldAbortSync(<MatrixError>err)) {\n return;\n }\n }\n }\n\n // start syncing\n await this.slidingSync.start();\n }\n\n /**\n * Stops the sync object from syncing.\n */\n public stop(): void {\n this.syncOpts.logger.debug(\"SyncApi.stop\");\n this.slidingSync.stop();\n }\n\n /**\n * Sets the sync state and emits an event to say so\n * @param newState - The new state string\n * @param data - Object of additional data to emit in the event\n */\n private updateSyncState(newState: SyncState, data?: ISyncStateData): void {\n const old = this.syncState;\n this.syncState = newState;\n this.syncStateData = data;\n this.client.emit(ClientEvent.Sync, this.syncState, old, data);\n }\n\n /**\n * Takes a list of timelineEvents and adds and adds to notifEvents\n * as appropriate.\n * This must be called after the room the events belong to has been stored.\n *\n * @param timelineEventList - A list of timeline events. Lower index\n * is earlier in time. Higher index is later.\n */\n private addNotifications(timelineEventList: MatrixEvent[]): void {\n // gather our notifications into this.notifEvents\n if (!this.client.getNotifTimelineSet()) {\n return;\n }\n for (const timelineEvent of timelineEventList) {\n const pushActions = this.client.getPushActionsForEvent(timelineEvent);\n if (pushActions && pushActions.notify && pushActions.tweaks && pushActions.tweaks.highlight) {\n this.notifEvents.push(timelineEvent);\n }\n }\n }\n\n /**\n * Purge any events in the notifEvents array. Used after a /sync has been complete.\n * This should not be called at a per-room scope (e.g in onRoomData) because otherwise the ordering\n * will be messed up e.g room A gets a bing, room B gets a newer bing, but both in the same /sync\n * response. If we purge at a per-room scope then we could process room B before room A leading to\n * room B appearing earlier in the notifications timeline, even though it has the higher origin_server_ts.\n */\n private purgeNotifications(): void {\n this.notifEvents.sort(function (a, b) {\n return a.getTs() - b.getTs();\n });\n this.notifEvents.forEach((event) => {\n this.client.getNotifTimelineSet()?.addLiveEvent(event, { addToState: false });\n });\n this.notifEvents = [];\n }\n}\n\nfunction ensureNameEvent(client: MatrixClient, roomId: string, roomData: MSC3575RoomData): MSC3575RoomData {\n // make sure m.room.name is in required_state if there is a name, replacing anything previously\n // there if need be. This ensures clients transparently 'calculate' the right room name. Native\n // sliding sync clients should just read the \"name\" field.\n if (!roomData.name) {\n return roomData;\n }\n for (const stateEvent of roomData.required_state) {\n if (stateEvent.type === EventType.RoomName && stateEvent.state_key === \"\") {\n stateEvent.content = {\n name: roomData.name,\n };\n return roomData;\n }\n }\n roomData.required_state.push({\n event_id: \"$fake-sliding-sync-name-event-\" + roomId,\n state_key: \"\",\n type: EventType.RoomName,\n content: {\n name: roomData.name,\n },\n sender: client.getUserId()!,\n origin_server_ts: new Date().getTime(),\n });\n return roomData;\n}\n\ntype TaggedEvent = (IStrippedState | IRoomEvent | IStateEvent | IMinimalEvent) & { room_id?: string };\n\n// Helper functions which set up JS SDK structs are below and are identical to the sync v2 counterparts,\n// just outside the class.\nfunction mapEvents(client: MatrixClient, roomId: string | undefined, events: object[], decrypt = true): MatrixEvent[] {\n const mapper = client.getEventMapper({ decrypt });\n return (events as TaggedEvent[]).map(function (e) {\n e.room_id = roomId;\n return mapper(e);\n });\n}\n\nfunction processEphemeralEvents(client: MatrixClient, roomId: string, ephEvents: IMinimalEvent[]): void {\n const ephemeralEvents = mapEvents(client, roomId, ephEvents);\n const room = client.getRoom(roomId);\n if (!room) {\n logger.warn(\"got ephemeral events for room but room doesn't exist on client:\", roomId);\n return;\n }\n room.addEphemeralEvents(ephemeralEvents);\n ephemeralEvents.forEach((e) => {\n client.emit(ClientEvent.Event, e);\n });\n}\n","/*\nCopyright 2017 - 2021 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 IMinimalEvent, type ISyncData, type ISyncResponse, SyncAccumulator } from \"../sync-accumulator.ts\";\nimport { deepCopy, promiseTry } from \"../utils.ts\";\nimport { exists as idbExists } from \"../indexeddb-helpers.ts\";\nimport { logger } from \"../logger.ts\";\nimport type { SyncUserProfile, IStateEventWithRoomId, IStoredClientOpts } from \"../matrix.ts\";\nimport { type ISavedSync } from \"./index.ts\";\nimport { type IIndexedDBBackend, type UserTuple } from \"./indexeddb-backend.ts\";\nimport { type IndexedToDeviceBatch, type ToDeviceBatchWithTxnId } from \"../models/ToDeviceMessage.ts\";\n\ntype DbMigration = (db: IDBDatabase) => void;\nconst DB_MIGRATIONS: DbMigration[] = [\n (db): void => {\n // Make user store, clobber based on user ID. (userId property of User objects)\n db.createObjectStore(\"users\", { keyPath: [\"userId\"] });\n\n // Make account data store, clobber based on event type.\n // (event.type property of MatrixEvent objects)\n db.createObjectStore(\"accountData\", { keyPath: [\"type\"] });\n\n // Make /sync store (sync tokens, room data, etc), always clobber (const key).\n db.createObjectStore(\"sync\", { keyPath: [\"clobber\"] });\n },\n (db): void => {\n const oobMembersStore = db.createObjectStore(\"oob_membership_events\", {\n keyPath: [\"room_id\", \"state_key\"],\n });\n oobMembersStore.createIndex(\"room\", \"room_id\");\n },\n (db): void => {\n db.createObjectStore(\"client_options\", { keyPath: [\"clobber\"] });\n },\n (db): void => {\n db.createObjectStore(\"to_device_queue\", { autoIncrement: true });\n },\n (db): void => {\n db.createObjectStore(\"user_profile\", { keyPath: [\"userId\"] });\n },\n // Expand as needed.\n];\nconst VERSION = DB_MIGRATIONS.length;\n\n/**\n * Helper method to collect results from a Cursor and promiseify it.\n * @param store - The store to perform openCursor on.\n * @param keyRange - Optional key range to apply on the cursor.\n * @param resultMapper - A function which is repeatedly called with a\n * Cursor.\n * Return the data you want to keep.\n * @returns Promise which resolves to an array of whatever you returned from\n * resultMapper.\n * @throws If there was an error completing the query.\n */\nfunction selectQuery<T>(\n store: IDBObjectStore,\n keyRange: IDBKeyRange | IDBValidKey | undefined,\n resultMapper: (cursor: IDBCursorWithValue) => T,\n): Promise<T[]> {\n const query = store.openCursor(keyRange);\n return new Promise((resolve, reject) => {\n const results: T[] = [];\n query.onerror = (): void => {\n reject(new Error(`selectQuery failed for ${store.name}`, { cause: query.error }));\n };\n // collect results\n query.onsuccess = (): void => {\n const cursor = query.result;\n if (!cursor) {\n resolve(results);\n return; // end of results\n }\n results.push(resultMapper(cursor));\n cursor.continue();\n };\n });\n}\n\nfunction txnAsPromise(txn: IDBTransaction): Promise<Event> {\n return new Promise((resolve, reject) => {\n txn.oncomplete = function (event): void {\n resolve(event);\n };\n txn.onerror = function (): void {\n reject(txn.error);\n };\n });\n}\n\nfunction reqAsEventPromise(req: IDBRequest): Promise<Event> {\n return new Promise((resolve, reject) => {\n req.onsuccess = function (event): void {\n resolve(event);\n };\n req.onerror = function (): void {\n reject(req.error);\n };\n });\n}\n\nfunction reqAsPromise(req: IDBRequest): Promise<IDBRequest> {\n return new Promise((resolve, reject) => {\n req.onsuccess = (): void => resolve(req);\n req.onerror = (err): void => reject(err);\n });\n}\n\nfunction reqAsCursorPromise<T>(req: IDBRequest<T>): Promise<T> {\n return reqAsEventPromise(req).then((event) => req.result);\n}\n\nexport class LocalIndexedDBStoreBackend implements IIndexedDBBackend {\n public static exists(indexedDB: IDBFactory, dbName: string): Promise<boolean> {\n dbName = \"matrix-js-sdk:\" + (dbName || \"default\");\n return idbExists(indexedDB, dbName);\n }\n\n private readonly dbName: string;\n private readonly syncAccumulator: SyncAccumulator;\n private db?: IDBDatabase;\n private disconnected = true;\n private _isNewlyCreated = false;\n private syncToDatabasePromise?: Promise<void>;\n private pendingUserPresenceData: UserTuple[] = [];\n\n /**\n * Does the actual reading from and writing to the indexeddb\n *\n * Construct a new Indexed Database store backend. This requires a call to\n * `connect()` before this store can be used.\n * @param indexedDB - The Indexed DB interface e.g\n * `window.indexedDB`\n * @param dbName - Optional database name. The same name must be used\n * to open the same database.\n */\n public constructor(\n private readonly indexedDB: IDBFactory,\n dbName = \"default\",\n ) {\n this.dbName = \"matrix-js-sdk:\" + dbName;\n this.syncAccumulator = new SyncAccumulator();\n }\n\n /**\n * Attempt to connect to the database. This can fail if the user does not\n * grant permission.\n * @returns Promise which resolves if successfully connected.\n */\n public connect(onClose?: () => void): Promise<void> {\n if (!this.disconnected) {\n logger.log(`LocalIndexedDBStoreBackend.connect: already connected or connecting`);\n return Promise.resolve();\n }\n\n this.disconnected = false;\n\n logger.log(`LocalIndexedDBStoreBackend.connect: connecting...`);\n const req = this.indexedDB.open(this.dbName, VERSION);\n req.onupgradeneeded = (ev): void => {\n const db = req.result;\n const oldVersion = ev.oldVersion;\n logger.log(`LocalIndexedDBStoreBackend.connect: upgrading from ${oldVersion}`);\n if (oldVersion < 1) {\n // The database did not previously exist\n this._isNewlyCreated = true;\n }\n DB_MIGRATIONS.forEach((migration, index) => {\n if (oldVersion <= index) migration(db);\n });\n };\n\n req.onblocked = (): void => {\n logger.log(`can't yet open LocalIndexedDBStoreBackend because it is open elsewhere`);\n };\n\n logger.log(`LocalIndexedDBStoreBackend.connect: awaiting connection...`);\n return reqAsEventPromise(req).then(async () => {\n logger.log(`LocalIndexedDBStoreBackend.connect: connected`);\n this.db = req.result;\n\n // add a poorly-named listener for when deleteDatabase is called\n // so we can close our db connections.\n this.db.onversionchange = (): void => {\n this.db?.close(); // this does not call onclose\n this.disconnected = true;\n this.db = undefined;\n };\n this.db.onclose = (): void => {\n this.disconnected = true;\n this.db = undefined;\n onClose?.();\n };\n\n await this.init();\n });\n }\n\n /** @returns whether or not the database was newly created in this session. */\n public isNewlyCreated(): Promise<boolean> {\n return Promise.resolve(this._isNewlyCreated);\n }\n\n /**\n * Having connected, load initial data from the database and prepare for use\n * @returns Promise which resolves on success\n */\n private init(): Promise<unknown> {\n return Promise.all([this.loadAccountData(), this.loadSyncData()]).then(([accountData, syncData]) => {\n logger.log(`LocalIndexedDBStoreBackend: loaded initial data`);\n this.syncAccumulator.accumulate(\n {\n next_batch: syncData.nextBatch,\n rooms: syncData.roomsData,\n account_data: {\n events: accountData,\n },\n },\n true,\n );\n });\n }\n\n /**\n * Returns the out-of-band membership events for this room that\n * were previously loaded.\n * @returns the events, potentially an empty array if OOB loading didn't yield any new members\n * @returns in case the members for this room haven't been stored yet\n */\n public getOutOfBandMembers(roomId: string): Promise<IStateEventWithRoomId[] | null> {\n return new Promise<IStateEventWithRoomId[] | null>((resolve, reject) => {\n const tx = this.db!.transaction([\"oob_membership_events\"], \"readonly\");\n const store = tx.objectStore(\"oob_membership_events\");\n const roomIndex = store.index(\"room\");\n const range = IDBKeyRange.only(roomId);\n const request = roomIndex.openCursor(range);\n\n const membershipEvents: IStateEventWithRoomId[] = [];\n // did we encounter the oob_written marker object\n // amongst the results? That means OOB member\n // loading already happened for this room\n // but there were no members to persist as they\n // were all known already\n let oobWritten = false;\n\n request.onsuccess = (): void => {\n const cursor = request.result;\n if (!cursor) {\n // Unknown room\n if (!membershipEvents.length && !oobWritten) {\n return resolve(null);\n }\n return resolve(membershipEvents);\n }\n const record = cursor.value;\n if (record.oob_written) {\n oobWritten = true;\n } else {\n membershipEvents.push(record);\n }\n cursor.continue();\n };\n request.onerror = (err): void => {\n reject(err);\n };\n }).then((events) => {\n logger.log(`LL: got ${events?.length} membershipEvents from storage for room ${roomId} ...`);\n return events;\n });\n }\n\n /**\n * Stores the out-of-band membership events for this room. Note that\n * it still makes sense to store an empty array as the OOB status for the room is\n * marked as fetched, and getOutOfBandMembers will return an empty array instead of null\n * @param membershipEvents - the membership events to store\n */\n public async setOutOfBandMembers(roomId: string, membershipEvents: IStateEventWithRoomId[]): Promise<void> {\n logger.log(`LL: backend about to store ${membershipEvents.length}` + ` members for ${roomId}`);\n const tx = this.db!.transaction([\"oob_membership_events\"], \"readwrite\");\n const store = tx.objectStore(\"oob_membership_events\");\n membershipEvents.forEach((e) => {\n store.put(e);\n });\n // aside from all the events, we also write a marker object to the store\n // to mark the fact that OOB members have been written for this room.\n // It's possible that 0 members need to be written as all where previously know\n // but we still need to know whether to return null or [] from getOutOfBandMembers\n // where null means out of band members haven't been stored yet for this room\n const markerObject = {\n room_id: roomId,\n oob_written: true,\n state_key: 0,\n };\n store.put(markerObject);\n await txnAsPromise(tx);\n logger.log(`LL: backend done storing for ${roomId}!`);\n }\n\n public async clearOutOfBandMembers(roomId: string): Promise<void> {\n // the approach to delete all members for a room\n // is to get the min and max state key from the index\n // for that room, and then delete between those\n // keys in the store.\n // this should be way faster than deleting every member\n // individually for a large room.\n const readTx = this.db!.transaction([\"oob_membership_events\"], \"readonly\");\n const store = readTx.objectStore(\"oob_membership_events\");\n const roomIndex = store.index(\"room\");\n const roomRange = IDBKeyRange.only(roomId);\n\n const minStateKeyProm = reqAsCursorPromise(roomIndex.openKeyCursor(roomRange, \"next\")).then(\n (cursor) => (<IDBValidKey[]>cursor?.primaryKey)?.[1],\n );\n const maxStateKeyProm = reqAsCursorPromise(roomIndex.openKeyCursor(roomRange, \"prev\")).then(\n (cursor) => (<IDBValidKey[]>cursor?.primaryKey)?.[1],\n );\n const [minStateKey, maxStateKey] = await Promise.all([minStateKeyProm, maxStateKeyProm]);\n\n const writeTx = this.db!.transaction([\"oob_membership_events\"], \"readwrite\");\n const writeStore = writeTx.objectStore(\"oob_membership_events\");\n const membersKeyRange = IDBKeyRange.bound([roomId, minStateKey], [roomId, maxStateKey]);\n\n logger.log(\n `LL: Deleting all users + marker in storage for room ${roomId}, with key range:`,\n [roomId, minStateKey],\n [roomId, maxStateKey],\n );\n await reqAsPromise(writeStore.delete(membersKeyRange));\n }\n\n /**\n * Clear the entire database. This should be used when logging out of a client\n * to prevent mixing data between accounts. Closes the database.\n * @returns Resolved when the database is cleared.\n */\n public clearDatabase(): Promise<void> {\n return new Promise((resolve) => {\n logger.log(`Removing indexeddb instance: ${this.dbName}`);\n\n // Close the database first to avoid firing unexpected close events\n this.db?.close();\n\n const req = this.indexedDB.deleteDatabase(this.dbName);\n\n req.onblocked = (): void => {\n logger.log(`can't yet delete indexeddb ${this.dbName} because it is open elsewhere`);\n };\n\n req.onerror = (): void => {\n // in firefox, with indexedDB disabled, this fails with a\n // DOMError. We treat this as non-fatal, so that we can still\n // use the app.\n logger.warn(`unable to delete js-sdk store indexeddb: ${req.error?.name}`);\n resolve();\n };\n\n req.onsuccess = (): void => {\n logger.log(`Removed indexeddb instance: ${this.dbName}`);\n resolve();\n };\n });\n }\n\n /**\n * @param copy - If false, the data returned is from internal\n * buffers and must not be mutated. Otherwise, a copy is made before\n * returning such that the data can be safely mutated. Default: true.\n *\n * @returns Promise which resolves with a sync response to restore the\n * client state to where it was at the last save, or null if there\n * is no saved sync data.\n */\n public getSavedSync(copy = true): Promise<ISavedSync | null> {\n const data = this.syncAccumulator.getJSON();\n if (!data.nextBatch) return Promise.resolve(null);\n if (copy) {\n // We must deep copy the stored data so that the /sync processing code doesn't\n // corrupt the internal state of the sync accumulator (it adds non-clonable keys)\n return Promise.resolve(deepCopy(data));\n } else {\n return Promise.resolve(data);\n }\n }\n\n public getNextBatchToken(): Promise<string> {\n return Promise.resolve(this.syncAccumulator.getNextBatchToken());\n }\n\n public setSyncData(syncData: ISyncResponse): Promise<void> {\n return Promise.resolve().then(() => {\n this.syncAccumulator.accumulate(syncData);\n });\n }\n\n /**\n * Sync users and all accumulated sync data to the database.\n * If a previous sync is in flight, the new data will be added to the\n * next sync and the current sync's promise will be returned.\n * @param userTuples - The user tuples\n * @returns Promise which resolves if the data was persisted.\n */\n public async syncToDatabase(userTuples: UserTuple[]): Promise<void> {\n if (this.syncToDatabasePromise) {\n logger.warn(\"Skipping syncToDatabase() as persist already in flight\");\n this.pendingUserPresenceData.push(...userTuples);\n return this.syncToDatabasePromise;\n }\n userTuples.unshift(...this.pendingUserPresenceData);\n this.syncToDatabasePromise = this.doSyncToDatabase(userTuples);\n return this.syncToDatabasePromise;\n }\n\n private async doSyncToDatabase(userTuples: UserTuple[]): Promise<void> {\n try {\n const syncData = this.syncAccumulator.getJSON(true);\n await Promise.all([\n this.persistUserPresenceEvents(userTuples),\n this.persistAccountData(syncData.accountData),\n this.persistSyncData(syncData.nextBatch, syncData.roomsData),\n ]);\n } finally {\n this.syncToDatabasePromise = undefined;\n }\n }\n\n /**\n * Persist rooms /sync data along with the next batch token.\n * @param nextBatch - The next_batch /sync value.\n * @param roomsData - The 'rooms' /sync data from a SyncAccumulator\n * @returns Promise which resolves if the data was persisted.\n */\n private persistSyncData(nextBatch: string, roomsData: ISyncResponse[\"rooms\"]): Promise<void> {\n logger.log(\"Persisting sync data up to\", nextBatch);\n return promiseTry<void>(() => {\n const txn = this.db!.transaction([\"sync\"], \"readwrite\");\n const store = txn.objectStore(\"sync\");\n store.put({\n clobber: \"-\", // constant key so will always clobber\n nextBatch,\n roomsData,\n }); // put == UPSERT\n return txnAsPromise(txn).then(() => {\n logger.log(\"Persisted sync data up to\", nextBatch);\n });\n });\n }\n\n /**\n * Persist a list of account data events. Events with the same 'type' will\n * be replaced.\n * @param accountData - An array of raw user-scoped account data events\n * @returns Promise which resolves if the events were persisted.\n */\n private persistAccountData(accountData: IMinimalEvent[]): Promise<void> {\n return promiseTry<void>(() => {\n const txn = this.db!.transaction([\"accountData\"], \"readwrite\");\n const store = txn.objectStore(\"accountData\");\n for (const event of accountData) {\n store.put(event); // put == UPSERT\n }\n return txnAsPromise(txn).then();\n });\n }\n\n /**\n * Persist a list of [user id, presence event] they are for.\n * Users with the same 'userId' will be replaced.\n * Presence events should be the event in its raw form (not the Event\n * object)\n * @param tuples - An array of [userid, event] tuples\n * @returns Promise which resolves if the users were persisted.\n */\n private persistUserPresenceEvents(tuples: UserTuple[]): Promise<void> {\n return promiseTry<void>(() => {\n const txn = this.db!.transaction([\"users\"], \"readwrite\");\n const store = txn.objectStore(\"users\");\n for (const tuple of tuples) {\n store.put({\n userId: tuple[0],\n event: tuple[1],\n }); // put == UPSERT\n }\n return txnAsPromise(txn).then();\n });\n }\n\n /**\n * Load all user presence events from the database. This is not cached.\n * FIXME: It would probably be more sensible to store the events in the\n * sync.\n * @returns A list of presence events in their raw form.\n */\n public getUserPresenceEvents(): Promise<UserTuple[]> {\n return promiseTry<UserTuple[]>(() => {\n const txn = this.db!.transaction([\"users\"], \"readonly\");\n const store = txn.objectStore(\"users\");\n return selectQuery(store, undefined, (cursor) => {\n return [cursor.value.userId, cursor.value.event];\n });\n });\n }\n\n /**\n * Load all the account data events from the database. This is not cached.\n * @returns A list of raw global account events.\n */\n private loadAccountData(): Promise<IMinimalEvent[]> {\n logger.log(`LocalIndexedDBStoreBackend: loading account data...`);\n return promiseTry<IMinimalEvent[]>(() => {\n const txn = this.db!.transaction([\"accountData\"], \"readonly\");\n const store = txn.objectStore(\"accountData\");\n return selectQuery(store, undefined, (cursor) => {\n return cursor.value;\n }).then((result: IMinimalEvent[]) => {\n logger.log(`LocalIndexedDBStoreBackend: loaded account data`);\n return result;\n });\n });\n }\n\n /**\n * Load the sync data from the database.\n * @returns An object with \"roomsData\" and \"nextBatch\" keys.\n */\n private loadSyncData(): Promise<ISyncData> {\n logger.log(`LocalIndexedDBStoreBackend: loading sync data...`);\n return promiseTry<ISyncData>(() => {\n const txn = this.db!.transaction([\"sync\"], \"readonly\");\n const store = txn.objectStore(\"sync\");\n return selectQuery(store, undefined, (cursor) => {\n return cursor.value;\n }).then((results: ISyncData[]) => {\n logger.log(`LocalIndexedDBStoreBackend: loaded sync data`);\n if (results.length > 1) {\n logger.warn(\"loadSyncData: More than 1 sync row found.\");\n }\n return results.length > 0 ? results[0] : ({} as ISyncData);\n });\n });\n }\n\n public getClientOptions(): Promise<IStoredClientOpts | undefined> {\n return Promise.resolve().then(() => {\n const txn = this.db!.transaction([\"client_options\"], \"readonly\");\n const store = txn.objectStore(\"client_options\");\n return selectQuery(store, undefined, (cursor) => {\n return cursor.value?.options;\n }).then((results) => results[0]);\n });\n }\n\n public async storeClientOptions(options: IStoredClientOpts): Promise<void> {\n const txn = this.db!.transaction([\"client_options\"], \"readwrite\");\n const store = txn.objectStore(\"client_options\");\n store.put({\n clobber: \"-\", // constant key so will always clobber\n options: options,\n }); // put == UPSERT\n await txnAsPromise(txn);\n }\n\n public async saveToDeviceBatches(batches: ToDeviceBatchWithTxnId[]): Promise<void> {\n const txn = this.db!.transaction([\"to_device_queue\"], \"readwrite\");\n const store = txn.objectStore(\"to_device_queue\");\n for (const batch of batches) {\n store.add(batch);\n }\n await txnAsPromise(txn);\n }\n\n public async getOldestToDeviceBatch(): Promise<IndexedToDeviceBatch | null> {\n const txn = this.db!.transaction([\"to_device_queue\"], \"readonly\");\n const store = txn.objectStore(\"to_device_queue\");\n const cursor = await reqAsCursorPromise(store.openCursor());\n if (!cursor) return null;\n\n const resultBatch = cursor.value as ToDeviceBatchWithTxnId;\n\n return {\n id: cursor.key as number,\n txnId: resultBatch.txnId,\n eventType: resultBatch.eventType,\n batch: resultBatch.batch,\n };\n }\n\n public async removeToDeviceBatch(id: number): Promise<void> {\n const txn = this.db!.transaction([\"to_device_queue\"], \"readwrite\");\n const store = txn.objectStore(\"to_device_queue\");\n store.delete(id);\n await txnAsPromise(txn);\n }\n\n public async getUserProfile(userId: string): Promise<SyncUserProfile | undefined> {\n return Promise.resolve().then(() => {\n const txn = this.db!.transaction([\"user_profile\"], \"readonly\");\n const store = txn.objectStore(\"user_profile\");\n return selectQuery(store, [userId], (cursor) => {\n return cursor.value?.profile;\n }).then((results) => results[0]);\n });\n }\n\n public async storeUserProfiles(userProfiles: Map<string, SyncUserProfile>): Promise<void> {\n const txn = this.db!.transaction([\"user_profile\"], \"readwrite\");\n const store = txn.objectStore(\"user_profile\");\n for (const [userId, profile] of userProfiles.entries()) {\n store.put({ profile, userId });\n }\n await txnAsPromise(txn);\n }\n\n public async removeUserProfiles(userIds: string[]): Promise<void> {\n const txn = this.db!.transaction([\"user_profile\"], \"readwrite\");\n const store = txn.objectStore(\"user_profile\");\n for (const userId of userIds) {\n store.delete([userId]);\n }\n await txnAsPromise(txn);\n }\n\n public async removeEventsFromRoom(roomId: string, eventIds: string[]): Promise<void> {\n try {\n this.syncAccumulator.removeEventsFromRoom(roomId, eventIds);\n const syncData = this.syncAccumulator.getJSON(true);\n await this.persistSyncData(syncData.nextBatch, syncData.roomsData);\n } finally {\n this.syncToDatabasePromise = undefined;\n }\n }\n\n /*\n * Close the database\n */\n public async destroy(): Promise<void> {\n this.db?.close();\n }\n}\n","/*\nCopyright 2015 - 2021 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\n/**\n * This is an internal module.\n */\n\nimport { type EventType } from \"../@types/event.ts\";\nimport { type Room } from \"../models/room.ts\";\nimport { type User } from \"../models/user.ts\";\nimport { type IEvent, type MatrixEvent } from \"../models/event.ts\";\nimport { type Filter } from \"../filter.ts\";\nimport { type ISavedSync, type IStore, type UserCreator } from \"./index.ts\";\nimport { type RoomSummary } from \"../models/room-summary.ts\";\nimport { type ISyncResponse } from \"../sync-accumulator.ts\";\nimport { type IStateEventWithRoomId } from \"../@types/search.ts\";\nimport { type IndexedToDeviceBatch, type ToDeviceBatch } from \"../models/ToDeviceMessage.ts\";\nimport { type IStoredClientOpts } from \"../client.ts\";\n\n/**\n * Construct a stub store. This does no-ops on most store methods.\n */\nexport class StubStore implements IStore {\n public readonly accountData = new Map(); // stub\n private fromToken: string | null = null;\n\n /** @returns whether or not the database was newly created in this session. */\n public isNewlyCreated(): Promise<boolean> {\n return Promise.resolve(true);\n }\n\n /**\n * Get the sync token.\n */\n public getSyncToken(): string | null {\n return this.fromToken;\n }\n\n /**\n * Set the sync token.\n */\n public setSyncToken(token: string): void {\n this.fromToken = token;\n }\n\n /**\n * No-op.\n */\n public storeRoom(room: Room): void {}\n\n /**\n * No-op.\n */\n public getRoom(roomId: string): Room | null {\n return null;\n }\n\n /**\n * No-op.\n * @returns An empty array.\n */\n public getRooms(): Room[] {\n return [];\n }\n\n /**\n * Permanently delete a room.\n */\n public removeRoom(roomId: string): void {\n return;\n }\n\n /**\n * No-op.\n * @returns An empty array.\n */\n public getRoomSummaries(): RoomSummary[] {\n return [];\n }\n\n /**\n * No-op.\n */\n public storeUser(user: User): void {}\n\n /**\n * No-op.\n */\n public getUser(userId: string): User | null {\n return null;\n }\n\n /**\n * No-op.\n */\n public getUsers(): User[] {\n return [];\n }\n\n /**\n * No-op.\n */\n public scrollback(room: Room, limit: number): MatrixEvent[] {\n return [];\n }\n\n /**\n * No-op.\n */\n public setUserCreator(creator: UserCreator): void {\n return;\n }\n\n /**\n * Store events for a room.\n * @param room - The room to store events for.\n * @param events - The events to store.\n * @param token - The token associated with these events.\n * @param toStart - True if these are paginated results.\n */\n public storeEvents(room: Room, events: MatrixEvent[], token: string | null, toStart: boolean): void {}\n\n /**\n * Store a filter.\n */\n public storeFilter(filter: Filter): void {}\n\n /**\n * Retrieve a filter.\n * @returns A filter or null.\n */\n public getFilter(userId: string, filterId: string): Filter | null {\n return null;\n }\n\n /**\n * Retrieve a filter ID with the given name.\n * @param filterName - The filter name.\n * @returns The filter ID or null.\n */\n public getFilterIdByName(filterName: string): string | null {\n return null;\n }\n\n /**\n * Set a filter name to ID mapping.\n */\n public setFilterIdByName(filterName: string, filterId?: string): void {}\n\n /**\n * Store user-scoped account data events\n * @param events - The events to store.\n */\n public storeAccountDataEvents(events: MatrixEvent[]): void {}\n\n /**\n * Get account data event by event type\n * @param eventType - The event type being queried\n */\n public getAccountData(eventType: EventType | string): MatrixEvent | undefined {\n return undefined;\n }\n\n /**\n * setSyncData does nothing as there is no backing data store.\n *\n * @param syncData - The sync data\n * @returns An immediately resolved promise.\n */\n public setSyncData(syncData: ISyncResponse): Promise<void> {\n return Promise.resolve();\n }\n\n /**\n * We never want to save because we have nothing to save to.\n *\n * @returns If the store wants to save\n */\n public wantsSave(): boolean {\n return false;\n }\n\n /**\n * Save does nothing as there is no backing data store.\n */\n public save(): Promise<void> {\n return Promise.resolve();\n }\n\n /**\n * Startup does nothing.\n * @returns An immediately resolved promise.\n */\n public startup(): Promise<void> {\n return Promise.resolve();\n }\n\n /**\n * @returns Promise which resolves with a sync response to restore the\n * client state to where it was at the last save, or null if there\n * is no saved sync data.\n */\n public getSavedSync(): Promise<ISavedSync | null> {\n return Promise.resolve(null);\n }\n\n /**\n * @returns If there is a saved sync, the nextBatch token\n * for this sync, otherwise null.\n */\n public getSavedSyncToken(): Promise<string | null> {\n return Promise.resolve(null);\n }\n\n /**\n * Delete all data from this store. Does nothing since this store\n * doesn't store anything.\n * @returns An immediately resolved promise.\n */\n public deleteAllData(): Promise<void> {\n return Promise.resolve();\n }\n\n public getOutOfBandMembers(): Promise<IStateEventWithRoomId[] | null> {\n return Promise.resolve(null);\n }\n\n public setOutOfBandMembers(roomId: string, membershipEvents: IStateEventWithRoomId[]): Promise<void> {\n return Promise.resolve();\n }\n\n public clearOutOfBandMembers(): Promise<void> {\n return Promise.resolve();\n }\n\n public getClientOptions(): Promise<IStoredClientOpts | undefined> {\n return Promise.resolve(undefined);\n }\n\n public storeClientOptions(options: IStoredClientOpts): Promise<void> {\n return Promise.resolve();\n }\n\n public async getPendingEvents(roomId: string): Promise<Partial<IEvent>[]> {\n return [];\n }\n\n public setPendingEvents(roomId: string, events: Partial<IEvent>[]): Promise<void> {\n return Promise.resolve();\n }\n\n public async saveToDeviceBatches(batch: ToDeviceBatch[]): Promise<void> {\n return Promise.resolve();\n }\n\n public getOldestToDeviceBatch(): Promise<IndexedToDeviceBatch | null> {\n return Promise.resolve(null);\n }\n\n public async removeToDeviceBatch(id: number): Promise<void> {\n return Promise.resolve();\n }\n\n public async getUserProfile(): Promise<undefined> {\n return undefined;\n }\n\n public async storeUserProfiles(): Promise<void> {\n return;\n }\n\n public async removeUserProfiles(): Promise<void> {\n return;\n }\n\n public async destroy(): Promise<void> {\n // Nothing to do\n }\n public async removeEventsFromRoom(roomId: string, eventIds: string[]): Promise<void> {\n // Nothing to do\n }\n}\n","/*\nCopyright 2023 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 { THREAD_RELATION_TYPE } from \"./models/thread.ts\";\nimport { type IEvent } from \"./models/event.ts\";\n\n/**\n * Returns a filter function for the /relations endpoint to filter out relations directly\n * to the thread root event that should not live in the thread timeline\n *\n * @param threadId - the thread ID (ie. the event ID of the root event of the thread)\n * @returns the filtered list of events\n */\nexport function getRelationsThreadFilter(threadId: string): (e: Partial<IEvent>) => boolean {\n return (e: Partial<IEvent>) =>\n e.content?.[\"m.relates_to\"]?.event_id !== threadId ||\n e.content?.[\"m.relates_to\"]?.rel_type === THREAD_RELATION_TYPE.name;\n}\n","/*\n * Copyright 2024 The Matrix.org Foundation C.I.C.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { decodeBase64, encodeBase64 } from \"../base64.ts\";\nimport { deriveKeys } from \"./internal/deriveKeys.ts\";\nimport { type AESEncryptedSecretStoragePayload } from \"../@types/AESEncryptedSecretStoragePayload.ts\";\n\n/**\n * Encrypt a string as a secret storage item, using AES-CTR.\n *\n * @param data - the plaintext to encrypt\n * @param key - the encryption key to use as an input to the HKDF function which is used to derive the AES key for\n * encryption. Obviously, the same key must be provided when decrypting.\n * @param name - the name of the secret. Used as an input to the HKDF operation which is used to derive the AES key,\n * so again the same value must be provided when decrypting.\n * @param ivStr - the base64-encoded initialization vector to use. If not supplied, a random one will be generated.\n *\n * @returns The encrypted result, including the ciphertext itself, the initialization vector (as supplied in `ivStr`,\n * or generated), and an HMAC on the ciphertext — all base64-encoded.\n */\nexport default async function encryptAESSecretStorageItem(\n data: string,\n key: Uint8Array<ArrayBuffer>,\n name: string,\n ivStr?: string,\n): Promise<AESEncryptedSecretStoragePayload> {\n let iv: Uint8Array<ArrayBuffer>;\n if (ivStr) {\n iv = decodeBase64(ivStr);\n } else {\n iv = new Uint8Array(16);\n globalThis.crypto.getRandomValues(iv);\n\n // clear bit 63 of the IV to stop us hitting the 64-bit counter boundary\n // (which would mean we wouldn't be able to decrypt on Android). The loss\n // of a single bit of iv is a price we have to pay.\n iv[8] &= 0x7f;\n }\n\n const [aesKey, hmacKey] = await deriveKeys(key, name);\n const encodedData = new TextEncoder().encode(data);\n\n const ciphertext = await globalThis.crypto.subtle.encrypt(\n {\n name: \"AES-CTR\",\n counter: iv,\n length: 64,\n },\n aesKey,\n encodedData,\n );\n\n const hmac = await globalThis.crypto.subtle.sign({ name: \"HMAC\" }, hmacKey, ciphertext);\n\n return {\n iv: encodeBase64(iv),\n ciphertext: encodeBase64(new Uint8Array(ciphertext)),\n mac: encodeBase64(new Uint8Array(hmac)),\n };\n}\n","/*\n * Copyright 2024 The Matrix.org Foundation C.I.C.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// salt for HKDF, with 8 bytes of zeros\nconst zeroSalt = new Uint8Array(8);\n\n/**\n * Derive AES and HMAC keys from a master key.\n *\n * This is used for deriving secret storage keys: see https://spec.matrix.org/v1.11/client-server-api/#msecret_storagev1aes-hmac-sha2 (step 1).\n *\n * @param key\n * @param name\n */\nexport async function deriveKeys(key: Uint8Array<ArrayBuffer>, name: string): Promise<[CryptoKey, CryptoKey]> {\n const hkdfkey = await globalThis.crypto.subtle.importKey(\"raw\", key, { name: \"HKDF\" }, false, [\"deriveBits\"]);\n const keybits = await globalThis.crypto.subtle.deriveBits(\n {\n name: \"HKDF\",\n salt: zeroSalt,\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore: https://github.com/microsoft/TypeScript-DOM-lib-generator/pull/879\n info: new TextEncoder().encode(name),\n hash: \"SHA-256\",\n },\n hkdfkey,\n 512,\n );\n\n const aesKey = keybits.slice(0, 32);\n const hmacKey = keybits.slice(32);\n\n const aesProm = globalThis.crypto.subtle.importKey(\"raw\", aesKey, { name: \"AES-CTR\" }, false, [\n \"encrypt\",\n \"decrypt\",\n ]);\n\n const hmacProm = globalThis.crypto.subtle.importKey(\n \"raw\",\n hmacKey,\n {\n name: \"HMAC\",\n hash: { name: \"SHA-256\" },\n },\n false,\n [\"sign\", \"verify\"],\n );\n\n return Promise.all([aesProm, hmacProm]);\n}\n","/*\nCopyright 2025 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\n/**\n * Room versions strings that we know about and do not use hydra semantics.\n */\nconst PRE_HYDRA_ROOM_VERSIONS = [\"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\", \"10\", \"11\"];\n\n/**\n * Checks if the given room version is one where new \"hydra\" power level\n * semantics (ie. room version 12 or later) should be used\n * (see https://github.com/matrix-org/matrix-spec-proposals/pull/4289).\n * This will return `false` for versions that are known to the js-sdk and\n * do not use hydra: any room versions unknown to the js-sdk (experimental or\n * otherwise) will cause the function to return true.\n *\n * @param roomVersion - The version of the room to check.\n * @returns `true` if hydra semantics should be used for the room version, `false` otherwise.\n */\nexport function shouldUseHydraForRoomVersion(roomVersion: string): boolean {\n return !PRE_HYDRA_ROOM_VERSIONS.includes(roomVersion);\n}\n","/*\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\nlet audioContext: AudioContext | null = null;\nlet refCount = 0;\n\n/**\n * Acquires a reference to the shared AudioContext.\n * It's highly recommended to reuse this AudioContext rather than creating your\n * own, because multiple AudioContexts can be problematic in some browsers.\n * Make sure to call releaseContext when you're done using it.\n * @returns The shared AudioContext\n */\nexport const acquireContext = (): AudioContext => {\n if (audioContext === null) audioContext = new AudioContext();\n refCount++;\n return audioContext;\n};\n\n/**\n * Signals that one of the references to the shared AudioContext has been\n * released, allowing the context and associated hardware resources to be\n * cleaned up if nothing else is using it.\n */\nexport const releaseContext = (): void => {\n refCount--;\n if (refCount === 0) {\n audioContext?.close();\n audioContext = null;\n }\n};\n","/*\nCopyright 2020 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 MatrixEvent } from \"../models/event.ts\";\nimport { logger } from \"../logger.ts\";\nimport { CallDirection, CallError, CallErrorCode, CallState, createNewMatrixCall, type MatrixCall } from \"./call.ts\";\nimport { EventType } from \"../@types/event.ts\";\nimport { ClientEvent, type MatrixClient } from \"../client.ts\";\nimport { type MCallAnswer, type MCallHangupReject } from \"./callEventTypes.ts\";\nimport { type GroupCall, GroupCallErrorCode, GroupCallEvent, GroupCallUnknownDeviceError } from \"./groupCall.ts\";\nimport { RoomEvent } from \"../models/room.ts\";\n\n// Don't ring unless we'd be ringing for at least 3 seconds: the user needs some\n// time to press the 'accept' button\nconst RING_GRACE_PERIOD = 3000;\n\nexport enum CallEventHandlerEvent {\n Incoming = \"Call.incoming\",\n}\n\nexport type CallEventHandlerEventHandlerMap = {\n /**\n * Fires whenever an incoming call arrives.\n * @param call - The incoming call.\n * @example\n * ```\n * matrixClient.on(\"Call.incoming\", function(call){\n * call.answer(); // auto-answer\n * });\n * ```\n */\n [CallEventHandlerEvent.Incoming]: (call: MatrixCall) => void;\n};\n\nexport class CallEventHandler {\n // XXX: Most of these are only public because of the tests\n public calls: Map<string, MatrixCall>;\n public callEventBuffer: MatrixEvent[];\n public nextSeqByCall: Map<string, number> = new Map();\n public toDeviceEventBuffers: Map<string, Array<MatrixEvent>> = new Map();\n\n private client: MatrixClient;\n private candidateEventsByCall: Map<string, Array<MatrixEvent>>;\n private eventBufferPromiseChain?: Promise<void>;\n\n public constructor(client: MatrixClient) {\n this.client = client;\n this.calls = new Map<string, MatrixCall>();\n // The sync code always emits one event at a time, so it will patiently\n // wait for us to finish processing a call invite before delivering the\n // next event, even if that next event is a hangup. We therefore accumulate\n // all our call events and then process them on the 'sync' event, ie.\n // each time a sync has completed. This way, we can avoid emitting incoming\n // call events if we get both the invite and answer/hangup in the same sync.\n // This happens quite often, eg. replaying sync from storage, catchup sync\n // after loading and after we've been offline for a bit.\n this.callEventBuffer = [];\n this.candidateEventsByCall = new Map<string, Array<MatrixEvent>>();\n }\n\n public start(): void {\n this.client.on(ClientEvent.Sync, this.onSync);\n this.client.on(RoomEvent.Timeline, this.onRoomTimeline);\n this.client.on(ClientEvent.ToDeviceEvent, this.onToDeviceEvent);\n }\n\n public stop(): void {\n this.client.removeListener(ClientEvent.Sync, this.onSync);\n this.client.removeListener(RoomEvent.Timeline, this.onRoomTimeline);\n this.client.removeListener(ClientEvent.ToDeviceEvent, this.onToDeviceEvent);\n }\n\n private onSync = (): void => {\n // Process the current event buffer and start queuing into a new one.\n const currentEventBuffer = this.callEventBuffer;\n this.callEventBuffer = [];\n\n // Ensure correct ordering by only processing this queue after the previous one has finished processing\n if (this.eventBufferPromiseChain) {\n this.eventBufferPromiseChain = this.eventBufferPromiseChain.then(() =>\n this.evaluateEventBuffer(currentEventBuffer),\n );\n } else {\n this.eventBufferPromiseChain = this.evaluateEventBuffer(currentEventBuffer);\n }\n };\n\n private async evaluateEventBuffer(eventBuffer: MatrixEvent[]): Promise<void> {\n await Promise.all(eventBuffer.map((event) => this.client.decryptEventIfNeeded(event)));\n\n const callEvents = eventBuffer.filter((event) => {\n const eventType = event.getType();\n return eventType.startsWith(\"m.call.\") || eventType.startsWith(\"org.matrix.call.\");\n });\n\n const ignoreCallIds = new Set<string>();\n\n // inspect the buffer and mark all calls which have been answered\n // or hung up before passing them to the call event handler.\n for (const event of callEvents) {\n const eventType = event.getType();\n\n if (eventType === EventType.CallAnswer || eventType === EventType.CallHangup) {\n ignoreCallIds.add(event.getContent().call_id);\n }\n }\n\n // Process call events in the order that they were received\n for (const event of callEvents) {\n const eventType = event.getType();\n const callId = event.getContent().call_id;\n\n if (eventType === EventType.CallInvite && ignoreCallIds.has(callId)) {\n // This call has previously been answered or hung up: ignore it\n continue;\n }\n\n try {\n await this.handleCallEvent(event);\n } catch (e) {\n logger.error(\"CallEventHandler evaluateEventBuffer() caught exception handling call event\", e);\n }\n }\n }\n\n private onRoomTimeline = (event: MatrixEvent): void => {\n this.callEventBuffer.push(event);\n };\n\n private onToDeviceEvent = (event: MatrixEvent): void => {\n const content = event.getContent();\n\n if (!content.call_id) {\n this.callEventBuffer.push(event);\n return;\n }\n\n if (!this.nextSeqByCall.has(content.call_id)) {\n this.nextSeqByCall.set(content.call_id, 0);\n }\n\n if (content.seq === undefined) {\n this.callEventBuffer.push(event);\n return;\n }\n\n const nextSeq = this.nextSeqByCall.get(content.call_id) || 0;\n\n if (content.seq !== nextSeq) {\n if (!this.toDeviceEventBuffers.has(content.call_id)) {\n this.toDeviceEventBuffers.set(content.call_id, []);\n }\n\n const buffer = this.toDeviceEventBuffers.get(content.call_id)!;\n const index = buffer.findIndex((e) => e.getContent().seq > content.seq);\n\n if (index === -1) {\n buffer.push(event);\n } else {\n buffer.splice(index, 0, event);\n }\n } else {\n const callId = content.call_id;\n this.callEventBuffer.push(event);\n this.nextSeqByCall.set(callId, content.seq + 1);\n\n const buffer = this.toDeviceEventBuffers.get(callId);\n\n let nextEvent = buffer && buffer.shift();\n\n while (nextEvent && nextEvent.getContent().seq === this.nextSeqByCall.get(callId)) {\n this.callEventBuffer.push(nextEvent);\n this.nextSeqByCall.set(callId, nextEvent.getContent().seq + 1);\n nextEvent = buffer!.shift();\n }\n }\n };\n\n private async handleCallEvent(event: MatrixEvent): Promise<void> {\n this.client.emit(ClientEvent.ReceivedVoipEvent, event);\n\n const content = event.getContent();\n const callRoomId =\n event.getRoomId() || this.client.groupCallEventHandler!.getGroupCallById(content.conf_id)?.room?.roomId;\n const groupCallId = content.conf_id;\n const type = event.getType() as EventType;\n const senderId = event.getSender()!;\n let call = content.call_id ? this.calls.get(content.call_id) : undefined;\n\n let opponentDeviceId: string | undefined;\n\n let groupCall: GroupCall | undefined;\n if (groupCallId) {\n groupCall = this.client.groupCallEventHandler!.getGroupCallById(groupCallId);\n\n if (!groupCall) {\n logger.warn(\n `CallEventHandler handleCallEvent() could not find a group call - ignoring event (groupCallId=${groupCallId}, type=${type})`,\n );\n return;\n }\n\n opponentDeviceId = content.device_id;\n\n if (!opponentDeviceId) {\n logger.warn(\n `CallEventHandler handleCallEvent() could not find a device id - ignoring event (senderId=${senderId})`,\n );\n groupCall.emit(GroupCallEvent.Error, new GroupCallUnknownDeviceError(senderId));\n return;\n }\n\n if (content.dest_session_id !== this.client.getSessionId()) {\n logger.warn(\n \"CallEventHandler handleCallEvent() call event does not match current session id - ignoring\",\n );\n return;\n }\n }\n\n const weSentTheEvent =\n senderId === this.client.credentials.userId &&\n (opponentDeviceId === undefined || opponentDeviceId === this.client.getDeviceId()!);\n\n if (!callRoomId) return;\n\n if (type === EventType.CallInvite) {\n // ignore invites you send\n if (weSentTheEvent) return;\n // expired call\n if (event.getLocalAge() > content.lifetime - RING_GRACE_PERIOD) return;\n // stale/old invite event\n if (call && call.state === CallState.Ended) return;\n\n if (call) {\n logger.warn(\n `CallEventHandler handleCallEvent() already has a call but got an invite - clobbering (callId=${content.call_id})`,\n );\n }\n\n if (content.invitee && content.invitee !== this.client.getUserId()) {\n return; // This invite was meant for another user in the room\n }\n\n const timeUntilTurnCresExpire = (this.client.getTurnServersExpiry() ?? 0) - Date.now();\n logger.info(\n \"CallEventHandler handleCallEvent() current turn creds expire in \" + timeUntilTurnCresExpire + \" ms\",\n );\n call =\n createNewMatrixCall(this.client, callRoomId, {\n forceTURN: this.client.forceTURN,\n opponentDeviceId,\n groupCallId,\n opponentSessionId: content.sender_session_id,\n }) ?? undefined;\n if (!call) {\n logger.log(\n `CallEventHandler handleCallEvent() this client does not support WebRTC (callId=${content.call_id})`,\n );\n // don't hang up the call: there could be other clients\n // connected that do support WebRTC and declining the\n // the call on their behalf would be really annoying.\n return;\n }\n\n call.callId = content.call_id;\n const stats = groupCall?.getGroupCallStats();\n if (stats) {\n call.initStats(stats);\n }\n\n try {\n await call.initWithInvite(event);\n } catch (e) {\n if (e instanceof CallError) {\n if (e.code === GroupCallErrorCode.UnknownDevice) {\n groupCall?.emit(GroupCallEvent.Error, e);\n } else {\n logger.error(e);\n }\n }\n }\n this.calls.set(call.callId, call);\n\n // if we stashed candidate events for that call ID, play them back now\n if (this.candidateEventsByCall.get(call.callId)) {\n for (const ev of this.candidateEventsByCall.get(call.callId)!) {\n call.onRemoteIceCandidatesReceived(ev);\n }\n }\n\n // Were we trying to call that user (room)?\n let existingCall: MatrixCall | undefined;\n for (const thisCall of this.calls.values()) {\n const isCalling = [CallState.WaitLocalMedia, CallState.CreateOffer, CallState.InviteSent].includes(\n thisCall.state,\n );\n\n if (\n call.roomId === thisCall.roomId &&\n thisCall.direction === CallDirection.Outbound &&\n call.getOpponentMember()?.userId === thisCall.invitee &&\n isCalling\n ) {\n existingCall = thisCall;\n break;\n }\n }\n\n if (existingCall) {\n if (existingCall.callId > call.callId) {\n logger.log(\n `CallEventHandler handleCallEvent() detected glare - answering incoming call and canceling outgoing call (incomingId=${call.callId}, outgoingId=${existingCall.callId})`,\n );\n existingCall.replacedBy(call);\n } else {\n logger.log(\n `CallEventHandler handleCallEvent() detected glare - hanging up incoming call (incomingId=${call.callId}, outgoingId=${existingCall.callId})`,\n );\n call.hangup(CallErrorCode.Replaced, true);\n }\n } else {\n this.client.emit(CallEventHandlerEvent.Incoming, call);\n }\n return;\n } else if (type === EventType.CallCandidates) {\n if (weSentTheEvent) return;\n\n if (!call) {\n // store the candidates; we may get a call eventually.\n if (!this.candidateEventsByCall.has(content.call_id)) {\n this.candidateEventsByCall.set(content.call_id, []);\n }\n this.candidateEventsByCall.get(content.call_id)!.push(event);\n } else {\n call.onRemoteIceCandidatesReceived(event);\n }\n return;\n } else if ([EventType.CallHangup, EventType.CallReject].includes(type)) {\n // Note that we also observe our own hangups here so we can see\n // if we've already rejected a call that would otherwise be valid\n if (!call) {\n // if not live, store the fact that the call has ended because\n // we're probably getting events backwards so\n // the hangup will come before the invite\n call =\n createNewMatrixCall(this.client, callRoomId, {\n opponentDeviceId,\n opponentSessionId: content.sender_session_id,\n }) ?? undefined;\n if (call) {\n call.callId = content.call_id;\n call.initWithHangup(event);\n this.calls.set(content.call_id, call);\n }\n } else {\n if (call.state !== CallState.Ended) {\n if (type === EventType.CallHangup) {\n call.onHangupReceived(content as MCallHangupReject);\n } else {\n call.onRejectReceived(content as MCallHangupReject);\n }\n\n // @ts-expect-error typescript thinks the state can't be 'ended' because we're\n // inside the if block where it wasn't, but it could have changed because\n // on[Hangup|Reject]Received are side-effecty.\n if (call.state === CallState.Ended) this.calls.delete(content.call_id);\n }\n }\n return;\n }\n\n // The following events need a call and a peer connection\n if (!call || !call.hasPeerConnection) {\n logger.info(\n `CallEventHandler handleCallEvent() discarding possible call event as we don't have a call (type=${type})`,\n );\n return;\n }\n // Ignore remote echo\n if (event.getContent().party_id === call.ourPartyId) return;\n\n switch (type) {\n case EventType.CallAnswer:\n if (weSentTheEvent) {\n if (call.state === CallState.Ringing) {\n call.onAnsweredElsewhere(content as MCallAnswer);\n }\n } else {\n call.onAnswerReceived(event);\n }\n break;\n case EventType.CallSelectAnswer:\n call.onSelectAnswerReceived(event);\n break;\n\n case EventType.CallNegotiate:\n call.onNegotiateReceived(event);\n break;\n\n case EventType.CallAssertedIdentity:\n case EventType.CallAssertedIdentityPrefix:\n call.onAssertedIdentityReceived(event);\n break;\n\n case EventType.CallSDPStreamMetadataChanged:\n case EventType.CallSDPStreamMetadataChangedPrefix:\n call.onSDPStreamMetadataChangedReceived(event);\n break;\n }\n }\n}\n","// allow non-camelcase as these are events type that go onto the wire\n/* eslint-disable camelcase */\n\nimport { type CallErrorCode } from \"./call.ts\";\nimport { NamespacedValue } from \"../NamespacedValue.ts\";\n\nexport const SDPStreamMetadataKey = new NamespacedValue(\n \"sdp_stream_metadata\",\n \"org.matrix.msc3077.sdp_stream_metadata\",\n);\n\nexport enum SDPStreamMetadataPurpose {\n Usermedia = \"m.usermedia\",\n Screenshare = \"m.screenshare\",\n}\n\nexport interface SDPStreamMetadataObject {\n purpose: SDPStreamMetadataPurpose;\n audio_muted: boolean;\n video_muted: boolean;\n}\n\nexport interface SDPStreamMetadata {\n [key: string]: SDPStreamMetadataObject;\n}\n\nexport interface CallCapabilities {\n \"m.call.transferee\": boolean;\n \"m.call.dtmf\": boolean;\n}\n\nexport interface CallReplacesTarget {\n id: string;\n display_name: string;\n avatar_url: string;\n}\n\nexport interface MCallBase {\n call_id: string;\n conf_id?: string;\n version: string | number;\n party_id?: string;\n sender_session_id?: string;\n dest_session_id?: string;\n}\n\ntype Description = Pick<RTCSessionDescription, \"type\" | \"sdp\">;\n\nexport interface MCallAnswer extends MCallBase {\n \"answer\": Description;\n \"capabilities\"?: CallCapabilities;\n \"sdp_stream_metadata\"?: SDPStreamMetadata;\n \"org.matrix.msc3077.sdp_stream_metadata\"?: SDPStreamMetadata;\n}\n\nexport interface MCallSelectAnswer extends MCallBase {\n selected_party_id: string;\n}\n\nexport interface MCallInviteNegotiate extends MCallBase {\n \"offer\": Description;\n \"description\": Description;\n \"lifetime\": number;\n \"capabilities\"?: CallCapabilities;\n \"invitee\"?: string;\n \"sender_session_id\"?: string;\n \"dest_session_id\"?: string;\n \"sdp_stream_metadata\"?: SDPStreamMetadata;\n \"org.matrix.msc3077.sdp_stream_metadata\"?: SDPStreamMetadata;\n}\n\nexport interface MCallSDPStreamMetadataChanged extends MCallBase {\n \"sdp_stream_metadata\"?: SDPStreamMetadata;\n \"org.matrix.msc3077.sdp_stream_metadata\"?: SDPStreamMetadata;\n}\n\nexport interface MCallReplacesEvent extends MCallBase {\n replacement_id: string;\n target_user: CallReplacesTarget;\n create_call: string;\n await_call: string;\n target_room: string;\n}\n\nexport interface MCAllAssertedIdentity extends MCallBase {\n asserted_identity: {\n id: string;\n display_name: string;\n avatar_url: string;\n };\n}\n\nexport interface MCallCandidates extends MCallBase {\n candidates: Omit<RTCIceCandidateInit, \"usernameFragment\">[];\n}\n\nexport interface MCallHangupReject extends MCallBase {\n reason?: CallErrorCode;\n}\n\n/* eslint-enable camelcase */\n","/*\nCopyright 2021 Šimon Brandner <simon.bra.ag@gmail.com>\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 MatrixEvent } from \"../models/event.ts\";\nimport { type MatrixClient, ClientEvent } from \"../client.ts\";\nimport { GroupCall, GroupCallIntent, GroupCallType, type IGroupCallDataChannelOptions } from \"./groupCall.ts\";\nimport { type Room } from \"../models/room.ts\";\nimport { type RoomState, RoomStateEvent } from \"../models/room-state.ts\";\nimport { type RoomMember } from \"../models/room-member.ts\";\nimport { logger } from \"../logger.ts\";\nimport { EventType } from \"../@types/event.ts\";\nimport { SyncState } from \"../sync.ts\";\n\nexport enum GroupCallEventHandlerEvent {\n Incoming = \"GroupCall.incoming\",\n Outgoing = \"GroupCall.outgoing\",\n Ended = \"GroupCall.ended\",\n Participants = \"GroupCall.participants\",\n}\n\nexport type GroupCallEventHandlerEventHandlerMap = {\n [GroupCallEventHandlerEvent.Incoming]: (call: GroupCall) => void;\n [GroupCallEventHandlerEvent.Outgoing]: (call: GroupCall) => void;\n [GroupCallEventHandlerEvent.Ended]: (call: GroupCall) => void;\n [GroupCallEventHandlerEvent.Participants]: (participants: RoomMember[], call: GroupCall) => void;\n};\n\ninterface RoomDeferred {\n prom: Promise<void>;\n resolve?: () => void;\n}\n\nexport class GroupCallEventHandler {\n public groupCalls = new Map<string, GroupCall>(); // roomId -> GroupCall\n\n // All rooms we know about and whether we've seen a 'Room' event\n // for them. The promise will be fulfilled once we've processed that\n // event which means we're \"up to date\" on what calls are in a room\n // and get\n private roomDeferreds = new Map<string, RoomDeferred>();\n\n public constructor(private client: MatrixClient) {}\n\n public async start(): Promise<void> {\n // We wait until the client has started syncing for real.\n // This is because we only support one call at a time, and want\n // the latest. We therefore want the latest state of the room before\n // we create a group call for the room so we can be fairly sure that\n // the group call we create is really the latest one.\n if (this.client.getSyncState() !== SyncState.Syncing) {\n logger.debug(\"GroupCallEventHandler start() waiting for client to start syncing\");\n await new Promise<void>((resolve) => {\n const onSync = (): void => {\n if (this.client.getSyncState() === SyncState.Syncing) {\n this.client.off(ClientEvent.Sync, onSync);\n return resolve();\n }\n };\n this.client.on(ClientEvent.Sync, onSync);\n });\n }\n\n const rooms = this.client.getRooms();\n\n for (const room of rooms) {\n this.createGroupCallForRoom(room);\n }\n\n this.client.on(ClientEvent.Room, this.onRoomsChanged);\n this.client.on(RoomStateEvent.Events, this.onRoomStateChanged);\n }\n\n public stop(): void {\n this.client.removeListener(ClientEvent.Room, this.onRoomsChanged);\n this.client.removeListener(RoomStateEvent.Events, this.onRoomStateChanged);\n }\n\n private getRoomDeferred(roomId: string): RoomDeferred {\n let deferred = this.roomDeferreds.get(roomId);\n if (deferred === undefined) {\n let resolveFunc: () => void;\n deferred = {\n prom: new Promise<void>((resolve) => {\n resolveFunc = resolve;\n }),\n };\n deferred.resolve = resolveFunc!;\n this.roomDeferreds.set(roomId, deferred);\n }\n\n return deferred;\n }\n\n public waitUntilRoomReadyForGroupCalls(roomId: string): Promise<void> {\n return this.getRoomDeferred(roomId).prom;\n }\n\n public getGroupCallById(groupCallId: string): GroupCall | undefined {\n return [...this.groupCalls.values()].find((groupCall) => groupCall.groupCallId === groupCallId);\n }\n\n private createGroupCallForRoom(room: Room): void {\n const callEvents = room.currentState.getStateEvents(EventType.GroupCallPrefix);\n const sortedCallEvents = callEvents.sort((a, b) => b.getTs() - a.getTs());\n\n for (const callEvent of sortedCallEvents) {\n const content = callEvent.getContent();\n\n if (content[\"m.terminated\"] || callEvent.isRedacted()) {\n continue;\n }\n\n logger.debug(\n `GroupCallEventHandler createGroupCallForRoom() choosing group call from possible calls (stateKey=${callEvent.getStateKey()}, ts=${callEvent.getTs()}, roomId=${\n room.roomId\n }, numOfPossibleCalls=${callEvents.length})`,\n );\n\n this.createGroupCallFromRoomStateEvent(callEvent);\n break;\n }\n\n this.getRoomDeferred(room.roomId).resolve!();\n }\n\n private createGroupCallFromRoomStateEvent(event: MatrixEvent): GroupCall | undefined {\n const roomId = event.getRoomId();\n const content = event.getContent();\n\n const room = this.client.getRoom(roomId);\n\n if (!room) {\n logger.warn(\n `GroupCallEventHandler createGroupCallFromRoomStateEvent() couldn't find room for call (roomId=${roomId})`,\n );\n return;\n }\n\n const groupCallId = event.getStateKey();\n\n const callType = content[\"m.type\"];\n\n if (!Object.values(GroupCallType).includes(callType)) {\n logger.warn(\n `GroupCallEventHandler createGroupCallFromRoomStateEvent() received invalid call type (type=${callType}, roomId=${roomId})`,\n );\n return;\n }\n\n const callIntent = content[\"m.intent\"];\n\n if (!Object.values(GroupCallIntent).includes(callIntent)) {\n logger.warn(`Received invalid group call intent (type=${callType}, roomId=${roomId})`);\n return;\n }\n\n const isPtt = Boolean(content[\"io.element.ptt\"]);\n\n let dataChannelOptions: IGroupCallDataChannelOptions | undefined;\n\n if (content?.dataChannelsEnabled && content?.dataChannelOptions) {\n // Pull out just the dataChannelOptions we want to support.\n const { ordered, maxPacketLifeTime, maxRetransmits, protocol } = content.dataChannelOptions;\n dataChannelOptions = { ordered, maxPacketLifeTime, maxRetransmits, protocol };\n }\n\n const groupCall = new GroupCall(\n this.client,\n room,\n callType,\n isPtt,\n callIntent,\n groupCallId,\n // Because without Media section a WebRTC connection is not possible, so need a RTCDataChannel to set up a\n // no media WebRTC connection anyway.\n content?.dataChannelsEnabled || this.client.isVoipWithNoMediaAllowed,\n dataChannelOptions,\n this.client.isVoipWithNoMediaAllowed,\n this.client.useLivekitForGroupCalls,\n content[\"io.element.livekit_service_url\"],\n );\n\n this.groupCalls.set(room.roomId, groupCall);\n this.client.emit(GroupCallEventHandlerEvent.Incoming, groupCall);\n\n return groupCall;\n }\n\n private onRoomsChanged = (room: Room): void => {\n this.createGroupCallForRoom(room);\n };\n\n private onRoomStateChanged = (event: MatrixEvent, state: RoomState): void => {\n const eventType = event.getType();\n\n if (eventType === EventType.GroupCallPrefix) {\n const groupCallId = event.getStateKey();\n const content = event.getContent();\n\n const currentGroupCall = this.groupCalls.get(state.roomId);\n\n if (!currentGroupCall && !content[\"m.terminated\"] && !event.isRedacted()) {\n this.createGroupCallFromRoomStateEvent(event);\n } else if (currentGroupCall && currentGroupCall.groupCallId === groupCallId) {\n if (content[\"m.terminated\"] || event.isRedacted()) {\n currentGroupCall.terminate(false);\n } else if (content[\"m.type\"] !== currentGroupCall.type) {\n // TODO: Handle the callType changing when the room state changes\n logger.warn(\n `GroupCallEventHandler onRoomStateChanged() currently does not support changing type (roomId=${state.roomId})`,\n );\n }\n } else if (currentGroupCall && currentGroupCall.groupCallId !== groupCallId) {\n // TODO: Handle new group calls and multiple group calls\n logger.warn(\n `GroupCallEventHandler onRoomStateChanged() currently does not support multiple calls (roomId=${state.roomId})`,\n );\n }\n }\n };\n}\n","/*\nCopyright 2023 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*/\nimport { type CallFeedReport, type CallFeedStats, type TrackStats, type TransceiverStats } from \"./statsReport.ts\";\nimport { type CallFeed } from \"../callFeed.ts\";\n\nexport class CallFeedStatsReporter {\n public static buildCallFeedReport(callId: string, opponentMemberId: string, pc: RTCPeerConnection): CallFeedReport {\n const rtpTransceivers = pc.getTransceivers();\n const transceiver: TransceiverStats[] = [];\n const callFeeds: CallFeedStats[] = [];\n\n rtpTransceivers.forEach((t) => {\n const sender = t.sender?.track ? CallFeedStatsReporter.buildTrackStats(t.sender.track, \"sender\") : null;\n const receiver = CallFeedStatsReporter.buildTrackStats(t.receiver.track, \"receiver\");\n transceiver.push({\n mid: t.mid == null ? \"null\" : t.mid,\n direction: t.direction,\n currentDirection: t.currentDirection == null ? \"null\" : t.currentDirection,\n sender,\n receiver,\n });\n });\n\n return {\n callId,\n opponentMemberId,\n transceiver,\n callFeeds,\n };\n }\n\n private static buildTrackStats(track: MediaStreamTrack, label = \"--\"): TrackStats {\n const settingDeviceId = track.getSettings()?.deviceId;\n const constrainDeviceId = track.getConstraints()?.deviceId;\n\n return {\n id: track.id,\n kind: track.kind,\n settingDeviceId: settingDeviceId ?? \"unknown\",\n constrainDeviceId: constrainDeviceId ?? \"unknown\",\n muted: track.muted,\n enabled: track.enabled,\n readyState: track.readyState,\n label,\n } as TrackStats;\n }\n\n public static expandCallFeedReport(\n report: CallFeedReport,\n callFeeds: CallFeed[],\n prefix = \"unknown\",\n ): CallFeedReport {\n callFeeds.forEach((feed) => {\n const audioTracks = feed.stream.getAudioTracks();\n const videoTracks = feed.stream.getVideoTracks();\n const audio =\n audioTracks.length > 0\n ? CallFeedStatsReporter.buildTrackStats(feed.stream.getAudioTracks()[0], feed.purpose)\n : null;\n const video =\n videoTracks.length > 0\n ? CallFeedStatsReporter.buildTrackStats(feed.stream.getVideoTracks()[0], feed.purpose)\n : null;\n const feedStats = {\n stream: feed.stream.id,\n type: feed.isLocal() ? \"local\" : \"remote\",\n audio,\n video,\n purpose: feed.purpose,\n prefix,\n isVideoMuted: feed.isVideoMuted(),\n isAudioMuted: feed.isAudioMuted(),\n } as CallFeedStats;\n report.callFeeds.push(feedStats);\n });\n return report;\n }\n}\n","/*\nCopyright 2023 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 TransportStats } from \"./transportStats.ts\";\nimport { type Bitrate } from \"./media/mediaTrackStats.ts\";\n\nexport interface ConnectionStatsBandwidth {\n /**\n * bytes per second\n */\n download: number;\n /**\n * bytes per second\n */\n upload: number;\n}\n\nexport interface ConnectionStatsBitrate extends Bitrate {\n audio?: Bitrate;\n video?: Bitrate;\n}\n\nexport interface PacketLoss {\n total: number;\n download: number;\n upload: number;\n}\n\nexport class ConnectionStats {\n public bandwidth: ConnectionStatsBitrate = {} as ConnectionStatsBitrate;\n public bitrate: ConnectionStatsBitrate = {} as ConnectionStatsBitrate;\n public packetLoss: PacketLoss = {} as PacketLoss;\n public transport: TransportStats[] = [];\n}\n","/*\nCopyright 2023 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*/\nimport { type Bitrate } from \"./media/mediaTrackStats.ts\";\n\nexport class ConnectionStatsBuilder {\n public static buildBandwidthReport(now: RTCIceCandidatePairStats): Bitrate {\n const availableIncomingBitrate = now.availableIncomingBitrate;\n const availableOutgoingBitrate = now.availableOutgoingBitrate;\n\n return {\n download: availableIncomingBitrate ? Math.round(availableIncomingBitrate / 1000) : 0,\n upload: availableOutgoingBitrate ? Math.round(availableOutgoingBitrate / 1000) : 0,\n };\n }\n}\n","import { type TransportStats } from \"./transportStats.ts\";\n\nexport class TransportStatsBuilder {\n public static buildReport(\n report: RTCStatsReport | undefined,\n now: RTCIceCandidatePairStats,\n conferenceStatsTransport: TransportStats[],\n isFocus: boolean,\n ): TransportStats[] {\n const localUsedCandidate = report?.get(now.localCandidateId);\n const remoteUsedCandidate = report?.get(now.remoteCandidateId);\n\n // RTCIceCandidateStats\n // https://w3c.github.io/webrtc-stats/#icecandidate-dict*\n if (remoteUsedCandidate && localUsedCandidate) {\n const remoteIpAddress =\n remoteUsedCandidate.ip !== undefined ? remoteUsedCandidate.ip : remoteUsedCandidate.address;\n const remotePort = remoteUsedCandidate.port;\n const ip = `${remoteIpAddress}:${remotePort}`;\n\n const localIpAddress =\n localUsedCandidate.ip !== undefined ? localUsedCandidate.ip : localUsedCandidate.address;\n const localPort = localUsedCandidate.port;\n const localIp = `${localIpAddress}:${localPort}`;\n\n const type = remoteUsedCandidate.protocol;\n\n // Save the address unless it has been saved already.\n if (\n !conferenceStatsTransport.some(\n (t: TransportStats) => t.ip === ip && t.type === type && t.localIp === localIp,\n )\n ) {\n conferenceStatsTransport.push({\n ip,\n type,\n localIp,\n isFocus,\n localCandidateType: localUsedCandidate.candidateType,\n remoteCandidateType: remoteUsedCandidate.candidateType,\n networkType: localUsedCandidate.networkType,\n rtt: now.currentRoundTripTime ? now.currentRoundTripTime * 1000 : NaN,\n } as TransportStats);\n }\n }\n return conferenceStatsTransport;\n }\n}\n","/*\nCopyright 2023 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 { parse as parseSdp } from \"sdp-transform\";\n\nexport type Mid = string;\nexport type Ssrc = string;\nexport type MapType = \"local\" | \"remote\";\n\nexport class MediaSsrcHandler {\n private readonly ssrcToMid = { local: new Map<Mid, Ssrc[]>(), remote: new Map<Mid, Ssrc[]>() };\n\n public findMidBySsrc(ssrc: Ssrc, type: \"local\" | \"remote\"): Mid | undefined {\n let mid: Mid | undefined;\n this.ssrcToMid[type].forEach((ssrcs, m) => {\n if (ssrcs.find((s) => s == ssrc)) {\n mid = m;\n return;\n }\n });\n return mid;\n }\n\n public parse(description: string, type: MapType): void {\n const sdp = parseSdp(description);\n const ssrcToMid = new Map<Mid, Ssrc[]>();\n sdp.media.forEach((m) => {\n if ((!!m.mid && m.type === \"video\") || m.type === \"audio\") {\n const ssrcs: Ssrc[] = [];\n m.ssrcs?.forEach((ssrc) => {\n if (ssrc.attribute === \"cname\") {\n ssrcs.push(`${ssrc.id}`);\n }\n });\n ssrcToMid.set(`${m.mid}`, ssrcs);\n }\n });\n this.ssrcToMid[type] = ssrcToMid;\n }\n\n public getSsrcToMidMap(type: MapType): Map<Mid, Ssrc[]> {\n return this.ssrcToMid[type];\n }\n}\n","/*\nCopyright 2023 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\nexport type TrackId = string;\n\nexport class MediaTrackHandler {\n public constructor(private readonly pc: RTCPeerConnection) {}\n\n public getLocalTracks(kind: \"audio\" | \"video\"): MediaStreamTrack[] {\n const isNotNullAndKind = (track: MediaStreamTrack | null): boolean => {\n return track !== null && track.kind === kind;\n };\n return this.pc\n .getTransceivers()\n .filter((t) => t.currentDirection === \"sendonly\" || t.currentDirection === \"sendrecv\")\n .filter((t) => t.sender !== null)\n .map((t) => t.sender)\n .map((s) => s.track)\n .filter(isNotNullAndKind) as MediaStreamTrack[];\n }\n\n public getTackById(trackId: string): MediaStreamTrack | undefined {\n return this.pc\n .getTransceivers()\n .map((t) => {\n if (t?.sender.track !== null && t.sender.track.id === trackId) {\n return t.sender.track;\n }\n if (t?.receiver.track !== null && t.receiver.track.id === trackId) {\n return t.receiver.track;\n }\n return undefined;\n })\n .find((t) => t !== undefined);\n }\n\n public getLocalTrackIdByMid(mid: string): string | undefined {\n const transceiver = this.pc.getTransceivers().find((t) => t.mid === mid);\n return transceiver?.sender?.track?.id;\n }\n\n public getRemoteTrackIdByMid(mid: string): string | undefined {\n const transceiver = this.pc.getTransceivers().find((t) => t.mid === mid);\n return transceiver?.receiver?.track?.id;\n }\n\n public getActiveSimulcastStreams(): number {\n //@TODO implement this right.. Check how many layer configured\n return 3;\n }\n\n public getTransceiverByTrackId(trackId: TrackId): RTCRtpTransceiver | undefined {\n return this.pc.getTransceivers().find((t) => {\n return t.receiver.track.id === trackId || (t.sender.track !== null && t.sender.track.id === trackId);\n });\n }\n}\n","/*\nCopyright 2023 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 AudioConcealment } from \"../statsReport.ts\";\nimport { type TrackId } from \"./mediaTrackHandler.ts\";\n\nexport interface PacketLoss {\n packetsTotal: number;\n packetsLost: number;\n isDownloadStream: boolean;\n}\n\nexport interface Bitrate {\n /**\n * bytes per second\n */\n download: number;\n /**\n * bytes per second\n */\n upload: number;\n}\nexport interface ConcealedAudio {\n /**\n * duration in ms\n */\n duration: number;\n\n ratio: number;\n}\nexport interface Resolution {\n width: number;\n height: number;\n}\n\nexport type TrackStatsType = \"local\" | \"remote\";\n\nexport class MediaTrackStats {\n private loss: PacketLoss = { packetsTotal: 0, packetsLost: 0, isDownloadStream: false };\n private bitrate: Bitrate = { download: 0, upload: 0 };\n private resolution: Resolution = { width: -1, height: -1 };\n private audioConcealment: AudioConcealment = { concealedAudio: 0, totalAudioDuration: 0 };\n private framerate = 0;\n private jitter = 0;\n private codec = \"\";\n private isAlive = true;\n private isMuted = false;\n private isEnabled = true;\n\n public constructor(\n public readonly trackId: TrackId,\n public readonly type: TrackStatsType,\n public readonly kind: \"audio\" | \"video\",\n ) {}\n\n public getType(): TrackStatsType {\n return this.type;\n }\n\n public setLoss(loss: PacketLoss): void {\n this.loss = loss;\n }\n\n public getLoss(): PacketLoss {\n return this.loss;\n }\n\n public setResolution(resolution: Resolution): void {\n this.resolution = resolution;\n }\n\n public getResolution(): Resolution {\n return this.resolution;\n }\n\n public setFramerate(framerate: number): void {\n this.framerate = framerate;\n }\n\n public getFramerate(): number {\n return this.framerate;\n }\n\n public setBitrate(bitrate: Bitrate): void {\n this.bitrate = bitrate;\n }\n\n public getBitrate(): Bitrate {\n return this.bitrate;\n }\n\n public setCodec(codecShortType: string): boolean {\n this.codec = codecShortType;\n return true;\n }\n\n public getCodec(): string {\n return this.codec;\n }\n\n public resetBitrate(): void {\n this.bitrate = { download: 0, upload: 0 };\n }\n\n public set alive(isAlive: boolean) {\n this.isAlive = isAlive;\n }\n\n /**\n * A MediaTrackState is alive if the corresponding MediaStreamTrack track bound to a transceiver and the\n * MediaStreamTrack is in state MediaStreamTrack.readyState === live\n */\n public get alive(): boolean {\n return this.isAlive;\n }\n\n public set muted(isMuted: boolean) {\n this.isMuted = isMuted;\n }\n\n /**\n * A MediaTrackState.isMuted corresponding to MediaStreamTrack.muted.\n * But these values only match if MediaTrackState.isAlive.\n */\n public get muted(): boolean {\n return this.isMuted;\n }\n\n public set enabled(isEnabled: boolean) {\n this.isEnabled = isEnabled;\n }\n\n /**\n * A MediaTrackState.isEnabled corresponding to MediaStreamTrack.enabled.\n * But these values only match if MediaTrackState.isAlive.\n */\n public get enabled(): boolean {\n return this.isEnabled;\n }\n\n public setJitter(jitter: number): void {\n this.jitter = jitter;\n }\n\n /**\n * Jitter in milliseconds\n */\n public getJitter(): number {\n return this.jitter;\n }\n\n /**\n * Audio concealment ration (conceled duration / total duration)\n */\n public setAudioConcealment(concealedAudioDuration: number, totalAudioDuration: number): void {\n this.audioConcealment.concealedAudio = concealedAudioDuration;\n this.audioConcealment.totalAudioDuration = totalAudioDuration;\n }\n\n public getAudioConcealment(): AudioConcealment {\n return this.audioConcealment;\n }\n}\n","/*\nCopyright 2023 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*/\nimport { type TrackID } from \"../statsReport.ts\";\nimport { MediaTrackStats } from \"./mediaTrackStats.ts\";\nimport { type MediaTrackHandler, type TrackId } from \"./mediaTrackHandler.ts\";\nimport { type MediaSsrcHandler } from \"./mediaSsrcHandler.ts\";\n\nexport class MediaTrackStatsHandler {\n private readonly track2stats = new Map<TrackID, MediaTrackStats>();\n\n public constructor(\n public readonly mediaSsrcHandler: MediaSsrcHandler,\n public readonly mediaTrackHandler: MediaTrackHandler,\n ) {}\n\n /**\n * Find tracks by rtc stats\n * Argument report is any because the stats api is not consistent:\n * For example `trackIdentifier`, `mid` not existing in every implementations\n * https://www.w3.org/TR/webrtc-stats/#dom-rtcinboundrtpstreamstats\n * https://developer.mozilla.org/en-US/docs/Web/API/RTCInboundRtpStreamStats\n */\n public findTrack2Stats(report: any, type: \"remote\" | \"local\"): MediaTrackStats | undefined {\n let trackID;\n if (report.trackIdentifier) {\n trackID = report.trackIdentifier;\n } else if (report.mid) {\n trackID =\n type === \"remote\"\n ? this.mediaTrackHandler.getRemoteTrackIdByMid(report.mid)\n : this.mediaTrackHandler.getLocalTrackIdByMid(report.mid);\n } else if (report.ssrc) {\n const mid = this.mediaSsrcHandler.findMidBySsrc(report.ssrc, type);\n if (!mid) {\n return undefined;\n }\n trackID =\n type === \"remote\"\n ? this.mediaTrackHandler.getRemoteTrackIdByMid(report.mid)\n : this.mediaTrackHandler.getLocalTrackIdByMid(report.mid);\n }\n\n if (!trackID) {\n return undefined;\n }\n\n let trackStats = this.track2stats.get(trackID);\n\n if (!trackStats) {\n const track = this.mediaTrackHandler.getTackById(trackID);\n if (track !== undefined) {\n const kind: \"audio\" | \"video\" = track.kind === \"audio\" ? track.kind : \"video\";\n trackStats = new MediaTrackStats(trackID, type, kind);\n this.track2stats.set(trackID, trackStats);\n } else {\n return undefined;\n }\n }\n return trackStats;\n }\n\n public findLocalVideoTrackStats(report: any): MediaTrackStats | undefined {\n const localVideoTracks = this.mediaTrackHandler.getLocalTracks(\"video\");\n if (localVideoTracks.length === 0) {\n return undefined;\n }\n return this.findTrack2Stats(report, \"local\");\n }\n\n public getTrack2stats(): Map<TrackID, MediaTrackStats> {\n return this.track2stats;\n }\n\n public findTransceiverByTrackId(trackID: TrackId): undefined | RTCRtpTransceiver {\n return this.mediaTrackHandler.getTransceiverByTrackId(trackID);\n }\n}\n","/*\nCopyright 2023 The Matrix.org Foundation C.I.C.\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 http://www.apache.org/licenses/LICENSE-2.0\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*/\nexport class ValueFormatter {\n public static getNonNegativeValue(imput: any): number {\n let value = imput;\n\n if (typeof value !== \"number\") {\n value = Number(value);\n }\n\n if (isNaN(value)) {\n return 0;\n }\n\n return Math.max(0, value);\n }\n}\n","import { type MediaTrackStats } from \"./media/mediaTrackStats.ts\";\nimport { ValueFormatter } from \"./valueFormatter.ts\";\nimport { type TrackSummary } from \"./callStatsReportSummary.ts\";\n\nexport class TrackStatsBuilder {\n public static buildFramerateResolution(trackStats: MediaTrackStats, now: any): void {\n const resolution = {\n height: now.frameHeight,\n width: now.frameWidth,\n };\n const frameRate = now.framesPerSecond;\n\n if (resolution.height && resolution.width) {\n trackStats.setResolution(resolution);\n }\n trackStats.setFramerate(Math.round(frameRate || 0));\n }\n\n public static calculateSimulcastFramerate(trackStats: MediaTrackStats, now: any, before: any, layer: number): void {\n let frameRate = trackStats.getFramerate();\n if (!frameRate) {\n if (before) {\n const timeMs = now.timestamp - before.timestamp;\n\n if (timeMs > 0 && now.framesSent) {\n const numberOfFramesSinceBefore = now.framesSent - before.framesSent;\n\n frameRate = (numberOfFramesSinceBefore / timeMs) * 1000;\n }\n }\n\n if (!frameRate) {\n return;\n }\n }\n\n // Reset frame rate to 0 when video is suspended as a result of endpoint falling out of last-n.\n frameRate = layer ? Math.round(frameRate / layer) : 0;\n trackStats.setFramerate(frameRate);\n }\n\n public static buildCodec(report: RTCStatsReport | undefined, trackStats: MediaTrackStats, now: any): void {\n const codec = report?.get(now.codecId);\n\n if (codec) {\n /**\n * The mime type has the following form: video/VP8 or audio/ISAC,\n * so we what to keep just the type after the '/', audio and video\n * keys will be added on the processing side.\n */\n const codecShortType = codec.mimeType.split(\"/\")[1];\n\n if (codecShortType) trackStats.setCodec(codecShortType);\n }\n }\n\n public static buildBitrateReceived(trackStats: MediaTrackStats, now: any, before: any): void {\n trackStats.setBitrate({\n download: TrackStatsBuilder.calculateBitrate(\n now.bytesReceived,\n before.bytesReceived,\n now.timestamp,\n before.timestamp,\n ),\n upload: 0,\n });\n }\n\n public static buildBitrateSend(trackStats: MediaTrackStats, now: any, before: any): void {\n trackStats.setBitrate({\n download: 0,\n upload: this.calculateBitrate(now.bytesSent, before.bytesSent, now.timestamp, before.timestamp),\n });\n }\n\n public static buildPacketsLost(trackStats: MediaTrackStats, now: any, before: any): void {\n const key = now.type === \"outbound-rtp\" ? \"packetsSent\" : \"packetsReceived\";\n\n let packetsNow = now[key];\n if (!packetsNow || packetsNow < 0) {\n packetsNow = 0;\n }\n\n const packetsBefore = ValueFormatter.getNonNegativeValue(before[key]);\n const packetsDiff = Math.max(0, packetsNow - packetsBefore);\n\n const packetsLostNow = ValueFormatter.getNonNegativeValue(now.packetsLost);\n const packetsLostBefore = ValueFormatter.getNonNegativeValue(before.packetsLost);\n const packetsLostDiff = Math.max(0, packetsLostNow - packetsLostBefore);\n\n trackStats.setLoss({\n packetsTotal: packetsDiff + packetsLostDiff,\n packetsLost: packetsLostDiff,\n isDownloadStream: now.type !== \"outbound-rtp\",\n });\n }\n\n private static calculateBitrate(\n bytesNowAny: any,\n bytesBeforeAny: any,\n nowTimestamp: number,\n beforeTimestamp: number,\n ): number {\n const bytesNow = ValueFormatter.getNonNegativeValue(bytesNowAny);\n const bytesBefore = ValueFormatter.getNonNegativeValue(bytesBeforeAny);\n const bytesProcessed = Math.max(0, bytesNow - bytesBefore);\n\n const timeMs = nowTimestamp - beforeTimestamp;\n let bitrateKbps = 0;\n\n if (timeMs > 0) {\n bitrateKbps = Math.round((bytesProcessed * 8) / timeMs);\n }\n\n return bitrateKbps;\n }\n\n public static setTrackStatsState(trackStats: MediaTrackStats, transceiver: RTCRtpTransceiver | undefined): void {\n if (transceiver === undefined) {\n trackStats.alive = false;\n return;\n }\n\n const track = trackStats.getType() === \"remote\" ? transceiver.receiver.track : transceiver?.sender?.track;\n if (track === undefined || track === null) {\n trackStats.alive = false;\n return;\n }\n\n if (track.readyState === \"ended\") {\n trackStats.alive = false;\n return;\n }\n trackStats.muted = track.muted;\n trackStats.enabled = track.enabled;\n trackStats.alive = true;\n }\n\n public static buildTrackSummary(trackStatsList: MediaTrackStats[]): {\n audioTrackSummary: TrackSummary;\n videoTrackSummary: TrackSummary;\n } {\n const videoTrackSummary: TrackSummary = {\n count: 0,\n muted: 0,\n maxJitter: 0,\n maxPacketLoss: 0,\n concealedAudio: 0,\n totalAudio: 0,\n };\n const audioTrackSummary: TrackSummary = {\n count: 0,\n muted: 0,\n maxJitter: 0,\n maxPacketLoss: 0,\n concealedAudio: 0,\n totalAudio: 0,\n };\n\n const remoteTrackList = trackStatsList.filter((t) => t.getType() === \"remote\");\n const audioTrackList = remoteTrackList.filter((t) => t.kind === \"audio\");\n\n remoteTrackList.forEach((stats) => {\n const trackSummary = stats.kind === \"video\" ? videoTrackSummary : audioTrackSummary;\n trackSummary.count++;\n if (stats.alive && stats.muted) {\n trackSummary.muted++;\n }\n if (trackSummary.maxJitter < stats.getJitter()) {\n trackSummary.maxJitter = stats.getJitter();\n }\n if (trackSummary.maxPacketLoss < stats.getLoss().packetsLost) {\n trackSummary.maxPacketLoss = stats.getLoss().packetsLost;\n }\n if (audioTrackList.length > 0) {\n trackSummary.concealedAudio += stats.getAudioConcealment()?.concealedAudio;\n trackSummary.totalAudio += stats.getAudioConcealment()?.totalAudioDuration;\n }\n });\n\n return { audioTrackSummary, videoTrackSummary };\n }\n\n public static buildJitter(trackStats: MediaTrackStats, statsReport: any): void {\n if (statsReport.type !== \"inbound-rtp\") {\n return;\n }\n\n const jitterStr = statsReport?.jitter;\n if (jitterStr !== undefined) {\n const jitter = ValueFormatter.getNonNegativeValue(jitterStr);\n trackStats.setJitter(Math.round(jitter * 1000));\n } else {\n trackStats.setJitter(-1);\n }\n }\n\n public static buildAudioConcealment(trackStats: MediaTrackStats, statsReport: any): void {\n if (statsReport.type !== \"inbound-rtp\") {\n return;\n }\n const msPerSample = (1000 * statsReport?.totalSamplesDuration) / statsReport?.totalSamplesReceived;\n const concealedAudioDuration = msPerSample * statsReport?.concealedSamples;\n const totalAudioDuration = 1000 * statsReport?.totalSamplesDuration;\n trackStats.setAudioConcealment(concealedAudioDuration, totalAudioDuration);\n }\n}\n","/*\nCopyright 2023 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*/\nimport {\n type AudioConcealment,\n type CodecMap,\n type ConnectionStatsReport,\n type FramerateMap,\n type ResolutionMap,\n type TrackID,\n} from \"./statsReport.ts\";\nimport { type MediaTrackStats, type Resolution } from \"./media/mediaTrackStats.ts\";\n\nexport class ConnectionStatsReportBuilder {\n public static build(stats: Map<TrackID, MediaTrackStats>): ConnectionStatsReport {\n const report = {} as ConnectionStatsReport;\n\n // process stats\n const totalPackets = {\n download: 0,\n upload: 0,\n };\n const lostPackets = {\n download: 0,\n upload: 0,\n };\n let bitrateDownload = 0;\n let bitrateUpload = 0;\n const resolutions: ResolutionMap = {\n local: new Map<TrackID, Resolution>(),\n remote: new Map<TrackID, Resolution>(),\n };\n const framerates: FramerateMap = { local: new Map<TrackID, number>(), remote: new Map<TrackID, number>() };\n const codecs: CodecMap = { local: new Map<TrackID, string>(), remote: new Map<TrackID, string>() };\n const jitter = new Map<TrackID, number>();\n const audioConcealment = new Map<TrackID, AudioConcealment>();\n\n let audioBitrateDownload = 0;\n let audioBitrateUpload = 0;\n let videoBitrateDownload = 0;\n let videoBitrateUpload = 0;\n\n let totalConcealedAudio = 0;\n let totalAudioDuration = 0;\n\n for (const [trackId, trackStats] of stats) {\n // process packet loss stats\n const loss = trackStats.getLoss();\n const type = loss.isDownloadStream ? \"download\" : \"upload\";\n\n totalPackets[type] += loss.packetsTotal;\n lostPackets[type] += loss.packetsLost;\n\n // process bitrate stats\n bitrateDownload += trackStats.getBitrate().download;\n bitrateUpload += trackStats.getBitrate().upload;\n\n // collect resolutions and framerates\n if (trackStats.kind === \"audio\") {\n // process audio quality stats\n const audioConcealmentForTrack = trackStats.getAudioConcealment();\n totalConcealedAudio += audioConcealmentForTrack.concealedAudio;\n totalAudioDuration += audioConcealmentForTrack.totalAudioDuration;\n\n audioBitrateDownload += trackStats.getBitrate().download;\n audioBitrateUpload += trackStats.getBitrate().upload;\n } else {\n videoBitrateDownload += trackStats.getBitrate().download;\n videoBitrateUpload += trackStats.getBitrate().upload;\n }\n\n resolutions[trackStats.getType()].set(trackId, trackStats.getResolution());\n framerates[trackStats.getType()].set(trackId, trackStats.getFramerate());\n codecs[trackStats.getType()].set(trackId, trackStats.getCodec());\n if (trackStats.getType() === \"remote\") {\n jitter.set(trackId, trackStats.getJitter());\n if (trackStats.kind === \"audio\") {\n audioConcealment.set(trackId, trackStats.getAudioConcealment());\n }\n }\n\n trackStats.resetBitrate();\n }\n\n report.bitrate = {\n upload: bitrateUpload,\n download: bitrateDownload,\n };\n\n report.bitrate.audio = {\n upload: audioBitrateUpload,\n download: audioBitrateDownload,\n };\n\n report.bitrate.video = {\n upload: videoBitrateUpload,\n download: videoBitrateDownload,\n };\n\n report.packetLoss = {\n total: ConnectionStatsReportBuilder.calculatePacketLoss(\n lostPackets.download + lostPackets.upload,\n totalPackets.download + totalPackets.upload,\n ),\n download: ConnectionStatsReportBuilder.calculatePacketLoss(lostPackets.download, totalPackets.download),\n upload: ConnectionStatsReportBuilder.calculatePacketLoss(lostPackets.upload, totalPackets.upload),\n };\n report.audioConcealment = audioConcealment;\n report.totalAudioConcealment = {\n concealedAudio: totalConcealedAudio,\n totalAudioDuration,\n };\n\n report.framerate = framerates;\n report.resolution = resolutions;\n report.codec = codecs;\n report.jitter = jitter;\n return report;\n }\n\n private static calculatePacketLoss(lostPackets: number, totalPackets: number): number {\n if (!totalPackets || totalPackets <= 0 || !lostPackets || lostPackets <= 0) {\n return 0;\n }\n\n return Math.round((lostPackets / totalPackets) * 100);\n }\n}\n","/*\nCopyright 2023 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 { ConnectionStats } from \"./connectionStats.ts\";\nimport { type StatsReportEmitter } from \"./statsReportEmitter.ts\";\nimport { type ByteSend, type ByteSentStatsReport, type TrackID } from \"./statsReport.ts\";\nimport { ConnectionStatsBuilder } from \"./connectionStatsBuilder.ts\";\nimport { TransportStatsBuilder } from \"./transportStatsBuilder.ts\";\nimport { MediaSsrcHandler } from \"./media/mediaSsrcHandler.ts\";\nimport { MediaTrackHandler } from \"./media/mediaTrackHandler.ts\";\nimport { MediaTrackStatsHandler } from \"./media/mediaTrackStatsHandler.ts\";\nimport { TrackStatsBuilder } from \"./trackStatsBuilder.ts\";\nimport { ConnectionStatsReportBuilder } from \"./connectionStatsReportBuilder.ts\";\nimport { ValueFormatter } from \"./valueFormatter.ts\";\nimport { type CallStatsReportSummary } from \"./callStatsReportSummary.ts\";\nimport { logger } from \"../../logger.ts\";\nimport { CallFeedStatsReporter } from \"./callFeedStatsReporter.ts\";\n\nexport class CallStatsReportGatherer {\n private isActive = true;\n private previousStatsReport: RTCStatsReport | undefined;\n private currentStatsReport: RTCStatsReport | undefined;\n private readonly connectionStats = new ConnectionStats();\n\n private readonly trackStats: MediaTrackStatsHandler;\n\n public constructor(\n public readonly callId: string,\n private opponentMemberId: string,\n private readonly pc: RTCPeerConnection,\n private readonly emitter: StatsReportEmitter,\n private readonly isFocus = true,\n ) {\n pc.addEventListener(\"signalingstatechange\", this.onSignalStateChange.bind(this));\n this.trackStats = new MediaTrackStatsHandler(new MediaSsrcHandler(), new MediaTrackHandler(pc));\n }\n\n public async processStats(groupCallId: string, localUserId: string): Promise<CallStatsReportSummary> {\n const summary = {\n isFirstCollection: this.previousStatsReport === undefined,\n receivedMedia: 0,\n receivedAudioMedia: 0,\n receivedVideoMedia: 0,\n audioTrackSummary: { count: 0, muted: 0, maxPacketLoss: 0, maxJitter: 0, concealedAudio: 0, totalAudio: 0 },\n videoTrackSummary: { count: 0, muted: 0, maxPacketLoss: 0, maxJitter: 0, concealedAudio: 0, totalAudio: 0 },\n } as CallStatsReportSummary;\n if (this.isActive) {\n const statsPromise = this.pc.getStats();\n if (typeof statsPromise?.then === \"function\") {\n return statsPromise\n .then((report) => {\n // @ts-ignore\n this.currentStatsReport = typeof report?.result === \"function\" ? report.result() : report;\n\n try {\n this.processStatsReport(groupCallId, localUserId);\n } catch (error) {\n this.handleError(error);\n return summary;\n }\n\n this.previousStatsReport = this.currentStatsReport;\n summary.receivedMedia = this.connectionStats.bitrate.download;\n summary.receivedAudioMedia = this.connectionStats.bitrate.audio?.download || 0;\n summary.receivedVideoMedia = this.connectionStats.bitrate.video?.download || 0;\n const trackSummary = TrackStatsBuilder.buildTrackSummary(\n Array.from(this.trackStats.getTrack2stats().values()),\n );\n return {\n ...summary,\n audioTrackSummary: trackSummary.audioTrackSummary,\n videoTrackSummary: trackSummary.videoTrackSummary,\n };\n })\n .catch((error) => {\n this.handleError(error);\n return summary;\n });\n }\n this.isActive = false;\n }\n return Promise.resolve(summary);\n }\n\n private processStatsReport(groupCallId: string, localUserId: string): void {\n const byteSentStatsReport: ByteSentStatsReport = new Map<TrackID, ByteSend>() as ByteSentStatsReport;\n byteSentStatsReport.callId = this.callId;\n byteSentStatsReport.opponentMemberId = this.opponentMemberId;\n\n this.currentStatsReport?.forEach((now) => {\n const before = this.previousStatsReport ? this.previousStatsReport.get(now.id) : null;\n // RTCIceCandidatePairStats - https://w3c.github.io/webrtc-stats/#candidatepair-dict*\n if (now.type === \"candidate-pair\" && now.nominated && now.state === \"succeeded\") {\n this.connectionStats.bandwidth = ConnectionStatsBuilder.buildBandwidthReport(now);\n this.connectionStats.transport = TransportStatsBuilder.buildReport(\n this.currentStatsReport,\n now,\n this.connectionStats.transport,\n this.isFocus,\n );\n\n // RTCReceivedRtpStreamStats\n // https://w3c.github.io/webrtc-stats/#receivedrtpstats-dict*\n // RTCSentRtpStreamStats\n // https://w3c.github.io/webrtc-stats/#sentrtpstats-dict*\n } else if (now.type === \"inbound-rtp\" || now.type === \"outbound-rtp\") {\n const trackStats = this.trackStats.findTrack2Stats(\n now,\n now.type === \"inbound-rtp\" ? \"remote\" : \"local\",\n );\n if (!trackStats) {\n return;\n }\n\n if (before) {\n TrackStatsBuilder.buildPacketsLost(trackStats, now, before);\n }\n\n // Get the resolution and framerate for only remote video sources here. For the local video sources,\n // 'track' stats will be used since they have the updated resolution based on the simulcast streams\n // currently being sent. Promise based getStats reports three 'outbound-rtp' streams and there will be\n // more calculations needed to determine what is the highest resolution stream sent by the client if the\n // 'outbound-rtp' stats are used.\n if (now.type === \"inbound-rtp\") {\n TrackStatsBuilder.buildFramerateResolution(trackStats, now);\n if (before) {\n TrackStatsBuilder.buildBitrateReceived(trackStats, now, before);\n }\n const ts = this.trackStats.findTransceiverByTrackId(trackStats.trackId);\n TrackStatsBuilder.setTrackStatsState(trackStats, ts);\n TrackStatsBuilder.buildJitter(trackStats, now);\n TrackStatsBuilder.buildAudioConcealment(trackStats, now);\n } else if (before) {\n byteSentStatsReport.set(trackStats.trackId, ValueFormatter.getNonNegativeValue(now.bytesSent));\n TrackStatsBuilder.buildBitrateSend(trackStats, now, before);\n }\n TrackStatsBuilder.buildCodec(this.currentStatsReport, trackStats, now);\n } else if (now.type === \"track\" && now.kind === \"video\" && !now.remoteSource) {\n const trackStats = this.trackStats.findLocalVideoTrackStats(now);\n if (!trackStats) {\n return;\n }\n TrackStatsBuilder.buildFramerateResolution(trackStats, now);\n TrackStatsBuilder.calculateSimulcastFramerate(\n trackStats,\n now,\n before,\n this.trackStats.mediaTrackHandler.getActiveSimulcastStreams(),\n );\n }\n });\n\n this.emitter.emitByteSendReport(byteSentStatsReport);\n this.emitter.emitCallFeedReport(\n CallFeedStatsReporter.buildCallFeedReport(this.callId, this.opponentMemberId, this.pc),\n );\n this.processAndEmitConnectionStatsReport();\n }\n\n public setActive(isActive: boolean): void {\n this.isActive = isActive;\n }\n\n public getActive(): boolean {\n return this.isActive;\n }\n\n private handleError(error: any): void {\n this.isActive = false;\n logger.warn(`CallStatsReportGatherer ${this.callId} processStatsReport fails and set to inactive ${error}`);\n }\n\n private processAndEmitConnectionStatsReport(): void {\n const report = ConnectionStatsReportBuilder.build(this.trackStats.getTrack2stats());\n report.callId = this.callId;\n report.opponentMemberId = this.opponentMemberId;\n\n this.connectionStats.bandwidth = report.bandwidth;\n this.connectionStats.bitrate = report.bitrate;\n this.connectionStats.packetLoss = report.packetLoss;\n\n this.emitter.emitConnectionStatsReport({\n ...report,\n transport: this.connectionStats.transport,\n });\n\n this.connectionStats.transport = [];\n }\n\n public stopProcessingStats(): void {}\n\n private onSignalStateChange(): void {\n if (this.pc.signalingState === \"stable\") {\n if (this.pc.currentRemoteDescription) {\n this.trackStats.mediaSsrcHandler.parse(this.pc.currentRemoteDescription.sdp, \"remote\");\n }\n if (this.pc.currentLocalDescription) {\n this.trackStats.mediaSsrcHandler.parse(this.pc.currentLocalDescription.sdp, \"local\");\n }\n }\n }\n\n public setOpponentMemberId(id: string): void {\n this.opponentMemberId = id;\n }\n}\n","/*\nCopyright 2023 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 { TypedEventEmitter } from \"../../models/typed-event-emitter.ts\";\nimport {\n type ByteSentStatsReport,\n type CallFeedReport,\n type ConnectionStatsReport,\n StatsReport,\n type SummaryStatsReport,\n} from \"./statsReport.ts\";\n\nexport type StatsReportHandlerMap = {\n [StatsReport.BYTE_SENT_STATS]: (report: ByteSentStatsReport) => void;\n [StatsReport.CONNECTION_STATS]: (report: ConnectionStatsReport) => void;\n [StatsReport.CALL_FEED_REPORT]: (report: CallFeedReport) => void;\n [StatsReport.SUMMARY_STATS]: (report: SummaryStatsReport) => void;\n};\n\nexport class StatsReportEmitter extends TypedEventEmitter<StatsReport, StatsReportHandlerMap> {\n public emitByteSendReport(byteSentStats: ByteSentStatsReport): void {\n this.emit(StatsReport.BYTE_SENT_STATS, byteSentStats);\n }\n\n public emitConnectionStatsReport(report: ConnectionStatsReport): void {\n this.emit(StatsReport.CONNECTION_STATS, report);\n }\n\n public emitCallFeedReport(report: CallFeedReport): void {\n this.emit(StatsReport.CALL_FEED_REPORT, report);\n }\n\n public emitSummaryStatsReport(report: SummaryStatsReport): void {\n this.emit(StatsReport.SUMMARY_STATS, report);\n }\n}\n","/*\nCopyright 2023 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*/\nimport { CallStatsReportGatherer } from \"./callStatsReportGatherer.ts\";\nimport { StatsReportEmitter } from \"./statsReportEmitter.ts\";\nimport { type CallStatsReportSummary } from \"./callStatsReportSummary.ts\";\nimport { SummaryStatsReportGatherer } from \"./summaryStatsReportGatherer.ts\";\nimport { logger } from \"../../logger.ts\";\n\nexport class GroupCallStats {\n private timer: undefined | ReturnType<typeof setTimeout>;\n private readonly gatherers: Map<string, CallStatsReportGatherer> = new Map<string, CallStatsReportGatherer>();\n public readonly reports = new StatsReportEmitter();\n private readonly summaryStatsReportGatherer = new SummaryStatsReportGatherer(this.reports);\n\n public constructor(\n private groupCallId: string,\n private userId: string,\n private interval: number = 10000,\n ) {}\n\n public start(): void {\n if (this.timer === undefined && this.interval > 0) {\n this.timer = setInterval(() => {\n this.processStats();\n }, this.interval);\n }\n }\n\n public stop(): void {\n if (this.timer !== undefined) {\n clearInterval(this.timer);\n this.gatherers.forEach((c) => c.stopProcessingStats());\n }\n }\n\n public hasStatsReportGatherer(callId: string): boolean {\n return this.gatherers.has(callId);\n }\n\n public addStatsReportGatherer(\n callId: string,\n opponentMemberId: string,\n peerConnection: RTCPeerConnection,\n ): boolean {\n if (this.hasStatsReportGatherer(callId)) {\n return false;\n }\n this.gatherers.set(callId, new CallStatsReportGatherer(callId, opponentMemberId, peerConnection, this.reports));\n return true;\n }\n\n public removeStatsReportGatherer(callId: string): boolean {\n return this.gatherers.delete(callId);\n }\n\n public getStatsReportGatherer(callId: string): CallStatsReportGatherer | undefined {\n return this.hasStatsReportGatherer(callId) ? this.gatherers.get(callId) : undefined;\n }\n\n public updateOpponentMember(callId: string, opponentMember: string): void {\n this.getStatsReportGatherer(callId)?.setOpponentMemberId(opponentMember);\n }\n\n private processStats(): void {\n const summary: Promise<CallStatsReportSummary>[] = [];\n this.gatherers.forEach((c) => {\n summary.push(c.processStats(this.groupCallId, this.userId));\n });\n\n Promise.all(summary)\n .then((s: Awaited<CallStatsReportSummary>[]) => this.summaryStatsReportGatherer.build(s))\n .catch((err) => {\n logger.error(\"Could not build summary stats report\", err);\n });\n }\n\n public setInterval(interval: number): void {\n this.interval = interval;\n }\n}\n","/*\nCopyright 2023 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 ConnectionStatsBandwidth, type ConnectionStatsBitrate, type PacketLoss } from \"./connectionStats.ts\";\nimport { type TransportStats } from \"./transportStats.ts\";\nimport { type Resolution } from \"./media/mediaTrackStats.ts\";\n\nexport enum StatsReport {\n CONNECTION_STATS = \"StatsReport.connection_stats\",\n CALL_FEED_REPORT = \"StatsReport.call_feed_report\",\n BYTE_SENT_STATS = \"StatsReport.byte_sent_stats\",\n SUMMARY_STATS = \"StatsReport.summary_stats\",\n}\n\n/// ByteSentStatsReport ################################################################################################\nexport interface ByteSentStatsReport extends Map<TrackID, ByteSend> {\n callId?: string;\n opponentMemberId?: string;\n // is a map: `local trackID` => byte send\n}\n\nexport type TrackID = string;\nexport type ByteSend = number;\n\n/// ConnectionStatsReport ##############################################################################################\nexport interface ConnectionStatsReport {\n callId?: string;\n opponentMemberId?: string;\n bandwidth: ConnectionStatsBandwidth;\n bitrate: ConnectionStatsBitrate;\n packetLoss: PacketLoss;\n audioConcealment: Map<TrackID, AudioConcealment>;\n totalAudioConcealment: AudioConcealment;\n resolution: ResolutionMap;\n framerate: FramerateMap;\n codec: CodecMap;\n jitter: Map<TrackID, number>;\n transport: TransportStats[];\n}\n\nexport interface AudioConcealment {\n concealedAudio: number;\n totalAudioDuration: number;\n}\n\nexport interface ResolutionMap {\n local: Map<TrackID, Resolution>;\n remote: Map<TrackID, Resolution>;\n}\n\nexport interface FramerateMap {\n local: Map<TrackID, number>;\n remote: Map<TrackID, number>;\n}\n\nexport interface CodecMap {\n local: Map<TrackID, string>;\n remote: Map<TrackID, string>;\n}\n\n/// SummaryStatsReport #################################################################################################\nexport interface SummaryStatsReport {\n /**\n * Aggregated the information for percentage of received media\n *\n * This measure whether the current user receive data from a call participants.\n * As soon as a participant sends at least a byte media to this user, this counts as one measurement unit.\n * The units of measure divided by the total number of participants is a value between 0 and 1.\n */\n percentageReceivedMedia: number;\n percentageReceivedAudioMedia: number;\n percentageReceivedVideoMedia: number;\n maxJitter: number;\n maxPacketLoss: number;\n percentageConcealedAudio: number;\n peerConnections: number;\n opponentUsersInCall?: number;\n opponentDevicesInCall?: number;\n diffDevicesToPeerConnections?: number;\n ratioPeerConnectionToDevices?: number;\n // Todo: Decide if we want an index (or a timestamp) of this report in relation to the group call, to help differenciate when issues occur and ignore/track initial connection delays.\n}\n\n/// CallFeedReport #####################################################################################################\nexport interface CallFeedReport {\n callId: string;\n opponentMemberId: string;\n transceiver: TransceiverStats[];\n callFeeds: CallFeedStats[];\n}\n\nexport interface CallFeedStats {\n stream: string;\n type: \"remote\" | \"local\";\n audio: TrackStats | null;\n video: TrackStats | null;\n purpose: string;\n prefix: string;\n isVideoMuted: boolean;\n isAudioMuted: boolean;\n}\n\nexport interface TransceiverStats {\n readonly mid: string;\n readonly sender: TrackStats | null;\n readonly receiver: TrackStats | null;\n readonly direction: string;\n readonly currentDirection: string;\n}\n\nexport interface TrackStats {\n readonly id: string;\n readonly kind: \"audio\" | \"video\";\n readonly settingDeviceId: string;\n readonly constrainDeviceId: string;\n readonly muted: boolean;\n readonly enabled: boolean;\n readonly readyState: \"ended\" | \"live\";\n readonly label: string;\n}\n","/*\nCopyright 2023 The Matrix.org Foundation C.I.C.\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 http://www.apache.org/licenses/LICENSE-2.0\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*/\nimport { type StatsReportEmitter } from \"./statsReportEmitter.ts\";\nimport { type CallStatsReportSummary } from \"./callStatsReportSummary.ts\";\nimport { type SummaryStatsReport } from \"./statsReport.ts\";\nimport { type ParticipantState } from \"../groupCall.ts\";\nimport { type RoomMember } from \"../../matrix.ts\";\n\ninterface CallStatsReportSummaryCounter {\n receivedAudio: number;\n receivedVideo: number;\n receivedMedia: number;\n concealedAudio: number;\n totalAudio: number;\n}\n\nexport class SummaryStatsReportGatherer {\n public constructor(private emitter: StatsReportEmitter) {}\n\n public build(allSummary: CallStatsReportSummary[]): void {\n // Filter all stats which collect the first time webrtc stats.\n // Because stats based on time interval and the first collection of a summery stats has no previous\n // webrtcStats as basement all the calculation are 0. We don't want track the 0 stats.\n const summary = allSummary.filter((s) => !s.isFirstCollection);\n const summaryTotalCount = summary.length;\n // For counting the peer connections we also want to consider the ignored summaries\n const peerConnectionsCount = allSummary.length;\n if (summaryTotalCount === 0) {\n return;\n }\n\n const summaryCounter: CallStatsReportSummaryCounter = {\n receivedAudio: 0,\n receivedVideo: 0,\n receivedMedia: 0,\n concealedAudio: 0,\n totalAudio: 0,\n };\n let maxJitter = 0;\n let maxPacketLoss = 0;\n summary.forEach((stats) => {\n this.countTrackListReceivedMedia(summaryCounter, stats);\n this.countConcealedAudio(summaryCounter, stats);\n maxJitter = this.buildMaxJitter(maxJitter, stats);\n maxPacketLoss = this.buildMaxPacketLoss(maxPacketLoss, stats);\n });\n const decimalPlaces = 5;\n const report = {\n percentageReceivedMedia: Number((summaryCounter.receivedMedia / summaryTotalCount).toFixed(decimalPlaces)),\n percentageReceivedVideoMedia: Number(\n (summaryCounter.receivedVideo / summaryTotalCount).toFixed(decimalPlaces),\n ),\n percentageReceivedAudioMedia: Number(\n (summaryCounter.receivedAudio / summaryTotalCount).toFixed(decimalPlaces),\n ),\n maxJitter,\n maxPacketLoss,\n percentageConcealedAudio: Number(\n summaryCounter.totalAudio > 0\n ? (summaryCounter.concealedAudio / summaryCounter.totalAudio).toFixed(decimalPlaces)\n : 0,\n ),\n peerConnections: peerConnectionsCount,\n } as SummaryStatsReport;\n this.emitter.emitSummaryStatsReport(report);\n }\n\n public static extendSummaryReport(\n report: SummaryStatsReport,\n callParticipants: Map<RoomMember, Map<string, ParticipantState>>,\n ): void {\n // Calculate the actual number of devices based on the participants state event\n // (this is used, to compare the expected participant count from the room state with the acutal peer connections)\n // const devices = callParticipants.()\n const devices: [string, ParticipantState][] = [];\n const users: [RoomMember, Map<string, ParticipantState>][] = [];\n for (const userEntry of callParticipants) {\n users.push(userEntry);\n for (const device of userEntry[1]) {\n devices.push(device);\n }\n }\n report.opponentDevicesInCall = Math.max(0, devices.length - 1);\n report.opponentUsersInCall = Math.max(0, users.length - 1);\n report.diffDevicesToPeerConnections = Math.max(0, devices.length - 1) - report.peerConnections;\n report.ratioPeerConnectionToDevices =\n Math.max(0, devices.length - 1) == 0 ? 0 : report.peerConnections / (devices.length - 1);\n }\n\n private countTrackListReceivedMedia(counter: CallStatsReportSummaryCounter, stats: CallStatsReportSummary): void {\n let hasReceivedAudio = false;\n let hasReceivedVideo = false;\n if (stats.receivedAudioMedia > 0 || stats.audioTrackSummary.count === 0) {\n counter.receivedAudio++;\n hasReceivedAudio = true;\n }\n if (stats.receivedVideoMedia > 0 || stats.videoTrackSummary.count === 0) {\n counter.receivedVideo++;\n hasReceivedVideo = true;\n } else {\n if (stats.videoTrackSummary.muted > 0 && stats.videoTrackSummary.muted === stats.videoTrackSummary.count) {\n counter.receivedVideo++;\n hasReceivedVideo = true;\n }\n }\n\n if (hasReceivedVideo && hasReceivedAudio) {\n counter.receivedMedia++;\n }\n }\n\n private buildMaxJitter(maxJitter: number, stats: CallStatsReportSummary): number {\n if (maxJitter < stats.videoTrackSummary.maxJitter) {\n maxJitter = stats.videoTrackSummary.maxJitter;\n }\n\n if (maxJitter < stats.audioTrackSummary.maxJitter) {\n maxJitter = stats.audioTrackSummary.maxJitter;\n }\n return maxJitter;\n }\n\n private buildMaxPacketLoss(maxPacketLoss: number, stats: CallStatsReportSummary): number {\n if (maxPacketLoss < stats.videoTrackSummary.maxPacketLoss) {\n maxPacketLoss = stats.videoTrackSummary.maxPacketLoss;\n }\n\n if (maxPacketLoss < stats.audioTrackSummary.maxPacketLoss) {\n maxPacketLoss = stats.audioTrackSummary.maxPacketLoss;\n }\n return maxPacketLoss;\n }\n\n private countConcealedAudio(summaryCounter: CallStatsReportSummaryCounter, stats: CallStatsReportSummary): void {\n summaryCounter.concealedAudio += stats.audioTrackSummary.concealedAudio;\n summaryCounter.totalAudio += stats.audioTrackSummary.totalAudio;\n }\n}\n","// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// copy of this software and associated documentation files (the\n// \"Software\"), to deal in the Software without restriction, including\n// without limitation the rights to use, copy, modify, merge, publish,\n// distribute, sublicense, and/or sell copies of the Software, and to permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n'use strict';\n\nvar R = typeof Reflect === 'object' ? Reflect : null\nvar ReflectApply = R && typeof R.apply === 'function'\n ? R.apply\n : function ReflectApply(target, receiver, args) {\n return Function.prototype.apply.call(target, receiver, args);\n }\n\nvar ReflectOwnKeys\nif (R && typeof R.ownKeys === 'function') {\n ReflectOwnKeys = R.ownKeys\n} else if (Object.getOwnPropertySymbols) {\n ReflectOwnKeys = function ReflectOwnKeys(target) {\n return Object.getOwnPropertyNames(target)\n .concat(Object.getOwnPropertySymbols(target));\n };\n} else {\n ReflectOwnKeys = function ReflectOwnKeys(target) {\n return Object.getOwnPropertyNames(target);\n };\n}\n\nfunction ProcessEmitWarning(warning) {\n if (console && console.warn) console.warn(warning);\n}\n\nvar NumberIsNaN = Number.isNaN || function NumberIsNaN(value) {\n return value !== value;\n}\n\nfunction EventEmitter() {\n EventEmitter.init.call(this);\n}\nmodule.exports = EventEmitter;\nmodule.exports.once = once;\n\n// Backwards-compat with node 0.10.x\nEventEmitter.EventEmitter = EventEmitter;\n\nEventEmitter.prototype._events = undefined;\nEventEmitter.prototype._eventsCount = 0;\nEventEmitter.prototype._maxListeners = undefined;\n\n// By default EventEmitters will print a warning if more than 10 listeners are\n// added to it. This is a useful default which helps finding memory leaks.\nvar defaultMaxListeners = 10;\n\nfunction checkListener(listener) {\n if (typeof listener !== 'function') {\n throw new TypeError('The \"listener\" argument must be of type Function. Received type ' + typeof listener);\n }\n}\n\nObject.defineProperty(EventEmitter, 'defaultMaxListeners', {\n enumerable: true,\n get: function() {\n return defaultMaxListeners;\n },\n set: function(arg) {\n if (typeof arg !== 'number' || arg < 0 || NumberIsNaN(arg)) {\n throw new RangeError('The value of \"defaultMaxListeners\" is out of range. It must be a non-negative number. Received ' + arg + '.');\n }\n defaultMaxListeners = arg;\n }\n});\n\nEventEmitter.init = function() {\n\n if (this._events === undefined ||\n this._events === Object.getPrototypeOf(this)._events) {\n this._events = Object.create(null);\n this._eventsCount = 0;\n }\n\n this._maxListeners = this._maxListeners || undefined;\n};\n\n// Obviously not all Emitters should be limited to 10. This function allows\n// that to be increased. Set to zero for unlimited.\nEventEmitter.prototype.setMaxListeners = function setMaxListeners(n) {\n if (typeof n !== 'number' || n < 0 || NumberIsNaN(n)) {\n throw new RangeError('The value of \"n\" is out of range. It must be a non-negative number. Received ' + n + '.');\n }\n this._maxListeners = n;\n return this;\n};\n\nfunction _getMaxListeners(that) {\n if (that._maxListeners === undefined)\n return EventEmitter.defaultMaxListeners;\n return that._maxListeners;\n}\n\nEventEmitter.prototype.getMaxListeners = function getMaxListeners() {\n return _getMaxListeners(this);\n};\n\nEventEmitter.prototype.emit = function emit(type) {\n var args = [];\n for (var i = 1; i < arguments.length; i++) args.push(arguments[i]);\n var doError = (type === 'error');\n\n var events = this._events;\n if (events !== undefined)\n doError = (doError && events.error === undefined);\n else if (!doError)\n return false;\n\n // If there is no 'error' event listener then throw.\n if (doError) {\n var er;\n if (args.length > 0)\n er = args[0];\n if (er instanceof Error) {\n // Note: The comments on the `throw` lines are intentional, they show\n // up in Node's output if this results in an unhandled exception.\n throw er; // Unhandled 'error' event\n }\n // At least give some kind of context to the user\n var err = new Error('Unhandled error.' + (er ? ' (' + er.message + ')' : ''));\n err.context = er;\n throw err; // Unhandled 'error' event\n }\n\n var handler = events[type];\n\n if (handler === undefined)\n return false;\n\n if (typeof handler === 'function') {\n ReflectApply(handler, this, args);\n } else {\n var len = handler.length;\n var listeners = arrayClone(handler, len);\n for (var i = 0; i < len; ++i)\n ReflectApply(listeners[i], this, args);\n }\n\n return true;\n};\n\nfunction _addListener(target, type, listener, prepend) {\n var m;\n var events;\n var existing;\n\n checkListener(listener);\n\n events = target._events;\n if (events === undefined) {\n events = target._events = Object.create(null);\n target._eventsCount = 0;\n } else {\n // To avoid recursion in the case that type === \"newListener\"! Before\n // adding it to the listeners, first emit \"newListener\".\n if (events.newListener !== undefined) {\n target.emit('newListener', type,\n listener.listener ? listener.listener : listener);\n\n // Re-assign `events` because a newListener handler could have caused the\n // this._events to be assigned to a new object\n events = target._events;\n }\n existing = events[type];\n }\n\n if (existing === undefined) {\n // Optimize the case of one listener. Don't need the extra array object.\n existing = events[type] = listener;\n ++target._eventsCount;\n } else {\n if (typeof existing === 'function') {\n // Adding the second element, need to change to array.\n existing = events[type] =\n prepend ? [listener, existing] : [existing, listener];\n // If we've already got an array, just append.\n } else if (prepend) {\n existing.unshift(listener);\n } else {\n existing.push(listener);\n }\n\n // Check for listener leak\n m = _getMaxListeners(target);\n if (m > 0 && existing.length > m && !existing.warned) {\n existing.warned = true;\n // No error code for this since it is a Warning\n // eslint-disable-next-line no-restricted-syntax\n var w = new Error('Possible EventEmitter memory leak detected. ' +\n existing.length + ' ' + String(type) + ' listeners ' +\n 'added. Use emitter.setMaxListeners() to ' +\n 'increase limit');\n w.name = 'MaxListenersExceededWarning';\n w.emitter = target;\n w.type = type;\n w.count = existing.length;\n ProcessEmitWarning(w);\n }\n }\n\n return target;\n}\n\nEventEmitter.prototype.addListener = function addListener(type, listener) {\n return _addListener(this, type, listener, false);\n};\n\nEventEmitter.prototype.on = EventEmitter.prototype.addListener;\n\nEventEmitter.prototype.prependListener =\n function prependListener(type, listener) {\n return _addListener(this, type, listener, true);\n };\n\nfunction onceWrapper() {\n if (!this.fired) {\n this.target.removeListener(this.type, this.wrapFn);\n this.fired = true;\n if (arguments.length === 0)\n return this.listener.call(this.target);\n return this.listener.apply(this.target, arguments);\n }\n}\n\nfunction _onceWrap(target, type, listener) {\n var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener };\n var wrapped = onceWrapper.bind(state);\n wrapped.listener = listener;\n state.wrapFn = wrapped;\n return wrapped;\n}\n\nEventEmitter.prototype.once = function once(type, listener) {\n checkListener(listener);\n this.on(type, _onceWrap(this, type, listener));\n return this;\n};\n\nEventEmitter.prototype.prependOnceListener =\n function prependOnceListener(type, listener) {\n checkListener(listener);\n this.prependListener(type, _onceWrap(this, type, listener));\n return this;\n };\n\n// Emits a 'removeListener' event if and only if the listener was removed.\nEventEmitter.prototype.removeListener =\n function removeListener(type, listener) {\n var list, events, position, i, originalListener;\n\n checkListener(listener);\n\n events = this._events;\n if (events === undefined)\n return this;\n\n list = events[type];\n if (list === undefined)\n return this;\n\n if (list === listener || list.listener === listener) {\n if (--this._eventsCount === 0)\n this._events = Object.create(null);\n else {\n delete events[type];\n if (events.removeListener)\n this.emit('removeListener', type, list.listener || listener);\n }\n } else if (typeof list !== 'function') {\n position = -1;\n\n for (i = list.length - 1; i >= 0; i--) {\n if (list[i] === listener || list[i].listener === listener) {\n originalListener = list[i].listener;\n position = i;\n break;\n }\n }\n\n if (position < 0)\n return this;\n\n if (position === 0)\n list.shift();\n else {\n spliceOne(list, position);\n }\n\n if (list.length === 1)\n events[type] = list[0];\n\n if (events.removeListener !== undefined)\n this.emit('removeListener', type, originalListener || listener);\n }\n\n return this;\n };\n\nEventEmitter.prototype.off = EventEmitter.prototype.removeListener;\n\nEventEmitter.prototype.removeAllListeners =\n function removeAllListeners(type) {\n var listeners, events, i;\n\n events = this._events;\n if (events === undefined)\n return this;\n\n // not listening for removeListener, no need to emit\n if (events.removeListener === undefined) {\n if (arguments.length === 0) {\n this._events = Object.create(null);\n this._eventsCount = 0;\n } else if (events[type] !== undefined) {\n if (--this._eventsCount === 0)\n this._events = Object.create(null);\n else\n delete events[type];\n }\n return this;\n }\n\n // emit removeListener for all listeners on all events\n if (arguments.length === 0) {\n var keys = Object.keys(events);\n var key;\n for (i = 0; i < keys.length; ++i) {\n key = keys[i];\n if (key === 'removeListener') continue;\n this.removeAllListeners(key);\n }\n this.removeAllListeners('removeListener');\n this._events = Object.create(null);\n this._eventsCount = 0;\n return this;\n }\n\n listeners = events[type];\n\n if (typeof listeners === 'function') {\n this.removeListener(type, listeners);\n } else if (listeners !== undefined) {\n // LIFO order\n for (i = listeners.length - 1; i >= 0; i--) {\n this.removeListener(type, listeners[i]);\n }\n }\n\n return this;\n };\n\nfunction _listeners(target, type, unwrap) {\n var events = target._events;\n\n if (events === undefined)\n return [];\n\n var evlistener = events[type];\n if (evlistener === undefined)\n return [];\n\n if (typeof evlistener === 'function')\n return unwrap ? [evlistener.listener || evlistener] : [evlistener];\n\n return unwrap ?\n unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length);\n}\n\nEventEmitter.prototype.listeners = function listeners(type) {\n return _listeners(this, type, true);\n};\n\nEventEmitter.prototype.rawListeners = function rawListeners(type) {\n return _listeners(this, type, false);\n};\n\nEventEmitter.listenerCount = function(emitter, type) {\n if (typeof emitter.listenerCount === 'function') {\n return emitter.listenerCount(type);\n } else {\n return listenerCount.call(emitter, type);\n }\n};\n\nEventEmitter.prototype.listenerCount = listenerCount;\nfunction listenerCount(type) {\n var events = this._events;\n\n if (events !== undefined) {\n var evlistener = events[type];\n\n if (typeof evlistener === 'function') {\n return 1;\n } else if (evlistener !== undefined) {\n return evlistener.length;\n }\n }\n\n return 0;\n}\n\nEventEmitter.prototype.eventNames = function eventNames() {\n return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : [];\n};\n\nfunction arrayClone(arr, n) {\n var copy = new Array(n);\n for (var i = 0; i < n; ++i)\n copy[i] = arr[i];\n return copy;\n}\n\nfunction spliceOne(list, index) {\n for (; index + 1 < list.length; index++)\n list[index] = list[index + 1];\n list.pop();\n}\n\nfunction unwrapListeners(arr) {\n var ret = new Array(arr.length);\n for (var i = 0; i < ret.length; ++i) {\n ret[i] = arr[i].listener || arr[i];\n }\n return ret;\n}\n\nfunction once(emitter, name) {\n return new Promise(function (resolve, reject) {\n function errorListener(err) {\n emitter.removeListener(name, resolver);\n reject(err);\n }\n\n function resolver() {\n if (typeof emitter.removeListener === 'function') {\n emitter.removeListener('error', errorListener);\n }\n resolve([].slice.call(arguments));\n };\n\n eventTargetAgnosticAddListener(emitter, name, resolver, { once: true });\n if (name !== 'error') {\n addErrorHandlerIfEventEmitter(emitter, errorListener, { once: true });\n }\n });\n}\n\nfunction addErrorHandlerIfEventEmitter(emitter, handler, flags) {\n if (typeof emitter.on === 'function') {\n eventTargetAgnosticAddListener(emitter, 'error', handler, flags);\n }\n}\n\nfunction eventTargetAgnosticAddListener(emitter, name, listener, flags) {\n if (typeof emitter.on === 'function') {\n if (flags.once) {\n emitter.once(name, listener);\n } else {\n emitter.on(name, listener);\n }\n } else if (typeof emitter.addEventListener === 'function') {\n // EventTarget does not have `error` event semantics like Node\n // EventEmitters, we do not listen for `error` events here.\n emitter.addEventListener(name, function wrapListener(arg) {\n // IE does not have builtin `{ once: true }` support so we\n // have to do it manually.\n if (flags.once) {\n emitter.removeEventListener(name, wrapListener);\n }\n listener(arg);\n });\n } else {\n throw new TypeError('The \"emitter\" argument must be of type EventEmitter. Received type ' + typeof emitter);\n }\n}\n","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.ExtensibleEvents = void 0;\n\nvar _NamespacedMap = require(\"./NamespacedMap\");\n\nvar _InvalidEventError = require(\"./InvalidEventError\");\n\nvar _MRoomMessage = require(\"./interpreters/legacy/MRoomMessage\");\n\nvar _MMessage = require(\"./interpreters/modern/MMessage\");\n\nvar _message_types = require(\"./events/message_types\");\n\nvar _poll_types = require(\"./events/poll_types\");\n\nvar _MPoll = require(\"./interpreters/modern/MPoll\");\n\nfunction _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== \"undefined\" && o[Symbol.iterator] || o[\"@@iterator\"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === \"number\") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it[\"return\"] != null) it[\"return\"](); } finally { if (didErr) throw err; } } }; }\n\nfunction _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === \"string\") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === \"Object\" && o.constructor) n = o.constructor.name; if (n === \"Map\" || n === \"Set\") return Array.from(o); if (n === \"Arguments\" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }\n\nfunction _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, \"prototype\", { writable: false }); return Constructor; }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\n/**\n * Utility class for parsing and identifying event types in a renderable form. An\n * instance of this class can be created to change rendering preference depending\n * on use-case.\n */\nvar ExtensibleEvents = /*#__PURE__*/function () {\n function ExtensibleEvents() {\n _classCallCheck(this, ExtensibleEvents);\n\n _defineProperty(this, \"interpreters\", new _NamespacedMap.NamespacedMap([// Remember to add your unit test when adding to this! (\"known events\" test description)\n [_MRoomMessage.LEGACY_M_ROOM_MESSAGE, _MRoomMessage.parseMRoomMessage], [_message_types.M_MESSAGE, _MMessage.parseMMessage], [_message_types.M_EMOTE, _MMessage.parseMMessage], [_message_types.M_NOTICE, _MMessage.parseMMessage], [_poll_types.M_POLL_START, _MPoll.parseMPoll], [_poll_types.M_POLL_RESPONSE, _MPoll.parseMPoll], [_poll_types.M_POLL_END, _MPoll.parseMPoll]]));\n\n _defineProperty(this, \"_unknownInterpretOrder\", [_message_types.M_MESSAGE]);\n }\n /**\n * Gets the default instance for all extensible event parsing.\n */\n\n\n _createClass(ExtensibleEvents, [{\n key: \"unknownInterpretOrder\",\n get:\n /**\n * Gets the order the internal processor will use for unknown primary\n * event types.\n */\n function get() {\n var _this$_unknownInterpr;\n\n return (_this$_unknownInterpr = this._unknownInterpretOrder) !== null && _this$_unknownInterpr !== void 0 ? _this$_unknownInterpr : [];\n }\n /**\n * Sets the order the internal processor will use for unknown primary\n * event types.\n * @param {NamespacedValue<string, string>[]} val The parsing order.\n */\n ,\n set: function set(val) {\n this._unknownInterpretOrder = val;\n }\n /**\n * Gets the order the internal processor will use for unknown primary\n * event types.\n */\n\n }, {\n key: \"registerInterpreter\",\n value:\n /**\n * Registers a primary event type interpreter. Note that the interpreter might be\n * called with non-primary events if the event is being parsed as a fallback.\n * @param {NamespacedValue<string, string>} wireEventType The event type.\n * @param {EventInterpreter} interpreter The interpreter.\n */\n function registerInterpreter(wireEventType, interpreter) {\n this.interpreters.set(wireEventType, interpreter);\n }\n /**\n * Registers a primary event type interpreter. Note that the interpreter might be\n * called with non-primary events if the event is being parsed as a fallback.\n * @param {NamespacedValue<string, string>} wireEventType The event type.\n * @param {EventInterpreter} interpreter The interpreter.\n */\n\n }, {\n key: \"parse\",\n value:\n /**\n * Parses an event, trying the primary event type first. If the primary type is not known\n * then the content will be inspected to find the most suitable fallback.\n *\n * If the parsing failed or was a completely unknown type, this will return falsy.\n * @param {IPartialEvent<object>} wireFormat The event to parse.\n * @returns {Optional<ExtensibleEvent>} The parsed extensible event.\n */\n function parse(wireFormat) {\n try {\n if (this.interpreters.hasNamespaced(wireFormat.type)) {\n return this.interpreters.getNamespaced(wireFormat.type)(wireFormat);\n }\n\n var _iterator = _createForOfIteratorHelper(this.unknownInterpretOrder),\n _step;\n\n try {\n for (_iterator.s(); !(_step = _iterator.n()).done;) {\n var tryType = _step.value;\n\n if (this.interpreters.has(tryType)) {\n var val = this.interpreters.get(tryType)(wireFormat);\n if (val) return val;\n }\n }\n } catch (err) {\n _iterator.e(err);\n } finally {\n _iterator.f();\n }\n\n return null; // cannot be parsed\n } catch (e) {\n if (e instanceof _InvalidEventError.InvalidEventError) {\n return null; // fail parsing and move on\n }\n\n throw e; // re-throw everything else\n }\n }\n /**\n * Parses an event, trying the primary event type first. If the primary type is not known\n * then the content will be inspected to find the most suitable fallback.\n *\n * If the parsing failed or was a completely unknown type, this will return falsy.\n * @param {IPartialEvent<object>} wireFormat The event to parse.\n * @returns {Optional<ExtensibleEvent>} The parsed extensible event.\n */\n\n }], [{\n key: \"defaultInstance\",\n get: function get() {\n return ExtensibleEvents._defaultInstance;\n }\n }, {\n key: \"unknownInterpretOrder\",\n get: function get() {\n return ExtensibleEvents.defaultInstance.unknownInterpretOrder;\n }\n /**\n * Sets the order the internal processor will use for unknown primary\n * event types.\n * @param {NamespacedValue<string, string>[]} val The parsing order.\n */\n ,\n set: function set(val) {\n ExtensibleEvents.defaultInstance.unknownInterpretOrder = val;\n }\n }, {\n key: \"registerInterpreter\",\n value: function registerInterpreter(wireEventType, interpreter) {\n ExtensibleEvents.defaultInstance.registerInterpreter(wireEventType, interpreter);\n }\n }, {\n key: \"parse\",\n value: function parse(wireFormat) {\n return ExtensibleEvents.defaultInstance.parse(wireFormat);\n }\n }]);\n\n return ExtensibleEvents;\n}();\n\nexports.ExtensibleEvents = ExtensibleEvents;\n\n_defineProperty(ExtensibleEvents, \"_defaultInstance\", new ExtensibleEvents());","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});","\"use strict\";\n\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && \"function\" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }, _typeof(obj); }\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.InvalidEventError = void 0;\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, \"prototype\", { writable: false }); return Constructor; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, \"prototype\", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } else if (call !== void 0) { throw new TypeError(\"Derived constructors may only return object or undefined\"); } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _wrapNativeSuper(Class) { var _cache = typeof Map === \"function\" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== \"function\") { throw new TypeError(\"Super expression must either be null or a function\"); } if (typeof _cache !== \"undefined\") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); }\n\nfunction _construct(Parent, args, Class) { if (_isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _isNativeFunction(fn) { return Function.toString.call(fn).indexOf(\"[native code]\") !== -1; }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\n/*\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\n/**\n * Thrown when an event is unforgivably unparsable.\n */\nvar InvalidEventError = /*#__PURE__*/function (_Error) {\n _inherits(InvalidEventError, _Error);\n\n var _super = _createSuper(InvalidEventError);\n\n function InvalidEventError(message) {\n _classCallCheck(this, InvalidEventError);\n\n return _super.call(this, message);\n }\n\n return _createClass(InvalidEventError);\n}( /*#__PURE__*/_wrapNativeSuper(Error));\n\nexports.InvalidEventError = InvalidEventError;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.NamespacedMap = void 0;\n\nfunction _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== \"undefined\" && o[Symbol.iterator] || o[\"@@iterator\"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === \"number\") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it[\"return\"] != null) it[\"return\"](); } finally { if (didErr) throw err; } } }; }\n\nfunction _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === \"string\") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === \"Object\" && o.constructor) n = o.constructor.name; if (n === \"Map\" || n === \"Set\") return Array.from(o); if (n === \"Arguments\" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }\n\nfunction _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, \"prototype\", { writable: false }); return Constructor; }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\n/**\n * A `Map` implementation which accepts a NamespacedValue as a key, and arbitrary value. The\n * namespaced value must be a string type.\n */\nvar NamespacedMap = /*#__PURE__*/function () {\n // protected to make tests happy for access\n\n /**\n * Creates a new map with optional seed data.\n * @param {Array<[NS, V]>} initial The seed data.\n */\n function NamespacedMap(initial) {\n _classCallCheck(this, NamespacedMap);\n\n _defineProperty(this, \"internalMap\", new Map());\n\n if (initial) {\n var _iterator = _createForOfIteratorHelper(initial),\n _step;\n\n try {\n for (_iterator.s(); !(_step = _iterator.n()).done;) {\n var val = _step.value;\n this.set(val[0], val[1]);\n }\n } catch (err) {\n _iterator.e(err);\n } finally {\n _iterator.f();\n }\n }\n }\n /**\n * Gets a value from the map. If the value does not exist under\n * either namespace option, falsy is returned.\n * @param {NS} key The key.\n * @returns {Optional<V>} The value, or falsy.\n */\n\n\n _createClass(NamespacedMap, [{\n key: \"get\",\n value: function get(key) {\n if (key.name && this.internalMap.has(key.name)) {\n return this.internalMap.get(key.name);\n }\n\n if (key.altName && this.internalMap.has(key.altName)) {\n return this.internalMap.get(key.altName);\n }\n\n return null;\n }\n /**\n * Sets a value in the map.\n * @param {NS} key The key.\n * @param {V} val The value.\n */\n\n }, {\n key: \"set\",\n value: function set(key, val) {\n if (key.name) {\n this.internalMap.set(key.name, val);\n }\n\n if (key.altName) {\n this.internalMap.set(key.altName, val);\n }\n }\n /**\n * Determines if any of the valid namespaced values are present\n * in the map.\n * @param {NS} key The key.\n * @returns {boolean} True if present.\n */\n\n }, {\n key: \"has\",\n value: function has(key) {\n return !!this.get(key);\n }\n /**\n * Removes all the namespaced values from the map.\n * @param {NS} key The key.\n */\n\n }, {\n key: \"delete\",\n value: function _delete(key) {\n if (key.name) {\n this.internalMap[\"delete\"](key.name);\n }\n\n if (key.altName) {\n this.internalMap[\"delete\"](key.altName);\n }\n }\n /**\n * Determines if the map contains a specific namespaced value\n * instead of the parent NS type.\n * @param {string} key The key.\n * @returns {boolean} True if present.\n */\n\n }, {\n key: \"hasNamespaced\",\n value: function hasNamespaced(key) {\n return this.internalMap.has(key);\n }\n /**\n * Gets a specific namespaced value from the map instead of the\n * parent NS type. Returns falsy if not found.\n * @param {string} key The key.\n * @returns {Optional<V>} The value, or falsy.\n */\n\n }, {\n key: \"getNamespaced\",\n value: function getNamespaced(key) {\n return this.internalMap.get(key);\n }\n }]);\n\n return NamespacedMap;\n}();\n\nexports.NamespacedMap = NamespacedMap;","\"use strict\";\n\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && \"function\" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }, _typeof(obj); }\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.UnstableValue = exports.NamespacedValue = void 0;\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, \"prototype\", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } else if (call !== void 0) { throw new TypeError(\"Derived constructors may only return object or undefined\"); } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, \"prototype\", { writable: false }); return Constructor; }\n\n/*\nCopyright 2021 - 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\n/**\n * Represents a simple Matrix namespaced value. This will assume that if a stable prefix\n * is provided that the stable prefix should be used when representing the identifier.\n */\nvar NamespacedValue = /*#__PURE__*/function () {\n // Stable is optional, but one of the two parameters is required, hence the weird-looking types.\n // Goal is to have developers explicitly say there is no stable value (if applicable).\n function NamespacedValue(stable, unstable) {\n _classCallCheck(this, NamespacedValue);\n\n this.stable = stable;\n this.unstable = unstable;\n\n if (!this.unstable && !this.stable) {\n throw new Error(\"One of stable or unstable values must be supplied\");\n }\n }\n\n _createClass(NamespacedValue, [{\n key: \"name\",\n get: function get() {\n if (this.stable) {\n return this.stable;\n }\n\n return this.unstable;\n }\n }, {\n key: \"altName\",\n get: function get() {\n if (!this.stable) {\n return null;\n }\n\n return this.unstable;\n }\n }, {\n key: \"matches\",\n value: function matches(val) {\n return !!this.name && this.name === val || !!this.altName && this.altName === val;\n } // this desperately wants https://github.com/microsoft/TypeScript/pull/26349 at the top level of the class\n // so we can instantiate `NamespacedValue<string, _, _>` as a default type for that namespace.\n\n }, {\n key: \"findIn\",\n value: function findIn(obj) {\n var val;\n\n if (this.name) {\n val = obj === null || obj === void 0 ? void 0 : obj[this.name];\n }\n\n if (!val && this.altName) {\n val = obj === null || obj === void 0 ? void 0 : obj[this.altName];\n }\n\n return val;\n }\n }, {\n key: \"includedIn\",\n value: function includedIn(arr) {\n var included = false;\n\n if (this.name) {\n included = arr.includes(this.name);\n }\n\n if (!included && this.altName) {\n included = arr.includes(this.altName);\n }\n\n return included;\n }\n }]);\n\n return NamespacedValue;\n}();\n/**\n * Represents a namespaced value which prioritizes the unstable value over the stable\n * value.\n */\n\n\nexports.NamespacedValue = NamespacedValue;\n\nvar UnstableValue = /*#__PURE__*/function (_NamespacedValue) {\n _inherits(UnstableValue, _NamespacedValue);\n\n var _super = _createSuper(UnstableValue);\n\n // Note: Constructor difference is that `unstable` is *required*.\n function UnstableValue(stable, unstable) {\n var _this;\n\n _classCallCheck(this, UnstableValue);\n\n _this = _super.call(this, stable, unstable);\n\n if (!_this.unstable) {\n throw new Error(\"Unstable value must be supplied\");\n }\n\n return _this;\n }\n\n _createClass(UnstableValue, [{\n key: \"name\",\n get: function get() {\n return this.unstable;\n }\n }, {\n key: \"altName\",\n get: function get() {\n return this.stable;\n }\n }]);\n\n return UnstableValue;\n}(NamespacedValue);\n\nexports.UnstableValue = UnstableValue;","\"use strict\";\n\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && \"function\" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }, _typeof(obj); }\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.EmoteEvent = void 0;\n\nvar _MessageEvent2 = require(\"./MessageEvent\");\n\nvar _message_types = require(\"./message_types\");\n\nvar _events = require(\"../utility/events\");\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, \"prototype\", { writable: false }); return Constructor; }\n\nfunction _get() { if (typeof Reflect !== \"undefined\" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(arguments.length < 3 ? target : receiver); } return desc.value; }; } return _get.apply(this, arguments); }\n\nfunction _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, \"prototype\", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } else if (call !== void 0) { throw new TypeError(\"Derived constructors may only return object or undefined\"); } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\n// Emote events are just decorated message events\n\n/**\n * Represents an emote. This is essentially a MessageEvent with\n * emote characteristics considered.\n */\nvar EmoteEvent = /*#__PURE__*/function (_MessageEvent) {\n _inherits(EmoteEvent, _MessageEvent);\n\n var _super = _createSuper(EmoteEvent);\n\n function EmoteEvent(wireFormat) {\n _classCallCheck(this, EmoteEvent);\n\n return _super.call(this, wireFormat);\n }\n\n _createClass(EmoteEvent, [{\n key: \"isEmote\",\n get: function get() {\n return true; // override\n }\n }, {\n key: \"isEquivalentTo\",\n value: function isEquivalentTo(primaryEventType) {\n return (0, _events.isEventTypeSame)(primaryEventType, _message_types.M_EMOTE) || _get(_getPrototypeOf(EmoteEvent.prototype), \"isEquivalentTo\", this).call(this, primaryEventType);\n }\n }, {\n key: \"serialize\",\n value: function serialize() {\n var message = _get(_getPrototypeOf(EmoteEvent.prototype), \"serialize\", this).call(this);\n\n message.content['msgtype'] = \"m.emote\";\n return message;\n }\n /**\n * Creates a new EmoteEvent from text and HTML.\n * @param {string} text The text.\n * @param {string} html Optional HTML.\n * @returns {MessageEvent} The representative message event.\n */\n\n }], [{\n key: \"from\",\n value: function from(text, html) {\n var _content;\n\n return new EmoteEvent({\n type: _message_types.M_EMOTE.name,\n content: (_content = {}, _defineProperty(_content, _message_types.M_TEXT.name, text), _defineProperty(_content, _message_types.M_HTML.name, html), _content)\n });\n }\n }]);\n\n return EmoteEvent;\n}(_MessageEvent2.MessageEvent);\n\nexports.EmoteEvent = EmoteEvent;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.ExtensibleEvent = void 0;\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, \"prototype\", { writable: false }); return Constructor; }\n\n/*\nCopyright 2021 - 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\n/**\n * Represents an Extensible Event in Matrix.\n */\nvar ExtensibleEvent = /*#__PURE__*/function () {\n function ExtensibleEvent(wireFormat) {\n _classCallCheck(this, ExtensibleEvent);\n\n this.wireFormat = wireFormat;\n }\n /**\n * Shortcut to wireFormat.content\n */\n\n\n _createClass(ExtensibleEvent, [{\n key: \"wireContent\",\n get: function get() {\n return this.wireFormat.content;\n }\n /**\n * Serializes the event into a format which can be used to send the\n * event to the room.\n * @returns {IPartialEvent<object>} The serialized event.\n */\n\n }]);\n\n return ExtensibleEvent;\n}();\n\nexports.ExtensibleEvent = ExtensibleEvent;","\"use strict\";\n\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && \"function\" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }, _typeof(obj); }\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.MessageEvent = void 0;\n\nvar _ExtensibleEvent2 = require(\"./ExtensibleEvent\");\n\nvar _types = require(\"../types\");\n\nvar _InvalidEventError = require(\"../InvalidEventError\");\n\nvar _message_types = require(\"./message_types\");\n\nvar _events = require(\"../utility/events\");\n\nfunction ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }\n\nfunction _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, \"prototype\", { writable: false }); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, \"prototype\", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } else if (call !== void 0) { throw new TypeError(\"Derived constructors may only return object or undefined\"); } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\n/**\n * Represents a message event. Message events are the simplest form of event with\n * just text (optionally of different mimetypes, like HTML).\n *\n * Message events can additionally be an Emote or Notice, though typically those\n * are represented as EmoteEvent and NoticeEvent respectively.\n */\nvar MessageEvent = /*#__PURE__*/function (_ExtensibleEvent) {\n _inherits(MessageEvent, _ExtensibleEvent);\n\n var _super = _createSuper(MessageEvent);\n\n /**\n * The default text for the event.\n */\n\n /**\n * The default HTML for the event, if provided.\n */\n\n /**\n * All the different renderings of the message. Note that this is the same\n * format as an m.message body but may contain elements not found directly\n * in the event content: this is because this is interpreted based off the\n * other information available in the event.\n */\n\n /**\n * Creates a new MessageEvent from a pure format. Note that the event is\n * *not* parsed here: it will be treated as a literal m.message primary\n * typed event.\n * @param {IPartialEvent<M_MESSAGE_EVENT_CONTENT>} wireFormat The event.\n */\n function MessageEvent(wireFormat) {\n var _this;\n\n _classCallCheck(this, MessageEvent);\n\n _this = _super.call(this, wireFormat);\n\n _defineProperty(_assertThisInitialized(_this), \"text\", void 0);\n\n _defineProperty(_assertThisInitialized(_this), \"html\", void 0);\n\n _defineProperty(_assertThisInitialized(_this), \"renderings\", void 0);\n\n var mmessage = _message_types.M_MESSAGE.findIn(_this.wireContent);\n\n var mtext = _message_types.M_TEXT.findIn(_this.wireContent);\n\n var mhtml = _message_types.M_HTML.findIn(_this.wireContent);\n\n if ((0, _types.isProvided)(mmessage)) {\n if (!Array.isArray(mmessage)) {\n throw new _InvalidEventError.InvalidEventError(\"m.message contents must be an array\");\n }\n\n var text = mmessage.find(function (r) {\n return !(0, _types.isProvided)(r.mimetype) || r.mimetype === \"text/plain\";\n });\n var html = mmessage.find(function (r) {\n return r.mimetype === \"text/html\";\n });\n if (!text) throw new _InvalidEventError.InvalidEventError(\"m.message is missing a plain text representation\");\n _this.text = text.body;\n _this.html = html === null || html === void 0 ? void 0 : html.body;\n _this.renderings = mmessage;\n } else if ((0, _types.isOptionalAString)(mtext)) {\n _this.text = mtext;\n _this.html = mhtml;\n _this.renderings = [{\n body: mtext,\n mimetype: \"text/plain\"\n }];\n\n if (_this.html) {\n _this.renderings.push({\n body: _this.html,\n mimetype: \"text/html\"\n });\n }\n } else {\n throw new _InvalidEventError.InvalidEventError(\"Missing textual representation for event\");\n }\n\n return _this;\n }\n /**\n * Gets whether this message is considered an \"emote\". Note that a message\n * might be an emote and notice at the same time: while technically possible,\n * the event should be interpreted as one or the other.\n */\n\n\n _createClass(MessageEvent, [{\n key: \"isEmote\",\n get: function get() {\n return _message_types.M_EMOTE.matches(this.wireFormat.type) || (0, _types.isProvided)(_message_types.M_EMOTE.findIn(this.wireFormat.content));\n }\n /**\n * Gets whether this message is considered a \"notice\". Note that a message\n * might be an emote and notice at the same time: while technically possible,\n * the event should be interpreted as one or the other.\n */\n\n }, {\n key: \"isNotice\",\n get: function get() {\n return _message_types.M_NOTICE.matches(this.wireFormat.type) || (0, _types.isProvided)(_message_types.M_NOTICE.findIn(this.wireFormat.content));\n }\n }, {\n key: \"isEquivalentTo\",\n value: function isEquivalentTo(primaryEventType) {\n return (0, _events.isEventTypeSame)(primaryEventType, _message_types.M_MESSAGE);\n }\n }, {\n key: \"serializeMMessageOnly\",\n value: function serializeMMessageOnly() {\n var messageRendering = _defineProperty({}, _message_types.M_MESSAGE.name, this.renderings); // Use the shorthand if it's just a simple text event\n\n\n if (this.renderings.length === 1) {\n var mime = this.renderings[0].mimetype;\n\n if (mime === undefined || mime === \"text/plain\") {\n messageRendering = _defineProperty({}, _message_types.M_TEXT.name, this.renderings[0].body);\n }\n }\n\n return messageRendering;\n }\n }, {\n key: \"serialize\",\n value: function serialize() {\n var _this$html;\n\n return {\n type: \"m.room.message\",\n content: _objectSpread(_objectSpread({}, this.serializeMMessageOnly()), {}, {\n body: this.text,\n msgtype: \"m.text\",\n format: this.html ? \"org.matrix.custom.html\" : undefined,\n formatted_body: (_this$html = this.html) !== null && _this$html !== void 0 ? _this$html : undefined\n })\n };\n }\n /**\n * Creates a new MessageEvent from text and HTML.\n * @param {string} text The text.\n * @param {string} html Optional HTML.\n * @returns {MessageEvent} The representative message event.\n */\n\n }], [{\n key: \"from\",\n value: function from(text, html) {\n var _content;\n\n return new MessageEvent({\n type: _message_types.M_MESSAGE.name,\n content: (_content = {}, _defineProperty(_content, _message_types.M_TEXT.name, text), _defineProperty(_content, _message_types.M_HTML.name, html), _content)\n });\n }\n }]);\n\n return MessageEvent;\n}(_ExtensibleEvent2.ExtensibleEvent);\n\nexports.MessageEvent = MessageEvent;","\"use strict\";\n\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && \"function\" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }, _typeof(obj); }\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.NoticeEvent = void 0;\n\nvar _MessageEvent2 = require(\"./MessageEvent\");\n\nvar _message_types = require(\"./message_types\");\n\nvar _events = require(\"../utility/events\");\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, \"prototype\", { writable: false }); return Constructor; }\n\nfunction _get() { if (typeof Reflect !== \"undefined\" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(arguments.length < 3 ? target : receiver); } return desc.value; }; } return _get.apply(this, arguments); }\n\nfunction _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, \"prototype\", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } else if (call !== void 0) { throw new TypeError(\"Derived constructors may only return object or undefined\"); } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\n// Notice events are just decorated message events\n\n/**\n * Represents a notice. This is essentially a MessageEvent with\n * notice characteristics considered.\n */\nvar NoticeEvent = /*#__PURE__*/function (_MessageEvent) {\n _inherits(NoticeEvent, _MessageEvent);\n\n var _super = _createSuper(NoticeEvent);\n\n function NoticeEvent(wireFormat) {\n _classCallCheck(this, NoticeEvent);\n\n return _super.call(this, wireFormat);\n }\n\n _createClass(NoticeEvent, [{\n key: \"isNotice\",\n get: function get() {\n return true; // override\n }\n }, {\n key: \"isEquivalentTo\",\n value: function isEquivalentTo(primaryEventType) {\n return (0, _events.isEventTypeSame)(primaryEventType, _message_types.M_NOTICE) || _get(_getPrototypeOf(NoticeEvent.prototype), \"isEquivalentTo\", this).call(this, primaryEventType);\n }\n }, {\n key: \"serialize\",\n value: function serialize() {\n var message = _get(_getPrototypeOf(NoticeEvent.prototype), \"serialize\", this).call(this);\n\n message.content['msgtype'] = \"m.notice\";\n return message;\n }\n /**\n * Creates a new NoticeEvent from text and HTML.\n * @param {string} text The text.\n * @param {string} html Optional HTML.\n * @returns {MessageEvent} The representative message event.\n */\n\n }], [{\n key: \"from\",\n value: function from(text, html) {\n var _content;\n\n return new NoticeEvent({\n type: _message_types.M_NOTICE.name,\n content: (_content = {}, _defineProperty(_content, _message_types.M_TEXT.name, text), _defineProperty(_content, _message_types.M_HTML.name, html), _content)\n });\n }\n }]);\n\n return NoticeEvent;\n}(_MessageEvent2.MessageEvent);\n\nexports.NoticeEvent = NoticeEvent;","\"use strict\";\n\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && \"function\" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }, _typeof(obj); }\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.PollEndEvent = void 0;\n\nvar _poll_types = require(\"./poll_types\");\n\nvar _InvalidEventError = require(\"../InvalidEventError\");\n\nvar _relationship_types = require(\"./relationship_types\");\n\nvar _MessageEvent = require(\"./MessageEvent\");\n\nvar _message_types = require(\"./message_types\");\n\nvar _events = require(\"../utility/events\");\n\nvar _ExtensibleEvent2 = require(\"./ExtensibleEvent\");\n\nfunction ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }\n\nfunction _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, \"prototype\", { writable: false }); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, \"prototype\", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } else if (call !== void 0) { throw new TypeError(\"Derived constructors may only return object or undefined\"); } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\n/**\n * Represents a poll end/closure event.\n */\nvar PollEndEvent = /*#__PURE__*/function (_ExtensibleEvent) {\n _inherits(PollEndEvent, _ExtensibleEvent);\n\n var _super = _createSuper(PollEndEvent);\n\n /**\n * The poll start event ID referenced by the response.\n */\n\n /**\n * The closing message for the event.\n */\n\n /**\n * Creates a new PollEndEvent from a pure format. Note that the event is *not*\n * parsed here: it will be treated as a literal m.poll.response primary typed event.\n * @param {IPartialEvent<M_POLL_END_EVENT_CONTENT>} wireFormat The event.\n */\n function PollEndEvent(wireFormat) {\n var _this;\n\n _classCallCheck(this, PollEndEvent);\n\n _this = _super.call(this, wireFormat);\n\n _defineProperty(_assertThisInitialized(_this), \"pollEventId\", void 0);\n\n _defineProperty(_assertThisInitialized(_this), \"closingMessage\", void 0);\n\n var rel = _this.wireContent[\"m.relates_to\"];\n\n if (!_relationship_types.REFERENCE_RELATION.matches(rel === null || rel === void 0 ? void 0 : rel.rel_type) || typeof (rel === null || rel === void 0 ? void 0 : rel.event_id) !== \"string\") {\n throw new _InvalidEventError.InvalidEventError(\"Relationship must be a reference to an event\");\n }\n\n _this.pollEventId = rel.event_id;\n _this.closingMessage = new _MessageEvent.MessageEvent(_this.wireFormat);\n return _this;\n }\n\n _createClass(PollEndEvent, [{\n key: \"isEquivalentTo\",\n value: function isEquivalentTo(primaryEventType) {\n return (0, _events.isEventTypeSame)(primaryEventType, _poll_types.M_POLL_END);\n }\n }, {\n key: \"serialize\",\n value: function serialize() {\n return {\n type: _poll_types.M_POLL_END.name,\n content: _objectSpread(_defineProperty({\n \"m.relates_to\": {\n rel_type: _relationship_types.REFERENCE_RELATION.name,\n event_id: this.pollEventId\n }\n }, _poll_types.M_POLL_END.name, {}), this.closingMessage.serialize().content)\n };\n }\n /**\n * Creates a new PollEndEvent from a poll event ID.\n * @param {string} pollEventId The poll start event ID.\n * @param {string} message A closing message, typically revealing the top answer.\n * @returns {PollStartEvent} The representative poll closure event.\n */\n\n }], [{\n key: \"from\",\n value: function from(pollEventId, message) {\n var _content;\n\n return new PollEndEvent({\n type: _poll_types.M_POLL_END.name,\n content: (_content = {\n \"m.relates_to\": {\n rel_type: _relationship_types.REFERENCE_RELATION.name,\n event_id: pollEventId\n }\n }, _defineProperty(_content, _poll_types.M_POLL_END.name, {}), _defineProperty(_content, _message_types.M_TEXT.name, message), _content)\n });\n }\n }]);\n\n return PollEndEvent;\n}(_ExtensibleEvent2.ExtensibleEvent);\n\nexports.PollEndEvent = PollEndEvent;","\"use strict\";\n\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && \"function\" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }, _typeof(obj); }\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.PollResponseEvent = void 0;\n\nvar _ExtensibleEvent2 = require(\"./ExtensibleEvent\");\n\nvar _poll_types = require(\"./poll_types\");\n\nvar _InvalidEventError = require(\"../InvalidEventError\");\n\nvar _relationship_types = require(\"./relationship_types\");\n\nvar _events = require(\"../utility/events\");\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, \"prototype\", { writable: false }); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, \"prototype\", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } else if (call !== void 0) { throw new TypeError(\"Derived constructors may only return object or undefined\"); } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\n/**\n * Represents a poll response event.\n */\nvar PollResponseEvent = /*#__PURE__*/function (_ExtensibleEvent) {\n _inherits(PollResponseEvent, _ExtensibleEvent);\n\n var _super = _createSuper(PollResponseEvent);\n\n /**\n * Creates a new PollResponseEvent from a pure format. Note that the event is *not*\n * parsed here: it will be treated as a literal m.poll.response primary typed event.\n *\n * To validate the response against a poll, call `validateAgainst` after creation.\n * @param {IPartialEvent<M_POLL_RESPONSE_EVENT_CONTENT>} wireFormat The event.\n */\n function PollResponseEvent(wireFormat) {\n var _this;\n\n _classCallCheck(this, PollResponseEvent);\n\n _this = _super.call(this, wireFormat);\n\n _defineProperty(_assertThisInitialized(_this), \"internalAnswerIds\", void 0);\n\n _defineProperty(_assertThisInitialized(_this), \"internalSpoiled\", void 0);\n\n _defineProperty(_assertThisInitialized(_this), \"pollEventId\", void 0);\n\n var rel = _this.wireContent[\"m.relates_to\"];\n\n if (!_relationship_types.REFERENCE_RELATION.matches(rel === null || rel === void 0 ? void 0 : rel.rel_type) || typeof (rel === null || rel === void 0 ? void 0 : rel.event_id) !== \"string\") {\n throw new _InvalidEventError.InvalidEventError(\"Relationship must be a reference to an event\");\n }\n\n _this.pollEventId = rel.event_id;\n\n _this.validateAgainst(null);\n\n return _this;\n }\n /**\n * Validates the poll response using the poll start event as a frame of reference. This\n * is used to determine if the vote is spoiled, whether the answers are valid, etc.\n * @param {PollStartEvent} poll The poll start event.\n */\n\n\n _createClass(PollResponseEvent, [{\n key: \"answerIds\",\n get:\n /**\n * The provided answers for the poll. Note that this may be falsy/unpredictable if\n * the `spoiled` property is true.\n */\n function get() {\n return this.internalAnswerIds;\n }\n /**\n * The poll start event ID referenced by the response.\n */\n\n }, {\n key: \"spoiled\",\n get:\n /**\n * Whether the vote is spoiled.\n */\n function get() {\n return this.internalSpoiled;\n }\n }, {\n key: \"validateAgainst\",\n value: function validateAgainst(poll) {\n var response = _poll_types.M_POLL_RESPONSE.findIn(this.wireContent);\n\n if (!Array.isArray(response === null || response === void 0 ? void 0 : response.answers)) {\n this.internalSpoiled = true;\n this.internalAnswerIds = [];\n return;\n }\n\n var answers = response.answers;\n\n if (answers.some(function (a) {\n return typeof a !== \"string\";\n }) || answers.length === 0) {\n this.internalSpoiled = true;\n this.internalAnswerIds = [];\n return;\n }\n\n if (poll) {\n if (answers.some(function (a) {\n return !poll.answers.some(function (pa) {\n return pa.id === a;\n });\n })) {\n this.internalSpoiled = true;\n this.internalAnswerIds = [];\n return;\n }\n\n answers = answers.slice(0, poll.maxSelections);\n }\n\n this.internalAnswerIds = answers;\n this.internalSpoiled = false;\n }\n }, {\n key: \"isEquivalentTo\",\n value: function isEquivalentTo(primaryEventType) {\n return (0, _events.isEventTypeSame)(primaryEventType, _poll_types.M_POLL_RESPONSE);\n }\n }, {\n key: \"serialize\",\n value: function serialize() {\n return {\n type: _poll_types.M_POLL_RESPONSE.name,\n content: _defineProperty({\n \"m.relates_to\": {\n rel_type: _relationship_types.REFERENCE_RELATION.name,\n event_id: this.pollEventId\n }\n }, _poll_types.M_POLL_RESPONSE.name, {\n answers: this.spoiled ? undefined : this.answerIds\n })\n };\n }\n /**\n * Creates a new PollResponseEvent from a set of answers. To spoil the vote, pass an empty\n * answers array.\n * @param {string} answers The user's answers. Should be valid from a poll's answer IDs.\n * @param {string} pollEventId The poll start event ID.\n * @returns {PollStartEvent} The representative poll response event.\n */\n\n }], [{\n key: \"from\",\n value: function from(answers, pollEventId) {\n return new PollResponseEvent({\n type: _poll_types.M_POLL_RESPONSE.name,\n content: _defineProperty({\n \"m.relates_to\": {\n rel_type: _relationship_types.REFERENCE_RELATION.name,\n event_id: pollEventId\n }\n }, _poll_types.M_POLL_RESPONSE.name, {\n answers: answers\n })\n });\n }\n }]);\n\n return PollResponseEvent;\n}(_ExtensibleEvent2.ExtensibleEvent);\n\nexports.PollResponseEvent = PollResponseEvent;","\"use strict\";\n\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && \"function\" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }, _typeof(obj); }\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.PollStartEvent = exports.PollAnswerSubevent = void 0;\n\nvar _poll_types = require(\"./poll_types\");\n\nvar _MessageEvent2 = require(\"./MessageEvent\");\n\nvar _message_types = require(\"./message_types\");\n\nvar _InvalidEventError = require(\"../InvalidEventError\");\n\nvar _NamespacedValue = require(\"../NamespacedValue\");\n\nvar _events = require(\"../utility/events\");\n\nvar _ExtensibleEvent2 = require(\"./ExtensibleEvent\");\n\nfunction _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }\n\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\n\nfunction _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === \"string\") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === \"Object\" && o.constructor) n = o.constructor.name; if (n === \"Map\" || n === \"Set\") return Array.from(o); if (n === \"Arguments\" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }\n\nfunction _iterableToArray(iter) { if (typeof Symbol !== \"undefined\" && iter[Symbol.iterator] != null || iter[\"@@iterator\"] != null) return Array.from(iter); }\n\nfunction _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }\n\nfunction _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }\n\nfunction ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }\n\nfunction _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, \"prototype\", { writable: false }); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, \"prototype\", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } else if (call !== void 0) { throw new TypeError(\"Derived constructors may only return object or undefined\"); } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\n/**\n * Represents a poll answer. Note that this is represented as a subtype and is\n * not registered as a parsable event - it is implied for usage exclusively\n * within the PollStartEvent parsing.\n */\nvar PollAnswerSubevent = /*#__PURE__*/function (_MessageEvent) {\n _inherits(PollAnswerSubevent, _MessageEvent);\n\n var _super = _createSuper(PollAnswerSubevent);\n\n /**\n * The answer ID.\n */\n function PollAnswerSubevent(wireFormat) {\n var _this;\n\n _classCallCheck(this, PollAnswerSubevent);\n\n _this = _super.call(this, wireFormat);\n\n _defineProperty(_assertThisInitialized(_this), \"id\", void 0);\n\n var id = wireFormat.content.id;\n\n if (!id || typeof id !== \"string\") {\n throw new _InvalidEventError.InvalidEventError(\"Answer ID must be a non-empty string\");\n }\n\n _this.id = id;\n return _this;\n }\n\n _createClass(PollAnswerSubevent, [{\n key: \"serialize\",\n value: function serialize() {\n return {\n type: \"org.matrix.sdk.poll.answer\",\n content: _objectSpread({\n id: this.id\n }, this.serializeMMessageOnly())\n };\n }\n /**\n * Creates a new PollAnswerSubevent from ID and text.\n * @param {string} id The answer ID (unique within the poll).\n * @param {string} text The text.\n * @returns {PollAnswerSubevent} The representative answer.\n */\n\n }], [{\n key: \"from\",\n value: function from(id, text) {\n return new PollAnswerSubevent({\n type: \"org.matrix.sdk.poll.answer\",\n content: _defineProperty({\n id: id\n }, _message_types.M_TEXT.name, text)\n });\n }\n }]);\n\n return PollAnswerSubevent;\n}(_MessageEvent2.MessageEvent);\n/**\n * Represents a poll start event.\n */\n\n\nexports.PollAnswerSubevent = PollAnswerSubevent;\n\nvar PollStartEvent = /*#__PURE__*/function (_ExtensibleEvent) {\n _inherits(PollStartEvent, _ExtensibleEvent);\n\n var _super2 = _createSuper(PollStartEvent);\n\n /**\n * The question being asked, as a MessageEvent node.\n */\n\n /**\n * The interpreted kind of poll. Note that this will infer a value that is known to the\n * SDK rather than verbatim - this means unknown types will be represented as undisclosed\n * polls.\n *\n * To get the raw kind, use rawKind.\n */\n\n /**\n * The true kind as provided by the event sender. Might not be valid.\n */\n\n /**\n * The maximum number of selections a user is allowed to make.\n */\n\n /**\n * The possible answers for the poll.\n */\n\n /**\n * Creates a new PollStartEvent from a pure format. Note that the event is *not*\n * parsed here: it will be treated as a literal m.poll.start primary typed event.\n * @param {IPartialEvent<M_POLL_START_EVENT_CONTENT>} wireFormat The event.\n */\n function PollStartEvent(wireFormat) {\n var _this2;\n\n _classCallCheck(this, PollStartEvent);\n\n _this2 = _super2.call(this, wireFormat);\n\n _defineProperty(_assertThisInitialized(_this2), \"question\", void 0);\n\n _defineProperty(_assertThisInitialized(_this2), \"kind\", void 0);\n\n _defineProperty(_assertThisInitialized(_this2), \"rawKind\", void 0);\n\n _defineProperty(_assertThisInitialized(_this2), \"maxSelections\", void 0);\n\n _defineProperty(_assertThisInitialized(_this2), \"answers\", void 0);\n\n var poll = _poll_types.M_POLL_START.findIn(_this2.wireContent);\n\n if (!poll.question) {\n throw new _InvalidEventError.InvalidEventError(\"A question is required\");\n }\n\n _this2.question = new _MessageEvent2.MessageEvent({\n type: \"org.matrix.sdk.poll.question\",\n content: poll.question\n });\n _this2.rawKind = poll.kind;\n\n if (_poll_types.M_POLL_KIND_DISCLOSED.matches(_this2.rawKind)) {\n _this2.kind = _poll_types.M_POLL_KIND_DISCLOSED;\n } else {\n _this2.kind = _poll_types.M_POLL_KIND_UNDISCLOSED; // default & assumed value\n }\n\n _this2.maxSelections = Number.isFinite(poll.max_selections) && poll.max_selections > 0 ? poll.max_selections : 1;\n\n if (!Array.isArray(poll.answers)) {\n throw new _InvalidEventError.InvalidEventError(\"Poll answers must be an array\");\n }\n\n var answers = poll.answers.slice(0, 20).map(function (a) {\n return new PollAnswerSubevent({\n type: \"org.matrix.sdk.poll.answer\",\n content: a\n });\n });\n\n if (answers.length <= 0) {\n throw new _InvalidEventError.InvalidEventError(\"No answers available\");\n }\n\n _this2.answers = answers;\n return _this2;\n }\n\n _createClass(PollStartEvent, [{\n key: \"isEquivalentTo\",\n value: function isEquivalentTo(primaryEventType) {\n return (0, _events.isEventTypeSame)(primaryEventType, _poll_types.M_POLL_START);\n }\n }, {\n key: \"serialize\",\n value: function serialize() {\n var _content2;\n\n return {\n type: _poll_types.M_POLL_START.name,\n content: (_content2 = {}, _defineProperty(_content2, _poll_types.M_POLL_START.name, {\n question: this.question.serialize().content,\n kind: this.rawKind,\n max_selections: this.maxSelections,\n answers: this.answers.map(function (a) {\n return a.serialize().content;\n })\n }), _defineProperty(_content2, _message_types.M_TEXT.name, \"\".concat(this.question.text, \"\\n\").concat(this.answers.map(function (a, i) {\n return \"\".concat(i + 1, \". \").concat(a.text);\n }).join(\"\\n\"))), _content2)\n };\n }\n /**\n * Creates a new PollStartEvent from question, answers, and metadata.\n * @param {string} question The question to ask.\n * @param {string} answers The answers. Should be unique within each other.\n * @param {KNOWN_POLL_KIND|string} kind The kind of poll.\n * @param {number} maxSelections The maximum number of selections. Must be 1 or higher.\n * @returns {PollStartEvent} The representative poll start event.\n */\n\n }], [{\n key: \"from\",\n value: function from(question, answers, kind) {\n var _content3;\n\n var maxSelections = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 1;\n return new PollStartEvent({\n type: _poll_types.M_POLL_START.name,\n content: (_content3 = {}, _defineProperty(_content3, _message_types.M_TEXT.name, question), _defineProperty(_content3, _poll_types.M_POLL_START.name, {\n question: _defineProperty({}, _message_types.M_TEXT.name, question),\n kind: kind instanceof _NamespacedValue.NamespacedValue ? kind.name : kind,\n max_selections: maxSelections,\n answers: answers.map(function (a) {\n return _defineProperty({\n id: makeId()\n }, _message_types.M_TEXT.name, a);\n })\n }), _content3)\n });\n }\n }]);\n\n return PollStartEvent;\n}(_ExtensibleEvent2.ExtensibleEvent);\n\nexports.PollStartEvent = PollStartEvent;\nvar LETTERS = \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\";\n\nfunction makeId() {\n return _toConsumableArray(Array(16)).map(function () {\n return LETTERS.charAt(Math.floor(Math.random() * LETTERS.length));\n }).join('');\n}","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.M_TEXT = exports.M_NOTICE = exports.M_MESSAGE = exports.M_HTML = exports.M_EMOTE = void 0;\n\nvar _NamespacedValue = require(\"../NamespacedValue\");\n\n/*\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\n/**\n * The namespaced value for m.message\n */\nvar M_MESSAGE = new _NamespacedValue.UnstableValue(\"m.message\", \"org.matrix.msc1767.message\");\n/**\n * An m.message event rendering\n */\n\nexports.M_MESSAGE = M_MESSAGE;\n\n/**\n * The namespaced value for m.text\n */\nvar M_TEXT = new _NamespacedValue.UnstableValue(\"m.text\", \"org.matrix.msc1767.text\");\n/**\n * The content for an m.text event\n */\n\nexports.M_TEXT = M_TEXT;\n\n/**\n * The namespaced value for m.html\n */\nvar M_HTML = new _NamespacedValue.UnstableValue(\"m.html\", \"org.matrix.msc1767.html\");\n/**\n * The content for an m.html event\n */\n\nexports.M_HTML = M_HTML;\n\n/**\n * The namespaced value for m.emote\n */\nvar M_EMOTE = new _NamespacedValue.UnstableValue(\"m.emote\", \"org.matrix.msc1767.emote\");\n/**\n * The event definition for an m.emote event (in content)\n */\n\nexports.M_EMOTE = M_EMOTE;\n\n/**\n * The namespaced value for m.notice\n */\nvar M_NOTICE = new _NamespacedValue.UnstableValue(\"m.notice\", \"org.matrix.msc1767.notice\");\n/**\n * The event definition for an m.notice event (in content)\n */\n\nexports.M_NOTICE = M_NOTICE;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.M_POLL_START = exports.M_POLL_RESPONSE = exports.M_POLL_KIND_UNDISCLOSED = exports.M_POLL_KIND_DISCLOSED = exports.M_POLL_END = void 0;\n\nvar _NamespacedValue = require(\"../NamespacedValue\");\n\n/*\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\n/**\n * Identifier for a disclosed poll.\n */\nvar M_POLL_KIND_DISCLOSED = new _NamespacedValue.UnstableValue(\"m.poll.disclosed\", \"org.matrix.msc3381.poll.disclosed\");\n/**\n * Identifier for an undisclosed poll.\n */\n\nexports.M_POLL_KIND_DISCLOSED = M_POLL_KIND_DISCLOSED;\nvar M_POLL_KIND_UNDISCLOSED = new _NamespacedValue.UnstableValue(\"m.poll.undisclosed\", \"org.matrix.msc3381.poll.undisclosed\");\n/**\n * Any poll kind.\n */\n\nexports.M_POLL_KIND_UNDISCLOSED = M_POLL_KIND_UNDISCLOSED;\n\n/**\n * The namespaced value for m.poll.start\n */\nvar M_POLL_START = new _NamespacedValue.UnstableValue(\"m.poll.start\", \"org.matrix.msc3381.poll.start\");\n/**\n * The m.poll.start type within event content\n */\n\nexports.M_POLL_START = M_POLL_START;\n\n/**\n * The namespaced value for m.poll.response\n */\nvar M_POLL_RESPONSE = new _NamespacedValue.UnstableValue(\"m.poll.response\", \"org.matrix.msc3381.poll.response\");\n/**\n * The m.poll.response type within event content\n */\n\nexports.M_POLL_RESPONSE = M_POLL_RESPONSE;\n\n/**\n * The namespaced value for m.poll.end\n */\nvar M_POLL_END = new _NamespacedValue.UnstableValue(\"m.poll.end\", \"org.matrix.msc3381.poll.end\");\n/**\n * The event definition for an m.poll.end event (in content)\n */\n\nexports.M_POLL_END = M_POLL_END;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.REFERENCE_RELATION = void 0;\n\nvar _NamespacedValue = require(\"../NamespacedValue\");\n\n/*\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\n/**\n * The namespaced value for an m.reference relation\n */\nvar REFERENCE_RELATION = new _NamespacedValue.NamespacedValue(\"m.reference\");\n/**\n * Represents any relation type\n */\n\nexports.REFERENCE_RELATION = REFERENCE_RELATION;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _ExtensibleEvents = require(\"./ExtensibleEvents\");\n\nObject.keys(_ExtensibleEvents).forEach(function (key) {\n if (key === \"default\" || key === \"__esModule\") return;\n if (key in exports && exports[key] === _ExtensibleEvents[key]) return;\n Object.defineProperty(exports, key, {\n enumerable: true,\n get: function get() {\n return _ExtensibleEvents[key];\n }\n });\n});\n\nvar _IPartialEvent = require(\"./IPartialEvent\");\n\nObject.keys(_IPartialEvent).forEach(function (key) {\n if (key === \"default\" || key === \"__esModule\") return;\n if (key in exports && exports[key] === _IPartialEvent[key]) return;\n Object.defineProperty(exports, key, {\n enumerable: true,\n get: function get() {\n return _IPartialEvent[key];\n }\n });\n});\n\nvar _InvalidEventError = require(\"./InvalidEventError\");\n\nObject.keys(_InvalidEventError).forEach(function (key) {\n if (key === \"default\" || key === \"__esModule\") return;\n if (key in exports && exports[key] === _InvalidEventError[key]) return;\n Object.defineProperty(exports, key, {\n enumerable: true,\n get: function get() {\n return _InvalidEventError[key];\n }\n });\n});\n\nvar _NamespacedValue = require(\"./NamespacedValue\");\n\nObject.keys(_NamespacedValue).forEach(function (key) {\n if (key === \"default\" || key === \"__esModule\") return;\n if (key in exports && exports[key] === _NamespacedValue[key]) return;\n Object.defineProperty(exports, key, {\n enumerable: true,\n get: function get() {\n return _NamespacedValue[key];\n }\n });\n});\n\nvar _NamespacedMap = require(\"./NamespacedMap\");\n\nObject.keys(_NamespacedMap).forEach(function (key) {\n if (key === \"default\" || key === \"__esModule\") return;\n if (key in exports && exports[key] === _NamespacedMap[key]) return;\n Object.defineProperty(exports, key, {\n enumerable: true,\n get: function get() {\n return _NamespacedMap[key];\n }\n });\n});\n\nvar _types = require(\"./types\");\n\nObject.keys(_types).forEach(function (key) {\n if (key === \"default\" || key === \"__esModule\") return;\n if (key in exports && exports[key] === _types[key]) return;\n Object.defineProperty(exports, key, {\n enumerable: true,\n get: function get() {\n return _types[key];\n }\n });\n});\n\nvar _MessageMatchers = require(\"./utility/MessageMatchers\");\n\nObject.keys(_MessageMatchers).forEach(function (key) {\n if (key === \"default\" || key === \"__esModule\") return;\n if (key in exports && exports[key] === _MessageMatchers[key]) return;\n Object.defineProperty(exports, key, {\n enumerable: true,\n get: function get() {\n return _MessageMatchers[key];\n }\n });\n});\n\nvar _events = require(\"./utility/events\");\n\nObject.keys(_events).forEach(function (key) {\n if (key === \"default\" || key === \"__esModule\") return;\n if (key in exports && exports[key] === _events[key]) return;\n Object.defineProperty(exports, key, {\n enumerable: true,\n get: function get() {\n return _events[key];\n }\n });\n});\n\nvar _MRoomMessage = require(\"./interpreters/legacy/MRoomMessage\");\n\nObject.keys(_MRoomMessage).forEach(function (key) {\n if (key === \"default\" || key === \"__esModule\") return;\n if (key in exports && exports[key] === _MRoomMessage[key]) return;\n Object.defineProperty(exports, key, {\n enumerable: true,\n get: function get() {\n return _MRoomMessage[key];\n }\n });\n});\n\nvar _MMessage = require(\"./interpreters/modern/MMessage\");\n\nObject.keys(_MMessage).forEach(function (key) {\n if (key === \"default\" || key === \"__esModule\") return;\n if (key in exports && exports[key] === _MMessage[key]) return;\n Object.defineProperty(exports, key, {\n enumerable: true,\n get: function get() {\n return _MMessage[key];\n }\n });\n});\n\nvar _MPoll = require(\"./interpreters/modern/MPoll\");\n\nObject.keys(_MPoll).forEach(function (key) {\n if (key === \"default\" || key === \"__esModule\") return;\n if (key in exports && exports[key] === _MPoll[key]) return;\n Object.defineProperty(exports, key, {\n enumerable: true,\n get: function get() {\n return _MPoll[key];\n }\n });\n});\n\nvar _relationship_types = require(\"./events/relationship_types\");\n\nObject.keys(_relationship_types).forEach(function (key) {\n if (key === \"default\" || key === \"__esModule\") return;\n if (key in exports && exports[key] === _relationship_types[key]) return;\n Object.defineProperty(exports, key, {\n enumerable: true,\n get: function get() {\n return _relationship_types[key];\n }\n });\n});\n\nvar _ExtensibleEvent = require(\"./events/ExtensibleEvent\");\n\nObject.keys(_ExtensibleEvent).forEach(function (key) {\n if (key === \"default\" || key === \"__esModule\") return;\n if (key in exports && exports[key] === _ExtensibleEvent[key]) return;\n Object.defineProperty(exports, key, {\n enumerable: true,\n get: function get() {\n return _ExtensibleEvent[key];\n }\n });\n});\n\nvar _message_types = require(\"./events/message_types\");\n\nObject.keys(_message_types).forEach(function (key) {\n if (key === \"default\" || key === \"__esModule\") return;\n if (key in exports && exports[key] === _message_types[key]) return;\n Object.defineProperty(exports, key, {\n enumerable: true,\n get: function get() {\n return _message_types[key];\n }\n });\n});\n\nvar _MessageEvent = require(\"./events/MessageEvent\");\n\nObject.keys(_MessageEvent).forEach(function (key) {\n if (key === \"default\" || key === \"__esModule\") return;\n if (key in exports && exports[key] === _MessageEvent[key]) return;\n Object.defineProperty(exports, key, {\n enumerable: true,\n get: function get() {\n return _MessageEvent[key];\n }\n });\n});\n\nvar _EmoteEvent = require(\"./events/EmoteEvent\");\n\nObject.keys(_EmoteEvent).forEach(function (key) {\n if (key === \"default\" || key === \"__esModule\") return;\n if (key in exports && exports[key] === _EmoteEvent[key]) return;\n Object.defineProperty(exports, key, {\n enumerable: true,\n get: function get() {\n return _EmoteEvent[key];\n }\n });\n});\n\nvar _NoticeEvent = require(\"./events/NoticeEvent\");\n\nObject.keys(_NoticeEvent).forEach(function (key) {\n if (key === \"default\" || key === \"__esModule\") return;\n if (key in exports && exports[key] === _NoticeEvent[key]) return;\n Object.defineProperty(exports, key, {\n enumerable: true,\n get: function get() {\n return _NoticeEvent[key];\n }\n });\n});\n\nvar _poll_types = require(\"./events/poll_types\");\n\nObject.keys(_poll_types).forEach(function (key) {\n if (key === \"default\" || key === \"__esModule\") return;\n if (key in exports && exports[key] === _poll_types[key]) return;\n Object.defineProperty(exports, key, {\n enumerable: true,\n get: function get() {\n return _poll_types[key];\n }\n });\n});\n\nvar _PollStartEvent = require(\"./events/PollStartEvent\");\n\nObject.keys(_PollStartEvent).forEach(function (key) {\n if (key === \"default\" || key === \"__esModule\") return;\n if (key in exports && exports[key] === _PollStartEvent[key]) return;\n Object.defineProperty(exports, key, {\n enumerable: true,\n get: function get() {\n return _PollStartEvent[key];\n }\n });\n});\n\nvar _PollResponseEvent = require(\"./events/PollResponseEvent\");\n\nObject.keys(_PollResponseEvent).forEach(function (key) {\n if (key === \"default\" || key === \"__esModule\") return;\n if (key in exports && exports[key] === _PollResponseEvent[key]) return;\n Object.defineProperty(exports, key, {\n enumerable: true,\n get: function get() {\n return _PollResponseEvent[key];\n }\n });\n});\n\nvar _PollEndEvent = require(\"./events/PollEndEvent\");\n\nObject.keys(_PollEndEvent).forEach(function (key) {\n if (key === \"default\" || key === \"__esModule\") return;\n if (key in exports && exports[key] === _PollEndEvent[key]) return;\n Object.defineProperty(exports, key, {\n enumerable: true,\n get: function get() {\n return _PollEndEvent[key];\n }\n });\n});","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.LEGACY_M_ROOM_MESSAGE = void 0;\nexports.parseMRoomMessage = parseMRoomMessage;\n\nvar _MessageEvent = require(\"../../events/MessageEvent\");\n\nvar _NoticeEvent = require(\"../../events/NoticeEvent\");\n\nvar _EmoteEvent = require(\"../../events/EmoteEvent\");\n\nvar _NamespacedValue = require(\"../../NamespacedValue\");\n\nvar _message_types = require(\"../../events/message_types\");\n\nfunction ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }\n\nfunction _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nvar LEGACY_M_ROOM_MESSAGE = new _NamespacedValue.NamespacedValue(\"m.room.message\");\nexports.LEGACY_M_ROOM_MESSAGE = LEGACY_M_ROOM_MESSAGE;\n\nfunction parseMRoomMessage(wireEvent) {\n var _wireEvent$content, _wireEvent$content2, _wireEvent$content3;\n\n if (_message_types.M_MESSAGE.findIn(wireEvent.content) || _message_types.M_TEXT.findIn(wireEvent.content)) {\n // We know enough about the event to coerce it into the right type\n return new _MessageEvent.MessageEvent(wireEvent);\n }\n\n var msgtype = (_wireEvent$content = wireEvent.content) === null || _wireEvent$content === void 0 ? void 0 : _wireEvent$content.msgtype;\n var text = (_wireEvent$content2 = wireEvent.content) === null || _wireEvent$content2 === void 0 ? void 0 : _wireEvent$content2.body;\n var html = ((_wireEvent$content3 = wireEvent.content) === null || _wireEvent$content3 === void 0 ? void 0 : _wireEvent$content3.format) === \"org.matrix.custom.html\" ? wireEvent.content.formatted_body : null;\n\n if (msgtype === \"m.text\") {\n var _objectSpread2;\n\n return new _MessageEvent.MessageEvent(_objectSpread(_objectSpread({}, wireEvent), {}, {\n content: _objectSpread(_objectSpread({}, wireEvent.content), {}, (_objectSpread2 = {}, _defineProperty(_objectSpread2, _message_types.M_TEXT.name, text), _defineProperty(_objectSpread2, _message_types.M_HTML.name, html), _objectSpread2))\n }));\n } else if (msgtype === \"m.notice\") {\n var _objectSpread3;\n\n return new _NoticeEvent.NoticeEvent(_objectSpread(_objectSpread({}, wireEvent), {}, {\n content: _objectSpread(_objectSpread({}, wireEvent.content), {}, (_objectSpread3 = {}, _defineProperty(_objectSpread3, _message_types.M_TEXT.name, text), _defineProperty(_objectSpread3, _message_types.M_HTML.name, html), _objectSpread3))\n }));\n } else if (msgtype === \"m.emote\") {\n var _objectSpread4;\n\n return new _EmoteEvent.EmoteEvent(_objectSpread(_objectSpread({}, wireEvent), {}, {\n content: _objectSpread(_objectSpread({}, wireEvent.content), {}, (_objectSpread4 = {}, _defineProperty(_objectSpread4, _message_types.M_TEXT.name, text), _defineProperty(_objectSpread4, _message_types.M_HTML.name, html), _objectSpread4))\n }));\n } else {\n // TODO: Handle other types\n return null;\n }\n}","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.parseMMessage = parseMMessage;\n\nvar _MessageEvent = require(\"../../events/MessageEvent\");\n\nvar _message_types = require(\"../../events/message_types\");\n\nvar _EmoteEvent = require(\"../../events/EmoteEvent\");\n\nvar _NoticeEvent = require(\"../../events/NoticeEvent\");\n\n/*\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*/\nfunction parseMMessage(wireEvent) {\n if (_message_types.M_EMOTE.matches(wireEvent.type)) {\n return new _EmoteEvent.EmoteEvent(wireEvent);\n } else if (_message_types.M_NOTICE.matches(wireEvent.type)) {\n return new _NoticeEvent.NoticeEvent(wireEvent);\n } // default: return a generic message\n\n\n return new _MessageEvent.MessageEvent(wireEvent);\n}","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.parseMPoll = parseMPoll;\n\nvar _poll_types = require(\"../../events/poll_types\");\n\nvar _PollStartEvent = require(\"../../events/PollStartEvent\");\n\nvar _PollResponseEvent = require(\"../../events/PollResponseEvent\");\n\nvar _PollEndEvent = require(\"../../events/PollEndEvent\");\n\n/*\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*/\nfunction parseMPoll(wireEvent) {\n if (_poll_types.M_POLL_START.matches(wireEvent.type)) {\n return new _PollStartEvent.PollStartEvent(wireEvent);\n } else if (_poll_types.M_POLL_RESPONSE.matches(wireEvent.type)) {\n return new _PollResponseEvent.PollResponseEvent(wireEvent);\n } else if (_poll_types.M_POLL_END.matches(wireEvent.type)) {\n return new _PollEndEvent.PollEndEvent(wireEvent);\n }\n\n return null; // not a poll event\n}","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.isOptionalAString = isOptionalAString;\nexports.isProvided = isProvided;\n\n/*\nCopyright 2021 - 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\n/**\n * Represents an optional type: can either be T or a falsy value.\n */\n\n/**\n * Determines if the given optional string is a defined string.\n * @param {Optional<string>} s The input string.\n * @returns {boolean} True if the input is a defined string.\n */\nfunction isOptionalAString(s) {\n return isProvided(s) && typeof s === 'string';\n}\n/**\n * Determines if the given optional was provided a value.\n * @param {Optional<T>} s The optional to test.\n * @returns {boolean} True if the value is defined.\n */\n\n\nfunction isProvided(s) {\n return s !== null && s !== undefined;\n}\n/**\n * Represents either just T1, just T2, or T1 and T2 mixed.\n */","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.LegacyMsgType = void 0;\nexports.isEventLike = isEventLike;\n\nvar _message_types = require(\"../events/message_types\");\n\n/*\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\n/**\n * Represents a legacy m.room.message msgtype\n */\nvar LegacyMsgType;\n/**\n * Determines if the given partial event looks similar enough to the given legacy msgtype\n * to count as that message type.\n * @param {IPartialEvent<EitherAnd<IPartialLegacyContent, M_MESSAGE_EVENT_CONTENT>>} event The event.\n * @param {LegacyMsgType} msgtype The message type to compare for.\n * @returns {boolean} True if the event appears to look similar enough to the msgtype.\n */\n\nexports.LegacyMsgType = LegacyMsgType;\n\n(function (LegacyMsgType) {\n LegacyMsgType[\"Text\"] = \"m.text\";\n LegacyMsgType[\"Notice\"] = \"m.notice\";\n LegacyMsgType[\"Emote\"] = \"m.emote\";\n})(LegacyMsgType || (exports.LegacyMsgType = LegacyMsgType = {}));\n\nfunction isEventLike(event, msgtype) {\n var content = event.content;\n\n if (msgtype === LegacyMsgType.Text) {\n return _message_types.M_MESSAGE.matches(event.type) || event.type === \"m.room.message\" && (content === null || content === void 0 ? void 0 : content['msgtype']) === \"m.text\";\n } else if (msgtype === LegacyMsgType.Emote) {\n return _message_types.M_EMOTE.matches(event.type) || event.type === \"m.room.message\" && (content === null || content === void 0 ? void 0 : content['msgtype']) === \"m.emote\";\n } else if (msgtype === LegacyMsgType.Notice) {\n return _message_types.M_NOTICE.matches(event.type) || event.type === \"m.room.message\" && (content === null || content === void 0 ? void 0 : content['msgtype']) === \"m.notice\";\n }\n\n return false;\n}","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.isEventTypeSame = isEventTypeSame;\n\n/*\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\n/**\n * Represents a potentially namespaced event type.\n */\n\n/**\n * Determines if two event types are the same, including namespaces.\n * @param {EventType} given The given event type. This will be compared\n * against the expected type.\n * @param {EventType} expected The expected event type.\n * @returns {boolean} True if the given type matches the expected type.\n */\nfunction isEventTypeSame(given, expected) {\n if (typeof given === \"string\") {\n if (typeof expected === \"string\") {\n return expected === given;\n } else {\n return expected.matches(given);\n }\n } else {\n if (typeof expected === \"string\") {\n return given.matches(expected);\n } else {\n var expectedNs = expected;\n var givenNs = given;\n return expectedNs.matches(givenNs.name) || expectedNs.matches(givenNs.altName);\n }\n }\n}","var grammar = module.exports = {\n v: [{\n name: 'version',\n reg: /^(\\d*)$/\n }],\n o: [{\n // o=- 20518 0 IN IP4 203.0.113.1\n // NB: sessionId will be a String in most cases because it is huge\n name: 'origin',\n reg: /^(\\S*) (\\d*) (\\d*) (\\S*) IP(\\d) (\\S*)/,\n names: ['username', 'sessionId', 'sessionVersion', 'netType', 'ipVer', 'address'],\n format: '%s %s %d %s IP%d %s'\n }],\n // default parsing of these only (though some of these feel outdated)\n s: [{ name: 'name' }],\n i: [{ name: 'description' }],\n u: [{ name: 'uri' }],\n e: [{ name: 'email' }],\n p: [{ name: 'phone' }],\n z: [{ name: 'timezones' }], // TODO: this one can actually be parsed properly...\n r: [{ name: 'repeats' }], // TODO: this one can also be parsed properly\n // k: [{}], // outdated thing ignored\n t: [{\n // t=0 0\n name: 'timing',\n reg: /^(\\d*) (\\d*)/,\n names: ['start', 'stop'],\n format: '%d %d'\n }],\n c: [{\n // c=IN IP4 10.47.197.26\n name: 'connection',\n reg: /^IN IP(\\d) (\\S*)/,\n names: ['version', 'ip'],\n format: 'IN IP%d %s'\n }],\n b: [{\n // b=AS:4000\n push: 'bandwidth',\n reg: /^(TIAS|AS|CT|RR|RS):(\\d*)/,\n names: ['type', 'limit'],\n format: '%s:%s'\n }],\n m: [{\n // m=video 51744 RTP/AVP 126 97 98 34 31\n // NB: special - pushes to session\n // TODO: rtp/fmtp should be filtered by the payloads found here?\n reg: /^(\\w*) (\\d*) ([\\w/]*)(?: (.*))?/,\n names: ['type', 'port', 'protocol', 'payloads'],\n format: '%s %d %s %s'\n }],\n a: [\n {\n // a=rtpmap:110 opus/48000/2\n push: 'rtp',\n reg: /^rtpmap:(\\d*) ([\\w\\-.]*)(?:\\s*\\/(\\d*)(?:\\s*\\/(\\S*))?)?/,\n names: ['payload', 'codec', 'rate', 'encoding'],\n format: function (o) {\n return (o.encoding)\n ? 'rtpmap:%d %s/%s/%s'\n : o.rate\n ? 'rtpmap:%d %s/%s'\n : 'rtpmap:%d %s';\n }\n },\n {\n // a=fmtp:108 profile-level-id=24;object=23;bitrate=64000\n // a=fmtp:111 minptime=10; useinbandfec=1\n push: 'fmtp',\n reg: /^fmtp:(\\d*) ([\\S| ]*)/,\n names: ['payload', 'config'],\n format: 'fmtp:%d %s'\n },\n {\n // a=control:streamid=0\n name: 'control',\n reg: /^control:(.*)/,\n format: 'control:%s'\n },\n {\n // a=rtcp:65179 IN IP4 193.84.77.194\n name: 'rtcp',\n reg: /^rtcp:(\\d*)(?: (\\S*) IP(\\d) (\\S*))?/,\n names: ['port', 'netType', 'ipVer', 'address'],\n format: function (o) {\n return (o.address != null)\n ? 'rtcp:%d %s IP%d %s'\n : 'rtcp:%d';\n }\n },\n {\n // a=rtcp-fb:98 trr-int 100\n push: 'rtcpFbTrrInt',\n reg: /^rtcp-fb:(\\*|\\d*) trr-int (\\d*)/,\n names: ['payload', 'value'],\n format: 'rtcp-fb:%s trr-int %d'\n },\n {\n // a=rtcp-fb:98 nack rpsi\n push: 'rtcpFb',\n reg: /^rtcp-fb:(\\*|\\d*) ([\\w-_]*)(?: ([\\w-_]*))?/,\n names: ['payload', 'type', 'subtype'],\n format: function (o) {\n return (o.subtype != null)\n ? 'rtcp-fb:%s %s %s'\n : 'rtcp-fb:%s %s';\n }\n },\n {\n // a=extmap:2 urn:ietf:params:rtp-hdrext:toffset\n // a=extmap:1/recvonly URI-gps-string\n // a=extmap:3 urn:ietf:params:rtp-hdrext:encrypt urn:ietf:params:rtp-hdrext:smpte-tc 25@600/24\n push: 'ext',\n reg: /^extmap:(\\d+)(?:\\/(\\w+))?(?: (urn:ietf:params:rtp-hdrext:encrypt))? (\\S*)(?: (\\S*))?/,\n names: ['value', 'direction', 'encrypt-uri', 'uri', 'config'],\n format: function (o) {\n return (\n 'extmap:%d' +\n (o.direction ? '/%s' : '%v') +\n (o['encrypt-uri'] ? ' %s' : '%v') +\n ' %s' +\n (o.config ? ' %s' : '')\n );\n }\n },\n {\n // a=extmap-allow-mixed\n name: 'extmapAllowMixed',\n reg: /^(extmap-allow-mixed)/\n },\n {\n // a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:PS1uQCVeeCFCanVmcjkpPywjNWhcYD0mXXtxaVBR|2^20|1:32\n push: 'crypto',\n reg: /^crypto:(\\d*) ([\\w_]*) (\\S*)(?: (\\S*))?/,\n names: ['id', 'suite', 'config', 'sessionConfig'],\n format: function (o) {\n return (o.sessionConfig != null)\n ? 'crypto:%d %s %s %s'\n : 'crypto:%d %s %s';\n }\n },\n {\n // a=setup:actpass\n name: 'setup',\n reg: /^setup:(\\w*)/,\n format: 'setup:%s'\n },\n {\n // a=connection:new\n name: 'connectionType',\n reg: /^connection:(new|existing)/,\n format: 'connection:%s'\n },\n {\n // a=mid:1\n name: 'mid',\n reg: /^mid:([^\\s]*)/,\n format: 'mid:%s'\n },\n {\n // a=msid:0c8b064d-d807-43b4-b434-f92a889d8587 98178685-d409-46e0-8e16-7ef0db0db64a\n push: 'msid',\n reg: /^msid:([\\w-]+)(?: ([\\w-]+))?/,\n names: ['id', 'appdata'],\n format: 'msid:%s %s'\n },\n {\n // a=ptime:20\n name: 'ptime',\n reg: /^ptime:(\\d*(?:\\.\\d*)*)/,\n format: 'ptime:%d'\n },\n {\n // a=maxptime:60\n name: 'maxptime',\n reg: /^maxptime:(\\d*(?:\\.\\d*)*)/,\n format: 'maxptime:%d'\n },\n {\n // a=sendrecv\n name: 'direction',\n reg: /^(sendrecv|recvonly|sendonly|inactive)/\n },\n {\n // a=ice-lite\n name: 'icelite',\n reg: /^(ice-lite)/\n },\n {\n // a=ice-ufrag:F7gI\n name: 'iceUfrag',\n reg: /^ice-ufrag:(\\S*)/,\n format: 'ice-ufrag:%s'\n },\n {\n // a=ice-pwd:x9cml/YzichV2+XlhiMu8g\n name: 'icePwd',\n reg: /^ice-pwd:(\\S*)/,\n format: 'ice-pwd:%s'\n },\n {\n // a=fingerprint:SHA-1 00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33\n name: 'fingerprint',\n reg: /^fingerprint:(\\S*) (\\S*)/,\n names: ['type', 'hash'],\n format: 'fingerprint:%s %s'\n },\n {\n // a=candidate:0 1 UDP 2113667327 203.0.113.1 54400 typ host\n // a=candidate:1162875081 1 udp 2113937151 192.168.34.75 60017 typ host generation 0 network-id 3 network-cost 10\n // a=candidate:3289912957 2 udp 1845501695 193.84.77.194 60017 typ srflx raddr 192.168.34.75 rport 60017 generation 0 network-id 3 network-cost 10\n // a=candidate:229815620 1 tcp 1518280447 192.168.150.19 60017 typ host tcptype active generation 0 network-id 3 network-cost 10\n // a=candidate:3289912957 2 tcp 1845501695 193.84.77.194 60017 typ srflx raddr 192.168.34.75 rport 60017 tcptype passive generation 0 network-id 3 network-cost 10\n push:'candidates',\n reg: /^candidate:(\\S*) (\\d*) (\\S*) (\\d*) (\\S*) (\\d*) typ (\\S*)(?: raddr (\\S*) rport (\\d*))?(?: tcptype (\\S*))?(?: generation (\\d*))?(?: network-id (\\d*))?(?: network-cost (\\d*))?/,\n names: ['foundation', 'component', 'transport', 'priority', 'ip', 'port', 'type', 'raddr', 'rport', 'tcptype', 'generation', 'network-id', 'network-cost'],\n format: function (o) {\n var str = 'candidate:%s %d %s %d %s %d typ %s';\n\n str += (o.raddr != null) ? ' raddr %s rport %d' : '%v%v';\n\n // NB: candidate has three optional chunks, so %void middles one if it's missing\n str += (o.tcptype != null) ? ' tcptype %s' : '%v';\n\n if (o.generation != null) {\n str += ' generation %d';\n }\n\n str += (o['network-id'] != null) ? ' network-id %d' : '%v';\n str += (o['network-cost'] != null) ? ' network-cost %d' : '%v';\n return str;\n }\n },\n {\n // a=end-of-candidates (keep after the candidates line for readability)\n name: 'endOfCandidates',\n reg: /^(end-of-candidates)/\n },\n {\n // a=remote-candidates:1 203.0.113.1 54400 2 203.0.113.1 54401 ...\n name: 'remoteCandidates',\n reg: /^remote-candidates:(.*)/,\n format: 'remote-candidates:%s'\n },\n {\n // a=ice-options:google-ice\n name: 'iceOptions',\n reg: /^ice-options:(\\S*)/,\n format: 'ice-options:%s'\n },\n {\n // a=ssrc:2566107569 cname:t9YU8M1UxTF8Y1A1\n push: 'ssrcs',\n reg: /^ssrc:(\\d*) ([\\w_-]*)(?::(.*))?/,\n names: ['id', 'attribute', 'value'],\n format: function (o) {\n var str = 'ssrc:%d';\n if (o.attribute != null) {\n str += ' %s';\n if (o.value != null) {\n str += ':%s';\n }\n }\n return str;\n }\n },\n {\n // a=ssrc-group:FEC 1 2\n // a=ssrc-group:FEC-FR 3004364195 1080772241\n push: 'ssrcGroups',\n // token-char = %x21 / %x23-27 / %x2A-2B / %x2D-2E / %x30-39 / %x41-5A / %x5E-7E\n reg: /^ssrc-group:([\\x21\\x23\\x24\\x25\\x26\\x27\\x2A\\x2B\\x2D\\x2E\\w]*) (.*)/,\n names: ['semantics', 'ssrcs'],\n format: 'ssrc-group:%s %s'\n },\n {\n // a=msid-semantic: WMS Jvlam5X3SX1OP6pn20zWogvaKJz5Hjf9OnlV\n name: 'msidSemantic',\n reg: /^msid-semantic:\\s?(\\w*) (\\S*)/,\n names: ['semantic', 'token'],\n format: 'msid-semantic: %s %s' // space after ':' is not accidental\n },\n {\n // a=group:BUNDLE audio video\n push: 'groups',\n reg: /^group:(\\w*) (.*)/,\n names: ['type', 'mids'],\n format: 'group:%s %s'\n },\n {\n // a=rtcp-mux\n name: 'rtcpMux',\n reg: /^(rtcp-mux)/\n },\n {\n // a=rtcp-rsize\n name: 'rtcpRsize',\n reg: /^(rtcp-rsize)/\n },\n {\n // a=sctpmap:5000 webrtc-datachannel 1024\n name: 'sctpmap',\n reg: /^sctpmap:([\\w_/]*) (\\S*)(?: (\\S*))?/,\n names: ['sctpmapNumber', 'app', 'maxMessageSize'],\n format: function (o) {\n return (o.maxMessageSize != null)\n ? 'sctpmap:%s %s %s'\n : 'sctpmap:%s %s';\n }\n },\n {\n // a=x-google-flag:conference\n name: 'xGoogleFlag',\n reg: /^x-google-flag:([^\\s]*)/,\n format: 'x-google-flag:%s'\n },\n {\n // a=rid:1 send max-width=1280;max-height=720;max-fps=30;depend=0\n push: 'rids',\n reg: /^rid:([\\d\\w]+) (\\w+)(?: ([\\S| ]*))?/,\n names: ['id', 'direction', 'params'],\n format: function (o) {\n return (o.params) ? 'rid:%s %s %s' : 'rid:%s %s';\n }\n },\n {\n // a=imageattr:97 send [x=800,y=640,sar=1.1,q=0.6] [x=480,y=320] recv [x=330,y=250]\n // a=imageattr:* send [x=800,y=640] recv *\n // a=imageattr:100 recv [x=320,y=240]\n push: 'imageattrs',\n reg: new RegExp(\n // a=imageattr:97\n '^imageattr:(\\\\d+|\\\\*)' +\n // send [x=800,y=640,sar=1.1,q=0.6] [x=480,y=320]\n '[\\\\s\\\\t]+(send|recv)[\\\\s\\\\t]+(\\\\*|\\\\[\\\\S+\\\\](?:[\\\\s\\\\t]+\\\\[\\\\S+\\\\])*)' +\n // recv [x=330,y=250]\n '(?:[\\\\s\\\\t]+(recv|send)[\\\\s\\\\t]+(\\\\*|\\\\[\\\\S+\\\\](?:[\\\\s\\\\t]+\\\\[\\\\S+\\\\])*))?'\n ),\n names: ['pt', 'dir1', 'attrs1', 'dir2', 'attrs2'],\n format: function (o) {\n return 'imageattr:%s %s %s' + (o.dir2 ? ' %s %s' : '');\n }\n },\n {\n // a=simulcast:send 1,2,3;~4,~5 recv 6;~7,~8\n // a=simulcast:recv 1;4,5 send 6;7\n name: 'simulcast',\n reg: new RegExp(\n // a=simulcast:\n '^simulcast:' +\n // send 1,2,3;~4,~5\n '(send|recv) ([a-zA-Z0-9\\\\-_~;,]+)' +\n // space + recv 6;~7,~8\n '(?:\\\\s?(send|recv) ([a-zA-Z0-9\\\\-_~;,]+))?' +\n // end\n '$'\n ),\n names: ['dir1', 'list1', 'dir2', 'list2'],\n format: function (o) {\n return 'simulcast:%s %s' + (o.dir2 ? ' %s %s' : '');\n }\n },\n {\n // old simulcast draft 03 (implemented by Firefox)\n // https://tools.ietf.org/html/draft-ietf-mmusic-sdp-simulcast-03\n // a=simulcast: recv pt=97;98 send pt=97\n // a=simulcast: send rid=5;6;7 paused=6,7\n name: 'simulcast_03',\n reg: /^simulcast:[\\s\\t]+([\\S+\\s\\t]+)$/,\n names: ['value'],\n format: 'simulcast: %s'\n },\n {\n // a=framerate:25\n // a=framerate:29.97\n name: 'framerate',\n reg: /^framerate:(\\d+(?:$|\\.\\d+))/,\n format: 'framerate:%s'\n },\n {\n // RFC4570\n // a=source-filter: incl IN IP4 239.5.2.31 10.1.15.5\n name: 'sourceFilter',\n reg: /^source-filter: *(excl|incl) (\\S*) (IP4|IP6|\\*) (\\S*) (.*)/,\n names: ['filterMode', 'netType', 'addressTypes', 'destAddress', 'srcList'],\n format: 'source-filter: %s %s %s %s %s'\n },\n {\n // a=bundle-only\n name: 'bundleOnly',\n reg: /^(bundle-only)/\n },\n {\n // a=label:1\n name: 'label',\n reg: /^label:(.+)/,\n format: 'label:%s'\n },\n {\n // RFC version 26 for SCTP over DTLS\n // https://tools.ietf.org/html/draft-ietf-mmusic-sctp-sdp-26#section-5\n name: 'sctpPort',\n reg: /^sctp-port:(\\d+)$/,\n format: 'sctp-port:%s'\n },\n {\n // RFC version 26 for SCTP over DTLS\n // https://tools.ietf.org/html/draft-ietf-mmusic-sctp-sdp-26#section-6\n name: 'maxMessageSize',\n reg: /^max-message-size:(\\d+)$/,\n format: 'max-message-size:%s'\n },\n {\n // RFC7273\n // a=ts-refclk:ptp=IEEE1588-2008:39-A7-94-FF-FE-07-CB-D0:37\n push:'tsRefClocks',\n reg: /^ts-refclk:([^\\s=]*)(?:=(\\S*))?/,\n names: ['clksrc', 'clksrcExt'],\n format: function (o) {\n return 'ts-refclk:%s' + (o.clksrcExt != null ? '=%s' : '');\n }\n },\n {\n // RFC7273\n // a=mediaclk:direct=963214424\n name:'mediaClk',\n reg: /^mediaclk:(?:id=(\\S*))? *([^\\s=]*)(?:=(\\S*))?(?: *rate=(\\d+)\\/(\\d+))?/,\n names: ['id', 'mediaClockName', 'mediaClockValue', 'rateNumerator', 'rateDenominator'],\n format: function (o) {\n var str = 'mediaclk:';\n str += (o.id != null ? 'id=%s %s' : '%v%s');\n str += (o.mediaClockValue != null ? '=%s' : '');\n str += (o.rateNumerator != null ? ' rate=%s' : '');\n str += (o.rateDenominator != null ? '/%s' : '');\n return str;\n }\n },\n {\n // a=keywds:keywords\n name: 'keywords',\n reg: /^keywds:(.+)$/,\n format: 'keywds:%s'\n },\n {\n // a=content:main\n name: 'content',\n reg: /^content:(.+)/,\n format: 'content:%s'\n },\n // BFCP https://tools.ietf.org/html/rfc4583\n {\n // a=floorctrl:c-s\n name: 'bfcpFloorCtrl',\n reg: /^floorctrl:(c-only|s-only|c-s)/,\n format: 'floorctrl:%s'\n },\n {\n // a=confid:1\n name: 'bfcpConfId',\n reg: /^confid:(\\d+)/,\n format: 'confid:%s'\n },\n {\n // a=userid:1\n name: 'bfcpUserId',\n reg: /^userid:(\\d+)/,\n format: 'userid:%s'\n },\n {\n // a=floorid:1\n name: 'bfcpFloorId',\n reg: /^floorid:(.+) (?:m-stream|mstrm):(.+)/,\n names: ['id', 'mStream'],\n format: 'floorid:%s mstrm:%s'\n },\n {\n // any a= that we don't understand is kept verbatim on media.invalid\n push: 'invalid',\n names: ['value']\n }\n ]\n};\n\n// set sensible defaults to avoid polluting the grammar with boring details\nObject.keys(grammar).forEach(function (key) {\n var objs = grammar[key];\n objs.forEach(function (obj) {\n if (!obj.reg) {\n obj.reg = /(.*)/;\n }\n if (!obj.format) {\n obj.format = '%s';\n }\n });\n});\n","var parser = require('./parser');\nvar writer = require('./writer');\nvar grammar = require('./grammar');\n\nexports.grammar = grammar;\nexports.write = writer;\nexports.parse = parser.parse;\nexports.parseParams = parser.parseParams;\nexports.parseFmtpConfig = parser.parseFmtpConfig; // Alias of parseParams().\nexports.parsePayloads = parser.parsePayloads;\nexports.parseRemoteCandidates = parser.parseRemoteCandidates;\nexports.parseImageAttributes = parser.parseImageAttributes;\nexports.parseSimulcastStreamList = parser.parseSimulcastStreamList;\n","var toIntIfInt = function (v) {\n return String(Number(v)) === v ? Number(v) : v;\n};\n\nvar attachProperties = function (match, location, names, rawName) {\n if (rawName && !names) {\n location[rawName] = toIntIfInt(match[1]);\n }\n else {\n for (var i = 0; i < names.length; i += 1) {\n if (match[i+1] != null) {\n location[names[i]] = toIntIfInt(match[i+1]);\n }\n }\n }\n};\n\nvar parseReg = function (obj, location, content) {\n var needsBlank = obj.name && obj.names;\n if (obj.push && !location[obj.push]) {\n location[obj.push] = [];\n }\n else if (needsBlank && !location[obj.name]) {\n location[obj.name] = {};\n }\n var keyLocation = obj.push ?\n {} : // blank object that will be pushed\n needsBlank ? location[obj.name] : location; // otherwise, named location or root\n\n attachProperties(content.match(obj.reg), keyLocation, obj.names, obj.name);\n\n if (obj.push) {\n location[obj.push].push(keyLocation);\n }\n};\n\nvar grammar = require('./grammar');\nvar validLine = RegExp.prototype.test.bind(/^([a-z])=(.*)/);\n\nexports.parse = function (sdp) {\n var session = {}\n , media = []\n , location = session; // points at where properties go under (one of the above)\n\n // parse lines we understand\n sdp.split(/(\\r\\n|\\r|\\n)/).filter(validLine).forEach(function (l) {\n var type = l[0];\n var content = l.slice(2);\n if (type === 'm') {\n media.push({rtp: [], fmtp: []});\n location = media[media.length-1]; // point at latest media line\n }\n\n for (var j = 0; j < (grammar[type] || []).length; j += 1) {\n var obj = grammar[type][j];\n if (obj.reg.test(content)) {\n return parseReg(obj, location, content);\n }\n }\n });\n\n session.media = media; // link it up\n return session;\n};\n\nvar paramReducer = function (acc, expr) {\n var s = expr.split(/=(.+)/, 2);\n if (s.length === 2) {\n acc[s[0]] = toIntIfInt(s[1]);\n } else if (s.length === 1 && expr.length > 1) {\n acc[s[0]] = undefined;\n }\n return acc;\n};\n\nexports.parseParams = function (str) {\n return str.split(/;\\s?/).reduce(paramReducer, {});\n};\n\n// For backward compatibility - alias will be removed in 3.0.0\nexports.parseFmtpConfig = exports.parseParams;\n\nexports.parsePayloads = function (str) {\n return str.toString().split(' ').map(Number);\n};\n\nexports.parseRemoteCandidates = function (str) {\n var candidates = [];\n var parts = str.split(' ').map(toIntIfInt);\n for (var i = 0; i < parts.length; i += 3) {\n candidates.push({\n component: parts[i],\n ip: parts[i + 1],\n port: parts[i + 2]\n });\n }\n return candidates;\n};\n\nexports.parseImageAttributes = function (str) {\n return str.split(' ').map(function (item) {\n return item.substring(1, item.length-1).split(',').reduce(paramReducer, {});\n });\n};\n\nexports.parseSimulcastStreamList = function (str) {\n return str.split(';').map(function (stream) {\n return stream.split(',').map(function (format) {\n var scid, paused = false;\n\n if (format[0] !== '~') {\n scid = toIntIfInt(format);\n } else {\n scid = toIntIfInt(format.substring(1, format.length));\n paused = true;\n }\n\n return {\n scid: scid,\n paused: paused\n };\n });\n });\n};\n","var grammar = require('./grammar');\n\n// customized util.format - discards excess arguments and can void middle ones\nvar formatRegExp = /%[sdv%]/g;\nvar format = function (formatStr) {\n var i = 1;\n var args = arguments;\n var len = args.length;\n return formatStr.replace(formatRegExp, function (x) {\n if (i >= len) {\n return x; // missing argument\n }\n var arg = args[i];\n i += 1;\n switch (x) {\n case '%%':\n return '%';\n case '%s':\n return String(arg);\n case '%d':\n return Number(arg);\n case '%v':\n return '';\n }\n });\n // NB: we discard excess arguments - they are typically undefined from makeLine\n};\n\nvar makeLine = function (type, obj, location) {\n var str = obj.format instanceof Function ?\n (obj.format(obj.push ? location : location[obj.name])) :\n obj.format;\n\n var args = [type + '=' + str];\n if (obj.names) {\n for (var i = 0; i < obj.names.length; i += 1) {\n var n = obj.names[i];\n if (obj.name) {\n args.push(location[obj.name][n]);\n }\n else { // for mLine and push attributes\n args.push(location[obj.names[i]]);\n }\n }\n }\n else {\n args.push(location[obj.name]);\n }\n return format.apply(null, args);\n};\n\n// RFC specified order\n// TODO: extend this with all the rest\nvar defaultOuterOrder = [\n 'v', 'o', 's', 'i',\n 'u', 'e', 'p', 'c',\n 'b', 't', 'r', 'z', 'a'\n];\nvar defaultInnerOrder = ['i', 'c', 'b', 'a'];\n\n\nmodule.exports = function (session, opts) {\n opts = opts || {};\n // ensure certain properties exist\n if (session.version == null) {\n session.version = 0; // 'v=0' must be there (only defined version atm)\n }\n if (session.name == null) {\n session.name = ' '; // 's= ' must be there if no meaningful name set\n }\n session.media.forEach(function (mLine) {\n if (mLine.payloads == null) {\n mLine.payloads = '';\n }\n });\n\n var outerOrder = opts.outerOrder || defaultOuterOrder;\n var innerOrder = opts.innerOrder || defaultInnerOrder;\n var sdp = [];\n\n // loop through outerOrder for matching properties on session\n outerOrder.forEach(function (type) {\n grammar[type].forEach(function (obj) {\n if (obj.name in session && session[obj.name] != null) {\n sdp.push(makeLine(type, obj, session));\n }\n else if (obj.push in session && session[obj.push] != null) {\n session[obj.push].forEach(function (el) {\n sdp.push(makeLine(type, obj, el));\n });\n }\n });\n });\n\n // then for each media line, follow the innerOrder\n session.media.forEach(function (mLine) {\n sdp.push(makeLine('m', grammar.m[0], mLine));\n\n innerOrder.forEach(function (type) {\n grammar[type].forEach(function (obj) {\n if (obj.name in mLine && mLine[obj.name] != null) {\n sdp.push(makeLine(type, obj, mLine));\n }\n else if (obj.push in mLine && mLine[obj.push] != null) {\n mLine[obj.push].forEach(function (el) {\n sdp.push(makeLine(type, obj, el));\n });\n }\n });\n });\n });\n\n return sdp.join('\\r\\n') + '\\r\\n';\n};\n","'use strict';\n\n\nvar data = require('./data.json');\n\nfunction escapeRegexp(str) {\n return str.replace(/([.?*+^$[\\]\\\\(){}|-])/g, '\\\\$1');\n}\n\nvar REPLACE_RE = RegExp(Object.keys(data).map(escapeRegexp).join('|'), 'g');\n\nfunction replace_fn(match) {\n return data[match];\n}\n\nfunction unhomoglyph(str) {\n return str.replace(REPLACE_RE, replace_fn);\n}\n\nmodule.exports = unhomoglyph;\n","/*!\n * content-type\n * Copyright(c) 2015 Douglas Christopher Wilson\n * MIT Licensed\n */\n\nconst TEXT_REGEXP = /^[\\u0009\\u0020-\\u007e\\u0080-\\u00ff]*$/;\nconst TOKEN_REGEXP = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;\n\n/**\n * RegExp to match chars that must be quoted-pair in RFC 9110 sec 5.6.4\n */\nconst QUOTE_REGEXP = /[\\\\\"]/g;\n\n/**\n * RegExp to match type in RFC 9110 sec 8.3.1\n *\n * media-type = type \"/\" subtype\n * type = token\n * subtype = token\n */\nconst TYPE_REGEXP =\n /^[!#$%&'*+.^_`|~0-9A-Za-z-]+\\/[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;\n\n/**\n * Null object perf optimization. Faster than `Object.create(null)` and `{ __proto__: null }`.\n */\nconst NullObject = /* @__PURE__ */ (() => {\n const C = function () {};\n C.prototype = Object.create(null);\n return C;\n})() as unknown as { new (): any };\n\n/**\n * The content type object contains a type string and optional parameters.\n */\nexport interface ContentType {\n type: string;\n parameters: Record<string, string>;\n}\n\n/**\n * Format an object into a `Content-Type` header.\n */\nexport function format(obj: Partial<ContentType>): string {\n const { type, parameters } = obj;\n\n if (!type || !TYPE_REGEXP.test(type)) {\n throw new TypeError(`Invalid type: ${type}`);\n }\n\n let result = type;\n\n if (parameters) {\n for (const param of Object.keys(parameters)) {\n if (!TOKEN_REGEXP.test(param)) {\n throw new TypeError(`Invalid parameter name: ${param}`);\n }\n\n result += `; ${param}=${qstring(parameters[param])}`;\n }\n }\n\n return result;\n}\n\n/**\n * Options for parsing a `Content-Type` header.\n */\nexport interface ParseOptions {\n parameters?: boolean;\n}\n\n/**\n * Parse a `Content-Type` header.\n */\nexport function parse(header: string, options?: ParseOptions): ContentType {\n const len = header.length;\n let index = skipOWS(header, 0, len);\n\n const valueStart = index;\n index = skipValue(header, index, len);\n const valueEnd = trailingOWS(header, valueStart, index);\n const type = header.slice(valueStart, valueEnd).toLowerCase();\n const parameters =\n options?.parameters === false\n ? new NullObject()\n : parseParameters(header, index, len);\n\n return { type, parameters };\n}\n\nconst SP = 32; // \" \"\nconst HTAB = 9; // \"\\t\"\nconst SEMI = 59; // \";\"\nconst EQ = 61; // \"=\"\nconst DQUOTE = 34; // '\"'\nconst BSLASH = 92; // \"\\\\\"\n\n/**\n * Parses the parameters of a `Content-Type` header starting at the given index.\n */\nfunction parseParameters(\n header: string,\n index: number,\n len: number,\n): Record<string, string> {\n const parameters: Record<string, string> = new NullObject();\n\n parameter: while (index < len) {\n index = skipOWS(header, index + 1 /* Skip over ; */, len);\n\n const keyStart = index;\n\n while (index < len) {\n const code = header.charCodeAt(index);\n if (code === SEMI) continue parameter;\n\n if (code === EQ) {\n const keyEnd = trailingOWS(header, keyStart, index);\n const key = header.slice(keyStart, keyEnd).toLowerCase();\n\n index = skipOWS(header, index + 1, len);\n\n if (index < len && header.charCodeAt(index) === DQUOTE) {\n index++;\n\n let value = \"\";\n while (index < len) {\n const code = header.charCodeAt(index++);\n if (code === DQUOTE) {\n index = skipValue(header, index, len);\n if (parameters[key] === undefined) parameters[key] = value;\n break;\n }\n\n if (code === BSLASH && index < len) {\n value += header[index++];\n continue;\n }\n\n value += String.fromCharCode(code);\n }\n\n continue parameter;\n }\n\n const valueStart = index;\n index = skipValue(header, index, len);\n\n if (parameters[key] === undefined) {\n const valueEnd = trailingOWS(header, valueStart, index);\n parameters[key] = header.slice(valueStart, valueEnd);\n }\n\n continue parameter;\n }\n\n index++;\n }\n }\n\n return parameters;\n}\n\n/**\n * Skip over characters until a semicolon.\n */\nfunction skipValue(str: string, index: number, len: number): number {\n while (index < len) {\n const char = str.charCodeAt(index);\n if (char === SEMI) break;\n index++;\n }\n return index;\n}\n\n/**\n * Skip optional whitespace (OWS) in an HTTP header value.\n *\n * OWS is defined in RFC 9110 sec 5.6.3 as SP (\" \") or HTAB (\"\\t\").\n */\nfunction skipOWS(header: string, index: number, len: number): number {\n while (index < len) {\n const char = header.charCodeAt(index);\n if (char !== SP && char !== HTAB) break;\n index++;\n }\n return index;\n}\n\n/**\n * Trim optional whitespace (OWS) from the end of a substring.\n *\n * OWS is defined in RFC 9110 sec 5.6.3 as SP (\" \") or HTAB (\"\\t\").\n */\nfunction trailingOWS(header: string, start: number, end: number): number {\n while (end > start) {\n const char = header.charCodeAt(end - 1);\n if (char !== SP && char !== HTAB) break;\n end--;\n }\n return end;\n}\n\n/**\n * Serialize a parameter value.\n */\nfunction qstring(str: string): string {\n if (TOKEN_REGEXP.test(str)) return str;\n if (TEXT_REGEXP.test(str)) return `\"${str.replace(QUOTE_REGEXP, \"\\\\$&\")}\"`;\n\n throw new TypeError(`Invalid parameter value: ${str}`);\n}\n","import objectWithoutPropertiesLoose from \"./objectWithoutPropertiesLoose.js\";\nfunction _objectWithoutProperties(e, t) {\n if (null == e) return {};\n var o,\n r,\n i = objectWithoutPropertiesLoose(e, t);\n if (Object.getOwnPropertySymbols) {\n var n = Object.getOwnPropertySymbols(e);\n for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]);\n }\n return i;\n}\nexport { _objectWithoutProperties as default };","function _objectWithoutPropertiesLoose(r, e) {\n if (null == r) return {};\n var t = {};\n for (var n in r) if ({}.hasOwnProperty.call(r, n)) {\n if (-1 !== e.indexOf(n)) continue;\n t[n] = r[n];\n }\n return t;\n}\nexport { _objectWithoutPropertiesLoose as default };","// base-x encoding / decoding\n// Copyright (c) 2018 base-x contributors\n// Copyright (c) 2014-2018 The Bitcoin Core developers (base58.cpp)\n// Distributed under the MIT software license, see the accompanying\n// file LICENSE or http://www.opensource.org/licenses/mit-license.php.\nfunction base (ALPHABET) {\n if (ALPHABET.length >= 255) { throw new TypeError('Alphabet too long') }\n const BASE_MAP = new Uint8Array(256)\n for (let j = 0; j < BASE_MAP.length; j++) {\n BASE_MAP[j] = 255\n }\n for (let i = 0; i < ALPHABET.length; i++) {\n const x = ALPHABET.charAt(i)\n const xc = x.charCodeAt(0)\n if (BASE_MAP[xc] !== 255) { throw new TypeError(x + ' is ambiguous') }\n BASE_MAP[xc] = i\n }\n const BASE = ALPHABET.length\n const LEADER = ALPHABET.charAt(0)\n const FACTOR = Math.log(BASE) / Math.log(256) // log(BASE) / log(256), rounded up\n const iFACTOR = Math.log(256) / Math.log(BASE) // log(256) / log(BASE), rounded up\n function encode (source) {\n // eslint-disable-next-line no-empty\n if (source instanceof Uint8Array) { } else if (ArrayBuffer.isView(source)) {\n source = new Uint8Array(source.buffer, source.byteOffset, source.byteLength)\n } else if (Array.isArray(source)) {\n source = Uint8Array.from(source)\n }\n if (!(source instanceof Uint8Array)) { throw new TypeError('Expected Uint8Array') }\n if (source.length === 0) { return '' }\n // Skip & count leading zeroes.\n let zeroes = 0\n let length = 0\n let pbegin = 0\n const pend = source.length\n while (pbegin !== pend && source[pbegin] === 0) {\n pbegin++\n zeroes++\n }\n // Allocate enough space in big-endian base58 representation.\n const size = ((pend - pbegin) * iFACTOR + 1) >>> 0\n const b58 = new Uint8Array(size)\n // Process the bytes.\n while (pbegin !== pend) {\n let carry = source[pbegin]\n // Apply \"b58 = b58 * 256 + ch\".\n let i = 0\n for (let it1 = size - 1; (carry !== 0 || i < length) && (it1 !== -1); it1--, i++) {\n carry += (256 * b58[it1]) >>> 0\n b58[it1] = (carry % BASE) >>> 0\n carry = (carry / BASE) >>> 0\n }\n if (carry !== 0) { throw new Error('Non-zero carry') }\n length = i\n pbegin++\n }\n // Skip leading zeroes in base58 result.\n let it2 = size - length\n while (it2 !== size && b58[it2] === 0) {\n it2++\n }\n // Translate the result into a string.\n let str = LEADER.repeat(zeroes)\n for (; it2 < size; ++it2) { str += ALPHABET.charAt(b58[it2]) }\n return str\n }\n function decodeUnsafe (source) {\n if (typeof source !== 'string') { throw new TypeError('Expected String') }\n if (source.length === 0) { return new Uint8Array() }\n let psz = 0\n // Skip and count leading '1's.\n let zeroes = 0\n let length = 0\n while (source[psz] === LEADER) {\n zeroes++\n psz++\n }\n // Allocate enough space in big-endian base256 representation.\n const size = (((source.length - psz) * FACTOR) + 1) >>> 0 // log(58) / log(256), rounded up.\n const b256 = new Uint8Array(size)\n // Process the characters.\n while (psz < source.length) {\n // Find code of next character\n const charCode = source.charCodeAt(psz)\n // Base map can not be indexed using char code\n if (charCode > 255) { return }\n // Decode character\n let carry = BASE_MAP[charCode]\n // Invalid character\n if (carry === 255) { return }\n let i = 0\n for (let it3 = size - 1; (carry !== 0 || i < length) && (it3 !== -1); it3--, i++) {\n carry += (BASE * b256[it3]) >>> 0\n b256[it3] = (carry % 256) >>> 0\n carry = (carry / 256) >>> 0\n }\n if (carry !== 0) { throw new Error('Non-zero carry') }\n length = i\n psz++\n }\n // Skip leading zeroes in b256.\n let it4 = size - length\n while (it4 !== size && b256[it4] === 0) {\n it4++\n }\n const vch = new Uint8Array(zeroes + (size - it4))\n let j = zeroes\n while (it4 !== size) {\n vch[j++] = b256[it4++]\n }\n return vch\n }\n function decode (string) {\n const buffer = decodeUnsafe(string)\n if (buffer) { return buffer }\n throw new Error('Non-base' + BASE + ' character')\n }\n return {\n encode,\n decodeUnsafe,\n decode\n }\n}\nexport default base\n","import basex from 'base-x';\nvar ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';\nexport default basex(ALPHABET);\n","const objectToString = Object.prototype.toString;\n\nconst isError = value => objectToString.call(value) === '[object Error]';\n\nconst errorMessages = new Set([\n\t'network error', // Chrome\n\t'NetworkError when attempting to fetch resource.', // Firefox\n\t'The Internet connection appears to be offline.', // Safari 16\n\t'Network request failed', // `cross-fetch`\n\t'fetch failed', // Undici (Node.js)\n\t'terminated', // Undici (Node.js)\n\t' A network error occurred.', // Bun (WebKit)\n\t'Network connection lost', // Cloudflare Workers (fetch)\n]);\n\nexport default function isNetworkError(error) {\n\tconst isValid = error\n\t\t&& isError(error)\n\t\t&& error.name === 'TypeError'\n\t\t&& typeof error.message === 'string';\n\n\tif (!isValid) {\n\t\treturn false;\n\t}\n\n\tconst {message, stack} = error;\n\n\t// Safari 17+ has generic message but no stack for network errors\n\tif (message === 'Load failed' || (message.startsWith('Load failed (') && message.endsWith(')'))) {\n\t\treturn stack === undefined\n\t\t\t// Sentry adds its own stack trace to the fetch error, so also check for that\n\t\t\t|| '__sentry_captured__' in error;\n\t}\n\n\t// Deno network errors start with specific text\n\tif (message.startsWith('error sending request for url')) {\n\t\treturn true;\n\t}\n\n\t// Chrome: exact \"Failed to fetch\" or with hostname: \"Failed to fetch (example.com)\"\n\tif (message === 'Failed to fetch' || (message.startsWith('Failed to fetch (') && message.endsWith(')'))) {\n\t\treturn true;\n\t}\n\n\t// Standard network error messages\n\treturn errorMessages.has(message);\n}\n","import isNetworkError from 'is-network-error';\n\nfunction validateRetries(retries) {\n\tif (typeof retries === 'number') {\n\t\tif (retries < 0) {\n\t\t\tthrow new TypeError('Expected `retries` to be a non-negative number.');\n\t\t}\n\n\t\tif (Number.isNaN(retries)) {\n\t\t\tthrow new TypeError('Expected `retries` to be a valid number or Infinity, got NaN.');\n\t\t}\n\t} else if (retries !== undefined) {\n\t\tthrow new TypeError('Expected `retries` to be a number or Infinity.');\n\t}\n}\n\nfunction validateNumberOption(name, value, {min = 0, allowInfinity = false} = {}) {\n\tif (value === undefined) {\n\t\treturn;\n\t}\n\n\tif (typeof value !== 'number' || Number.isNaN(value)) {\n\t\tthrow new TypeError(`Expected \\`${name}\\` to be a number${allowInfinity ? ' or Infinity' : ''}.`);\n\t}\n\n\tif (!allowInfinity && !Number.isFinite(value)) {\n\t\tthrow new TypeError(`Expected \\`${name}\\` to be a finite number.`);\n\t}\n\n\tif (value < min) {\n\t\tthrow new TypeError(`Expected \\`${name}\\` to be \\u2265 ${min}.`);\n\t}\n}\n\nfunction validateFunctionOption(name, value) {\n\tif (value === undefined) {\n\t\treturn;\n\t}\n\n\tif (typeof value !== 'function') {\n\t\tthrow new TypeError(`Expected \\`${name}\\` to be a function.`);\n\t}\n}\n\nexport class AbortError extends Error {\n\tconstructor(message) {\n\t\tsuper();\n\n\t\tif (message instanceof Error) {\n\t\t\tthis.originalError = message;\n\t\t\t({message} = message);\n\t\t} else {\n\t\t\tthis.originalError = new Error(message);\n\t\t\tthis.originalError.stack = this.stack;\n\t\t}\n\n\t\tthis.name = 'AbortError';\n\t\tthis.message = message;\n\t}\n}\n\nfunction calculateDelay(retriesConsumed, options) {\n\tconst attempt = Math.max(1, retriesConsumed + 1);\n\tconst random = options.randomize ? (Math.random() + 1) : 1;\n\n\tlet timeout = Math.round(random * options.minTimeout * (options.factor ** (attempt - 1)));\n\ttimeout = Math.min(timeout, options.maxTimeout);\n\n\treturn timeout;\n}\n\nfunction calculateRemainingTime(start, max) {\n\tif (!Number.isFinite(max)) {\n\t\treturn max;\n\t}\n\n\treturn max - (performance.now() - start);\n}\n\nasync function delayForRetry(delay, options) {\n\tif (delay <= 0) {\n\t\treturn;\n\t}\n\n\tawait new Promise((resolve, reject) => {\n\t\tconst onAbort = () => {\n\t\t\tclearTimeout(timeoutToken);\n\t\t\toptions.signal?.removeEventListener('abort', onAbort);\n\t\t\treject(options.signal.reason);\n\t\t};\n\n\t\tconst timeoutToken = setTimeout(() => {\n\t\t\toptions.signal?.removeEventListener('abort', onAbort);\n\t\t\tresolve();\n\t\t}, delay);\n\n\t\tif (options.unref) {\n\t\t\ttimeoutToken.unref?.();\n\t\t}\n\n\t\toptions.signal?.addEventListener('abort', onAbort, {once: true});\n\t});\n}\n\nasync function onAttemptFailure({error, attemptNumber, retriesConsumed, startTime, options}) {\n\tconst normalizedError = error instanceof Error\n\t\t? error\n\t\t: new TypeError(`Non-error was thrown: \"${error}\". You should only throw errors.`);\n\n\tif (normalizedError instanceof AbortError) {\n\t\tthrow normalizedError.originalError;\n\t}\n\n\tconst retriesLeft = Number.isFinite(options.retries)\n\t\t? Math.max(0, options.retries - retriesConsumed)\n\t\t: options.retries;\n\n\tconst maxRetryTime = options.maxRetryTime ?? Number.POSITIVE_INFINITY;\n\tconst delayTime = calculateDelay(retriesConsumed, options);\n\tconst remainingTimeBeforeCallbacks = calculateRemainingTime(startTime, maxRetryTime);\n\n\tif (remainingTimeBeforeCallbacks <= 0) {\n\t\tconst context = Object.freeze({\n\t\t\terror: normalizedError,\n\t\t\tattemptNumber,\n\t\t\tretriesLeft,\n\t\t\tretriesConsumed,\n\t\t\tretryDelay: 0,\n\t\t});\n\n\t\tawait options.onFailedAttempt(context);\n\n\t\tthrow normalizedError;\n\t}\n\n\tconst consumeRetryContext = Object.freeze({\n\t\terror: normalizedError,\n\t\tattemptNumber,\n\t\tretriesLeft,\n\t\tretriesConsumed,\n\t\tretryDelay: retriesLeft > 0 ? delayTime : 0,\n\t});\n\n\tconst consumeRetry = await options.shouldConsumeRetry(consumeRetryContext);\n\tconst effectiveDelay = consumeRetry && retriesLeft > 0 ? delayTime : 0;\n\tconst context = Object.freeze({\n\t\terror: normalizedError,\n\t\tattemptNumber,\n\t\tretriesLeft,\n\t\tretriesConsumed,\n\t\tretryDelay: effectiveDelay,\n\t});\n\n\tawait options.onFailedAttempt(context);\n\n\tif (calculateRemainingTime(startTime, maxRetryTime) <= 0) {\n\t\tthrow normalizedError;\n\t}\n\n\tconst remainingTime = calculateRemainingTime(startTime, maxRetryTime);\n\n\tif (remainingTime <= 0 || retriesLeft <= 0) {\n\t\tthrow normalizedError;\n\t}\n\n\tif (normalizedError instanceof TypeError && !isNetworkError(normalizedError)) {\n\t\tthrow normalizedError;\n\t}\n\n\tif (!await options.shouldRetry(context)) {\n\t\tthrow normalizedError;\n\t}\n\n\tconst remainingTimeAfterShouldRetry = calculateRemainingTime(startTime, maxRetryTime);\n\n\tif (remainingTimeAfterShouldRetry <= 0) {\n\t\tthrow normalizedError;\n\t}\n\n\tif (!consumeRetry) {\n\t\toptions.signal?.throwIfAborted();\n\t\treturn false;\n\t}\n\n\tconst finalDelay = Math.min(effectiveDelay, remainingTimeAfterShouldRetry);\n\n\toptions.signal?.throwIfAborted();\n\n\tawait delayForRetry(finalDelay, options);\n\n\toptions.signal?.throwIfAborted();\n\n\treturn true;\n}\n\nexport default async function pRetry(input, options = {}) {\n\toptions = {...options};\n\n\tvalidateRetries(options.retries);\n\n\tif (Object.hasOwn(options, 'forever')) {\n\t\tthrow new Error('The `forever` option is no longer supported. For many use-cases, you can set `retries: Infinity` instead.');\n\t}\n\n\toptions.retries ??= 10;\n\toptions.factor ??= 2;\n\toptions.minTimeout ??= 1000;\n\toptions.maxTimeout ??= Number.POSITIVE_INFINITY;\n\toptions.maxRetryTime ??= Number.POSITIVE_INFINITY;\n\toptions.randomize ??= false;\n\toptions.onFailedAttempt ??= () => {};\n\toptions.shouldRetry ??= () => true;\n\toptions.shouldConsumeRetry ??= () => true;\n\n\t// Validate numeric options and normalize edge cases\n\tvalidateFunctionOption('onFailedAttempt', options.onFailedAttempt);\n\tvalidateFunctionOption('shouldRetry', options.shouldRetry);\n\tvalidateFunctionOption('shouldConsumeRetry', options.shouldConsumeRetry);\n\tvalidateNumberOption('factor', options.factor, {min: 0, allowInfinity: false});\n\tvalidateNumberOption('minTimeout', options.minTimeout, {min: 0, allowInfinity: false});\n\tvalidateNumberOption('maxTimeout', options.maxTimeout, {min: 0, allowInfinity: true});\n\tvalidateNumberOption('maxRetryTime', options.maxRetryTime, {min: 0, allowInfinity: true});\n\n\t// Treat non-positive factor as 1 to avoid zero backoff or negative behavior\n\tif (!(options.factor > 0)) {\n\t\toptions.factor = 1;\n\t}\n\n\toptions.signal?.throwIfAborted();\n\n\tlet attemptNumber = 0;\n\tlet retriesConsumed = 0;\n\tconst startTime = performance.now();\n\n\twhile (Number.isFinite(options.retries) ? retriesConsumed <= options.retries : true) {\n\t\tattemptNumber++;\n\n\t\ttry {\n\t\t\toptions.signal?.throwIfAborted();\n\n\t\t\tconst result = await input(attemptNumber);\n\n\t\t\toptions.signal?.throwIfAborted();\n\n\t\t\treturn result;\n\t\t} catch (error) {\n\t\t\tif (await onAttemptFailure({\n\t\t\t\terror,\n\t\t\t\tattemptNumber,\n\t\t\t\tretriesConsumed,\n\t\t\t\tstartTime,\n\t\t\t\toptions,\n\t\t\t})) {\n\t\t\t\tretriesConsumed++;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Should not reach here, but in case it does, throw an error\n\tthrow new Error('Retry attempts exhausted without throwing an error.');\n}\n\nexport function makeRetriable(function_, options) {\n\treturn function (...arguments_) {\n\t\treturn pRetry(() => function_.apply(this, arguments_), options);\n\t};\n}\n"],"names":["KnownMembership","ReceiptType","isSendDelayedEventRequestOpts","opts","parent_delay_id","delay","UpdateDelayedEventAction","SearchOrderBy","NamespacedValue","constructor","stable","unstable","this","Error","name","altName","names","push","matches","val","findIn","obj","includedIn","arr","included","includes","ServerControlledNamespacedValue","args","super","_defineProperty","setPreferUnstable","preferUnstable","UnstableValue","ReEmitter","target","WeakMap","reEmit","source","eventNames","reEmittersByEvent","reEmitters","get","Map","set","eventName","has","forSource","listenerCount","emit","on","stopReEmitting","off","delete","size","TypedReEmitter","ToDeviceMessageQueue","client","logger","async","retryTimeout","clearTimeout","sending","running","headBatch","debug","store","getOldestToDeviceBatch","sendBatch","removeToDeviceBatch","id","retryAttempts","e","retryDelay","MatrixScheduler","RETRY_BACKOFF_RATELIMIT","Math","floor","httpStatus","error","info","setTimeout","sendQueue","state","oldState","SyncState","Syncing","start","ClientEvent","Sync","onResumedSync","stop","removeListener","queueBatch","batch","batches","i","length","batchWithTxnId","eventType","slice","txnId","makeTxnId","msgmap","map","msg","userId","deviceId","payload","ToDeviceMessageId","saveToDeviceBatches","contentMap","MapWithDefault","item","getOrCreate","sendToDevice","toBase64","uint8Array","options","base64","btoa","reduce","acc","current","String","fromCharCode","omitPadding","replace","alphabet","encodeBase64","encodeUnpaddedBase64","encodeUnpaddedBase64Url","decodeBase64","Uint8Array","fromBase64","from","atob","c","charCodeAt","lastChunkHandling","CapabilityPoller","TypedEventEmitter","http","cached","fetch","clearTimeouts","refreshTimeout","globalThis","poll","deepCompare","howLong","random","warn","then","getCached","clearInterval","undefined","DecryptionError","code","details","detailedString","err","result","message","Object","keys","k","join","detailedStringForDecryptionError","serverNameRegex","mediaIdRegex","getHttpUriForMxc","baseUrl","mxc","width","height","resizeMethod","allowDirectLinks","allowRedirects","useAuthentication","animated","startsWith","serverName","mediaId","rest","split","exec","validateServerName","validateMediaId","prefix","verb","url","URL","searchParams","round","toString","JSON","stringify","href","CryptoEvent","deriveRecoveryKeyFromPassphrase","passphrase","salt","iterations","numBits","crypto","subtle","TextEncoder","key","importKey","encode","keybits","deriveBits","hash","sha256","plaintext","utf8","digest","eventMapperFor","preventReEmit","Boolean","decrypt","mapper","plainOldJsObject","room","getRoom","room_id","event","state_key","findEventById","event_id","status","MatrixEvent","setUnsigned","_objectSpread","getUnsigned","unsigned","bundledEdit","getServerAggregatedRelation","RelationType","Replace","content","replacement","makeReplaced","thread","findThreadForEvent","setThread","isEncrypted","reEmitter","MatrixEventEvent","Decrypted","decryptEventIfNeeded","Replaced","VisibilityChange","BeforeRedaction","ServerSupport","Feature","featureSupportResolver","Thread","unstablePrefixes","matrixVersion","ThreadUnreadNotifications","LoginTokenRequest","RelationBasedRedactions","AccountDataDeletion","RelationsRecursion","IntentionalMentions","buildFeatureSupportMap","versions","supportMap","feature","supportCondition","entries","_versions$versions$in","_versions$versions","_supportCondition$uns","_supportCondition$uns2","supportMatrixVersion","supportUnstablePrefixes","every","unstablePrefix","_versions$unstable_fe","unstable_features","Stable","Unstable","Unsupported","FilterComponent","filterJson","check","_event$getUnsigned","_bundledRelationships","bundledRelationships","relations","relationSenders","THREAD_RELATION_TYPE","current_user_participated","checkFields","getRoomId","getSender","getType","getContent","toJSON","fromEntries","types","not_types","rooms","not_rooms","senders","not_senders","contains_url","FILTER_RELATED_BY_SENDERS","FILTER_RELATED_BY_REL_TYPES","filter","_key","value","roomId","sender","containsUrl","relationTypes","literalKeys","v","actualValue","filterValue","endsWith","typePrefix","matchesWildcard","matchFunc","notName","disallowedValues","some","allowedValues","containsUrlFilter","relationTypesFilter","arrayMatchesFilter","relationSendersFilter","values","events","limit","HTTPError","httpHeaders","isRateLimitError","getRetryAfterMs","_this$httpHeaders","retryAfter","test","ms","Number","parseInt","isFinite","date","Date","toUTCString","getTime","now","MatrixError","errorJson","errcode","data","headerValue","isInteger","retry_after_ms","asWidgetApiErrorData","_this$httpStatus","_this$url","_this$errcode","_this$data$error","headers","http_status","http_headers","response","fromWidgetApiErrorData","Headers","safeGetRetryAfterMs","defaultMs","_error$getRetryAfterM","ConnectionError","cause","TokenRefreshError","_cause$message","TokenRefreshLogoutError","_cause$message2","MatrixSafetyErrorCode","MatrixSafetyError","props","body","harms","Set","Array","isArray","expiry","TokenRefreshOutcome","TokenRefresher","prepareForRequest","refreshIfNeeded","accessToken","refreshToken","latestTokenRefreshExpiry","tokenRefreshPromise","_handleUnknownToken","handleUnknownToken","snapshot","attempt","Logout","_this$tokenRefreshPro","doTokenRefresh","Success","_this$opts$logger","tokenRefreshFunction","sleep","min","_this$opts$logger2","_this$opts$logger3","_this$opts$logger5","_this$opts$logger4","Failure","FetchHttpApi","eventEmitter","_opts$useAuthorizatio","AbortController","checkObjectHasKeys","onlyData","useAuthorizationHeader","tokenRefresher","abort","abortController","resource","fetchFn","setIdBaseUrl","idBaseUrl","idServerRequest","method","path","params","queryParams","Method","Get","fullUri","getUrl","json","Authorization","requestOtherUrl","authedRequest","paramOpts","doAuthedRequest","deepCopy","abortSignal","requestSnapshot","access_token","request","outcome","inhibitLogoutEmit","HttpApiEvent","SessionLoggedOut","NoConsent","consent_uri","_opts$localTimeoutMs","_opts$keepAlive","_body$constructor","rawResponseBody","urlForLogs","sanitizeUrlForLogs","assign","jsonResponse","timeout","localTimeoutMs","keepAlive","signals","signal","timeoutSignal","cleanup","anySignal","cacheMode","res","mode","redirect","referrer","referrerPolicy","cache","credentials","keepalive","priority","ok","parseErrorResponse","text","blob","asUrl","sanitizedQs","URLSearchParams","append","sanitizedQsString","sanitizedQsUrlPiece","origin","pathname","baseUrlWithFallback","baseUrlWithoutTrailingSlash","extraParams","mergedParams","encodeParams","ClientPrefix","IdentityPrefix","MediaPrefix","controller","removeEventListener","onAbort","aborted","addEventListener","_contentType","_contentType2","isXhr","getAllResponseHeaders","trim","header","colonIdx","indexOf","substring","contentType","parseContentType","getResponseContentType","type","errorBody","parse","responseURL","retryNetworkOperation","maxAttempts","callback","attempts","lastConnectionError","pow","log","calculateRetryBackoff","retryConnectionError","exists","indexedDB","dbName","Promise","resolve","reject","req","open","onupgradeneeded","onblocked","onsuccess","close","deleteDatabase","onerror","getEncryptionKeyMapKey","membership","memberId","KeyTransportEvents","MembershipManagerEvent","Status","ActionScheduler","membershipLoopHandler","parentLogger","update","rootLogger","getChild","actions","_actions","startWithJoin","ts","MembershipActionType","SendDelayedEvent","sort","a","b","nextAction","wakeupUpdate","wakeupPromise","wakeup","race","handlerResult","splice","actionUpdate","insert","initiateJoin","_this$wakeup","call","initiateLeave","_this$wakeup2","SendScheduledDelayedLeaveEvent","isLivekitTransportConfig","object","MEMBERSHIP_STICKY_DURATION_MS","createInsertActionUpdate","offset","createReplaceActionUpdate","MembershipManager","isActivated","activated","isJoined","fociPreferred","multiSfuFocus","onError","scheduler","rtcTransport","leavePromiseResolvers","oldStatus","defaultState","catch","finally","_this$leavePromiseRes","StatusChanged","leave","withResolvers","_this$leavePromiseRes2","promise","onRTCSessionMemberUpdate","memberships","_ownMembership","find","m","isMyMembership","sendingMembershipActions","SendJoinEvent","hasMemberStateEvent","updateCallIntent","callIntent","ownMembership","sendJoinEvent","joinConfig","slotDescription","_unstable_sendDelayedStateEvent","delayedLeaveEventDelayMs","EventType","GroupCallMemberPrefix","stateKey","myMembership","sendStateEvent","getUserId","getDeviceId","makeMembershipStateKey","delayId","startTime","rateLimitRetries","networkErrorRetries","expireUpdateIterations","probablyLeft","networkErrorRetryMs","_this$joinConfig$netw","_this$joinConfig","membershipEventExpiryMs","_this$joinConfig$memb","_this$joinConfig2","DEFAULT_EXPIRE_DURATION","membershipEventExpiryHeadroomMs","_this$joinConfig$memb2","_this$joinConfig3","computeNextExpiryActionTs","iteration","_ref","_this$delayedLeaveEve","_this$joinConfig4","delayedLeaveEventDelayMsOverride","delayedLeaveEventRestartMs","_this$joinConfig$dela","_this$joinConfig5","maximumRateLimitRetryCount","_this$joinConfig$maxi","_this$joinConfig6","maximumNetworkErrorRetryCount","_this$joinConfig$maxi2","_this$joinConfig7","delayedLeaveEventRestartLocalTimeoutMs","_this$joinConfig$dela2","_this$joinConfig8","cancelKnownDelayIdBeforeSendDelayedEvent","sendOrResendDelayedLeaveEvent","RestartDelayedEvent","restartDelayedEvent","sendScheduledDelayedLeaveEventOrFallbackToSendLeaveEvent","SendLeaveEvent","UpdateExpiry","updateExpiryOnJoinedEvent","sendFallbackLeaveEvent","clientSendDelayedDisconnectMembership","expectedServerDelayLeaveTs","setAndEmitProbablyLeft","resetRateLimitCounter","setAndEmitDelayId","delay_id","repeatActionType","manageMaxDelayExceededSituation","actionUpdateFromErrors","isUnsupportedDelayedEndpoint","_unstable_cancelScheduledDelayedEvent","isNotFoundError","ProbablyLeft","DelayIdChanged","durationUntilServerDelayedLeave","abortPromise","_","AbortError","_unstable_restartScheduledDelayedEvent","_unstable_sendScheduledDelayedEvent","clientSendMembership","makeMyMembership","nextExpireUpdateIteration","localUserId","localDeviceId","application","getVersion","expires","_this$fociPreferred","_this$fociPreferred2","needsEmptyStringRoomFix","focusObjects","focus_active","focus_selection","foci_preferred","call_id","scope","device_id","membershipID","created_ts","createdTs","maxDelayAllowed","updateLimit","actionUpdateFromRateLimitError","updateNetwork","actionUpdateFromNetworkErrorRetry","_this$state$rateLimit","resendDelay","_this$state$networkEr","retries","retryDurationString","retryCounterString","retryDuration","UnsupportedDelayedEventsEndpointError","Connecting","Connected","Disconnecting","t","Unknown","Disconnected","StickyEventMembershipManager","clientWithSticky","sessionDescription","_unstable_sendStickyDelayedEvent","RTCMembership","msc4354_sticky_key","_unstable_sendStickyEvent","_StickyEventMembershi","nameMap","livekitTransport","relationObject","eventId","rel_type","Reference","slot_id","computeSlotId","rtc_transports","livekit_service_url","member","user_id","RTCEncryptionManager","getMemberships","transport","onEncryptionKeysChanged","rtcBackendIdProvider","OutdatedKeyFilter","keyBase64Encoded","index","timestamp","_this$logger2","_this$logger","manageMediaKeys","candidateInboundSession","keyIndex","creationTS","_this$logger3","keyBuffer","isOutdated","addKeyToParticipant","rtcIdentityProvider","computeRtcIdentityRaw","getOwnRtcBackendIdentity","ownRtcBackendIdentityCache","useHashedRtcBackendIdentity","_this$logger4","getEncryptionKeys","participantKeyRings","checkKeysWithoutMatchingRTCMembership","keyInfoTemp","keysWithoutMatchingRTCMembership","forEach","keyInfo","fullMembership","_this$logger5","addKeyToParticipantWithBackendIdentity","rtcBackendIdentity","mapKey","_joinConfig$manageMed","_joinConfig$unstableS","_joinConfig$useKeyDel","_joinConfig$keyRotati","_this$logger6","unstableSendStickyEvents","useKeyDelay","keyRotationGracePeriodMs","ReceivedKeys","onNewKeyReceived","clear","ensureKeyDistribution","_this$logger7","_this$logger0","currentKeyDistributionPromise","rolloutOutboundKey","_this$logger8","_this$logger9","needToEnsureKeyAgain","onMembershipsUpdate","oldMemberships","_this$logger1","trace","_this$outboundSession","_this$outboundSession2","outboundSession","firstKey","generateRandomKey","sharedWith","keyId","toShareWith","membershipTs","alreadySharedWith","x","o","anyLeft","anyJoined","outboundKey","toDistributeTo","hasKeyChanged","newOutboundKey","createNewOutboundSession","keyAge","_this$logger10","_this$logger11","_this$logger12","_this$logger13","_this$logger14","_this$logger15","sendKey","_this$logger16","_this$logger17","nextKeyIndex","getRandomValues","NotSupportedError","ToDeviceKeyTransport","setParentLogger","statistics","CallEncryptionKeysPrefix","getValidEventContent","receiveCallKeyEvent","ToDeviceEvent","onToDeviceEvent","members","claimed_device_id","session","sent_ts","targets","encryptAndSendToDevice","counters","roomEventEncryptionKeysSent","fromUser","_content$member$id","roomEventEncryptionKeysReceived","age","totals","roomEventEncryptionKeysReceivedTotalAge","hardcodedMemberIdAlternative","MatrixRTCMembershipParseError","AggregateError","errors","checkSessionsMembershipData","_data$focus_active","f","jsonStr","hashBuffer","checkRtcMembershipData","_data$application","_data$sticky_key","expectedSlotPrefix","slotIdToDescription","ex","MXID_PATTERN","sticky_key","rel","_this$tsBuffer$get","tsBuffer","latestTimestamp","slotId","unexpectedAdditionalValues","MSC3089Branch","indexEvent","directory","getStateKey","isActive","version","_this$indexEvent$getC","UNSTABLE_MSC3089_BRANCH","redactEvent","nextVersion","getVersionHistory","getName","setName","isLocked","setLocked","locked","getFileInfo","file","getFileEvent","getOriginalContent","httpUrl","mxcUrlToHttp","getUnfilteredTimelineSet","getLiveTimeline","getState","EventTimeline","BACKWARDS","paginationToken","scrollback","createNewVersion","encryptedContents","additionalContent","fileEventResponse","createFile","active","fileHistory","timelineEvents","getEvents","reverse","childEvent","parentEvent","replacingEventId","getId","branch","getFile","DEFAULT_TREE_POWER_LEVELS_TEMPLATE","invite","kick","ban","redact","state_default","events_default","users_default","RoomPowerLevels","RoomHistoryVisibility","RoomTombstone","RoomEncryption","RoomName","RoomMessage","RoomMessageEncrypted","Sticker","users","TreePermissions","MSC3089TreeSpace","isTopLevel","parentEvents","currentState","getStateEvents","SpaceParent","_e$getContent","andSubspaces","promises","retryInvite","getDirectories","d","all","simpleRetryOperation","setPermissions","role","_pls$events","currentPls","pls","viewLevel","editLevel","adminLevel","Viewer","Editor","Owner","getPermissions","_pls$events2","_pls$users","userLevel","createDirectory","unstableCreateFileTree","SpaceChild","via","getDomain","trees","children","child","tree","unstableGetFileTreeSpace","getDirectory","r","subdirectories","dir","kickMemberships","Invite","Knock","Join","RoomMember","getOrderedChildren","ordered","order","lexicographicCompare","_roomA$currentState$g","_roomA$currentState$g2","_roomB$currentState$g","_roomB$currentState$g2","roomA","roomB","createTsA","RoomCreate","getTs","createTsB","getParentRoom","parent","parentRoom","getOrder","findIndex","setOrder","_currentChild$getCont2","max","movingUp","prev","next","newOrder","DEFAULT_ALPHABET","ensureBeforeIsSane","nextString","startOrder","endOrder","averageBetweenStrings","prevString","lastOrder","_currentChild$getCont","currentChild","content_uri","uploadContent","includeFilename","fileContent","msgtype","MsgType","File","sendMessage","UNSTABLE_MSC3089_LEAF","fileEventId","listFiles","listAllFiles","_this$room$currentSta","compareEventOrdering","leftEventId","rightEventId","leftEvent","rightEvent","isLeftEventInMainTimeline","inMainTimelineForReceipt","isRightEventInMainTimeline","timelineSet","compareSameTimeline","leftTimeline","getTimelineForEvent","rightTimeline","guessOrderBasedOnTimestamp","compareEventsInMainTimeline","leftEventThreadId","threadIdForReceipt","rightEventThreadId","leftThread","getThread","compareEventsInThreads","leftTs","rightTs","EventContext","ourEvent","Direction","Backward","Forward","timeline","getEvent","ourEventIndex","getTimeline","getOurEventIndex","getPaginateToken","backwards","paginateTokens","setPaginateToken","token","addEvents","atStart","concat","EventStatus","POLICIES_ACCOUNT_EVENT_TYPE","IGNORE_INVITES_ACCOUNT_EVENT_KEY","PolicyRecommendation","PolicyScope","synthesizeReceipt","receiptType","unthreaded","thread_id","Receipt","ReadReceipt","getReadReceiptForUserId","ignoreSynthesized","Read","_this$receipts$get$ge","_this$receipts$get","realReceipt","syntheticReceipt","receipts","compareReceipts","_this$getUnfilteredTi","getEventReadUpTo","latestReceipt","getLatestReceipt","receiptPointsAtConsistentEvent","receipt","_receipt$data","MAIN_ROOM_TIMELINE","threadRootId","_ref2","publicReadReceipt","privateReadReceipt","ReadPrivate","comparison","addReceiptToStructure","synthetic","_pair$ReceiptPairSynt2","_pair$ReceiptPairSynt3","receiptTypesMap","pair","existingReceipt","_pair$ReceiptPairSynt","wrappedReceipt","ordering","preferSynthetic","cachedReceipt","receiptCacheByEventId","previousEventId","getReceiptsForEvent","fixupNotifications","lastEvent","setUnread","NotificationCountType","Total","Highlight","addLocalEchoReceipt","addReceipt","getUsersReadUpTo","isSupportedReceiptType","RelationsContainer","getChildEventsForEvent","relationType","_this$relations$get","getAllChildEventsForEvent","parentEventId","_this$relations$get2","relationsForEvent","relationsRecord","getRelations","aggregateParentEvent","relationsWithRelType","relationsWithEventType","setTargetEvent","aggregateChildEvent","isRedacted","CANCELLED","relation","getRelation","onEventDecrypted","isDecryptionFailure","once","isBeingDecrypted","shouldAttemptDecryption","relatesToEventId","_this$room","_timelineSet$findEven","Relations","relatesToEvent","getPendingEvent","addEvent","RoomReceipts","danglingReceipts","remove","danglingReceipt","threadedReceipts","unthreadedReceipts","ThreadedReceipts","ReceiptsByUser","DanglingReceipts","RoomEvent","Timeline","onTimelineEvent","add","receiptContent","eventReceipt","receiptsByUser","DanglingReceipt","hasUserReadEvent","isAfterOrSame","threadId","threaded","userSentLatestEventInThread","_this$room$getThread","ReceiptInfo","UserReceipts","real","receiptInfo","_this$synthetic","getByType","userReceipts","isAfter","_this$data$get","_this$data$get2","createFn","found","created","RoomRetentionPolicy","retentionService","hadRetentionPeriod","maxRetention","recalculateRetention","timelineUpdated","_serverPolicy$policie","_unstableEvent$getCon","_serverPolicy$policie2","_serverPolicy$limits2","unstableEvent","roomState","ROOM_RETENTION_TYPE","stableEvent","serverPolicy","serverRoomPolicy","policies","roomStatePolicy","validatePolicy","max_lifetime","maxLifetime","_serverPolicy$limits","_serverPolicy$limits$","_serverPolicy$limits$2","limits","MAX_SAFE_INTEGER","processTimeline","scheduleTimelineCheck","nextTs","retentionTimeout","RoomStateEvent","Events","handleRetentionUpdate","shouldEventBeRetained","ev","expireBefore","expiredEvents","earliestExpiringEvent","tryApplyRedaction","RoomRedaction","redacts","reason","origin_server_ts","removeEventsFromRoom","RoomSummary","isValidAuthMetadata","authMetadata","isRecord","hasRequiredStringProperty","hasOptionalStringProperty","optionalStringArrayProperty","requiredArrayValue","OAuthGrantType","AuthorizationCode","RefreshToken","OAuth2Error","RULEKINDS_IN_ORDER","PushRuleKind","Override","ContentSpecific","RoomSpecific","SenderSpecific","Underride","DEFAULT_OVERRIDE_RULES","rule_id","default","enabled","conditions","kind","ConditionKind","EventPropertyIs","SenderNotificationPermission","PushRuleActionName","Notify","set_tweak","TweakName","EventMatch","pattern","DontNotify","RoomServerAcl","UserDefinedRules","Symbol","EXPECTED_DEFAULT_OVERRIDE_RULE_IDS","RuleId","Master","SuppressNotices","InviteToSelf","MemberEvent","IsUserMention","ContainsDisplayName","IsRoomMention","AtRoomNotification","Tombstone","DEFAULT_UNDERRIDE_RULES","CallStarted","Sound","EXPECTED_DEFAULT_UNDERRIDE_RULE_IDS","IncomingCall","EncryptedDM","DM","Message","EncryptedMessage","mergeRulesWithDefaults","incomingRules","defaultRules","orderedRuleIds","incomingDefaultRules","rule","incomingCustomRules","insertDefaultPushRule","ruleId","newRules","nextExpectedRuleIdIndex","ruleIndex","PushProcessor","actionListToActionsObject","actionList","actionObj","notify","tweaks","action","rewriteDefaultRules","global","override","underride","getPushRuleGlobRegex","alignToWordBoundary","flags","suffix","cacheKey","cachedGlobToRegex","RegExp","globToRegexp","updateCachedPushRuleKeys","toRemoveKeys","parsedKeys","ruleset","condition","partsForDottedKey","matchingRuleFromKindSet","kindset","rawrule","templateRuleToRaw","ruleMatchesEvent","tprule","eventFulfillsCondition","cond","eventFulfillsEventMatchCondition","eventFulfillsEventPropertyIsCondition","EventPropertyContains","eventFulfillsEventPropertyContains","eventFulfillsDisplayNameCondition","RoomMemberCount","eventFulfillsRoomMemberCountCondition","eventFulfillsSenderNotifPermCondition","CallStartedPrefix","eventFulfillsCallStartedCondition","notifLevelKey","mayTriggerNotifOfType","is","memberCount","getJoinedMemberCount","match","ineq","rhs","isNaN","_room$currentState","getClearContent","getMember","displayName","pat","escapeRegExp","search","valueForDottedKey","regex","_cond","getPrevContent","str","part","escaped","parts","firstPart","currentIndex","isNullOrUndefined","matchingRuleForEventWithRulesets","rulesets","getSafeUserId","pushActionsForEventAndRulesets","highlight","_rule$conditions","supportsIntentionalMentions","ContainsUserName","actionsForEvent","pushRules","actionsAndRuleForEvent","getPushRuleById","_result$rule","getPushRuleAndKindById","_this$client$pushRule","realCallbackKey","count","callbackList","debuglog","func","delayMs","runAt","idx","array","mid","binarySearch","el","scheduleRealCallback","first","runCallbacks","callbacksToRun","cb","shift","apply","RetentionPolicyService","resp","SERVICE_TYPES","ExtensionE2EE","when","ExtensionState","PreProcess","onRequest","isInitial","markAllTrackedUsersAsDirty","onResponse","device_lists","processDeviceLists","processKeyCounts","device_one_time_keys_count","onSyncCompleted","ExtensionToDevice","cryptoCallbacks","since","nextBatch","receivedToDeviceMessages","preprocessToDeviceMessages","rawEvent","encryptionInfo","processToDeviceMessages","next_batch","ExtensionAccountData","PostProcess","processGlobalAccountData","accountDataEvents","mapEvents","addAccountData","Event","globalAccountData","prevEventsMap","getAccountData","storeAccountDataEvents","accountDataEvent","PushRules","rules","setPushRules","prevEvent","AccountData","ExtensionTyping","processEphemeralEvents","ExtensionReceipts","SlidingSyncSdk","slidingSync","syncOpts","defaultClientOpts","defaultSyncApiOpts","getNotifTimelineSet","TimelineReset","SlidingSyncEvent","Lifecycle","onLifecycle","bind","RoomData","onRoomData","extensions","ext","registerExtension","roomData","initial","_createAndReEmitRoom","processRoomData","SlidingSyncState","Complete","purgeNotifications","lastPos","updateSyncState","Prepared","oldSyncToken","nextSyncToken","pos","catchingUp","fromCache","RequestFinished","failCount","Reconnecting","shouldAbortSync","syncLeftRooms","peek","stopPeeking","setPresence","presence","getSyncState","syncState","getSyncStateData","_this$syncStateData","syncStateData","createRoom","timelineSupport","Room","lazyLoadMembers","pendingEventOrdering","Name","Redaction","RedactionCancelled","Tags","LocalEchoUpdated","MyMembership","registerStateListeners","Members","NewMember","Update","_this$client$getUser","user","getUser","RoomMemberEvent","Typing","PowerLevel","Membership","stateEvent","required_state","ensureNameEvent","stateEvents","ephemeralEvents","limited","knownEvents","oldEvents","newEvents","seenKnownEvent","recvEvent","unshift","addEventsToTimeline","prev_batch","encrypted","hasEncryptionStateEvent","notification_count","setUnreadNotificationCount","highlight_count","getUnreadNotificationCount","bump_stamp","setBumpStamp","invited_count","setInvitedMemberCount","joined_count","setJoinedMemberCount","invite_state","inviteStateEvents","injectRoomEvents","recalculate","storeRoom","_roomData$prev_batch","setPaginationToken","num_live","addEphemeralEvents","updateMyMembership","setMSC4186SummaryData","heroes","addNotifications","processRoomEvent","isState","onCryptoEvent","promiseMapSeries","decryptCriticalEvents","stateEventList","timelineEventList","numLive","liveTimeline","timelineWasEmpty","getPushActionsForEvent","initialiseState","setStateEvents","liveTimelineEvents","addLiveEvents","addToState","resolveInvites","resolveInvitesToProfiles","getMembersWithMembership","requestedProfileInfo","avatar_url","avatarUrl","displayname","getProfileInfo","inviteEvent","setMembershipEvent","_err","retryImmediately","sync","isGuest","getPushRules","newState","old","timelineEvent","pushActions","notifEvents","_this$client$getNotif","addLiveEvent","getEventMapper","ephEvents","DB_MIGRATIONS","db","createObjectStore","keyPath","createIndex","autoIncrement","VERSION","selectQuery","keyRange","resultMapper","query","openCursor","results","cursor","continue","txnAsPromise","txn","oncomplete","reqAsEventPromise","reqAsCursorPromise","LocalIndexedDBStoreBackend","idbExists","syncAccumulator","SyncAccumulator","connect","onClose","disconnected","oldVersion","_isNewlyCreated","migration","onversionchange","_this$db","onclose","init","isNewlyCreated","loadAccountData","loadSyncData","accountData","syncData","accumulate","roomsData","account_data","getOutOfBandMembers","roomIndex","transaction","objectStore","range","IDBKeyRange","only","membershipEvents","oobWritten","record","oob_written","setOutOfBandMembers","tx","put","markerObject","clearOutOfBandMembers","roomRange","minStateKeyProm","openKeyCursor","_cursor$primaryKey","primaryKey","maxStateKeyProm","_cursor$primaryKey2","minStateKey","maxStateKey","writeStore","membersKeyRange","bound","clearDatabase","_this$db2","_req$error","getSavedSync","copy","getJSON","getNextBatchToken","setSyncData","syncToDatabase","userTuples","syncToDatabasePromise","pendingUserPresenceData","doSyncToDatabase","persistUserPresenceEvents","persistAccountData","persistSyncData","promiseTry","clobber","tuples","tuple","getUserPresenceEvents","getClientOptions","_cursor$value","storeClientOptions","resultBatch","getUserProfile","_cursor$value2","profile","storeUserProfiles","userProfiles","removeUserProfiles","userIds","eventIds","destroy","_this$db3","StubStore","getSyncToken","fromToken","setSyncToken","getRooms","removeRoom","getRoomSummaries","storeUser","getUsers","setUserCreator","creator","storeEvents","toStart","storeFilter","getFilter","filterId","getFilterIdByName","filterName","setFilterIdByName","wantsSave","save","startup","getSavedSyncToken","deleteAllData","getPendingEvents","setPendingEvents","getRelationsThreadFilter","_e$content","_e$content2","encryptAESSecretStorageItem","ivStr","iv","aesKey","hmacKey","deriveKeys","encodedData","ciphertext","encrypt","counter","hmac","sign","mac","zeroSalt","hkdfkey","aesProm","hmacProm","PRE_HYDRA_ROOM_VERSIONS","shouldUseHydraForRoomVersion","roomVersion","audioContext","refCount","releaseContext","_audioContext","acquireContext","AudioContext","CallEventHandlerEvent","CallEventHandler","currentEventBuffer","callEventBuffer","eventBufferPromiseChain","evaluateEventBuffer","nextSeqByCall","seq","nextSeq","toDeviceEventBuffers","buffer","callId","nextEvent","calls","candidateEventsByCall","onSync","onRoomTimeline","eventBuffer","callEvents","ignoreCallIds","CallAnswer","CallHangup","CallInvite","handleCallEvent","_getGroupCallById","ReceivedVoipEvent","callRoomId","groupCallEventHandler","getGroupCallById","conf_id","groupCallId","senderId","opponentDeviceId","groupCall","GroupCallEvent","GroupCallUnknownDeviceError","dest_session_id","getSessionId","weSentTheEvent","_this$client$getTurnS","_createNewMatrixCall","_groupCall","getLocalAge","lifetime","CallState","Ended","invitee","timeUntilTurnCresExpire","getTurnServersExpiry","createNewMatrixCall","forceTURN","opponentSessionId","sender_session_id","stats","getGroupCallStats","initStats","initWithInvite","_groupCall2","CallError","GroupCallErrorCode","UnknownDevice","onRemoteIceCandidatesReceived","existingCall","thisCall","_call$getOpponentMemb","isCalling","WaitLocalMedia","CreateOffer","InviteSent","direction","CallDirection","Outbound","getOpponentMember","replacedBy","hangup","CallErrorCode","Incoming","CallCandidates","_createNewMatrixCall2","CallReject","onHangupReceived","onRejectReceived","initWithHangup","hasPeerConnection","party_id","ourPartyId","Ringing","onAnsweredElsewhere","onAnswerReceived","CallSelectAnswer","onSelectAnswerReceived","CallNegotiate","onNegotiateReceived","CallAssertedIdentity","CallAssertedIdentityPrefix","onAssertedIdentityReceived","CallSDPStreamMetadataChanged","CallSDPStreamMetadataChangedPrefix","onSDPStreamMetadataChangedReceived","SDPStreamMetadataKey","SDPStreamMetadataPurpose","GroupCallEventHandlerEvent","GroupCallEventHandler","createGroupCallForRoom","GroupCallPrefix","currentGroupCall","groupCalls","terminate","createGroupCallFromRoomStateEvent","onRoomsChanged","onRoomStateChanged","getRoomDeferred","deferred","roomDeferreds","resolveFunc","prom","waitUntilRoomReadyForGroupCalls","sortedCallEvents","callEvent","callType","GroupCallType","GroupCallIntent","isPtt","dataChannelOptions","dataChannelsEnabled","maxPacketLifeTime","maxRetransmits","protocol","GroupCall","isVoipWithNoMediaAllowed","useLivekitForGroupCalls","CallFeedStatsReporter","buildCallFeedReport","opponentMemberId","pc","rtpTransceivers","getTransceivers","transceiver","_t$sender","track","buildTrackStats","receiver","currentDirection","callFeeds","label","_track$getSettings","_track$getConstraints","settingDeviceId","getSettings","constrainDeviceId","getConstraints","muted","readyState","expandCallFeedReport","report","feed","audioTracks","stream","getAudioTracks","videoTracks","getVideoTracks","audio","purpose","video","feedStats","isLocal","isVideoMuted","isAudioMuted","ConnectionStats","ConnectionStatsBuilder","buildBandwidthReport","availableIncomingBitrate","availableOutgoingBitrate","download","upload","TransportStatsBuilder","buildReport","conferenceStatsTransport","isFocus","localUsedCandidate","localCandidateId","remoteUsedCandidate","remoteCandidateId","ip","address","port","localIp","localCandidateType","candidateType","remoteCandidateType","networkType","rtt","currentRoundTripTime","NaN","MediaSsrcHandler","local","remote","findMidBySsrc","ssrc","ssrcToMid","ssrcs","s","description","sdp","parseSdp","media","_m$ssrcs","attribute","getSsrcToMidMap","MediaTrackHandler","getLocalTracks","getTackById","trackId","getLocalTrackIdByMid","_transceiver$sender","getRemoteTrackIdByMid","_transceiver$receiver","getActiveSimulcastStreams","getTransceiverByTrackId","MediaTrackStats","packetsTotal","packetsLost","isDownloadStream","concealedAudio","totalAudioDuration","setLoss","loss","getLoss","setResolution","resolution","getResolution","setFramerate","framerate","getFramerate","setBitrate","bitrate","getBitrate","setCodec","codecShortType","codec","getCodec","resetBitrate","alive","isAlive","isMuted","isEnabled","setJitter","jitter","getJitter","setAudioConcealment","concealedAudioDuration","audioConcealment","getAudioConcealment","MediaTrackStatsHandler","mediaSsrcHandler","mediaTrackHandler","findTrack2Stats","trackID","trackIdentifier","trackStats","track2stats","findLocalVideoTrackStats","getTrack2stats","findTransceiverByTrackId","ValueFormatter","getNonNegativeValue","imput","TrackStatsBuilder","buildFramerateResolution","frameHeight","frameWidth","frameRate","framesPerSecond","calculateSimulcastFramerate","before","layer","timeMs","framesSent","buildCodec","codecId","mimeType","buildBitrateReceived","calculateBitrate","bytesReceived","buildBitrateSend","bytesSent","buildPacketsLost","packetsNow","packetsBefore","packetsDiff","packetsLostNow","packetsLostBefore","packetsLostDiff","bytesNowAny","bytesBeforeAny","nowTimestamp","beforeTimestamp","bytesNow","bytesBefore","bytesProcessed","bitrateKbps","setTrackStatsState","buildTrackSummary","trackStatsList","videoTrackSummary","maxJitter","maxPacketLoss","totalAudio","audioTrackSummary","remoteTrackList","audioTrackList","trackSummary","_stats$getAudioConcea","_stats$getAudioConcea2","buildJitter","statsReport","jitterStr","buildAudioConcealment","totalSamplesDuration","totalSamplesReceived","concealedSamples","ConnectionStatsReportBuilder","build","totalPackets","lostPackets","bitrateDownload","bitrateUpload","resolutions","framerates","codecs","audioBitrateDownload","audioBitrateUpload","videoBitrateDownload","videoBitrateUpload","totalConcealedAudio","audioConcealmentForTrack","packetLoss","total","calculatePacketLoss","totalAudioConcealment","CallStatsReportGatherer","emitter","onSignalStateChange","processStats","summary","isFirstCollection","previousStatsReport","receivedMedia","receivedAudioMedia","receivedVideoMedia","statsPromise","getStats","_this$connectionStats","_this$connectionStats2","currentStatsReport","processStatsReport","handleError","connectionStats","_this$currentStatsRep","byteSentStatsReport","nominated","bandwidth","remoteSource","emitByteSendReport","emitCallFeedReport","processAndEmitConnectionStatsReport","setActive","getActive","emitConnectionStatsReport","stopProcessingStats","signalingState","currentRemoteDescription","currentLocalDescription","setOpponentMemberId","StatsReportEmitter","byteSentStats","StatsReport","BYTE_SENT_STATS","CONNECTION_STATS","CALL_FEED_REPORT","emitSummaryStatsReport","SUMMARY_STATS","GroupCallStats","interval","SummaryStatsReportGatherer","reports","timer","setInterval","gatherers","hasStatsReportGatherer","addStatsReportGatherer","peerConnection","removeStatsReportGatherer","getStatsReportGatherer","updateOpponentMember","opponentMember","_this$getStatsReportG","summaryStatsReportGatherer","allSummary","summaryTotalCount","peerConnectionsCount","summaryCounter","receivedAudio","receivedVideo","countTrackListReceivedMedia","countConcealedAudio","buildMaxJitter","buildMaxPacketLoss","percentageReceivedMedia","toFixed","percentageReceivedVideoMedia","percentageReceivedAudioMedia","percentageConcealedAudio","peerConnections","extendSummaryReport","callParticipants","devices","userEntry","device","opponentDevicesInCall","opponentUsersInCall","diffDevicesToPeerConnections","ratioPeerConnectionToDevices","hasReceivedAudio","hasReceivedVideo","ReflectOwnKeys","R","Reflect","ReflectApply","Function","prototype","ownKeys","getOwnPropertySymbols","getOwnPropertyNames","NumberIsNaN","EventEmitter","module","exports","errorListener","resolver","arguments","eventTargetAgnosticAddListener","handler","addErrorHandlerIfEventEmitter","_events","_eventsCount","_maxListeners","defaultMaxListeners","checkListener","listener","TypeError","_getMaxListeners","that","_addListener","prepend","existing","warning","create","newListener","warned","w","console","onceWrapper","fired","wrapFn","_onceWrap","wrapped","_listeners","unwrap","evlistener","ret","unwrapListeners","arrayClone","n","wrapListener","arg","defineProperty","enumerable","RangeError","getPrototypeOf","setMaxListeners","getMaxListeners","doError","er","context","len","listeners","addListener","prependListener","prependOnceListener","list","position","originalListener","pop","spliceOne","removeAllListeners","rawListeners","ExtensibleEvents","_NamespacedMap","__webpack_require__","_InvalidEventError","_MRoomMessage","_MMessage","_message_types","_poll_types","_MPoll","_createForOfIteratorHelper","allowArrayLike","it","iterator","minLen","_arrayLikeToArray","_unsupportedIterableToArray","F","done","_e","normalCompletion","didErr","step","_e2","arr2","_defineProperties","descriptor","configurable","writable","instance","Constructor","_classCallCheck","NamespacedMap","LEGACY_M_ROOM_MESSAGE","parseMRoomMessage","M_MESSAGE","parseMMessage","M_EMOTE","M_NOTICE","M_POLL_START","parseMPoll","M_POLL_RESPONSE","M_POLL_END","protoProps","staticProps","_defaultInstance","defaultInstance","unknownInterpretOrder","wireEventType","interpreter","registerInterpreter","wireFormat","_this$_unknownInterpr","_unknownInterpretOrder","interpreters","hasNamespaced","getNamespaced","_step","_iterator","tryType","InvalidEventError","_typeof","_createSuper","Derived","hasNativeReflectConstruct","_isNativeReflectConstruct","Super","_getPrototypeOf","NewTarget","construct","self","ReferenceError","_assertThisInitialized","_possibleConstructorReturn","_wrapNativeSuper","Class","_cache","fn","Wrapper","_construct","_setPrototypeOf","Parent","sham","Proxy","valueOf","p","setPrototypeOf","__proto__","_Error","subClass","superClass","_inherits","_super","internalMap","_createClass","_NamespacedValue","_this","EmoteEvent","_MessageEvent2","_get","property","base","hasOwnProperty","_superPropBase","desc","getOwnPropertyDescriptor","_MessageEvent","html","_content","M_TEXT","M_HTML","primaryEventType","isEventTypeSame","MessageEvent","ExtensibleEvent","_ExtensibleEvent2","_types","enumerableOnly","symbols","sym","getOwnPropertyDescriptors","defineProperties","_ExtensibleEvent","mmessage","wireContent","mtext","mhtml","isProvided","mimetype","renderings","isOptionalAString","messageRendering","mime","_this$html","serializeMMessageOnly","format","formatted_body","NoticeEvent","PollEndEvent","_relationship_types","REFERENCE_RELATION","pollEventId","closingMessage","serialize","PollResponseEvent","validateAgainst","answers","internalAnswerIds","internalSpoiled","pa","maxSelections","spoiled","answerIds","PollStartEvent","PollAnswerSubevent","_toConsumableArray","_arrayWithoutHoles","iter","_iterableToArray","_nonIterableSpread","_super2","_this2","question","rawKind","M_POLL_KIND_DISCLOSED","M_POLL_KIND_UNDISCLOSED","max_selections","_content2","_content3","LETTERS","charAt","_ExtensibleEvents","_IPartialEvent","_MessageMatchers","_EmoteEvent","_NoticeEvent","_PollStartEvent","_PollResponseEvent","_PollEndEvent","wireEvent","_wireEvent$content","_wireEvent$content2","_wireEvent$content3","_objectSpread2","_objectSpread3","_objectSpread4","LegacyMsgType","isEventLike","Text","Emote","Notice","given","expected","expectedNs","givenNs","grammar","reg","u","z","rate","subtype","config","sessionConfig","raddr","tcptype","generation","maxMessageSize","dir2","clksrcExt","mediaClockValue","rateNumerator","rateDenominator","parser","writer","M9","qg","parseParams","parseFmtpConfig","parsePayloads","parseRemoteCandidates","parseImageAttributes","parseSimulcastStreamList","toIntIfInt","parseReg","location","needsBlank","keyLocation","rawName","attachProperties","validLine","l","rtp","fmtp","j","paramReducer","expr","candidates","component","scid","paused","formatRegExp","formatStr","makeLine","defaultOuterOrder","defaultInnerOrder","mLine","payloads","outerOrder","innerOrder","REPLACE_RE","replace_fn","skipOWS","valueStart","skipValue","valueEnd","trailingOWS","toLowerCase","parameters","NullObject","parameter","keyStart","keyEnd","parseParameters","TEXT_REGEXP","TOKEN_REGEXP","QUOTE_REGEXP","TYPE_REGEXP","C","char","end","qstring","_objectWithoutProperties","_objectWithoutPropertiesLoose","propertyIsEnumerable","esm","ALPHABET","BASE_MAP","xc","BASE","LEADER","FACTOR","iFACTOR","decodeUnsafe","psz","zeroes","b256","charCode","carry","it3","it4","vch","ArrayBuffer","isView","byteOffset","byteLength","pbegin","pend","b58","it1","it2","repeat","decode","string","src_esm","objectToString","errorMessages","isNetworkError","stack","validateNumberOption","allowInfinity","validateFunctionOption","originalError","calculateRemainingTime","performance","onAttemptFailure","attemptNumber","retriesConsumed","normalizedError","retriesLeft","maxRetryTime","POSITIVE_INFINITY","delayTime","randomize","minTimeout","factor","maxTimeout","calculateDelay","freeze","onFailedAttempt","consumeRetryContext","consumeRetry","shouldConsumeRetry","effectiveDelay","shouldRetry","remainingTimeAfterShouldRetry","throwIfAborted","finalDelay","timeoutToken","unref","delayForRetry","pRetry","input","validateRetries","hasOwn"],"sourceRoot":""}