matrix-js-sdk 34.2.0 → 34.3.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/git-revision.txt +1 -1
- package/lib/@types/global.d.js.map +1 -1
- package/lib/@types/requests.d.ts +37 -0
- package/lib/@types/requests.d.ts.map +1 -1
- package/lib/@types/requests.js +28 -1
- package/lib/@types/requests.js.map +1 -1
- package/lib/client.d.ts +48 -4
- package/lib/client.d.ts.map +1 -1
- package/lib/client.js +412 -257
- package/lib/client.js.map +1 -1
- package/lib/crypto/algorithms/base.d.ts +0 -2
- package/lib/crypto/algorithms/base.d.ts.map +1 -1
- package/lib/crypto/algorithms/base.js +0 -4
- package/lib/crypto/algorithms/base.js.map +1 -1
- package/lib/digest.d.ts +10 -0
- package/lib/digest.d.ts.map +1 -0
- package/lib/digest.js +40 -0
- package/lib/digest.js.map +1 -0
- package/lib/embedded.d.ts +24 -1
- package/lib/embedded.d.ts.map +1 -1
- package/lib/embedded.js +84 -26
- package/lib/embedded.js.map +1 -1
- package/lib/matrixrtc/MatrixRTCSession.d.ts +2 -0
- package/lib/matrixrtc/MatrixRTCSession.d.ts.map +1 -1
- package/lib/matrixrtc/MatrixRTCSession.js +44 -15
- package/lib/matrixrtc/MatrixRTCSession.js.map +1 -1
- package/lib/matrixrtc/index.d.ts +7 -0
- package/lib/matrixrtc/index.d.ts.map +1 -0
- package/lib/matrixrtc/index.js +23 -0
- package/lib/matrixrtc/index.js.map +1 -0
- package/lib/models/event.js.map +1 -1
- package/lib/oidc/authorize.d.ts.map +1 -1
- package/lib/oidc/authorize.js +4 -3
- package/lib/oidc/authorize.js.map +1 -1
- package/lib/rust-crypto/RoomEncryptor.d.ts +1 -1
- package/lib/rust-crypto/RoomEncryptor.d.ts.map +1 -1
- package/lib/rust-crypto/RoomEncryptor.js +6 -2
- package/lib/rust-crypto/RoomEncryptor.js.map +1 -1
- package/lib/rust-crypto/index.js +1 -0
- package/lib/rust-crypto/index.js.map +1 -1
- package/lib/rust-crypto/rust-crypto.d.ts +9 -0
- package/lib/rust-crypto/rust-crypto.d.ts.map +1 -1
- package/lib/rust-crypto/rust-crypto.js +83 -58
- package/lib/rust-crypto/rust-crypto.js.map +1 -1
- package/lib/sync-accumulator.js.map +1 -1
- package/lib/sync.d.ts.map +1 -1
- package/lib/sync.js.map +1 -1
- package/package.json +6 -6
- package/src/@types/global.d.ts +0 -45
- package/src/@types/requests.ts +50 -0
- package/src/client.ts +237 -46
- package/src/crypto/algorithms/base.ts +0 -4
- package/src/digest.ts +34 -0
- package/src/embedded.ts +109 -5
- package/src/matrixrtc/MatrixRTCSession.ts +52 -20
- package/src/matrixrtc/index.ts +22 -0
- package/src/models/event.ts +1 -1
- package/src/oidc/authorize.ts +4 -7
- package/src/rust-crypto/RoomEncryptor.ts +10 -6
- package/src/rust-crypto/index.ts +3 -0
- package/src/rust-crypto/rust-crypto.ts +51 -24
- package/src/sync-accumulator.ts +1 -1
- package/src/sync.ts +3 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "matrix-js-sdk",
|
|
3
|
-
"version": "34.
|
|
3
|
+
"version": "34.3.0-rc.0",
|
|
4
4
|
"description": "Matrix Client-Server SDK for Javascript",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=20.0.0"
|
|
@@ -53,15 +53,14 @@
|
|
|
53
53
|
],
|
|
54
54
|
"dependencies": {
|
|
55
55
|
"@babel/runtime": "^7.12.5",
|
|
56
|
-
"@matrix-org/matrix-sdk-crypto-wasm": "^
|
|
57
|
-
"@matrix-org/olm": "3.2.15",
|
|
56
|
+
"@matrix-org/matrix-sdk-crypto-wasm": "^7.0.0",
|
|
58
57
|
"another-json": "^0.2.0",
|
|
59
58
|
"bs58": "^6.0.0",
|
|
60
59
|
"content-type": "^1.0.4",
|
|
61
60
|
"jwt-decode": "^4.0.0",
|
|
62
61
|
"loglevel": "^1.7.1",
|
|
63
62
|
"matrix-events-sdk": "0.0.1",
|
|
64
|
-
"matrix-widget-api": "^1.
|
|
63
|
+
"matrix-widget-api": "^1.8.2",
|
|
65
64
|
"oidc-client-ts": "^3.0.1",
|
|
66
65
|
"p-retry": "4",
|
|
67
66
|
"sdp-transform": "^2.14.1",
|
|
@@ -83,6 +82,7 @@
|
|
|
83
82
|
"@babel/preset-env": "^7.12.11",
|
|
84
83
|
"@babel/preset-typescript": "^7.12.7",
|
|
85
84
|
"@casualbot/jest-sonar-reporter": "2.2.7",
|
|
85
|
+
"@matrix-org/olm": "3.2.15",
|
|
86
86
|
"@peculiar/webcrypto": "^1.4.5",
|
|
87
87
|
"@types/bs58": "^4.0.1",
|
|
88
88
|
"@types/content-type": "^1.1.5",
|
|
@@ -106,7 +106,7 @@
|
|
|
106
106
|
"eslint-plugin-tsdoc": "^0.3.0",
|
|
107
107
|
"eslint-plugin-unicorn": "^54.0.0",
|
|
108
108
|
"fake-indexeddb": "^5.0.2",
|
|
109
|
-
"fetch-mock": "10.0
|
|
109
|
+
"fetch-mock": "10.1.0",
|
|
110
110
|
"fetch-mock-jest": "^1.5.1",
|
|
111
111
|
"husky": "^9.0.0",
|
|
112
112
|
"jest": "^29.0.0",
|
|
@@ -117,7 +117,7 @@
|
|
|
117
117
|
"lint-staged": "^15.0.2",
|
|
118
118
|
"matrix-mock-request": "^2.5.0",
|
|
119
119
|
"node-fetch": "^2.7.0",
|
|
120
|
-
"prettier": "3.3.
|
|
120
|
+
"prettier": "3.3.3",
|
|
121
121
|
"rimraf": "^6.0.0",
|
|
122
122
|
"ts-node": "^10.9.2",
|
|
123
123
|
"typedoc": "^0.26.0",
|
package/src/@types/global.d.ts
CHANGED
|
@@ -29,20 +29,11 @@ declare global {
|
|
|
29
29
|
|
|
30
30
|
namespace NodeJS {
|
|
31
31
|
interface Global {
|
|
32
|
-
localStorage: Storage;
|
|
33
32
|
// marker variable used to detect both the browser & node entrypoints being used at once
|
|
34
33
|
__js_sdk_entrypoint: unknown;
|
|
35
34
|
}
|
|
36
35
|
}
|
|
37
36
|
|
|
38
|
-
interface Window {
|
|
39
|
-
webkitAudioContext: typeof AudioContext;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
interface Crypto {
|
|
43
|
-
webkitSubtle?: Window["crypto"]["subtle"];
|
|
44
|
-
}
|
|
45
|
-
|
|
46
37
|
interface MediaDevices {
|
|
47
38
|
// This is experimental and types don't know about it yet
|
|
48
39
|
// https://github.com/microsoft/TypeScript/issues/33232
|
|
@@ -76,40 +67,4 @@ declare global {
|
|
|
76
67
|
// on webkit: we should check if we still need to do this
|
|
77
68
|
webkitGetUserMedia: DummyInterfaceWeShouldntBeUsingThis;
|
|
78
69
|
}
|
|
79
|
-
|
|
80
|
-
export interface ISettledFulfilled<T> {
|
|
81
|
-
status: "fulfilled";
|
|
82
|
-
value: T;
|
|
83
|
-
}
|
|
84
|
-
export interface ISettledRejected {
|
|
85
|
-
status: "rejected";
|
|
86
|
-
reason: any;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
interface PromiseConstructor {
|
|
90
|
-
allSettled<T>(promises: Promise<T>[]): Promise<Array<ISettledFulfilled<T> | ISettledRejected>>;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
interface RTCRtpTransceiver {
|
|
94
|
-
// This has been removed from TS
|
|
95
|
-
// (https://github.com/microsoft/TypeScript-DOM-lib-generator/issues/1029),
|
|
96
|
-
// but we still need this for MatrixCall::getRidOfRTXCodecs()
|
|
97
|
-
setCodecPreferences(codecs: RTCRtpCodecCapability[]): void;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
interface RequestInit {
|
|
101
|
-
/**
|
|
102
|
-
* Specifies the priority of the fetch request relative to other requests of the same type.
|
|
103
|
-
* Must be one of the following strings:
|
|
104
|
-
* high: A high priority fetch request relative to other requests of the same type.
|
|
105
|
-
* low: A low priority fetch request relative to other requests of the same type.
|
|
106
|
-
* auto: Automatically determine the priority of the fetch request relative to other requests of the same type (default).
|
|
107
|
-
*
|
|
108
|
-
* @see https://html.spec.whatwg.org/multipage/urls-and-fetching.html#fetch-priority-attribute
|
|
109
|
-
* @see https://github.com/microsoft/TypeScript/issues/54472
|
|
110
|
-
* @see https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API#browser_compatibility
|
|
111
|
-
* Not yet supported in Safari or Firefox
|
|
112
|
-
*/
|
|
113
|
-
priority?: "high" | "low" | "auto";
|
|
114
|
-
}
|
|
115
70
|
}
|
package/src/@types/requests.ts
CHANGED
|
@@ -76,6 +76,56 @@ export interface ISendEventResponse {
|
|
|
76
76
|
event_id: string;
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
+
export type TimeoutDelay = {
|
|
80
|
+
delay: number;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export type ParentDelayId = {
|
|
84
|
+
parent_delay_id: string;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export type SendTimeoutDelayedEventRequestOpts = TimeoutDelay & Partial<ParentDelayId>;
|
|
88
|
+
export type SendActionDelayedEventRequestOpts = ParentDelayId;
|
|
89
|
+
|
|
90
|
+
export type SendDelayedEventRequestOpts = SendTimeoutDelayedEventRequestOpts | SendActionDelayedEventRequestOpts;
|
|
91
|
+
|
|
92
|
+
export type SendDelayedEventResponse = {
|
|
93
|
+
delay_id: string;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
export enum UpdateDelayedEventAction {
|
|
97
|
+
Cancel = "cancel",
|
|
98
|
+
Restart = "restart",
|
|
99
|
+
Send = "send",
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export type UpdateDelayedEventRequestOpts = SendDelayedEventResponse & {
|
|
103
|
+
action: UpdateDelayedEventAction;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
type DelayedPartialTimelineEvent = {
|
|
107
|
+
room_id: string;
|
|
108
|
+
type: string;
|
|
109
|
+
content: IContent;
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
type DelayedPartialStateEvent = DelayedPartialTimelineEvent & {
|
|
113
|
+
state_key: string;
|
|
114
|
+
transaction_id: string;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
type DelayedPartialEvent = DelayedPartialTimelineEvent | DelayedPartialStateEvent;
|
|
118
|
+
|
|
119
|
+
export type DelayedEventInfo = {
|
|
120
|
+
delayed_events: DelayedPartialEvent &
|
|
121
|
+
SendDelayedEventResponse &
|
|
122
|
+
SendDelayedEventRequestOpts &
|
|
123
|
+
{
|
|
124
|
+
running_since: number;
|
|
125
|
+
}[];
|
|
126
|
+
next_batch?: string;
|
|
127
|
+
};
|
|
128
|
+
|
|
79
129
|
export interface IPresenceOpts {
|
|
80
130
|
// One of "online", "offline" or "unavailable"
|
|
81
131
|
presence: "online" | "offline" | "unavailable";
|
package/src/client.ts
CHANGED
|
@@ -47,7 +47,7 @@ import { Direction, EventTimeline } from "./models/event-timeline";
|
|
|
47
47
|
import { IActionsObject, PushProcessor } from "./pushprocessor";
|
|
48
48
|
import { AutoDiscovery, AutoDiscoveryAction } from "./autodiscovery";
|
|
49
49
|
import * as olmlib from "./crypto/olmlib";
|
|
50
|
-
import { decodeBase64, encodeBase64 } from "./base64";
|
|
50
|
+
import { decodeBase64, encodeBase64, encodeUnpaddedBase64Url } from "./base64";
|
|
51
51
|
import { IExportedDevice as IExportedOlmDevice } from "./crypto/OlmDevice";
|
|
52
52
|
import { IOlmDevice } from "./crypto/algorithms/megolm";
|
|
53
53
|
import { TypedReEmitter } from "./ReEmitter";
|
|
@@ -114,6 +114,7 @@ import { NotificationCountType, Room, RoomEvent, RoomEventHandlerMap, RoomNameSt
|
|
|
114
114
|
import { RoomMemberEvent, RoomMemberEventHandlerMap } from "./models/room-member";
|
|
115
115
|
import { IPowerLevelsContent, RoomStateEvent, RoomStateEventHandlerMap } from "./models/room-state";
|
|
116
116
|
import {
|
|
117
|
+
DelayedEventInfo,
|
|
117
118
|
IAddThreePidOnlyBody,
|
|
118
119
|
IBindThreePidBody,
|
|
119
120
|
IContextResponse,
|
|
@@ -134,6 +135,9 @@ import {
|
|
|
134
135
|
IStatusResponse,
|
|
135
136
|
ITagsResponse,
|
|
136
137
|
KnockRoomOpts,
|
|
138
|
+
SendDelayedEventRequestOpts,
|
|
139
|
+
SendDelayedEventResponse,
|
|
140
|
+
UpdateDelayedEventAction,
|
|
137
141
|
} from "./@types/requests";
|
|
138
142
|
import {
|
|
139
143
|
EventType,
|
|
@@ -227,6 +231,7 @@ import { KnownMembership, Membership } from "./@types/membership";
|
|
|
227
231
|
import { RoomMessageEventContent, StickerEventContent } from "./@types/events";
|
|
228
232
|
import { ImageInfo } from "./@types/media";
|
|
229
233
|
import { Capabilities, ServerCapabilities } from "./serverCapabilities";
|
|
234
|
+
import { sha256 } from "./digest";
|
|
230
235
|
|
|
231
236
|
export type Store = IStore;
|
|
232
237
|
|
|
@@ -324,10 +329,13 @@ export interface ICreateClientOpts {
|
|
|
324
329
|
localTimeoutMs?: number;
|
|
325
330
|
|
|
326
331
|
/**
|
|
327
|
-
* Set to
|
|
328
|
-
*
|
|
332
|
+
* Set to false to send the access token to the server via a query parameter rather
|
|
333
|
+
* than the Authorization HTTP header.
|
|
329
334
|
*
|
|
330
|
-
*
|
|
335
|
+
* Note that as of v1.11 of the Matrix spec, sending the access token via a query
|
|
336
|
+
* is deprecated.
|
|
337
|
+
*
|
|
338
|
+
* Default true.
|
|
331
339
|
*/
|
|
332
340
|
useAuthorizationHeader?: boolean;
|
|
333
341
|
|
|
@@ -527,6 +535,8 @@ export const UNSTABLE_MSC2666_SHARED_ROOMS = "uk.half-shot.msc2666";
|
|
|
527
535
|
export const UNSTABLE_MSC2666_MUTUAL_ROOMS = "uk.half-shot.msc2666.mutual_rooms";
|
|
528
536
|
export const UNSTABLE_MSC2666_QUERY_MUTUAL_ROOMS = "uk.half-shot.msc2666.query_mutual_rooms";
|
|
529
537
|
|
|
538
|
+
export const UNSTABLE_MSC4140_DELAYED_EVENTS = "org.matrix.msc4140";
|
|
539
|
+
|
|
530
540
|
enum CrossSigningKeyType {
|
|
531
541
|
MasterKey = "master_key",
|
|
532
542
|
SelfSigningKey = "self_signing_key",
|
|
@@ -4570,12 +4580,19 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|
|
4570
4580
|
threadId = threadIdOrEventType;
|
|
4571
4581
|
}
|
|
4572
4582
|
|
|
4573
|
-
|
|
4574
|
-
|
|
4575
|
-
|
|
4576
|
-
|
|
4577
|
-
|
|
4578
|
-
|
|
4583
|
+
this.addThreadRelationIfNeeded(content, threadId, roomId);
|
|
4584
|
+
return this.sendCompleteEvent(roomId, threadId, { type: eventType, content }, txnId);
|
|
4585
|
+
}
|
|
4586
|
+
|
|
4587
|
+
/**
|
|
4588
|
+
* If we expect that an event is part of a thread but is missing the relation
|
|
4589
|
+
* we need to add it manually, as well as the reply fallback
|
|
4590
|
+
*/
|
|
4591
|
+
private addThreadRelationIfNeeded(content: IContent, threadId: string | null, roomId: string): void {
|
|
4592
|
+
if (threadId && !content["m.relates_to"]?.rel_type) {
|
|
4593
|
+
const isReply = !!content["m.relates_to"]?.["m.in_reply_to"];
|
|
4594
|
+
content["m.relates_to"] = {
|
|
4595
|
+
...content["m.relates_to"],
|
|
4579
4596
|
rel_type: THREAD_RELATION_TYPE.name,
|
|
4580
4597
|
event_id: threadId,
|
|
4581
4598
|
// Set is_falling_back to true unless this is actually intended to be a reply
|
|
@@ -4583,7 +4600,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|
|
4583
4600
|
};
|
|
4584
4601
|
const thread = this.getRoom(roomId)?.getThread(threadId);
|
|
4585
4602
|
if (thread && !isReply) {
|
|
4586
|
-
content
|
|
4603
|
+
content["m.relates_to"]["m.in_reply_to"] = {
|
|
4587
4604
|
event_id:
|
|
4588
4605
|
thread
|
|
4589
4606
|
.lastReply((ev: MatrixEvent) => {
|
|
@@ -4593,8 +4610,6 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|
|
4593
4610
|
};
|
|
4594
4611
|
}
|
|
4595
4612
|
}
|
|
4596
|
-
|
|
4597
|
-
return this.sendCompleteEvent(roomId, threadId, { type: eventType, content }, txnId);
|
|
4598
4613
|
}
|
|
4599
4614
|
|
|
4600
4615
|
/**
|
|
@@ -4608,7 +4623,38 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|
|
4608
4623
|
threadId: string | null,
|
|
4609
4624
|
eventObject: Partial<IEvent>,
|
|
4610
4625
|
txnId?: string,
|
|
4611
|
-
): Promise<ISendEventResponse
|
|
4626
|
+
): Promise<ISendEventResponse>;
|
|
4627
|
+
/**
|
|
4628
|
+
* Sends a delayed event (MSC4140).
|
|
4629
|
+
* @param eventObject - An object with the partial structure of an event, to which event_id, user_id, room_id and origin_server_ts will be added.
|
|
4630
|
+
* @param delayOpts - Properties of the delay for this event.
|
|
4631
|
+
* @param txnId - Optional.
|
|
4632
|
+
* @returns Promise which resolves: to an empty object `{}`
|
|
4633
|
+
* @returns Rejects: with an error response.
|
|
4634
|
+
*/
|
|
4635
|
+
private sendCompleteEvent(
|
|
4636
|
+
roomId: string,
|
|
4637
|
+
threadId: string | null,
|
|
4638
|
+
eventObject: Partial<IEvent>,
|
|
4639
|
+
delayOpts: SendDelayedEventRequestOpts,
|
|
4640
|
+
txnId?: string,
|
|
4641
|
+
): Promise<SendDelayedEventResponse>;
|
|
4642
|
+
private sendCompleteEvent(
|
|
4643
|
+
roomId: string,
|
|
4644
|
+
threadId: string | null,
|
|
4645
|
+
eventObject: Partial<IEvent>,
|
|
4646
|
+
delayOptsOrTxnId?: SendDelayedEventRequestOpts | string,
|
|
4647
|
+
txnIdOrVoid?: string,
|
|
4648
|
+
): Promise<ISendEventResponse | SendDelayedEventResponse> {
|
|
4649
|
+
let delayOpts: SendDelayedEventRequestOpts | undefined;
|
|
4650
|
+
let txnId: string | undefined;
|
|
4651
|
+
if (typeof delayOptsOrTxnId === "string") {
|
|
4652
|
+
txnId = delayOptsOrTxnId;
|
|
4653
|
+
} else {
|
|
4654
|
+
delayOpts = delayOptsOrTxnId;
|
|
4655
|
+
txnId = txnIdOrVoid;
|
|
4656
|
+
}
|
|
4657
|
+
|
|
4612
4658
|
if (!txnId) {
|
|
4613
4659
|
txnId = this.makeTxnId();
|
|
4614
4660
|
}
|
|
@@ -4631,9 +4677,11 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|
|
4631
4677
|
localEvent.setThread(thread);
|
|
4632
4678
|
}
|
|
4633
4679
|
|
|
4634
|
-
|
|
4635
|
-
|
|
4636
|
-
|
|
4680
|
+
if (!delayOpts) {
|
|
4681
|
+
// set up re-emitter for this new event - this is normally the job of EventMapper but we don't use it here
|
|
4682
|
+
this.reEmitter.reEmit(localEvent, [MatrixEventEvent.Replaced, MatrixEventEvent.VisibilityChange]);
|
|
4683
|
+
room?.reEmitter.reEmit(localEvent, [MatrixEventEvent.BeforeRedaction]);
|
|
4684
|
+
}
|
|
4637
4685
|
|
|
4638
4686
|
// if this is a relation or redaction of an event
|
|
4639
4687
|
// that hasn't been sent yet (e.g. with a local id starting with a ~)
|
|
@@ -4648,29 +4696,56 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|
|
4648
4696
|
}
|
|
4649
4697
|
|
|
4650
4698
|
const type = localEvent.getType();
|
|
4651
|
-
this.logger.debug(
|
|
4699
|
+
this.logger.debug(
|
|
4700
|
+
`sendEvent of type ${type} in ${roomId} with txnId ${txnId}${delayOpts ? " (delayed event)" : ""}`,
|
|
4701
|
+
);
|
|
4652
4702
|
|
|
4653
4703
|
localEvent.setTxnId(txnId);
|
|
4654
4704
|
localEvent.setStatus(EventStatus.SENDING);
|
|
4655
4705
|
|
|
4656
|
-
//
|
|
4657
|
-
|
|
4706
|
+
// TODO: separate store for delayed events?
|
|
4707
|
+
if (!delayOpts) {
|
|
4708
|
+
// add this event immediately to the local store as 'sending'.
|
|
4709
|
+
room?.addPendingEvent(localEvent, txnId);
|
|
4658
4710
|
|
|
4659
|
-
|
|
4660
|
-
|
|
4661
|
-
|
|
4662
|
-
|
|
4663
|
-
|
|
4664
|
-
|
|
4711
|
+
// addPendingEvent can change the state to NOT_SENT if it believes
|
|
4712
|
+
// that there's other events that have failed. We won't bother to
|
|
4713
|
+
// try sending the event if the state has changed as such.
|
|
4714
|
+
if (localEvent.status === EventStatus.NOT_SENT) {
|
|
4715
|
+
return Promise.reject(new Error("Event blocked by other events not yet sent"));
|
|
4716
|
+
}
|
|
4665
4717
|
|
|
4666
|
-
|
|
4718
|
+
return this.encryptAndSendEvent(room, localEvent);
|
|
4719
|
+
} else {
|
|
4720
|
+
return this.encryptAndSendEvent(room, localEvent, delayOpts);
|
|
4721
|
+
}
|
|
4667
4722
|
}
|
|
4668
4723
|
|
|
4669
4724
|
/**
|
|
4670
4725
|
* encrypts the event if necessary; adds the event to the queue, or sends it; marks the event as sent/unsent
|
|
4671
4726
|
* @returns returns a promise which resolves with the result of the send request
|
|
4672
4727
|
*/
|
|
4673
|
-
protected async encryptAndSendEvent(room: Room | null, event: MatrixEvent): Promise<ISendEventResponse
|
|
4728
|
+
protected async encryptAndSendEvent(room: Room | null, event: MatrixEvent): Promise<ISendEventResponse>;
|
|
4729
|
+
/**
|
|
4730
|
+
* Simply sends a delayed event without encrypting it.
|
|
4731
|
+
* TODO: Allow encrypted delayed events, and encrypt them properly
|
|
4732
|
+
* @param delayOpts - Properties of the delay for this event.
|
|
4733
|
+
* @returns returns a promise which resolves with the result of the delayed send request
|
|
4734
|
+
*/
|
|
4735
|
+
protected async encryptAndSendEvent(
|
|
4736
|
+
room: Room | null,
|
|
4737
|
+
event: MatrixEvent,
|
|
4738
|
+
delayOpts: SendDelayedEventRequestOpts,
|
|
4739
|
+
): Promise<SendDelayedEventResponse>;
|
|
4740
|
+
protected async encryptAndSendEvent(
|
|
4741
|
+
room: Room | null,
|
|
4742
|
+
event: MatrixEvent,
|
|
4743
|
+
delayOpts?: SendDelayedEventRequestOpts,
|
|
4744
|
+
): Promise<ISendEventResponse | SendDelayedEventResponse> {
|
|
4745
|
+
if (delayOpts) {
|
|
4746
|
+
return this.sendEventHttpRequest(event, delayOpts);
|
|
4747
|
+
}
|
|
4748
|
+
|
|
4674
4749
|
try {
|
|
4675
4750
|
let cancelled: boolean;
|
|
4676
4751
|
this.eventsBeingEncrypted.add(event.getId()!);
|
|
@@ -4821,7 +4896,15 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|
|
4821
4896
|
}
|
|
4822
4897
|
}
|
|
4823
4898
|
|
|
4824
|
-
private sendEventHttpRequest(event: MatrixEvent): Promise<ISendEventResponse
|
|
4899
|
+
private sendEventHttpRequest(event: MatrixEvent): Promise<ISendEventResponse>;
|
|
4900
|
+
private sendEventHttpRequest(
|
|
4901
|
+
event: MatrixEvent,
|
|
4902
|
+
delayOpts: SendDelayedEventRequestOpts,
|
|
4903
|
+
): Promise<SendDelayedEventResponse>;
|
|
4904
|
+
private sendEventHttpRequest(
|
|
4905
|
+
event: MatrixEvent,
|
|
4906
|
+
delayOpts?: SendDelayedEventRequestOpts,
|
|
4907
|
+
): Promise<ISendEventResponse | SendDelayedEventResponse> {
|
|
4825
4908
|
let txnId = event.getTxnId();
|
|
4826
4909
|
if (!txnId) {
|
|
4827
4910
|
txnId = this.makeTxnId();
|
|
@@ -4853,12 +4936,20 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|
|
4853
4936
|
path = utils.encodeUri("/rooms/$roomId/send/$eventType/$txnId", pathParams);
|
|
4854
4937
|
}
|
|
4855
4938
|
|
|
4856
|
-
|
|
4857
|
-
|
|
4858
|
-
.then((res) => {
|
|
4939
|
+
const content = event.getWireContent();
|
|
4940
|
+
if (!delayOpts) {
|
|
4941
|
+
return this.http.authedRequest<ISendEventResponse>(Method.Put, path, undefined, content).then((res) => {
|
|
4859
4942
|
this.logger.debug(`Event sent to ${event.getRoomId()} with event id ${res.event_id}`);
|
|
4860
4943
|
return res;
|
|
4861
4944
|
});
|
|
4945
|
+
} else {
|
|
4946
|
+
return this.http.authedRequest<SendDelayedEventResponse>(
|
|
4947
|
+
Method.Put,
|
|
4948
|
+
path,
|
|
4949
|
+
getUnstableDelayQueryOpts(delayOpts),
|
|
4950
|
+
content,
|
|
4951
|
+
);
|
|
4952
|
+
}
|
|
4862
4953
|
}
|
|
4863
4954
|
|
|
4864
4955
|
/**
|
|
@@ -5188,6 +5279,101 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|
|
5188
5279
|
return this.sendMessage(roomId, threadId, content);
|
|
5189
5280
|
}
|
|
5190
5281
|
|
|
5282
|
+
/**
|
|
5283
|
+
* Send a delayed timeline event.
|
|
5284
|
+
*
|
|
5285
|
+
* Note: This endpoint is unstable, and can throw an `Error`.
|
|
5286
|
+
* Check progress on [MSC4140](https://github.com/matrix-org/matrix-spec-proposals/pull/4140) for more details.
|
|
5287
|
+
*/
|
|
5288
|
+
// eslint-disable-next-line
|
|
5289
|
+
public async _unstable_sendDelayedEvent<K extends keyof TimelineEvents>(
|
|
5290
|
+
roomId: string,
|
|
5291
|
+
delayOpts: SendDelayedEventRequestOpts,
|
|
5292
|
+
threadId: string | null,
|
|
5293
|
+
eventType: K,
|
|
5294
|
+
content: TimelineEvents[K],
|
|
5295
|
+
txnId?: string,
|
|
5296
|
+
): Promise<SendDelayedEventResponse> {
|
|
5297
|
+
if (!(await this.doesServerSupportUnstableFeature(UNSTABLE_MSC4140_DELAYED_EVENTS))) {
|
|
5298
|
+
throw Error("Server does not support the delayed events API");
|
|
5299
|
+
}
|
|
5300
|
+
|
|
5301
|
+
this.addThreadRelationIfNeeded(content, threadId, roomId);
|
|
5302
|
+
return this.sendCompleteEvent(roomId, threadId, { type: eventType, content }, delayOpts, txnId);
|
|
5303
|
+
}
|
|
5304
|
+
|
|
5305
|
+
/**
|
|
5306
|
+
* Send a delayed state event.
|
|
5307
|
+
*
|
|
5308
|
+
* Note: This endpoint is unstable, and can throw an `Error`.
|
|
5309
|
+
* Check progress on [MSC4140](https://github.com/matrix-org/matrix-spec-proposals/pull/4140) for more details.
|
|
5310
|
+
*/
|
|
5311
|
+
// eslint-disable-next-line
|
|
5312
|
+
public async _unstable_sendDelayedStateEvent<K extends keyof StateEvents>(
|
|
5313
|
+
roomId: string,
|
|
5314
|
+
delayOpts: SendDelayedEventRequestOpts,
|
|
5315
|
+
eventType: K,
|
|
5316
|
+
content: StateEvents[K],
|
|
5317
|
+
stateKey = "",
|
|
5318
|
+
opts: IRequestOpts = {},
|
|
5319
|
+
): Promise<SendDelayedEventResponse> {
|
|
5320
|
+
if (!(await this.doesServerSupportUnstableFeature(UNSTABLE_MSC4140_DELAYED_EVENTS))) {
|
|
5321
|
+
throw Error("Server does not support the delayed events API");
|
|
5322
|
+
}
|
|
5323
|
+
|
|
5324
|
+
const pathParams = {
|
|
5325
|
+
$roomId: roomId,
|
|
5326
|
+
$eventType: eventType,
|
|
5327
|
+
$stateKey: stateKey,
|
|
5328
|
+
};
|
|
5329
|
+
let path = utils.encodeUri("/rooms/$roomId/state/$eventType", pathParams);
|
|
5330
|
+
if (stateKey !== undefined) {
|
|
5331
|
+
path = utils.encodeUri(path + "/$stateKey", pathParams);
|
|
5332
|
+
}
|
|
5333
|
+
return this.http.authedRequest(Method.Put, path, getUnstableDelayQueryOpts(delayOpts), content as Body, opts);
|
|
5334
|
+
}
|
|
5335
|
+
|
|
5336
|
+
/**
|
|
5337
|
+
* Get all pending delayed events for the calling user.
|
|
5338
|
+
*
|
|
5339
|
+
* Note: This endpoint is unstable, and can throw an `Error`.
|
|
5340
|
+
* Check progress on [MSC4140](https://github.com/matrix-org/matrix-spec-proposals/pull/4140) for more details.
|
|
5341
|
+
*/
|
|
5342
|
+
// eslint-disable-next-line
|
|
5343
|
+
public async _unstable_getDelayedEvents(fromToken?: string): Promise<DelayedEventInfo> {
|
|
5344
|
+
if (!(await this.doesServerSupportUnstableFeature(UNSTABLE_MSC4140_DELAYED_EVENTS))) {
|
|
5345
|
+
throw Error("Server does not support the delayed events API");
|
|
5346
|
+
}
|
|
5347
|
+
|
|
5348
|
+
const queryDict = fromToken ? { from: fromToken } : undefined;
|
|
5349
|
+
return await this.http.authedRequest(Method.Get, "/delayed_events", queryDict, undefined, {
|
|
5350
|
+
prefix: `${ClientPrefix.Unstable}/${UNSTABLE_MSC4140_DELAYED_EVENTS}`,
|
|
5351
|
+
});
|
|
5352
|
+
}
|
|
5353
|
+
|
|
5354
|
+
/**
|
|
5355
|
+
* Manage a delayed event associated with the given delay_id.
|
|
5356
|
+
*
|
|
5357
|
+
* Note: This endpoint is unstable, and can throw an `Error`.
|
|
5358
|
+
* Check progress on [MSC4140](https://github.com/matrix-org/matrix-spec-proposals/pull/4140) for more details.
|
|
5359
|
+
*/
|
|
5360
|
+
// eslint-disable-next-line
|
|
5361
|
+
public async _unstable_updateDelayedEvent(delayId: string, action: UpdateDelayedEventAction): Promise<{}> {
|
|
5362
|
+
if (!(await this.doesServerSupportUnstableFeature(UNSTABLE_MSC4140_DELAYED_EVENTS))) {
|
|
5363
|
+
throw Error("Server does not support the delayed events API");
|
|
5364
|
+
}
|
|
5365
|
+
|
|
5366
|
+
const path = utils.encodeUri("/delayed_events/$delayId", {
|
|
5367
|
+
$delayId: delayId,
|
|
5368
|
+
});
|
|
5369
|
+
const data = {
|
|
5370
|
+
action,
|
|
5371
|
+
};
|
|
5372
|
+
return await this.http.authedRequest(Method.Post, path, undefined, data, {
|
|
5373
|
+
prefix: `${ClientPrefix.Unstable}/${UNSTABLE_MSC4140_DELAYED_EVENTS}`,
|
|
5374
|
+
});
|
|
5375
|
+
}
|
|
5376
|
+
|
|
5191
5377
|
/**
|
|
5192
5378
|
* Send a receipt.
|
|
5193
5379
|
* @param event - The event being acknowledged
|
|
@@ -9299,20 +9485,19 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|
|
9299
9485
|
|
|
9300
9486
|
// When picking an algorithm, we pick the hashed over no hashes
|
|
9301
9487
|
if (hashes["algorithms"].includes("sha256")) {
|
|
9302
|
-
|
|
9303
|
-
|
|
9304
|
-
|
|
9305
|
-
|
|
9306
|
-
|
|
9307
|
-
|
|
9308
|
-
|
|
9309
|
-
|
|
9310
|
-
|
|
9311
|
-
|
|
9312
|
-
|
|
9313
|
-
|
|
9314
|
-
|
|
9315
|
-
});
|
|
9488
|
+
params["addresses"] = await Promise.all(
|
|
9489
|
+
addressPairs.map(async (p) => {
|
|
9490
|
+
const addr = p[0].toLowerCase(); // lowercase to get consistent hashes
|
|
9491
|
+
const med = p[1].toLowerCase();
|
|
9492
|
+
const hashBuffer = await sha256(`${addr} ${med} ${params["pepper"]}`);
|
|
9493
|
+
const hashed = encodeUnpaddedBase64Url(hashBuffer);
|
|
9494
|
+
|
|
9495
|
+
// Map the hash to a known (case-sensitive) address. We use the case
|
|
9496
|
+
// sensitive version because the caller might be expecting that.
|
|
9497
|
+
localMapping[hashed] = p[0];
|
|
9498
|
+
return hashed;
|
|
9499
|
+
}),
|
|
9500
|
+
);
|
|
9316
9501
|
params["algorithm"] = "sha256";
|
|
9317
9502
|
} else if (hashes["algorithms"].includes("none")) {
|
|
9318
9503
|
params["addresses"] = addressPairs.map((p) => {
|
|
@@ -9889,6 +10074,12 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|
|
9889
10074
|
}
|
|
9890
10075
|
}
|
|
9891
10076
|
|
|
10077
|
+
function getUnstableDelayQueryOpts(delayOpts: SendDelayedEventRequestOpts): QueryDict {
|
|
10078
|
+
return Object.fromEntries(
|
|
10079
|
+
Object.entries(delayOpts).map(([k, v]) => [`${UNSTABLE_MSC4140_DELAYED_EVENTS}.${k}`, v]),
|
|
10080
|
+
);
|
|
10081
|
+
}
|
|
10082
|
+
|
|
9892
10083
|
/**
|
|
9893
10084
|
* recalculates an accurate notifications count on event decryption.
|
|
9894
10085
|
* Servers do not have enough knowledge about encrypted events to calculate an
|
|
@@ -66,7 +66,6 @@ export abstract class EncryptionAlgorithm {
|
|
|
66
66
|
protected readonly crypto: Crypto;
|
|
67
67
|
protected readonly olmDevice: OlmDevice;
|
|
68
68
|
protected readonly baseApis: MatrixClient;
|
|
69
|
-
protected readonly roomId?: string;
|
|
70
69
|
|
|
71
70
|
/**
|
|
72
71
|
* @param params - parameters
|
|
@@ -77,7 +76,6 @@ export abstract class EncryptionAlgorithm {
|
|
|
77
76
|
this.crypto = params.crypto;
|
|
78
77
|
this.olmDevice = params.olmDevice;
|
|
79
78
|
this.baseApis = params.baseApis;
|
|
80
|
-
this.roomId = params.roomId;
|
|
81
79
|
}
|
|
82
80
|
|
|
83
81
|
/**
|
|
@@ -127,14 +125,12 @@ export abstract class DecryptionAlgorithm {
|
|
|
127
125
|
protected readonly crypto: Crypto;
|
|
128
126
|
protected readonly olmDevice: OlmDevice;
|
|
129
127
|
protected readonly baseApis: MatrixClient;
|
|
130
|
-
protected readonly roomId?: string;
|
|
131
128
|
|
|
132
129
|
public constructor(params: DecryptionClassParams) {
|
|
133
130
|
this.userId = params.userId;
|
|
134
131
|
this.crypto = params.crypto;
|
|
135
132
|
this.olmDevice = params.olmDevice;
|
|
136
133
|
this.baseApis = params.baseApis;
|
|
137
|
-
this.roomId = params.roomId;
|
|
138
134
|
}
|
|
139
135
|
|
|
140
136
|
/**
|
package/src/digest.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2024 The Matrix.org Foundation C.I.C.
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Computes a SHA-256 hash of a string (after utf-8 encoding) and returns it as an ArrayBuffer.
|
|
19
|
+
*
|
|
20
|
+
* @param plaintext The string to hash
|
|
21
|
+
* @returns An ArrayBuffer containing the SHA-256 hash of the input string
|
|
22
|
+
* @throws If the subtle crypto API is not available, for example if the code is running
|
|
23
|
+
* in a web page with an insecure context (eg. served over plain HTTP).
|
|
24
|
+
*/
|
|
25
|
+
export async function sha256(plaintext: string): Promise<ArrayBuffer> {
|
|
26
|
+
if (!globalThis.crypto.subtle) {
|
|
27
|
+
throw new Error("Crypto.subtle is not available: insecure context?");
|
|
28
|
+
}
|
|
29
|
+
const utf8 = new TextEncoder().encode(plaintext);
|
|
30
|
+
|
|
31
|
+
const digest = await globalThis.crypto.subtle.digest("SHA-256", utf8);
|
|
32
|
+
|
|
33
|
+
return digest;
|
|
34
|
+
}
|