import { type Capability, EventDirection, MatrixCapabilities, WidgetEventCapability, } from 'matrix-widget-api'; import { EventType } from 'matrix-js-sdk'; export function getCallCapabilities( roomId: string, userId: string, deviceId: string ): Set { const capabilities: Set = new Set(); capabilities.add(MatrixCapabilities.Screenshots); capabilities.add(MatrixCapabilities.AlwaysOnScreen); capabilities.add(MatrixCapabilities.MSC3846TurnServers); capabilities.add(MatrixCapabilities.MSC4157SendDelayedEvent); capabilities.add(MatrixCapabilities.MSC4157UpdateDelayedEvent); capabilities.add(`org.matrix.msc2762.timeline:${roomId}`); capabilities.add(`org.matrix.msc2762.state:${roomId}`); capabilities.add( WidgetEventCapability.forStateEvent(EventDirection.Receive, EventType.RoomMember).raw ); capabilities.add( WidgetEventCapability.forStateEvent(EventDirection.Receive, 'org.matrix.msc3401.call').raw ); capabilities.add( WidgetEventCapability.forStateEvent(EventDirection.Receive, EventType.RoomEncryption).raw ); capabilities.add( WidgetEventCapability.forStateEvent(EventDirection.Receive, EventType.RoomName).raw ); capabilities.add( WidgetEventCapability.forStateEvent( EventDirection.Send, 'org.matrix.msc3401.call.member', userId ).raw ); capabilities.add( WidgetEventCapability.forStateEvent( EventDirection.Send, 'org.matrix.msc3401.call.member', `_${userId}_${deviceId}_m.call` ).raw ); capabilities.add( WidgetEventCapability.forStateEvent( EventDirection.Send, 'org.matrix.msc3401.call.member', `${userId}_${deviceId}_m.call` ).raw ); capabilities.add( WidgetEventCapability.forStateEvent( EventDirection.Send, 'org.matrix.msc3401.call.member', `_${userId}_${deviceId}` ).raw ); capabilities.add( WidgetEventCapability.forStateEvent( EventDirection.Send, 'org.matrix.msc3401.call.member', `${userId}_${deviceId}` ).raw ); capabilities.add( WidgetEventCapability.forStateEvent(EventDirection.Receive, 'org.matrix.msc3401.call.member') .raw ); capabilities.add( WidgetEventCapability.forStateEvent(EventDirection.Receive, EventType.RoomCreate).raw ); capabilities.add( WidgetEventCapability.forRoomEvent(EventDirection.Send, 'org.matrix.msc4075.rtc.notification') .raw ); capabilities.add( WidgetEventCapability.forRoomEvent( EventDirection.Receive, 'org.matrix.msc4075.rtc.notification' ).raw ); [ 'io.element.call.encryption_keys', 'org.matrix.rageshake_request', EventType.Reaction, EventType.RoomRedaction, 'io.element.call.reaction', 'org.matrix.msc4310.rtc.decline', // MSC4310 — final stable name added alongside the unstable prefix to ease // future SDK transition (Element Web bundle already requests both). 'm.rtc.decline', // MSC4143 / MSC4354 sticky-event RTC membership. Sticky events go through // the room-event path (`_unstable_sendStickyEvent` / `_unstable_getStickyEvents`), // not state events — so capability here is `forRoomEvent`, not `forStateEvent`. // Vojo's homeserver currently advertises `org.matrix.msc4354: false` and EC // bundle uses legacy `m.call.member` state events, so today this path is // not exercised; allowlist matches the Element Web pattern for forward-compat // when either bundle or server flips. Both unstable (`org.matrix.msc4143.rtc.member`) // and stable (`m.rtc.member`) names registered for the same reason. 'org.matrix.msc4143.rtc.member', 'm.rtc.member', ].forEach((type) => { capabilities.add(WidgetEventCapability.forRoomEvent(EventDirection.Send, type).raw); capabilities.add(WidgetEventCapability.forRoomEvent(EventDirection.Receive, type).raw); }); [ EventType.CallInvite, EventType.CallCandidates, EventType.CallAnswer, EventType.CallHangup, EventType.CallReject, EventType.CallSelectAnswer, EventType.CallNegotiate, EventType.CallSDPStreamMetadataChanged, EventType.CallSDPStreamMetadataChangedPrefix, EventType.CallReplaces, EventType.CallEncryptionKeysPrefix, ].forEach((type) => { capabilities.add(WidgetEventCapability.forToDeviceEvent(EventDirection.Send, type).raw); capabilities.add(WidgetEventCapability.forToDeviceEvent(EventDirection.Receive, type).raw); }); return capabilities; }