You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-08-07 23:02:56 +03:00
Improve types for sendEvent
(#4108)
This commit is contained in:
committed by
GitHub
parent
85a55c79cd
commit
97844f0e47
@@ -50,6 +50,7 @@ import {
|
|||||||
ClientEvent,
|
ClientEvent,
|
||||||
createClient,
|
createClient,
|
||||||
CryptoEvent,
|
CryptoEvent,
|
||||||
|
HistoryVisibility,
|
||||||
IClaimOTKsResult,
|
IClaimOTKsResult,
|
||||||
IContent,
|
IContent,
|
||||||
IDownloadKeyResult,
|
IDownloadKeyResult,
|
||||||
@@ -59,11 +60,11 @@ import {
|
|||||||
MatrixClient,
|
MatrixClient,
|
||||||
MatrixEvent,
|
MatrixEvent,
|
||||||
MatrixEventEvent,
|
MatrixEventEvent,
|
||||||
|
MsgType,
|
||||||
PendingEventOrdering,
|
PendingEventOrdering,
|
||||||
Room,
|
Room,
|
||||||
RoomMember,
|
RoomMember,
|
||||||
RoomStateEvent,
|
RoomStateEvent,
|
||||||
HistoryVisibility,
|
|
||||||
} from "../../../src/matrix";
|
} from "../../../src/matrix";
|
||||||
import { DeviceInfo } from "../../../src/crypto/deviceinfo";
|
import { DeviceInfo } from "../../../src/crypto/deviceinfo";
|
||||||
import { E2EKeyReceiver } from "../../test-utils/E2EKeyReceiver";
|
import { E2EKeyReceiver } from "../../test-utils/E2EKeyReceiver";
|
||||||
@@ -1925,7 +1926,7 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("crypto (%s)", (backend: string,
|
|||||||
expectAliceKeyQuery({ device_keys: { "@other:user": {} }, failures: {} });
|
expectAliceKeyQuery({ device_keys: { "@other:user": {} }, failures: {} });
|
||||||
aliceClient.on(RoomStateEvent.NewMember, (_e, _s, member: RoomMember) => {
|
aliceClient.on(RoomStateEvent.NewMember, (_e, _s, member: RoomMember) => {
|
||||||
if (member.userId == "@other:user") {
|
if (member.userId == "@other:user") {
|
||||||
aliceClient.sendMessage(testRoomId, { msgtype: "m.text", body: "Hello, World" });
|
aliceClient.sendMessage(testRoomId, { msgtype: MsgType.Text, body: "Hello, World" });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -34,7 +34,7 @@ import { logger } from "../../../src/logger";
|
|||||||
import * as testUtils from "../../test-utils/test-utils";
|
import * as testUtils from "../../test-utils/test-utils";
|
||||||
import { TestClient } from "../../TestClient";
|
import { TestClient } from "../../TestClient";
|
||||||
import { CRYPTO_ENABLED, IClaimKeysRequest, IQueryKeysRequest, IUploadKeysRequest } from "../../../src/client";
|
import { CRYPTO_ENABLED, IClaimKeysRequest, IQueryKeysRequest, IUploadKeysRequest } from "../../../src/client";
|
||||||
import { ClientEvent, IContent, ISendEventResponse, MatrixClient, MatrixEvent } from "../../../src/matrix";
|
import { ClientEvent, IContent, ISendEventResponse, MatrixClient, MatrixEvent, MsgType } from "../../../src/matrix";
|
||||||
import { DeviceInfo } from "../../../src/crypto/deviceinfo";
|
import { DeviceInfo } from "../../../src/crypto/deviceinfo";
|
||||||
import { KnownMembership } from "../../../src/@types/membership";
|
import { KnownMembership } from "../../../src/@types/membership";
|
||||||
|
|
||||||
@@ -217,7 +217,7 @@ async function expectBobSendMessageRequest(): Promise<OlmPayload> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function sendMessage(client: MatrixClient): Promise<ISendEventResponse> {
|
function sendMessage(client: MatrixClient): Promise<ISendEventResponse> {
|
||||||
return client.sendMessage(roomId, { msgtype: "m.text", body: "Hello, World" });
|
return client.sendMessage(roomId, { msgtype: MsgType.Text, body: "Hello, World" });
|
||||||
}
|
}
|
||||||
|
|
||||||
async function expectSendMessageRequest(httpBackend: TestClient["httpBackend"]): Promise<IContent> {
|
async function expectSendMessageRequest(httpBackend: TestClient["httpBackend"]): Promise<IContent> {
|
||||||
|
@@ -16,7 +16,7 @@ limitations under the License.
|
|||||||
|
|
||||||
import HttpBackend from "matrix-mock-request";
|
import HttpBackend from "matrix-mock-request";
|
||||||
|
|
||||||
import { EventStatus, RoomEvent, MatrixClient, MatrixScheduler } from "../../src/matrix";
|
import { EventStatus, MatrixClient, MatrixScheduler, MsgType, RoomEvent } from "../../src/matrix";
|
||||||
import { Room } from "../../src/models/room";
|
import { Room } from "../../src/models/room";
|
||||||
import { TestClient } from "../TestClient";
|
import { TestClient } from "../TestClient";
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@ describe("MatrixClient retrying", function () {
|
|||||||
// send a couple of events; the second will be queued
|
// send a couple of events; the second will be queued
|
||||||
const p1 = client!
|
const p1 = client!
|
||||||
.sendMessage(roomId, {
|
.sendMessage(roomId, {
|
||||||
msgtype: "m.text",
|
msgtype: MsgType.Text,
|
||||||
body: "m1",
|
body: "m1",
|
||||||
})
|
})
|
||||||
.then(
|
.then(
|
||||||
@@ -77,7 +77,7 @@ describe("MatrixClient retrying", function () {
|
|||||||
// never gets resolved.
|
// never gets resolved.
|
||||||
// https://github.com/matrix-org/matrix-js-sdk/issues/496
|
// https://github.com/matrix-org/matrix-js-sdk/issues/496
|
||||||
client!.sendMessage(roomId, {
|
client!.sendMessage(roomId, {
|
||||||
msgtype: "m.text",
|
msgtype: MsgType.Text,
|
||||||
body: "m2",
|
body: "m2",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -152,7 +152,7 @@ describe("MatrixClient syncing", () => {
|
|||||||
await client!.sendEvent(roomId, EventType.Reaction, {
|
await client!.sendEvent(roomId, EventType.Reaction, {
|
||||||
"m.relates_to": {
|
"m.relates_to": {
|
||||||
rel_type: RelationType.Annotation,
|
rel_type: RelationType.Annotation,
|
||||||
event_id: threadReply.getId(),
|
event_id: threadReply.getId()!,
|
||||||
key: "",
|
key: "",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@@ -81,6 +81,12 @@ declare module "../../src/types" {
|
|||||||
hello: string;
|
hello: string;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface TimelineEvents {
|
||||||
|
"org.matrix.rageshake_request": {
|
||||||
|
request_id: number;
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
describe("RoomWidgetClient", () => {
|
describe("RoomWidgetClient", () => {
|
||||||
|
@@ -22,6 +22,7 @@ import { Filter } from "../../src/filter";
|
|||||||
import { DEFAULT_TREE_POWER_LEVELS_TEMPLATE } from "../../src/models/MSC3089TreeSpace";
|
import { DEFAULT_TREE_POWER_LEVELS_TEMPLATE } from "../../src/models/MSC3089TreeSpace";
|
||||||
import {
|
import {
|
||||||
EventType,
|
EventType,
|
||||||
|
MsgType,
|
||||||
RelationType,
|
RelationType,
|
||||||
RoomCreateTypeField,
|
RoomCreateTypeField,
|
||||||
RoomType,
|
RoomType,
|
||||||
@@ -73,6 +74,7 @@ import { StubStore } from "../../src/store/stub";
|
|||||||
import { SecretStorageKeyDescriptionAesV1, ServerSideSecretStorageImpl } from "../../src/secret-storage";
|
import { SecretStorageKeyDescriptionAesV1, ServerSideSecretStorageImpl } from "../../src/secret-storage";
|
||||||
import { CryptoBackend } from "../../src/common-crypto/CryptoBackend";
|
import { CryptoBackend } from "../../src/common-crypto/CryptoBackend";
|
||||||
import { KnownMembership } from "../../src/@types/membership";
|
import { KnownMembership } from "../../src/@types/membership";
|
||||||
|
import { RoomMessageEventContent } from "../../src/@types/events";
|
||||||
|
|
||||||
jest.useFakeTimers();
|
jest.useFakeTimers();
|
||||||
|
|
||||||
@@ -567,7 +569,7 @@ describe("MatrixClient", function () {
|
|||||||
describe("sendEvent", () => {
|
describe("sendEvent", () => {
|
||||||
const roomId = "!room:example.org";
|
const roomId = "!room:example.org";
|
||||||
const body = "This is the body";
|
const body = "This is the body";
|
||||||
const content = { body };
|
const content = { body, msgtype: MsgType.Text } satisfies RoomMessageEventContent;
|
||||||
|
|
||||||
it("overload without threadId works", async () => {
|
it("overload without threadId works", async () => {
|
||||||
const eventId = "$eventId:example.org";
|
const eventId = "$eventId:example.org";
|
||||||
@@ -662,12 +664,13 @@ describe("MatrixClient", function () {
|
|||||||
|
|
||||||
const content = {
|
const content = {
|
||||||
body,
|
body,
|
||||||
|
"msgtype": MsgType.Text,
|
||||||
"m.relates_to": {
|
"m.relates_to": {
|
||||||
"m.in_reply_to": {
|
"m.in_reply_to": {
|
||||||
event_id: "$other:event",
|
event_id: "$other:event",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
} satisfies RoomMessageEventContent;
|
||||||
|
|
||||||
const room = new Room(roomId, client, userId);
|
const room = new Room(roomId, client, userId);
|
||||||
mocked(store.getRoom).mockReturnValue(room);
|
mocked(store.getRoom).mockReturnValue(room);
|
||||||
|
@@ -26,6 +26,7 @@ import {
|
|||||||
import { DEFAULT_ALPHABET } from "../../../src/utils";
|
import { DEFAULT_ALPHABET } from "../../../src/utils";
|
||||||
import { MatrixError } from "../../../src/http-api";
|
import { MatrixError } from "../../../src/http-api";
|
||||||
import { KnownMembership } from "../../../src/@types/membership";
|
import { KnownMembership } from "../../../src/@types/membership";
|
||||||
|
import { EncryptedFile } from "../../../src/@types/media";
|
||||||
|
|
||||||
describe("MSC3089TreeSpace", () => {
|
describe("MSC3089TreeSpace", () => {
|
||||||
let client: MatrixClient;
|
let client: MatrixClient;
|
||||||
@@ -947,7 +948,7 @@ describe("MSC3089TreeSpace", () => {
|
|||||||
const fileInfo = {
|
const fileInfo = {
|
||||||
mimetype: "text/plain",
|
mimetype: "text/plain",
|
||||||
// other fields as required by encryption, but ignored here
|
// other fields as required by encryption, but ignored here
|
||||||
};
|
} as unknown as EncryptedFile;
|
||||||
const fileEventId = "$file";
|
const fileEventId = "$file";
|
||||||
const fileName = "My File.txt";
|
const fileName = "My File.txt";
|
||||||
const fileContents = "This is a test file";
|
const fileContents = "This is a test file";
|
||||||
@@ -1007,7 +1008,7 @@ describe("MSC3089TreeSpace", () => {
|
|||||||
const fileInfo = {
|
const fileInfo = {
|
||||||
mimetype: "text/plain",
|
mimetype: "text/plain",
|
||||||
// other fields as required by encryption, but ignored here
|
// other fields as required by encryption, but ignored here
|
||||||
};
|
} as unknown as EncryptedFile;
|
||||||
const fileEventId = "$file";
|
const fileEventId = "$file";
|
||||||
const fileName = "My File.txt";
|
const fileName = "My File.txt";
|
||||||
const fileContents = "This is a test file";
|
const fileContents = "This is a test file";
|
||||||
|
@@ -41,8 +41,23 @@ import {
|
|||||||
IGroupCallRoomState,
|
IGroupCallRoomState,
|
||||||
} from "../webrtc/groupCall";
|
} from "../webrtc/groupCall";
|
||||||
import { MSC3089EventContent } from "../models/MSC3089Branch";
|
import { MSC3089EventContent } from "../models/MSC3089Branch";
|
||||||
import { M_BEACON_INFO, MBeaconInfoEventContent } from "./beacon";
|
import { M_BEACON, M_BEACON_INFO, MBeaconEventContent, MBeaconInfoEventContent } from "./beacon";
|
||||||
import { XOR } from "./common";
|
import { XOR } from "./common";
|
||||||
|
import { ReactionEventContent, RoomMessageEventContent, StickerEventContent } from "./events";
|
||||||
|
import {
|
||||||
|
MCallAnswer,
|
||||||
|
MCallBase,
|
||||||
|
MCallCandidates,
|
||||||
|
MCallHangupReject,
|
||||||
|
MCallInviteNegotiate,
|
||||||
|
MCallReplacesEvent,
|
||||||
|
MCallSelectAnswer,
|
||||||
|
SDPStreamMetadata,
|
||||||
|
SDPStreamMetadataKey,
|
||||||
|
} from "../webrtc/callEventTypes";
|
||||||
|
import { EncryptionKeysEventContent, ICallNotifyContent } from "../matrixrtc/types";
|
||||||
|
import { EncryptedFile } from "./media";
|
||||||
|
import { M_POLL_END, M_POLL_START, PollEndEventContent, PollStartEventContent } from "./polls";
|
||||||
|
|
||||||
export enum EventType {
|
export enum EventType {
|
||||||
// Room state events
|
// Room state events
|
||||||
@@ -283,21 +298,37 @@ export const LOCAL_NOTIFICATION_SETTINGS_PREFIX = new UnstableValue(
|
|||||||
*/
|
*/
|
||||||
export const UNSIGNED_THREAD_ID_FIELD = new UnstableValue("thread_id", "org.matrix.msc4023.thread_id");
|
export const UNSIGNED_THREAD_ID_FIELD = new UnstableValue("thread_id", "org.matrix.msc4023.thread_id");
|
||||||
|
|
||||||
export interface IEncryptedFile {
|
/**
|
||||||
url: string;
|
* @deprecated in favour of {@link EncryptedFile}
|
||||||
mimetype?: string;
|
*/
|
||||||
key: {
|
export type IEncryptedFile = EncryptedFile;
|
||||||
alg: string;
|
|
||||||
key_ops: string[]; // eslint-disable-line camelcase
|
/**
|
||||||
kty: string;
|
* Mapped type from event type to content type for all specified non-state room events.
|
||||||
k: string;
|
*/
|
||||||
ext: boolean;
|
export interface TimelineEvents {
|
||||||
};
|
[EventType.RoomMessage]: RoomMessageEventContent;
|
||||||
iv: string;
|
[EventType.Sticker]: StickerEventContent;
|
||||||
hashes: { [alg: string]: string };
|
[EventType.Reaction]: ReactionEventContent;
|
||||||
v: string;
|
[EventType.CallReplaces]: MCallReplacesEvent;
|
||||||
|
[EventType.CallAnswer]: MCallAnswer;
|
||||||
|
[EventType.CallSelectAnswer]: MCallSelectAnswer;
|
||||||
|
[EventType.CallNegotiate]: Omit<MCallInviteNegotiate, "offer">;
|
||||||
|
[EventType.CallInvite]: MCallInviteNegotiate;
|
||||||
|
[EventType.CallCandidates]: MCallCandidates;
|
||||||
|
[EventType.CallHangup]: MCallHangupReject;
|
||||||
|
[EventType.CallReject]: MCallHangupReject;
|
||||||
|
[EventType.CallSDPStreamMetadataChangedPrefix]: MCallBase & { [SDPStreamMetadataKey]: SDPStreamMetadata };
|
||||||
|
[EventType.CallEncryptionKeysPrefix]: EncryptionKeysEventContent;
|
||||||
|
[EventType.CallNotify]: ICallNotifyContent;
|
||||||
|
[M_BEACON.name]: MBeaconEventContent;
|
||||||
|
[M_POLL_START.name]: PollStartEventContent;
|
||||||
|
[M_POLL_END.name]: PollEndEventContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mapped type from event type to content type for all specified room state events.
|
||||||
|
*/
|
||||||
export interface StateEvents {
|
export interface StateEvents {
|
||||||
[EventType.RoomCanonicalAlias]: RoomCanonicalAliasEventContent;
|
[EventType.RoomCanonicalAlias]: RoomCanonicalAliasEventContent;
|
||||||
[EventType.RoomCreate]: RoomCreateEventContent;
|
[EventType.RoomCreate]: RoomCreateEventContent;
|
||||||
|
119
src/@types/events.ts
Normal file
119
src/@types/events.ts
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2024 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { MsgType, RelationType } from "./event";
|
||||||
|
import { FileInfo, ImageInfo, MediaEventContent } from "./media";
|
||||||
|
import { XOR } from "./common";
|
||||||
|
|
||||||
|
interface BaseTimelineEvent {
|
||||||
|
"body": string;
|
||||||
|
"m.mentions"?: {
|
||||||
|
user_ids?: string[];
|
||||||
|
room?: boolean;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ReplyEvent {
|
||||||
|
"m.relates_to"?: {
|
||||||
|
"m.in_reply_to"?: {
|
||||||
|
event_id: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
interface NoRelationEvent {
|
||||||
|
"m.new_content"?: never;
|
||||||
|
"m.relates_to"?: never;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Partial content format of timeline events with rel_type `m.replace`
|
||||||
|
*
|
||||||
|
* @see https://spec.matrix.org/v1.9/client-server-api/#event-replacements
|
||||||
|
*/
|
||||||
|
export interface ReplacementEvent<T> {
|
||||||
|
"m.new_content": T;
|
||||||
|
"m.relates_to": {
|
||||||
|
event_id: string;
|
||||||
|
rel_type: RelationType.Replace;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Partial content format of timeline events with rel_type other than `m.replace`
|
||||||
|
*
|
||||||
|
* @see https://spec.matrix.org/v1.9/client-server-api/#forming-relationships-between-events
|
||||||
|
*/
|
||||||
|
export interface RelationEvent {
|
||||||
|
"m.new_content"?: never;
|
||||||
|
"m.relates_to": {
|
||||||
|
event_id: string;
|
||||||
|
rel_type: Exclude<RelationType, RelationType.Replace>;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Content format of timeline events with type `m.room.message` and `msgtype` `m.text`, `m.emote`, or `m.notice`
|
||||||
|
*
|
||||||
|
* @see https://spec.matrix.org/v1.9/client-server-api/#mroommessage
|
||||||
|
*/
|
||||||
|
export interface RoomMessageTextEventContent extends BaseTimelineEvent {
|
||||||
|
msgtype: MsgType.Text | MsgType.Emote | MsgType.Notice;
|
||||||
|
format?: "org.matrix.custom.html";
|
||||||
|
formatted_body?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Content format of timeline events with type `m.room.message` and `msgtype` `m.location`
|
||||||
|
*
|
||||||
|
* @see https://spec.matrix.org/v1.9/client-server-api/#mlocation
|
||||||
|
*/
|
||||||
|
export interface RoomMessageLocationEventContent extends BaseTimelineEvent {
|
||||||
|
body: string;
|
||||||
|
geo_uri: string;
|
||||||
|
info: Pick<FileInfo, "thumbnail_info" | "thumbnail_file" | "thumbnail_url">;
|
||||||
|
msgtype: MsgType.Location;
|
||||||
|
}
|
||||||
|
|
||||||
|
type MessageEventContent = RoomMessageTextEventContent | RoomMessageLocationEventContent | MediaEventContent;
|
||||||
|
|
||||||
|
export type RoomMessageEventContent = BaseTimelineEvent &
|
||||||
|
XOR<XOR<ReplacementEvent<MessageEventContent>, RelationEvent>, XOR<ReplyEvent, NoRelationEvent>> &
|
||||||
|
MessageEventContent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Content format of timeline events with type `m.sticker`
|
||||||
|
*
|
||||||
|
* @see https://spec.matrix.org/v1.9/client-server-api/#msticker
|
||||||
|
*/
|
||||||
|
export interface StickerEventContent extends BaseTimelineEvent {
|
||||||
|
body: string;
|
||||||
|
info: ImageInfo;
|
||||||
|
url: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Content format of timeline events with type `m.reaction`
|
||||||
|
*
|
||||||
|
* @see https://spec.matrix.org/v1.9/client-server-api/#mreaction
|
||||||
|
*/
|
||||||
|
export interface ReactionEventContent {
|
||||||
|
"m.relates_to": {
|
||||||
|
event_id: string;
|
||||||
|
key: string;
|
||||||
|
rel_type: RelationType.Annotation;
|
||||||
|
};
|
||||||
|
}
|
@@ -145,6 +145,7 @@ import {
|
|||||||
RoomCreateTypeField,
|
RoomCreateTypeField,
|
||||||
RoomType,
|
RoomType,
|
||||||
StateEvents,
|
StateEvents,
|
||||||
|
TimelineEvents,
|
||||||
UNSTABLE_MSC3088_ENABLED,
|
UNSTABLE_MSC3088_ENABLED,
|
||||||
UNSTABLE_MSC3088_PURPOSE,
|
UNSTABLE_MSC3088_PURPOSE,
|
||||||
UNSTABLE_MSC3089_TREE_SUBTYPE,
|
UNSTABLE_MSC3089_TREE_SUBTYPE,
|
||||||
@@ -223,6 +224,7 @@ import { RegisterRequest, RegisterResponse } from "./@types/registration";
|
|||||||
import { MatrixRTCSessionManager } from "./matrixrtc/MatrixRTCSessionManager";
|
import { MatrixRTCSessionManager } from "./matrixrtc/MatrixRTCSessionManager";
|
||||||
import { getRelationsThreadFilter } from "./thread-utils";
|
import { getRelationsThreadFilter } from "./thread-utils";
|
||||||
import { KnownMembership, Membership } from "./@types/membership";
|
import { KnownMembership, Membership } from "./@types/membership";
|
||||||
|
import { RoomMessageEventContent, StickerEventContent } from "./@types/events";
|
||||||
import { ImageInfo } from "./@types/media";
|
import { ImageInfo } from "./@types/media";
|
||||||
|
|
||||||
export type Store = IStore;
|
export type Store = IStore;
|
||||||
@@ -4551,12 +4553,17 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|||||||
return this.sendStateEvent(roomId, M_BEACON_INFO.name, beaconInfoContent, this.getUserId()!);
|
return this.sendStateEvent(roomId, M_BEACON_INFO.name, beaconInfoContent, this.getUserId()!);
|
||||||
}
|
}
|
||||||
|
|
||||||
public sendEvent(roomId: string, eventType: string, content: IContent, txnId?: string): Promise<ISendEventResponse>;
|
public sendEvent<K extends keyof TimelineEvents>(
|
||||||
public sendEvent(
|
roomId: string,
|
||||||
|
eventType: K,
|
||||||
|
content: TimelineEvents[K],
|
||||||
|
txnId?: string,
|
||||||
|
): Promise<ISendEventResponse>;
|
||||||
|
public sendEvent<K extends keyof TimelineEvents>(
|
||||||
roomId: string,
|
roomId: string,
|
||||||
threadId: string | null,
|
threadId: string | null,
|
||||||
eventType: string,
|
eventType: K,
|
||||||
content: IContent,
|
content: TimelineEvents[K],
|
||||||
txnId?: string,
|
txnId?: string,
|
||||||
): Promise<ISendEventResponse>;
|
): Promise<ISendEventResponse>;
|
||||||
public sendEvent(
|
public sendEvent(
|
||||||
@@ -4943,27 +4950,27 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|||||||
* @returns Promise which resolves: to an ISendEventResponse object
|
* @returns Promise which resolves: to an ISendEventResponse object
|
||||||
* @returns Rejects: with an error response.
|
* @returns Rejects: with an error response.
|
||||||
*/
|
*/
|
||||||
public sendMessage(roomId: string, content: IContent, txnId?: string): Promise<ISendEventResponse>;
|
public sendMessage(roomId: string, content: RoomMessageEventContent, txnId?: string): Promise<ISendEventResponse>;
|
||||||
public sendMessage(
|
public sendMessage(
|
||||||
roomId: string,
|
roomId: string,
|
||||||
threadId: string | null,
|
threadId: string | null,
|
||||||
content: IContent,
|
content: RoomMessageEventContent,
|
||||||
txnId?: string,
|
txnId?: string,
|
||||||
): Promise<ISendEventResponse>;
|
): Promise<ISendEventResponse>;
|
||||||
public sendMessage(
|
public sendMessage(
|
||||||
roomId: string,
|
roomId: string,
|
||||||
threadId: string | null | IContent,
|
threadId: string | null | RoomMessageEventContent,
|
||||||
content?: IContent | string,
|
content?: RoomMessageEventContent | string,
|
||||||
txnId?: string,
|
txnId?: string,
|
||||||
): Promise<ISendEventResponse> {
|
): Promise<ISendEventResponse> {
|
||||||
if (typeof threadId !== "string" && threadId !== null) {
|
if (typeof threadId !== "string" && threadId !== null) {
|
||||||
txnId = content as string;
|
txnId = content as string;
|
||||||
content = threadId as IContent;
|
content = threadId as RoomMessageEventContent;
|
||||||
threadId = null;
|
threadId = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const eventType: string = EventType.RoomMessage;
|
const eventType = EventType.RoomMessage;
|
||||||
const sendContent: IContent = content as IContent;
|
const sendContent = content as RoomMessageEventContent;
|
||||||
|
|
||||||
return this.sendEvent(roomId, threadId as string | null, eventType, sendContent, txnId);
|
return this.sendEvent(roomId, threadId as string | null, eventType, sendContent, txnId);
|
||||||
}
|
}
|
||||||
@@ -5076,10 +5083,10 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|||||||
}
|
}
|
||||||
const content = {
|
const content = {
|
||||||
msgtype: MsgType.Image,
|
msgtype: MsgType.Image,
|
||||||
url: url,
|
url: url as string,
|
||||||
info: info,
|
info: info as ImageInfo,
|
||||||
body: text,
|
body: text,
|
||||||
};
|
} satisfies RoomMessageEventContent;
|
||||||
return this.sendMessage(roomId, threadId, content);
|
return this.sendMessage(roomId, threadId, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5114,10 +5121,10 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|||||||
threadId = null;
|
threadId = null;
|
||||||
}
|
}
|
||||||
const content = {
|
const content = {
|
||||||
url: url,
|
url: url as string,
|
||||||
info: info,
|
info: info as ImageInfo,
|
||||||
body: text,
|
body: text,
|
||||||
};
|
} satisfies StickerEventContent;
|
||||||
|
|
||||||
return this.sendEvent(roomId, threadId, EventType.Sticker, content);
|
return this.sendEvent(roomId, threadId, EventType.Sticker, content);
|
||||||
}
|
}
|
||||||
|
@@ -30,7 +30,7 @@ import {
|
|||||||
LegacyLocationEventContent,
|
LegacyLocationEventContent,
|
||||||
} from "./@types/location";
|
} from "./@types/location";
|
||||||
import { MRoomTopicEventContent, MTopicContent, M_TOPIC } from "./@types/topic";
|
import { MRoomTopicEventContent, MTopicContent, M_TOPIC } from "./@types/topic";
|
||||||
import { IContent } from "./models/event";
|
import { RoomMessageEventContent } from "./@types/events";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates the content for a HTML Message event
|
* Generates the content for a HTML Message event
|
||||||
@@ -38,7 +38,7 @@ import { IContent } from "./models/event";
|
|||||||
* @param htmlBody - the HTML representation of the message
|
* @param htmlBody - the HTML representation of the message
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export function makeHtmlMessage(body: string, htmlBody: string): IContent {
|
export function makeHtmlMessage(body: string, htmlBody: string): RoomMessageEventContent {
|
||||||
return {
|
return {
|
||||||
msgtype: MsgType.Text,
|
msgtype: MsgType.Text,
|
||||||
format: "org.matrix.custom.html",
|
format: "org.matrix.custom.html",
|
||||||
@@ -53,7 +53,7 @@ export function makeHtmlMessage(body: string, htmlBody: string): IContent {
|
|||||||
* @param htmlBody - the HTML representation of the notice
|
* @param htmlBody - the HTML representation of the notice
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export function makeHtmlNotice(body: string, htmlBody: string): IContent {
|
export function makeHtmlNotice(body: string, htmlBody: string): RoomMessageEventContent {
|
||||||
return {
|
return {
|
||||||
msgtype: MsgType.Notice,
|
msgtype: MsgType.Notice,
|
||||||
format: "org.matrix.custom.html",
|
format: "org.matrix.custom.html",
|
||||||
@@ -68,7 +68,7 @@ export function makeHtmlNotice(body: string, htmlBody: string): IContent {
|
|||||||
* @param htmlBody - the HTML representation of the emote
|
* @param htmlBody - the HTML representation of the emote
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export function makeHtmlEmote(body: string, htmlBody: string): IContent {
|
export function makeHtmlEmote(body: string, htmlBody: string): RoomMessageEventContent {
|
||||||
return {
|
return {
|
||||||
msgtype: MsgType.Emote,
|
msgtype: MsgType.Emote,
|
||||||
format: "org.matrix.custom.html",
|
format: "org.matrix.custom.html",
|
||||||
@@ -82,7 +82,7 @@ export function makeHtmlEmote(body: string, htmlBody: string): IContent {
|
|||||||
* @param body - the plaintext body of the emote
|
* @param body - the plaintext body of the emote
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export function makeTextMessage(body: string): IContent {
|
export function makeTextMessage(body: string): RoomMessageEventContent {
|
||||||
return {
|
return {
|
||||||
msgtype: MsgType.Text,
|
msgtype: MsgType.Text,
|
||||||
body: body,
|
body: body,
|
||||||
@@ -94,7 +94,7 @@ export function makeTextMessage(body: string): IContent {
|
|||||||
* @param body - the plaintext body of the notice
|
* @param body - the plaintext body of the notice
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export function makeNotice(body: string): IContent {
|
export function makeNotice(body: string): RoomMessageEventContent {
|
||||||
return {
|
return {
|
||||||
msgtype: MsgType.Notice,
|
msgtype: MsgType.Notice,
|
||||||
body: body,
|
body: body,
|
||||||
@@ -106,7 +106,7 @@ export function makeNotice(body: string): IContent {
|
|||||||
* @param body - the plaintext body of the emote
|
* @param body - the plaintext body of the emote
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export function makeEmoteMessage(body: string): IContent {
|
export function makeEmoteMessage(body: string): RoomMessageEventContent {
|
||||||
return {
|
return {
|
||||||
msgtype: MsgType.Emote,
|
msgtype: MsgType.Emote,
|
||||||
body: body,
|
body: body,
|
||||||
|
@@ -18,7 +18,7 @@ limitations under the License.
|
|||||||
import { VerificationRequest, REQUEST_TYPE, READY_TYPE, START_TYPE } from "./VerificationRequest";
|
import { VerificationRequest, REQUEST_TYPE, READY_TYPE, START_TYPE } from "./VerificationRequest";
|
||||||
import { logger } from "../../../logger";
|
import { logger } from "../../../logger";
|
||||||
import { IVerificationChannel } from "./Channel";
|
import { IVerificationChannel } from "./Channel";
|
||||||
import { EventType } from "../../../@types/event";
|
import { EventType, TimelineEvents } from "../../../@types/event";
|
||||||
import { MatrixClient } from "../../../client";
|
import { MatrixClient } from "../../../client";
|
||||||
import { MatrixEvent } from "../../../models/event";
|
import { MatrixEvent } from "../../../models/event";
|
||||||
import { IRequestsMap } from "../..";
|
import { IRequestsMap } from "../..";
|
||||||
@@ -299,7 +299,11 @@ export class InRoomChannel implements IVerificationChannel {
|
|||||||
if (type === REQUEST_TYPE) {
|
if (type === REQUEST_TYPE) {
|
||||||
sendType = MESSAGE_TYPE;
|
sendType = MESSAGE_TYPE;
|
||||||
}
|
}
|
||||||
const response = await this.client.sendEvent(this.roomId, sendType, content);
|
const response = await this.client.sendEvent(
|
||||||
|
this.roomId,
|
||||||
|
sendType as keyof TimelineEvents,
|
||||||
|
content as TimelineEvents[keyof TimelineEvents],
|
||||||
|
);
|
||||||
if (type === REQUEST_TYPE) {
|
if (type === REQUEST_TYPE) {
|
||||||
this.requestEventId = response.event_id;
|
this.requestEventId = response.event_id;
|
||||||
}
|
}
|
||||||
|
@@ -15,12 +15,20 @@ limitations under the License.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { MatrixClient } from "../client";
|
import { MatrixClient } from "../client";
|
||||||
import { IEncryptedFile, RelationType, UNSTABLE_MSC3089_BRANCH } from "../@types/event";
|
import { RelationType, UNSTABLE_MSC3089_BRANCH } from "../@types/event";
|
||||||
import { IContent, MatrixEvent } from "./event";
|
import { IContent, MatrixEvent } from "./event";
|
||||||
import { MSC3089TreeSpace } from "./MSC3089TreeSpace";
|
import { MSC3089TreeSpace } from "./MSC3089TreeSpace";
|
||||||
import { EventTimeline } from "./event-timeline";
|
import { EventTimeline } from "./event-timeline";
|
||||||
import { FileType } from "../http-api";
|
import { FileType } from "../http-api";
|
||||||
import type { ISendEventResponse } from "../@types/requests";
|
import type { ISendEventResponse } from "../@types/requests";
|
||||||
|
import { EncryptedFile } from "../@types/media";
|
||||||
|
|
||||||
|
export interface MSC3089EventContent {
|
||||||
|
active?: boolean;
|
||||||
|
name?: string;
|
||||||
|
locked?: boolean;
|
||||||
|
version?: number;
|
||||||
|
}
|
||||||
|
|
||||||
export interface MSC3089EventContent {
|
export interface MSC3089EventContent {
|
||||||
active?: boolean;
|
active?: boolean;
|
||||||
@@ -138,7 +146,7 @@ export class MSC3089Branch {
|
|||||||
* Gets information about the file needed to download it.
|
* Gets information about the file needed to download it.
|
||||||
* @returns Information about the file.
|
* @returns Information about the file.
|
||||||
*/
|
*/
|
||||||
public async getFileInfo(): Promise<{ info: IEncryptedFile; httpUrl: string }> {
|
public async getFileInfo(): Promise<{ info: EncryptedFile; httpUrl: string }> {
|
||||||
const event = await this.getFileEvent();
|
const event = await this.getFileEvent();
|
||||||
|
|
||||||
const file = event.getOriginalContent()["file"];
|
const file = event.getOriginalContent()["file"];
|
||||||
@@ -186,7 +194,7 @@ export class MSC3089Branch {
|
|||||||
public async createNewVersion(
|
public async createNewVersion(
|
||||||
name: string,
|
name: string,
|
||||||
encryptedContents: FileType,
|
encryptedContents: FileType,
|
||||||
info: Partial<IEncryptedFile>,
|
info: EncryptedFile,
|
||||||
additionalContent?: IContent,
|
additionalContent?: IContent,
|
||||||
): Promise<ISendEventResponse> {
|
): Promise<ISendEventResponse> {
|
||||||
const fileEventResponse = await this.directory.createFile(name, encryptedContents, info, {
|
const fileEventResponse = await this.directory.createFile(name, encryptedContents, info, {
|
||||||
|
@@ -17,7 +17,7 @@ limitations under the License.
|
|||||||
import promiseRetry from "p-retry";
|
import promiseRetry from "p-retry";
|
||||||
|
|
||||||
import { MatrixClient } from "../client";
|
import { MatrixClient } from "../client";
|
||||||
import { EventType, IEncryptedFile, MsgType, UNSTABLE_MSC3089_BRANCH, UNSTABLE_MSC3089_LEAF } from "../@types/event";
|
import { EventType, MsgType, UNSTABLE_MSC3089_BRANCH, UNSTABLE_MSC3089_LEAF } from "../@types/event";
|
||||||
import { Room } from "./room";
|
import { Room } from "./room";
|
||||||
import { logger } from "../logger";
|
import { logger } from "../logger";
|
||||||
import { IContent, MatrixEvent } from "./event";
|
import { IContent, MatrixEvent } from "./event";
|
||||||
@@ -35,6 +35,7 @@ import { ISendEventResponse } from "../@types/requests";
|
|||||||
import { FileType } from "../http-api";
|
import { FileType } from "../http-api";
|
||||||
import { KnownMembership } from "../@types/membership";
|
import { KnownMembership } from "../@types/membership";
|
||||||
import { RoomPowerLevelsEventContent, SpaceChildEventContent } from "../@types/state_events";
|
import { RoomPowerLevelsEventContent, SpaceChildEventContent } from "../@types/state_events";
|
||||||
|
import { EncryptedFile, FileContent } from "../@types/media";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The recommended defaults for a tree space's power levels. Note that this
|
* The recommended defaults for a tree space's power levels. Note that this
|
||||||
@@ -79,6 +80,12 @@ export enum TreePermissions {
|
|||||||
Owner = "owner", // "Admin" or PL100
|
Owner = "owner", // "Admin" or PL100
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare module "../@types/media" {
|
||||||
|
interface FileContent {
|
||||||
|
[UNSTABLE_MSC3089_LEAF.name]?: {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a [MSC3089](https://github.com/matrix-org/matrix-doc/pull/3089)
|
* Represents a [MSC3089](https://github.com/matrix-org/matrix-doc/pull/3089)
|
||||||
* file tree Space. Note that this is UNSTABLE and subject to breaking changes
|
* file tree Space. Note that this is UNSTABLE and subject to breaking changes
|
||||||
@@ -502,7 +509,7 @@ export class MSC3089TreeSpace {
|
|||||||
public async createFile(
|
public async createFile(
|
||||||
name: string,
|
name: string,
|
||||||
encryptedContents: FileType,
|
encryptedContents: FileType,
|
||||||
info: Partial<IEncryptedFile>,
|
info: EncryptedFile,
|
||||||
additionalContent?: IContent,
|
additionalContent?: IContent,
|
||||||
): Promise<ISendEventResponse> {
|
): Promise<ISendEventResponse> {
|
||||||
const { content_uri: mxc } = await this.client.uploadContent(encryptedContents, {
|
const { content_uri: mxc } = await this.client.uploadContent(encryptedContents, {
|
||||||
@@ -510,7 +517,7 @@ export class MSC3089TreeSpace {
|
|||||||
});
|
});
|
||||||
info.url = mxc;
|
info.url = mxc;
|
||||||
|
|
||||||
const fileContent = {
|
const fileContent: FileContent = {
|
||||||
msgtype: MsgType.File,
|
msgtype: MsgType.File,
|
||||||
body: name,
|
body: name,
|
||||||
url: mxc,
|
url: mxc,
|
||||||
@@ -529,7 +536,7 @@ export class MSC3089TreeSpace {
|
|||||||
...additionalContent,
|
...additionalContent,
|
||||||
...fileContent,
|
...fileContent,
|
||||||
[UNSTABLE_MSC3089_LEAF.name]: {},
|
[UNSTABLE_MSC3089_LEAF.name]: {},
|
||||||
});
|
} as FileContent);
|
||||||
|
|
||||||
await this.client.sendStateEvent(
|
await this.client.sendStateEvent(
|
||||||
this.roomId,
|
this.roomId,
|
||||||
|
@@ -24,6 +24,7 @@ limitations under the License.
|
|||||||
export type * from "./@types/media";
|
export type * from "./@types/media";
|
||||||
export * from "./@types/membership";
|
export * from "./@types/membership";
|
||||||
export type * from "./@types/event";
|
export type * from "./@types/event";
|
||||||
|
export type * from "./@types/events";
|
||||||
export type * from "./@types/state_events";
|
export type * from "./@types/state_events";
|
||||||
|
|
||||||
/** The different methods for device and user verification */
|
/** The different methods for device and user verification */
|
||||||
|
@@ -26,8 +26,8 @@ import { parse as parseSdp, write as writeSdp } from "sdp-transform";
|
|||||||
|
|
||||||
import { logger } from "../logger";
|
import { logger } from "../logger";
|
||||||
import { checkObjectHasKeys, isNullOrUndefined, recursivelyAssign } from "../utils";
|
import { checkObjectHasKeys, isNullOrUndefined, recursivelyAssign } from "../utils";
|
||||||
import { IContent, MatrixEvent } from "../models/event";
|
import { MatrixEvent } from "../models/event";
|
||||||
import { EventType, ToDeviceMessageId } from "../@types/event";
|
import { EventType, TimelineEvents, ToDeviceMessageId } from "../@types/event";
|
||||||
import { RoomMember } from "../models/room-member";
|
import { RoomMember } from "../models/room-member";
|
||||||
import { randomString } from "../randomstring";
|
import { randomString } from "../randomstring";
|
||||||
import {
|
import {
|
||||||
@@ -293,13 +293,24 @@ function getCodecParamMods(isPtt: boolean): CodecParamsMod[] {
|
|||||||
return mods;
|
return mods;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CallEventType =
|
||||||
|
| EventType.CallReplaces
|
||||||
|
| EventType.CallAnswer
|
||||||
|
| EventType.CallSelectAnswer
|
||||||
|
| EventType.CallNegotiate
|
||||||
|
| EventType.CallInvite
|
||||||
|
| EventType.CallCandidates
|
||||||
|
| EventType.CallHangup
|
||||||
|
| EventType.CallReject
|
||||||
|
| EventType.CallSDPStreamMetadataChangedPrefix;
|
||||||
|
|
||||||
export interface VoipEvent {
|
export interface VoipEvent {
|
||||||
type: "toDevice" | "sendEvent";
|
type: "toDevice" | "sendEvent";
|
||||||
eventType: string;
|
eventType: string;
|
||||||
userId?: string;
|
userId?: string;
|
||||||
opponentDeviceId?: string;
|
opponentDeviceId?: string;
|
||||||
roomId?: string;
|
roomId?: string;
|
||||||
content: Record<string, unknown>;
|
content: TimelineEvents[CallEventType];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -406,7 +417,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
|
|||||||
// If candidates arrive before we've picked an opponent (which, in particular,
|
// If candidates arrive before we've picked an opponent (which, in particular,
|
||||||
// will happen if the opponent sends candidates eagerly before the user answers
|
// will happen if the opponent sends candidates eagerly before the user answers
|
||||||
// the call) we buffer them up here so we can then add the ones from the party we pick
|
// the call) we buffer them up here so we can then add the ones from the party we pick
|
||||||
private remoteCandidateBuffer = new Map<string, RTCIceCandidate[]>();
|
private remoteCandidateBuffer = new Map<string, MCallCandidates["candidates"]>();
|
||||||
|
|
||||||
private remoteAssertedIdentity?: AssertedIdentity;
|
private remoteAssertedIdentity?: AssertedIdentity;
|
||||||
private remoteSDPStreamMetadata?: SDPStreamMetadata;
|
private remoteSDPStreamMetadata?: SDPStreamMetadata;
|
||||||
@@ -1156,7 +1167,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
|
|||||||
this.terminate(CallParty.Local, reason, !suppressEvent);
|
this.terminate(CallParty.Local, reason, !suppressEvent);
|
||||||
// We don't want to send hangup here if we didn't even get to sending an invite
|
// We don't want to send hangup here if we didn't even get to sending an invite
|
||||||
if ([CallState.Fledgling, CallState.WaitLocalMedia].includes(this.state)) return;
|
if ([CallState.Fledgling, CallState.WaitLocalMedia].includes(this.state)) return;
|
||||||
const content: IContent = {};
|
const content: Omit<MCallHangupReject, "version" | "call_id" | "party_id" | "conf_id"> = {};
|
||||||
// Don't send UserHangup reason to older clients
|
// Don't send UserHangup reason to older clients
|
||||||
if ((this.opponentVersion && this.opponentVersion !== 0) || reason !== CallErrorCode.UserHangup) {
|
if ((this.opponentVersion && this.opponentVersion !== 0) || reason !== CallErrorCode.UserHangup) {
|
||||||
content["reason"] = reason;
|
content["reason"] = reason;
|
||||||
@@ -1916,7 +1927,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
|
|||||||
if (this.opponentPartyId !== null) {
|
if (this.opponentPartyId !== null) {
|
||||||
try {
|
try {
|
||||||
await this.sendVoipEvent(EventType.CallSelectAnswer, {
|
await this.sendVoipEvent(EventType.CallSelectAnswer, {
|
||||||
selected_party_id: this.opponentPartyId,
|
selected_party_id: this.opponentPartyId!,
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// This isn't fatal, and will just mean that if another party has raced to answer
|
// This isn't fatal, and will just mean that if another party has raced to answer
|
||||||
@@ -2012,6 +2023,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
|
|||||||
logger.debug(`Call ${this.callId} onNegotiateReceived() create an answer`);
|
logger.debug(`Call ${this.callId} onNegotiateReceived() create an answer`);
|
||||||
|
|
||||||
this.sendVoipEvent(EventType.CallNegotiate, {
|
this.sendVoipEvent(EventType.CallNegotiate, {
|
||||||
|
lifetime: CALL_TIMEOUT_MS,
|
||||||
description: this.peerConn!.localDescription?.toJSON(),
|
description: this.peerConn!.localDescription?.toJSON(),
|
||||||
[SDPStreamMetadataKey]: this.getLocalSDPStreamMetadata(true),
|
[SDPStreamMetadataKey]: this.getLocalSDPStreamMetadata(true),
|
||||||
});
|
});
|
||||||
@@ -2444,13 +2456,17 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
|
|||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
private async sendVoipEvent(eventType: string, content: object): Promise<void> {
|
private async sendVoipEvent<K extends keyof Pick<TimelineEvents, CallEventType>>(
|
||||||
const realContent = Object.assign({}, content, {
|
eventType: K,
|
||||||
|
content: Omit<TimelineEvents[K], "version" | "call_id" | "party_id" | "conf_id">,
|
||||||
|
): Promise<void> {
|
||||||
|
const realContent = {
|
||||||
|
...content,
|
||||||
version: VOIP_PROTO_VERSION,
|
version: VOIP_PROTO_VERSION,
|
||||||
call_id: this.callId,
|
call_id: this.callId,
|
||||||
party_id: this.ourPartyId,
|
party_id: this.ourPartyId,
|
||||||
conf_id: this.groupCallId,
|
conf_id: this.groupCallId,
|
||||||
});
|
} as TimelineEvents[K];
|
||||||
|
|
||||||
if (this.opponentDeviceId) {
|
if (this.opponentDeviceId) {
|
||||||
const toDeviceSeq = this.toDeviceSeq++;
|
const toDeviceSeq = this.toDeviceSeq++;
|
||||||
@@ -2729,7 +2745,9 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
|
|||||||
const candidates = this.candidateSendQueue;
|
const candidates = this.candidateSendQueue;
|
||||||
this.candidateSendQueue = [];
|
this.candidateSendQueue = [];
|
||||||
++this.candidateSendTries;
|
++this.candidateSendTries;
|
||||||
const content = { candidates: candidates.map((candidate) => candidate.toJSON()) };
|
const content: Pick<MCallCandidates, "candidates"> = {
|
||||||
|
candidates: candidates.map((candidate) => candidate.toJSON()),
|
||||||
|
};
|
||||||
if (this.candidatesEnded) {
|
if (this.candidatesEnded) {
|
||||||
// If there are no more candidates, signal this by adding an empty string candidate
|
// If there are no more candidates, signal this by adding an empty string candidate
|
||||||
content.candidates.push({
|
content.candidates.push({
|
||||||
@@ -2923,7 +2941,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
|
|||||||
this.remoteCandidateBuffer.clear();
|
this.remoteCandidateBuffer.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async addIceCandidates(candidates: RTCIceCandidate[]): Promise<void> {
|
private async addIceCandidates(candidates: RTCIceCandidate[] | MCallCandidates["candidates"]): Promise<void> {
|
||||||
for (const candidate of candidates) {
|
for (const candidate of candidates) {
|
||||||
if (
|
if (
|
||||||
(candidate.sdpMid === null || candidate.sdpMid === undefined) &&
|
(candidate.sdpMid === null || candidate.sdpMid === undefined) &&
|
||||||
|
@@ -34,6 +34,7 @@ export interface CallReplacesTarget {
|
|||||||
|
|
||||||
export interface MCallBase {
|
export interface MCallBase {
|
||||||
call_id: string;
|
call_id: string;
|
||||||
|
conf_id?: string;
|
||||||
version: string | number;
|
version: string | number;
|
||||||
party_id?: string;
|
party_id?: string;
|
||||||
sender_session_id?: string;
|
sender_session_id?: string;
|
||||||
@@ -82,7 +83,7 @@ export interface MCAllAssertedIdentity extends MCallBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface MCallCandidates extends MCallBase {
|
export interface MCallCandidates extends MCallBase {
|
||||||
candidates: RTCIceCandidate[];
|
candidates: Omit<RTCIceCandidateInit, "usernameFragment">[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MCallHangupReject extends MCallBase {
|
export interface MCallHangupReject extends MCallBase {
|
||||||
|
Reference in New Issue
Block a user