From 556d37539d6d9e24b6b54aa2727c284de553c249 Mon Sep 17 00:00:00 2001 From: Half-Shot Date: Tue, 2 May 2023 16:09:02 +0100 Subject: [PATCH 1/2] Add support for the /messages endpoint --- src/MatrixClient.ts | 15 +++++++++++++++ src/models/Messages.ts | 29 +++++++++++++++++++++++++++++ test/MatrixClientTest.ts | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+) create mode 100644 src/models/Messages.ts diff --git a/src/MatrixClient.ts b/src/MatrixClient.ts index 14c55956..467f1350 100644 --- a/src/MatrixClient.ts +++ b/src/MatrixClient.ts @@ -44,6 +44,7 @@ import { DMs } from "./DMs"; import { ServerVersions } from "./models/ServerVersions"; import { RoomCreateOptions } from "./models/CreateRoom"; import { PresenceState } from './models/events/PresenceEvent'; +import { GetRoomMessagesResponse } from "./models/Messages"; const SYNC_BACKOFF_MIN_MS = 5000; const SYNC_BACKOFF_MAX_MS = 15000; @@ -1977,6 +1978,20 @@ export class MatrixClient extends EventEmitter { return this.doRequest("GET", url); } + /** + * Get relations for a given event. + * @param {string} roomId The room ID to for the given event. + * @param {string} eventId The event ID to list relations for. + * @param {string?} relationType The type of relations (e.g. `m.room.member`) to filter for. Optional. + * @param {string?} eventType The type of event to look for (e.g. `m.room.member`). Optional. + * @returns {Promise<{chunk: any[]}>} Resolves to an object containing the chunk of relations + */ + @timedMatrixClientFunctionCall() + public async getMessages(roomId: string, dir: "b"|"f", opts: Partial<{filter: string, from: string, limit: number, to: string}>): Promise { + const url = `/_matrix/client/v1/rooms/${encodeURIComponent(roomId)}/messages`; + return this.doRequest("GET", url, { dir, ...opts }); + } + /** * Performs a web request to the homeserver, applying appropriate authorization headers for * this client. diff --git a/src/models/Messages.ts b/src/models/Messages.ts new file mode 100644 index 00000000..738d3961 --- /dev/null +++ b/src/models/Messages.ts @@ -0,0 +1,29 @@ +import { RoomEventContent } from "./events/RoomEvent"; + +export interface GetRoomMessagesResponse { + /** + * A list of room events. The order depends on the dir parameter passed to the function. + * For dir=b events will be in reverse-chronological order, + * For dir=f in chronological order. (The exact definition of chronological is dependent on the server implementation.) + * + * Note that an empty array does not necessarily imply that no more events are available. You can continue + * to paginate until `end` is empty. + */ + chunk: RoomEventContent[]; + /** + * A token corresponding to the end of `chunk`. This token can be passed back to getMessages to request further events. + * If no further events are available (either because we have reached the start of the timeline, or because you do + * not have permission to see any more events), this property will not be provided. + */ + end?: string; + /** + * A token corresponding to the start of chunk. + */ + start: string; + /** + * A list of state events relevant to showing the `chunk`. + * For example, if `lazy_load_members` is enabled in the provided filter then this + * may contain the membership events for the senders of events in the `chunk`. + */ + state: RoomEventContent[]; +} \ No newline at end of file diff --git a/test/MatrixClientTest.ts b/test/MatrixClientTest.ts index f7980df9..5f089298 100644 --- a/test/MatrixClientTest.ts +++ b/test/MatrixClientTest.ts @@ -6998,6 +6998,45 @@ describe('MatrixClient', () => { }); }); + describe('getMessages', () => { + it('should call the right endpoint', async () => { + const roomId = "!room_id:room.org"; + const { client, http } = createTestClient(); + + const dir = "b"; + const opts = { + filter: "my-filter", + from: "from-token", + limit: 50, + to: "to-token", + }; + const expectedResponse = { + chunk: [{ + my: "event", + }], + start: "start-token", + end: "end-token", + state: [{ + state: "event", + }], + }; + + // noinspection TypeScriptValidateJSTypes + http.when("GET", `/_matrix/client/v1/rooms/${encodeURIComponent(roomId)}/messages`).respond(200, (_path, _content, req) => { + expect(req.queryParams["dir"]).toEqual("b"); + expect(req.queryParams["filter"]).toEqual("my-filter"); + expect(req.queryParams["from"]).toEqual("from-token"); + expect(req.queryParams["limit"]).toEqual("50"); + expect(req.queryParams["to"]).toEqual("to-token"); + return expectedResponse; + }); + + + const [messageResponse] = await Promise.all([client.getMessages(roomId, dir, opts), http.flushAllExpected()]); + expect(messageResponse).toEqual(expectedResponse); + }); + }); + describe('redactObjectForLogging', () => { it('should redact multilevel objects', () => { const input = { From 263a57427eba465b909f9d45f92393ebbc475aaa Mon Sep 17 00:00:00 2001 From: Half-Shot Date: Tue, 2 May 2023 16:10:41 +0100 Subject: [PATCH 2/2] Fix tests --- src/MatrixClient.ts | 2 +- test/MatrixClientTest.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/MatrixClient.ts b/src/MatrixClient.ts index 467f1350..a7df31d1 100644 --- a/src/MatrixClient.ts +++ b/src/MatrixClient.ts @@ -1988,7 +1988,7 @@ export class MatrixClient extends EventEmitter { */ @timedMatrixClientFunctionCall() public async getMessages(roomId: string, dir: "b"|"f", opts: Partial<{filter: string, from: string, limit: number, to: string}>): Promise { - const url = `/_matrix/client/v1/rooms/${encodeURIComponent(roomId)}/messages`; + const url = `/_matrix/client/v3/rooms/${encodeURIComponent(roomId)}/messages`; return this.doRequest("GET", url, { dir, ...opts }); } diff --git a/test/MatrixClientTest.ts b/test/MatrixClientTest.ts index 5f089298..c0d95b4c 100644 --- a/test/MatrixClientTest.ts +++ b/test/MatrixClientTest.ts @@ -7022,11 +7022,11 @@ describe('MatrixClient', () => { }; // noinspection TypeScriptValidateJSTypes - http.when("GET", `/_matrix/client/v1/rooms/${encodeURIComponent(roomId)}/messages`).respond(200, (_path, _content, req) => { + http.when("GET", `/_matrix/client/v3/rooms/${encodeURIComponent(roomId)}/messages`).respond(200, (_path, _content, req) => { expect(req.queryParams["dir"]).toEqual("b"); expect(req.queryParams["filter"]).toEqual("my-filter"); expect(req.queryParams["from"]).toEqual("from-token"); - expect(req.queryParams["limit"]).toEqual("50"); + expect(req.queryParams["limit"]).toEqual(50); expect(req.queryParams["to"]).toEqual("to-token"); return expectedResponse; });