Improve types for sendStateEvent (#12331)

This commit is contained in:
Michael Telatynski 2024-03-20 14:27:29 +00:00 committed by GitHub
parent 4a05de485e
commit 2cbf92860b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 89 additions and 44 deletions

View file

@ -18,6 +18,7 @@ import { Page } from "@playwright/test";
import { test, expect } from "../../element-web-test"; import { test, expect } from "../../element-web-test";
import { ElementAppPage } from "../../pages/ElementAppPage"; import { ElementAppPage } from "../../pages/ElementAppPage";
import type { Container } from "../../../src/stores/widgets/types";
test.describe("Room Header", () => { test.describe("Room Header", () => {
test.use({ test.use({
@ -227,7 +228,7 @@ test.describe("Room Header", () => {
{ {
widgets: { widgets: {
[id]: { [id]: {
container: "top", container: "top" as Container,
index: 1, index: 1,
width: 100, width: 100,
height: 0, height: 0,

View file

@ -31,6 +31,7 @@ import type {
Visibility, Visibility,
UploadOpts, UploadOpts,
Upload, Upload,
StateEvents,
} from "matrix-js-sdk/src/matrix"; } from "matrix-js-sdk/src/matrix";
import { Credentials } from "../plugins/homeserver"; import { Credentials } from "../plugins/homeserver";
@ -407,7 +408,7 @@ export class Client {
const client = await this.prepareClient(); const client = await this.prepareClient();
return client.evaluate( return client.evaluate(
async (client, { roomId, eventType, content, stateKey }) => { async (client, { roomId, eventType, content, stateKey }) => {
return client.sendStateEvent(roomId, eventType, content, stateKey); return client.sendStateEvent(roomId, eventType as keyof StateEvents, content, stateKey);
}, },
{ roomId, eventType, content, stateKey }, { roomId, eventType, content, stateKey },
); );

View file

@ -16,12 +16,7 @@ limitations under the License.
import { JSXElementConstructor } from "react"; import { JSXElementConstructor } from "react";
export type { NonEmptyArray } from "matrix-js-sdk/src/matrix"; export type { NonEmptyArray, XOR, Writeable } from "matrix-js-sdk/src/matrix";
// Based on https://stackoverflow.com/a/53229857/3532235
export type Without<T, U> = { [P in Exclude<keyof T, keyof U>]?: never };
export type XOR<T, U> = T | U extends object ? (Without<T, U> & U) | (Without<U, T> & T) : T | U;
export type Writeable<T> = { -readonly [P in keyof T]: T[P] };
export type ComponentClass = keyof JSX.IntrinsicElements | JSXElementConstructor<any>; export type ComponentClass = keyof JSX.IntrinsicElements | JSXElementConstructor<any>;

View file

@ -291,7 +291,7 @@ Response:
*/ */
import { IContent, MatrixEvent, IEvent } from "matrix-js-sdk/src/matrix"; import { IContent, MatrixEvent, IEvent, StateEvents } from "matrix-js-sdk/src/matrix";
import { logger } from "matrix-js-sdk/src/logger"; import { logger } from "matrix-js-sdk/src/logger";
import { MatrixClientPeg } from "./MatrixClientPeg"; import { MatrixClientPeg } from "./MatrixClientPeg";
@ -721,7 +721,7 @@ async function getOpenIdToken(event: MessageEvent<any>): Promise<void> {
async function sendEvent( async function sendEvent(
event: MessageEvent<{ event: MessageEvent<{
type: string; type: keyof StateEvents;
state_key?: string; state_key?: string;
content?: IContent; content?: IContent;
}>, }>,

View file

@ -18,8 +18,9 @@ limitations under the License.
*/ */
import * as React from "react"; import * as React from "react";
import { User, IContent, Direction, ContentHelpers, MRoomTopicEventContent } from "matrix-js-sdk/src/matrix"; import { ContentHelpers, Direction, EventType, IContent, MRoomTopicEventContent, User } from "matrix-js-sdk/src/matrix";
import { logger } from "matrix-js-sdk/src/logger"; import { logger } from "matrix-js-sdk/src/logger";
import { RoomMemberEventContent } from "matrix-js-sdk/src/types";
import dis from "./dispatcher/dispatcher"; import dis from "./dispatcher/dispatcher";
import { _t, _td, UserFriendlyError } from "./languageHandler"; import { _t, _td, UserFriendlyError } from "./languageHandler";
@ -239,12 +240,12 @@ export const Commands = [
isEnabled: (cli) => !isCurrentLocalRoom(cli), isEnabled: (cli) => !isCurrentLocalRoom(cli),
runFn: function (cli, roomId, threadId, args) { runFn: function (cli, roomId, threadId, args) {
if (args) { if (args) {
const ev = cli.getRoom(roomId)?.currentState.getStateEvents("m.room.member", cli.getSafeUserId()); const ev = cli.getRoom(roomId)?.currentState.getStateEvents(EventType.RoomMember, cli.getSafeUserId());
const content = { const content: RoomMemberEventContent = {
...(ev ? ev.getContent() : { membership: "join" }), ...(ev ? ev.getContent() : { membership: "join" }),
displayname: args, displayname: args,
}; };
return success(cli.sendStateEvent(roomId, "m.room.member", content, cli.getSafeUserId())); return success(cli.sendStateEvent(roomId, EventType.RoomMember, content, cli.getSafeUserId()));
} }
return reject(this.getUsage()); return reject(this.getUsage());
}, },
@ -265,7 +266,7 @@ export const Commands = [
return success( return success(
promise.then((url) => { promise.then((url) => {
if (!url) return; if (!url) return;
return cli.sendStateEvent(roomId, "m.room.avatar", { url }, ""); return cli.sendStateEvent(roomId, EventType.RoomAvatar, { url }, "");
}), }),
); );
}, },
@ -289,12 +290,12 @@ export const Commands = [
return success( return success(
promise.then((url) => { promise.then((url) => {
if (!url) return; if (!url) return;
const ev = room?.currentState.getStateEvents("m.room.member", userId); const ev = room?.currentState.getStateEvents(EventType.RoomMember, userId);
const content = { const content: RoomMemberEventContent = {
...(ev ? ev.getContent() : { membership: "join" }), ...(ev ? ev.getContent() : { membership: "join" }),
avatar_url: url, avatar_url: url,
}; };
return cli.sendStateEvent(roomId, "m.room.member", content, userId); return cli.sendStateEvent(roomId, EventType.RoomMember, content, userId);
}), }),
); );
}, },

View file

@ -46,6 +46,7 @@ import { RoomHierarchy } from "matrix-js-sdk/src/room-hierarchy";
import classNames from "classnames"; import classNames from "classnames";
import { sortBy, uniqBy } from "lodash"; import { sortBy, uniqBy } from "lodash";
import { logger } from "matrix-js-sdk/src/logger"; import { logger } from "matrix-js-sdk/src/logger";
import { SpaceChildEventContent } from "matrix-js-sdk/src/types";
import defaultDispatcher from "../../dispatcher/dispatcher"; import defaultDispatcher from "../../dispatcher/dispatcher";
import { _t } from "../../languageHandler"; import { _t } from "../../languageHandler";
@ -726,7 +727,7 @@ const ManageButtons: React.FC<IManageButtonsProps> = ({ hierarchy, selected, set
const existingContent = hierarchy.getRelation(parentId, childId)?.content; const existingContent = hierarchy.getRelation(parentId, childId)?.content;
if (!existingContent || existingContent.suggested === suggested) continue; if (!existingContent || existingContent.suggested === suggested) continue;
const content = { const content: SpaceChildEventContent = {
...existingContent, ...existingContent,
suggested: !selectionAllSuggested, suggested: !selectionAllSuggested,
}; };

View file

@ -38,7 +38,7 @@ export const StateEventEditor: React.FC<IEditorProps> = ({ mxEvent, onBack }) =>
); );
const onSend = async ([eventType, stateKey]: string[], content: IContent): Promise<void> => { const onSend = async ([eventType, stateKey]: string[], content: IContent): Promise<void> => {
await cli.sendStateEvent(context.room.roomId, eventType, content, stateKey); await cli.sendStateEvent(context.room.roomId, eventType as any, content, stateKey);
}; };
const defaultContent = mxEvent ? stringify(mxEvent.getContent()) : undefined; const defaultContent = mxEvent ? stringify(mxEvent.getContent()) : undefined;

View file

@ -15,8 +15,9 @@ limitations under the License.
*/ */
import React, { ChangeEvent, ContextType, createRef, SyntheticEvent } from "react"; import React, { ChangeEvent, ContextType, createRef, SyntheticEvent } from "react";
import { IContent, MatrixEvent, EventType } from "matrix-js-sdk/src/matrix"; import { MatrixEvent, EventType } from "matrix-js-sdk/src/matrix";
import { logger } from "matrix-js-sdk/src/logger"; import { logger } from "matrix-js-sdk/src/logger";
import { RoomCanonicalAliasEventContent } from "matrix-js-sdk/src/types";
import EditableItemList from "../elements/EditableItemList"; import EditableItemList from "../elements/EditableItemList";
import { _t } from "../../../languageHandler"; import { _t } from "../../../languageHandler";
@ -169,7 +170,7 @@ export default class AliasSettings extends React.Component<IProps, IState> {
updatingCanonicalAlias: true, updatingCanonicalAlias: true,
}); });
const eventContent: IContent = { const eventContent: RoomCanonicalAliasEventContent = {
alt_aliases: this.state.altAliases, alt_aliases: this.state.altAliases,
}; };
@ -197,7 +198,7 @@ export default class AliasSettings extends React.Component<IProps, IState> {
updatingCanonicalAlias: true, updatingCanonicalAlias: true,
}); });
const eventContent: IContent = {}; const eventContent: RoomCanonicalAliasEventContent = {};
if (this.state.canonicalAlias) { if (this.state.canonicalAlias) {
eventContent["alias"] = this.state.canonicalAlias; eventContent["alias"] = this.state.canonicalAlias;

View file

@ -15,7 +15,7 @@ limitations under the License.
*/ */
import React from "react"; import React from "react";
import { MatrixEvent, Room, RoomStateEvent, EventType } from "matrix-js-sdk/src/matrix"; import { EventType, MatrixEvent, Room, RoomStateEvent } from "matrix-js-sdk/src/matrix";
import { logger } from "matrix-js-sdk/src/logger"; import { logger } from "matrix-js-sdk/src/logger";
import { Button, Text } from "@vector-im/compound-web"; import { Button, Text } from "@vector-im/compound-web";
@ -101,7 +101,7 @@ export default class ThirdPartyMemberInfo extends React.Component<IProps, IState
public onKickClick = (): void => { public onKickClick = (): void => {
MatrixClientPeg.safeGet() MatrixClientPeg.safeGet()
.sendStateEvent(this.state.roomId, "m.room.third_party_invite", {}, this.state.stateKey) .sendStateEvent(this.state.roomId, EventType.RoomThirdPartyInvite, {}, this.state.stateKey)
.catch((err) => { .catch((err) => {
logger.error(err); logger.error(err);

View file

@ -18,6 +18,7 @@ import React from "react";
import { EventType, RoomMember, RoomState, RoomStateEvent, Room, IContent } from "matrix-js-sdk/src/matrix"; import { EventType, RoomMember, RoomState, RoomStateEvent, Room, IContent } from "matrix-js-sdk/src/matrix";
import { logger } from "matrix-js-sdk/src/logger"; import { logger } from "matrix-js-sdk/src/logger";
import { throttle, get } from "lodash"; import { throttle, get } from "lodash";
import { RoomPowerLevelsEventContent } from "matrix-js-sdk/src/types";
import { _t, _td, TranslationKey } from "../../../../../languageHandler"; import { _t, _td, TranslationKey } from "../../../../../languageHandler";
import AccessibleButton from "../../../elements/AccessibleButton"; import AccessibleButton from "../../../elements/AccessibleButton";
@ -178,7 +179,7 @@ export default class RolesRoomSettingsTab extends React.Component<IProps> {
const client = this.context; const client = this.context;
const room = this.props.room; const room = this.props.room;
const plEvent = room.currentState.getStateEvents(EventType.RoomPowerLevels, ""); const plEvent = room.currentState.getStateEvents(EventType.RoomPowerLevels, "");
let plContent = plEvent?.getContent() ?? {}; let plContent = plEvent?.getContent<RoomPowerLevelsEventContent>() ?? {};
// Clone the power levels just in case // Clone the power levels just in case
plContent = Object.assign({}, plContent); plContent = Object.assign({}, plContent);
@ -192,7 +193,7 @@ export default class RolesRoomSettingsTab extends React.Component<IProps> {
} else { } else {
const keyPath = powerLevelKey.split("."); const keyPath = powerLevelKey.split(".");
let parentObj: IContent = {}; let parentObj: IContent = {};
let currentObj = plContent; let currentObj: IContent = plContent;
for (const key of keyPath) { for (const key of keyPath) {
if (!currentObj[key]) { if (!currentObj[key]) {
currentObj[key] = {}; currentObj[key] = {};
@ -222,7 +223,7 @@ export default class RolesRoomSettingsTab extends React.Component<IProps> {
const client = this.context; const client = this.context;
const room = this.props.room; const room = this.props.room;
const plEvent = room.currentState.getStateEvents(EventType.RoomPowerLevels, ""); const plEvent = room.currentState.getStateEvents(EventType.RoomPowerLevels, "");
let plContent = plEvent?.getContent() ?? {}; let plContent = plEvent?.getContent<RoomPowerLevelsEventContent>() ?? {};
// Clone the power levels just in case // Clone the power levels just in case
plContent = Object.assign({}, plContent); plContent = Object.assign({}, plContent);

View file

@ -16,12 +16,14 @@ limitations under the License.
// Inspiration largely taken from Mjolnir itself // Inspiration largely taken from Mjolnir itself
import { EventType } from "matrix-js-sdk/src/matrix";
import { ListRule, RECOMMENDATION_BAN, recommendationToStable } from "./ListRule"; import { ListRule, RECOMMENDATION_BAN, recommendationToStable } from "./ListRule";
import { MatrixClientPeg } from "../MatrixClientPeg"; import { MatrixClientPeg } from "../MatrixClientPeg";
export const RULE_USER = "m.policy.rule.user"; export const RULE_USER = EventType.PolicyRuleUser;
export const RULE_ROOM = "m.policy.rule.room"; export const RULE_ROOM = EventType.PolicyRuleRoom;
export const RULE_SERVER = "m.policy.rule.server"; export const RULE_SERVER = EventType.PolicyRuleServer;
// m.room.* events are legacy from when MSC2313 changed to m.policy.* last minute. // m.room.* events are legacy from when MSC2313 changed to m.policy.* last minute.
export const USER_RULE_TYPES = [RULE_USER, "m.room.rule.user", "org.matrix.mjolnir.rule.user"]; export const USER_RULE_TYPES = [RULE_USER, "m.room.rule.user", "org.matrix.mjolnir.rule.user"];
@ -29,7 +31,9 @@ export const ROOM_RULE_TYPES = [RULE_ROOM, "m.room.rule.room", "org.matrix.mjoln
export const SERVER_RULE_TYPES = [RULE_SERVER, "m.room.rule.server", "org.matrix.mjolnir.rule.server"]; export const SERVER_RULE_TYPES = [RULE_SERVER, "m.room.rule.server", "org.matrix.mjolnir.rule.server"];
export const ALL_RULE_TYPES = [...USER_RULE_TYPES, ...ROOM_RULE_TYPES, ...SERVER_RULE_TYPES]; export const ALL_RULE_TYPES = [...USER_RULE_TYPES, ...ROOM_RULE_TYPES, ...SERVER_RULE_TYPES];
export function ruleTypeToStable(rule: string): string | null { export function ruleTypeToStable(
rule: string,
): EventType.PolicyRuleUser | EventType.PolicyRuleRoom | EventType.PolicyRuleServer | null {
if (USER_RULE_TYPES.includes(rule)) { if (USER_RULE_TYPES.includes(rule)) {
return RULE_USER; return RULE_USER;
} }
@ -72,7 +76,7 @@ export class BanList {
{ {
entity: entity, entity: entity,
reason: reason, reason: reason,
recommendation: recommendationToStable(RECOMMENDATION_BAN, true), recommendation: recommendationToStable(RECOMMENDATION_BAN, true)!,
}, },
"rule:" + entity, "rule:" + entity,
); );

View file

@ -14,14 +14,24 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
// We are using experimental APIs here, so we need to disable the linter
// eslint-disable-next-line no-restricted-imports
import { PolicyRecommendation } from "matrix-js-sdk/src/models/invites-ignorer";
import { MatrixGlob } from "../utils/MatrixGlob"; import { MatrixGlob } from "../utils/MatrixGlob";
// Inspiration largely taken from Mjolnir itself // Inspiration largely taken from Mjolnir itself
export const RECOMMENDATION_BAN = "m.ban"; export const RECOMMENDATION_BAN = PolicyRecommendation.Ban;
export const RECOMMENDATION_BAN_TYPES = [RECOMMENDATION_BAN, "org.matrix.mjolnir.ban"]; export const RECOMMENDATION_BAN_TYPES: PolicyRecommendation[] = [
RECOMMENDATION_BAN,
"org.matrix.mjolnir.ban" as PolicyRecommendation,
];
export function recommendationToStable(recommendation: string, unstable = true): string | null { export function recommendationToStable(
recommendation: PolicyRecommendation,
unstable = true,
): PolicyRecommendation | null {
if (RECOMMENDATION_BAN_TYPES.includes(recommendation)) { if (RECOMMENDATION_BAN_TYPES.includes(recommendation)) {
return unstable ? RECOMMENDATION_BAN_TYPES[RECOMMENDATION_BAN_TYPES.length - 1] : RECOMMENDATION_BAN; return unstable ? RECOMMENDATION_BAN_TYPES[RECOMMENDATION_BAN_TYPES.length - 1] : RECOMMENDATION_BAN;
} }
@ -35,7 +45,7 @@ export class ListRule {
private readonly _reason: string; private readonly _reason: string;
private readonly _kind: string; private readonly _kind: string;
public constructor(entity: string, action: string, reason: string, kind: string) { public constructor(entity: string, action: PolicyRecommendation, reason: string, kind: string) {
this._glob = new MatrixGlob(entity); this._glob = new MatrixGlob(entity);
this._entity = entity; this._entity = entity;
this._action = recommendationToStable(action, false); this._action = recommendationToStable(action, false);

View file

@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import { MatrixClient, MatrixEvent, RoomState, RoomStateEvent } from "matrix-js-sdk/src/matrix"; import { MatrixClient, MatrixEvent, RoomState, RoomStateEvent, StateEvents } from "matrix-js-sdk/src/matrix";
import { defer } from "matrix-js-sdk/src/utils"; import { defer } from "matrix-js-sdk/src/utils";
import MatrixClientBackedSettingsHandler from "./MatrixClientBackedSettingsHandler"; import MatrixClientBackedSettingsHandler from "./MatrixClientBackedSettingsHandler";
@ -24,6 +24,9 @@ import { SettingLevel } from "../SettingLevel";
import { WatchManager } from "../WatchManager"; import { WatchManager } from "../WatchManager";
const DEFAULT_SETTINGS_EVENT_TYPE = "im.vector.web.settings"; const DEFAULT_SETTINGS_EVENT_TYPE = "im.vector.web.settings";
const PREVIEW_URLS_EVENT_TYPE = "org.matrix.room.preview_urls";
type RoomSettingsEventType = typeof DEFAULT_SETTINGS_EVENT_TYPE | typeof PREVIEW_URLS_EVENT_TYPE;
/** /**
* Gets and sets settings at the "room" level. * Gets and sets settings at the "room" level.
@ -88,7 +91,12 @@ export default class RoomSettingsHandler extends MatrixClientBackedSettingsHandl
} }
// helper function to send state event then await it being echoed back // helper function to send state event then await it being echoed back
private async sendStateEvent(roomId: string, eventType: string, field: string, value: any): Promise<void> { private async sendStateEvent<K extends RoomSettingsEventType, F extends keyof StateEvents[K]>(
roomId: string,
eventType: K,
field: F,
value: StateEvents[K][F],
): Promise<void> {
const content = this.getSettings(roomId, eventType) || {}; const content = this.getSettings(roomId, eventType) || {};
content[field] = value; content[field] = value;

View file

@ -43,6 +43,7 @@ import {
Room, Room,
Direction, Direction,
THREAD_RELATION_TYPE, THREAD_RELATION_TYPE,
StateEvents,
} from "matrix-js-sdk/src/matrix"; } from "matrix-js-sdk/src/matrix";
import { logger } from "matrix-js-sdk/src/logger"; import { logger } from "matrix-js-sdk/src/logger";
import { import {
@ -241,7 +242,19 @@ export class StopGapWidgetDriver extends WidgetDriver {
return allAllowed; return allAllowed;
} }
public async sendEvent<K extends keyof StateEvents>(
eventType: K,
content: StateEvents[K],
stateKey?: string,
targetRoomId?: string,
): Promise<ISendEventDetails>;
public async sendEvent( public async sendEvent(
eventType: Exclude<EventType, keyof StateEvents>,
content: IContent,
stateKey: null,
targetRoomId?: string,
): Promise<ISendEventDetails>;
public async sendEvent<K extends keyof StateEvents>(
eventType: string, eventType: string,
content: IContent, content: IContent,
stateKey?: string | null, stateKey?: string | null,
@ -255,7 +268,7 @@ export class StopGapWidgetDriver extends WidgetDriver {
let r: { event_id: string } | null; let r: { event_id: string } | null;
if (stateKey !== null) { if (stateKey !== null) {
// state event // state event
r = await client.sendStateEvent(roomId, eventType, content, stateKey); r = await client.sendStateEvent(roomId, eventType as K, content as StateEvents[K], stateKey);
} else if (eventType === EventType.RoomRedaction) { } else if (eventType === EventType.RoomRedaction) {
// special case: extract the `redacts` property and call redact // special case: extract the `redacts` property and call redact
r = await client.redactEvent(roomId, content["redacts"]); r = await client.redactEvent(roomId, content["redacts"]);

View file

@ -131,7 +131,7 @@ export async function upgradeRoom(
EventType.SpaceChild, EventType.SpaceChild,
{ {
...(currentEv?.getContent() || {}), // copy existing attributes like suggested ...(currentEv?.getContent() || {}), // copy existing attributes like suggested
via: [cli.getDomain()], via: [cli.getDomain()!],
}, },
newRoomId, newRoomId,
); );

View file

@ -24,6 +24,7 @@ import {
RoomStateEvent, RoomStateEvent,
PendingEventOrdering, PendingEventOrdering,
ISearchResults, ISearchResults,
IContent,
} from "matrix-js-sdk/src/matrix"; } from "matrix-js-sdk/src/matrix";
import { CallType } from "matrix-js-sdk/src/webrtc/call"; import { CallType } from "matrix-js-sdk/src/webrtc/call";
import { ClientWidgetApi, Widget } from "matrix-widget-api"; import { ClientWidgetApi, Widget } from "matrix-widget-api";
@ -111,7 +112,7 @@ describe("LegacyRoomHeader", () => {
room: roomId, room: roomId,
user: alice.userId, user: alice.userId,
skey: stateKey, skey: stateKey,
content, content: content as IContent,
}); });
room.addLiveEvents([event]); room.addLiveEvents([event]);
return { event_id: event.getId()! }; return { event_id: event.getId()! };

View file

@ -17,7 +17,15 @@ limitations under the License.
import EventEmitter from "events"; import EventEmitter from "events";
import { mocked } from "jest-mock"; import { mocked } from "jest-mock";
import { waitFor } from "@testing-library/react"; import { waitFor } from "@testing-library/react";
import { RoomType, Room, RoomEvent, MatrixEvent, RoomStateEvent, PendingEventOrdering } from "matrix-js-sdk/src/matrix"; import {
RoomType,
Room,
RoomEvent,
MatrixEvent,
RoomStateEvent,
PendingEventOrdering,
IContent,
} from "matrix-js-sdk/src/matrix";
import { Widget } from "matrix-widget-api"; import { Widget } from "matrix-widget-api";
// eslint-disable-next-line no-restricted-imports // eslint-disable-next-line no-restricted-imports
import { MatrixRTCSessionManagerEvents } from "matrix-js-sdk/src/matrixrtc/MatrixRTCSessionManager"; import { MatrixRTCSessionManagerEvents } from "matrix-js-sdk/src/matrixrtc/MatrixRTCSessionManager";
@ -116,7 +124,7 @@ const setUpClientRoomAndStores = (): {
room: roomId, room: roomId,
user: alice.userId, user: alice.userId,
skey: stateKey, skey: stateKey,
content, content: content as IContent,
}); });
room.addLiveEvents([event]); room.addLiveEvents([event]);
return { event_id: event.getId()! }; return { event_id: event.getId()! };