From f6f4a0a8fc054b07f58e9c38f15093116d17366f Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 3 Oct 2022 11:39:09 +0100 Subject: [PATCH] Remove deprecated callbacks support --- spec/unit/crypto/backup.spec.ts | 8 +- spec/unit/crypto/cross-signing.spec.ts | 2 +- spec/unit/crypto/secrets.spec.ts | 9 +- spec/unit/matrix-client.spec.ts | 36 +- src/@types/requests.ts | 2 - src/client.ts | 861 ++++++++----------------- src/crypto/EncryptionSetup.ts | 4 +- src/crypto/dehydration.ts | 2 - src/http-api.ts | 59 +- src/sync.ts | 9 +- 10 files changed, 300 insertions(+), 692 deletions(-) diff --git a/spec/unit/crypto/backup.spec.ts b/spec/unit/crypto/backup.spec.ts index acec47fcee2..e20f3679d51 100644 --- a/spec/unit/crypto/backup.spec.ts +++ b/spec/unit/crypto/backup.spec.ts @@ -299,7 +299,7 @@ describe("MegolmBackup", function() { let numCalls = 0; return new Promise((resolve, reject) => { client.http.authedRequest = function( - callback, method, path, queryParams, data, opts, + method, path, queryParams, data, opts, ) { ++numCalls; expect(numCalls).toBeLessThanOrEqual(1); @@ -382,7 +382,7 @@ describe("MegolmBackup", function() { let numCalls = 0; return new Promise((resolve, reject) => { client.http.authedRequest = function( - callback, method, path, queryParams, data, opts, + method, path, queryParams, data, opts, ) { ++numCalls; expect(numCalls).toBeLessThanOrEqual(1); @@ -439,7 +439,7 @@ describe("MegolmBackup", function() { new Promise((resolve, reject) => { let backupInfo; client.http.authedRequest = function( - callback, method, path, queryParams, data, opts, + method, path, queryParams, data, opts, ) { ++numCalls; expect(numCalls).toBeLessThanOrEqual(2); @@ -543,7 +543,7 @@ describe("MegolmBackup", function() { await new Promise((resolve, reject) => { client.http.authedRequest = function( - callback, method, path, queryParams, data, opts, + method, path, queryParams, data, opts, ) { ++numCalls; expect(numCalls).toBeLessThanOrEqual(2); diff --git a/spec/unit/crypto/cross-signing.spec.ts b/spec/unit/crypto/cross-signing.spec.ts index 30c1bf82ce3..bfa7625cbe8 100644 --- a/spec/unit/crypto/cross-signing.spec.ts +++ b/spec/unit/crypto/cross-signing.spec.ts @@ -141,7 +141,7 @@ describe("Cross Signing", function() { }; alice.uploadKeySignatures = async () => ({ failures: {} }); alice.setAccountData = async () => ({}); - alice.getAccountDataFromServer = async (): Promise => ({} as T); + alice.getAccountDataFromServer = async (): Promise => ({} as T); const authUploadDeviceSigningKeys = async func => await func({}); // Try bootstrap, expecting `authUploadDeviceSigningKeys` to pass diff --git a/spec/unit/crypto/secrets.spec.ts b/spec/unit/crypto/secrets.spec.ts index d6ae8c3a363..7692292fff2 100644 --- a/spec/unit/crypto/secrets.spec.ts +++ b/spec/unit/crypto/secrets.spec.ts @@ -109,16 +109,13 @@ describe("Secrets", function() { const secretStorage = alice.crypto.secretStorage; jest.spyOn(alice, 'setAccountData').mockImplementation( - async function(eventType, contents, callback) { + async function(eventType, contents) { alice.store.storeAccountDataEvents([ new MatrixEvent({ type: eventType, content: contents, }), ]); - if (callback) { - callback(undefined, undefined); - } return {}; }); @@ -192,7 +189,7 @@ describe("Secrets", function() { }, }, ); - alice.setAccountData = async function(eventType, contents, callback) { + alice.setAccountData = async function(eventType, contents) { alice.store.storeAccountDataEvents([ new MatrixEvent({ type: eventType, @@ -332,7 +329,7 @@ describe("Secrets", function() { ); bob.uploadDeviceSigningKeys = async () => ({}); bob.uploadKeySignatures = jest.fn().mockResolvedValue(undefined); - bob.setAccountData = async function(eventType, contents, callback) { + bob.setAccountData = async function(eventType, contents) { const event = new MatrixEvent({ type: eventType, content: contents, diff --git a/spec/unit/matrix-client.spec.ts b/spec/unit/matrix-client.spec.ts index 2b8faf5065a..f854d600835 100644 --- a/spec/unit/matrix-client.spec.ts +++ b/spec/unit/matrix-client.spec.ts @@ -103,7 +103,7 @@ describe("MatrixClient", function() { ]; let acceptKeepalives: boolean; let pendingLookup = null; - function httpReq(cb, method, path, qp, data, prefix) { + function httpReq(method, path, qp, data, prefix) { if (path === KEEP_ALIVE_PATH && acceptKeepalives) { return Promise.resolve({ unstable_features: { @@ -1153,8 +1153,7 @@ describe("MatrixClient", function() { // event type combined const expectedEventType = M_BEACON_INFO.name; - const [callback, method, path, queryParams, requestContent] = client.http.authedRequest.mock.calls[0]; - expect(callback).toBeFalsy(); + const [method, path, queryParams, requestContent] = client.http.authedRequest.mock.calls[0]; expect(method).toBe('PUT'); expect(path).toEqual( `/rooms/${encodeURIComponent(roomId)}/state/` + @@ -1168,7 +1167,7 @@ describe("MatrixClient", function() { await client.unstable_setLiveBeacon(roomId, content); // event type combined - const [, , path, , requestContent] = client.http.authedRequest.mock.calls[0]; + const [, path, , requestContent] = client.http.authedRequest.mock.calls[0]; expect(path).toEqual( `/rooms/${encodeURIComponent(roomId)}/state/` + `${encodeURIComponent(M_BEACON_INFO.name)}/${encodeURIComponent(userId)}`, @@ -1229,7 +1228,7 @@ describe("MatrixClient", function() { it("is called with plain text topic and callback and sends state event", async () => { const sendStateEvent = createSendStateEventMock("pizza"); client.sendStateEvent = sendStateEvent; - await client.setRoomTopic(roomId, "pizza", () => {}); + await client.setRoomTopic(roomId, "pizza"); expect(sendStateEvent).toHaveBeenCalledTimes(1); }); @@ -1244,15 +1243,9 @@ describe("MatrixClient", function() { describe("setPassword", () => { const auth = { session: 'abcdef', type: 'foo' }; const newPassword = 'newpassword'; - const callback = () => {}; - - const passwordTest = (expectedRequestContent: any, expectedCallback?: Function) => { - const [callback, method, path, queryParams, requestContent] = client.http.authedRequest.mock.calls[0]; - if (expectedCallback) { - expect(callback).toBe(expectedCallback); - } else { - expect(callback).toBeFalsy(); - } + + const passwordTest = (expectedRequestContent: any) => { + const [method, path, queryParams, requestContent] = client.http.authedRequest.mock.calls[0]; expect(method).toBe('POST'); expect(path).toEqual('/account/password'); expect(queryParams).toBeFalsy(); @@ -1269,8 +1262,8 @@ describe("MatrixClient", function() { }); it("no logout_devices specified + callback", async () => { - await client.setPassword(auth, newPassword, callback); - passwordTest({ auth, new_password: newPassword }, callback); + await client.setPassword(auth, newPassword); + passwordTest({ auth, new_password: newPassword }); }); it("overload logoutDevices=true", async () => { @@ -1279,8 +1272,8 @@ describe("MatrixClient", function() { }); it("overload logoutDevices=true + callback", async () => { - await client.setPassword(auth, newPassword, true, callback); - passwordTest({ auth, new_password: newPassword, logout_devices: true }, callback); + await client.setPassword(auth, newPassword, true); + passwordTest({ auth, new_password: newPassword, logout_devices: true }); }); it("overload logoutDevices=false", async () => { @@ -1289,8 +1282,8 @@ describe("MatrixClient", function() { }); it("overload logoutDevices=false + callback", async () => { - await client.setPassword(auth, newPassword, false, callback); - passwordTest({ auth, new_password: newPassword, logout_devices: false }, callback); + await client.setPassword(auth, newPassword, false); + passwordTest({ auth, new_password: newPassword, logout_devices: false }); }); }); @@ -1305,8 +1298,7 @@ describe("MatrixClient", function() { const result = await client.getLocalAliases(roomId); // Current version of the endpoint we support is v3 - const [callback, method, path, queryParams, data, opts] = client.http.authedRequest.mock.calls[0]; - expect(callback).toBeFalsy(); + const [method, path, queryParams, data, opts] = client.http.authedRequest.mock.calls[0]; expect(data).toBeFalsy(); expect(method).toBe('GET'); expect(path).toEqual(`/rooms/${encodeURIComponent(roomId)}/aliases`); diff --git a/src/@types/requests.ts b/src/@types/requests.ts index 9d0472cee1a..15e2faa0c15 100644 --- a/src/@types/requests.ts +++ b/src/@types/requests.ts @@ -14,7 +14,6 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { Callback } from "../client"; import { IContent, IEvent } from "../models/event"; import { Preset, Visibility } from "./partials"; import { IEventWithRoomId, SearchKey } from "./search"; @@ -125,7 +124,6 @@ export interface IUploadOpts { type?: string; rawResponse?: boolean; onlyContentUri?: boolean; - callback?: Callback; progressHandler?: (state: {loaded: number, total: number}) => void; } diff --git a/src/client.ts b/src/client.ts index 253f5fe7640..732adf8247b 100644 --- a/src/client.ts +++ b/src/client.ts @@ -204,7 +204,6 @@ import { LocalNotificationSettings } from "./@types/local_notifications"; export type Store = IStore; -export type Callback = (err: Error | any | null, data?: T) => void; export type ResetTimelineCallback = (roomId: string) => boolean; const SCROLLBACK_DELAY_MS = 3000; @@ -1321,7 +1320,6 @@ export class MatrixClient extends TypedEventEmitter( - undefined, Method.Post, "/dehydrated_device/claim", undefined, @@ -1362,7 +1360,6 @@ export class MatrixClient extends TypedEventEmitter { try { return await this.http.authedRequest( - undefined, Method.Get, "/dehydrated_device", undefined, undefined, @@ -1655,9 +1652,7 @@ export class MatrixClient extends TypedEventEmitter { + return this.http.authedRequest(Method.Get, "/capabilities").catch((e: Error): void => { // We swallow errors because we need a default object anyhow logger.error(e); }).then((r: { capabilities?: ICapabilities } = {}) => { @@ -2689,7 +2684,7 @@ export class MatrixClient extends TypedEventEmitter( - undefined, Method.Get, "/room_keys/version", undefined, undefined, + Method.Get, "/room_keys/version", undefined, undefined, { prefix: ClientPrefix.Unstable }, ); } catch (e) { @@ -2845,7 +2840,7 @@ export class MatrixClient extends TypedEventEmitter( - undefined, Method.Post, "/room_keys/version", undefined, data, + Method.Post, "/room_keys/version", undefined, data, { prefix: ClientPrefix.Unstable }, ); @@ -2877,19 +2872,15 @@ export class MatrixClient extends TypedEventEmitter; - public sendKeyBackup(roomId: string, sessionId: undefined, version: string, data: IKeyBackup): Promise; - public sendKeyBackup(roomId: string, sessionId: string, version: string, data: IKeyBackup): Promise; + public sendKeyBackup( + roomId: undefined, + sessionId: undefined, + version: string | undefined, + data: IKeyBackup, + ): Promise; public sendKeyBackup( roomId: string, + sessionId: undefined, + version: string | undefined, + data: IKeyBackup, + ): Promise; + public sendKeyBackup( + roomId: string, + sessionId: string, + version: string | undefined, + data: IKeyBackup, + ): Promise; + public sendKeyBackup( + roomId: string | undefined, sessionId: string | undefined, version: string | undefined, data: IKeyBackup, @@ -2931,7 +2937,7 @@ export class MatrixClient extends TypedEventEmitter( - undefined, Method.Get, path.path, path.queryData, undefined, + Method.Get, path.path, path.queryData, undefined, { prefix: ClientPrefix.Unstable }, ); @@ -3273,21 +3279,17 @@ export class MatrixClient extends TypedEventEmitter; - public deleteKeysFromBackup(roomId: string, sessionId: undefined, version: string): Promise; - public deleteKeysFromBackup(roomId: string, sessionId: string, version: string): Promise; - public deleteKeysFromBackup( - roomId: string | undefined, - sessionId: string | undefined, - version: string, - ): Promise { + public deleteKeysFromBackup(roomId: undefined, sessionId: undefined, version?: string): Promise; + public deleteKeysFromBackup(roomId: string, sessionId: undefined, version?: string): Promise; + public deleteKeysFromBackup(roomId: string, sessionId: string, version?: string): Promise; + public deleteKeysFromBackup(roomId?: string, sessionId?: string, version?: string): Promise { if (!this.crypto) { throw new Error("End-to-end encryption disabled"); } const path = this.makeKeyBackupPath(roomId, sessionId, version); return this.http.authedRequest( - undefined, Method.Delete, path.path, path.queryData, undefined, + Method.Delete, path.path, path.queryData, undefined, { prefix: ClientPrefix.Unstable }, ); } @@ -3328,12 +3330,11 @@ export class MatrixClient extends TypedEventEmitter { + public getMediaConfig(): Promise { return this.http.authedRequest( - callback, Method.Get, "/config", undefined, undefined, { + Method.Get, "/config", undefined, undefined, { prefix: MediaPrefix.R0, }, ); @@ -3416,22 +3417,17 @@ export class MatrixClient extends TypedEventEmitter { + public setAccountData(eventType: EventType | string, content: IContent): Promise<{}> { const path = utils.encodeUri("/user/$userId/account_data/$type", { $userId: this.credentials.userId, $type: eventType, }); - const promise = retryNetworkOperation(5, () => { - return this.http.authedRequest(undefined, Method.Put, path, undefined, content); + return retryNetworkOperation(5, () => { + return this.http.authedRequest(Method.Put, path, undefined, content); }); - if (callback) { - promise.then(result => callback(null, result), callback); - } - return promise; } /** @@ -3448,11 +3444,10 @@ export class MatrixClient extends TypedEventEmitter(eventType: string): Promise { + public async getAccountDataFromServer(eventType: string): Promise { if (this.isInitialSyncComplete()) { const event = this.store.getAccountData(eventType); if (!event) { @@ -3467,7 +3462,7 @@ export class MatrixClient extends TypedEventEmitter { + public setIgnoredUsers(userIds: string[]): Promise<{}> { const content = { ignored_users: {} }; userIds.forEach((u) => { content.ignored_users[u] = {}; }); - return this.setAccountData("m.ignored_user_list", content, callback); + return this.setAccountData("m.ignored_user_list", content); } /** @@ -3519,22 +3513,16 @@ export class MatrixClient extends TypedEventEmitter Default: true. * @param {boolean} opts.inviteSignUrl If the caller has a keypair 3pid invite, the signing URL is passed in this parameter. * @param {string[]} opts.viaServers The server names to try and join through in addition to those that are automatically chosen. - * @param {module:client.callback} callback Optional. * @return {Promise} Resolves: Room object. * @return {module:http-api.MatrixError} Rejects: with an error response. */ - public async joinRoom(roomIdOrAlias: string, opts?: IJoinRoomOpts, callback?: Callback): Promise { - // to help people when upgrading.. - if (utils.isFunction(opts)) { - throw new Error("Expected 'opts' object, got function."); - } - opts = opts || {}; + public async joinRoom(roomIdOrAlias: string, opts: IJoinRoomOpts = {}): Promise { if (opts.syncRoom === undefined) { opts.syncRoom = true; } const room = this.getRoom(roomIdOrAlias); - if (room && room.hasMembershipState(this.credentials.userId, "join")) { + if (room?.hasMembershipState(this.credentials.userId, "join")) { return Promise.resolve(room); } @@ -3542,7 +3530,7 @@ export class MatrixClient extends TypedEventEmitter { - return this.sendStateEvent(roomId, EventType.RoomName, { name: name }, undefined, callback); + public setRoomName(roomId: string, name: string): Promise { + return this.sendStateEvent(roomId, EventType.RoomName, { name: name }); } /** * @param {string} roomId * @param {string} topic * @param {string} htmlTopic Optional. - * @param {module:client.callback} callback Optional. * @return {Promise} Resolves: TODO * @return {module:http-api.MatrixError} Rejects: with an error response. */ @@ -3643,76 +3627,59 @@ export class MatrixClient extends TypedEventEmitter; - public setRoomTopic( - roomId: string, - topic: string, - callback?: Callback, - ): Promise; - public setRoomTopic( - roomId: string, - topic: string, - htmlTopicOrCallback?: string | Callback, ): Promise { - const isCallback = typeof htmlTopicOrCallback === 'function'; - const htmlTopic = isCallback ? undefined : htmlTopicOrCallback; - const callback = isCallback ? htmlTopicOrCallback : undefined; const content = ContentHelpers.makeTopicContent(topic, htmlTopic); - return this.sendStateEvent(roomId, EventType.RoomTopic, content, undefined, callback); + return this.sendStateEvent(roomId, EventType.RoomTopic, content); } /** * @param {string} roomId - * @param {module:client.callback} callback Optional. * @return {Promise} Resolves: to an object keyed by tagId with objects containing a numeric order field. * @return {module:http-api.MatrixError} Rejects: with an error response. */ - public getRoomTags(roomId: string, callback?: Callback): Promise { + public getRoomTags(roomId: string): Promise { const path = utils.encodeUri("/user/$userId/rooms/$roomId/tags", { $userId: this.credentials.userId, $roomId: roomId, }); - return this.http.authedRequest(callback, Method.Get, path); + return this.http.authedRequest(Method.Get, path); } /** * @param {string} roomId * @param {string} tagName name of room tag to be set * @param {object} metadata associated with that tag to be stored - * @param {module:client.callback} callback Optional. * @return {Promise} Resolves: to an empty object * @return {module:http-api.MatrixError} Rejects: with an error response. */ - public setRoomTag(roomId: string, tagName: string, metadata: ITagMetadata, callback?: Callback): Promise<{}> { + public setRoomTag(roomId: string, tagName: string, metadata: ITagMetadata): Promise<{}> { const path = utils.encodeUri("/user/$userId/rooms/$roomId/tags/$tag", { $userId: this.credentials.userId, $roomId: roomId, $tag: tagName, }); - return this.http.authedRequest(callback, Method.Put, path, undefined, metadata); + return this.http.authedRequest(Method.Put, path, undefined, metadata); } /** * @param {string} roomId * @param {string} tagName name of room tag to be removed - * @param {module:client.callback} callback Optional. * @return {Promise} Resolves: void * @return {module:http-api.MatrixError} Rejects: with an error response. */ - public deleteRoomTag(roomId: string, tagName: string, callback?: Callback): Promise { + public deleteRoomTag(roomId: string, tagName: string): Promise { const path = utils.encodeUri("/user/$userId/rooms/$roomId/tags/$tag", { $userId: this.credentials.userId, $roomId: roomId, $tag: tagName, }); - return this.http.authedRequest(callback, Method.Delete, path); + return this.http.authedRequest(Method.Delete, path); } /** * @param {string} roomId * @param {string} eventType event type to be set * @param {object} content event content - * @param {module:client.callback} callback Optional. * @return {Promise} Resolves: to an empty object {} * @return {module:http-api.MatrixError} Rejects: with an error response. */ @@ -3720,14 +3687,13 @@ export class MatrixClient extends TypedEventEmitter, - callback?: Callback, ): Promise<{}> { const path = utils.encodeUri("/user/$userId/rooms/$roomId/account_data/$type", { $userId: this.credentials.userId, $roomId: roomId, $type: eventType, }); - return this.http.authedRequest(callback, Method.Put, path, undefined, content); + return this.http.authedRequest(Method.Put, path, undefined, content); } /** @@ -3736,7 +3702,6 @@ export class MatrixClient extends TypedEventEmitter { let content = { users: {}, @@ -3759,7 +3723,7 @@ export class MatrixClient extends TypedEventEmitter; public sendEvent( roomId: string, @@ -3815,18 +3777,15 @@ export class MatrixClient extends TypedEventEmitter; public sendEvent( roomId: string, threadId: string | null, eventType: string | IContent, content: IContent | string, - txnId?: string | Callback, - callback?: Callback, + txnId?: string, ): Promise { if (!threadId?.startsWith(EVENT_ID_PREFIX) && threadId !== null) { - callback = txnId as Callback; txnId = content as string; content = eventType as IContent; eventType = threadId; @@ -3854,7 +3813,7 @@ export class MatrixClient extends TypedEventEmitter { - if (utils.isFunction(txnId)) { - callback = txnId as any as Callback; // convert for legacy - txnId = undefined; - } - if (!txnId) { txnId = this.makeTxnId(); } @@ -3935,18 +3887,17 @@ export class MatrixClient extends TypedEventEmitter { + private encryptAndSendEvent(room: Room, event: MatrixEvent): Promise { let cancelled = false; // Add an extra Promise.resolve() to turn synchronous exceptions into promise rejections, // so that we can handle synchronous and asynchronous exceptions with the @@ -3992,9 +3943,6 @@ export class MatrixClient extends TypedEventEmitter { - callback?.(null, res); - return res; }).catch(err => { logger.error("Error sending event", err.stack || err); try { @@ -4006,8 +3954,6 @@ export class MatrixClient extends TypedEventEmitter( - undefined, Method.Put, path, undefined, event.getWireContent(), + Method.Put, path, undefined, event.getWireContent(), ).then((res) => { logger.log(`Event sent to ${event.getRoomId()} with event id ${res.event_id}`); return res; @@ -4126,11 +4072,8 @@ export class MatrixClient extends TypedEventEmitter; public redactEvent( roomId: string, threadId: string | null, eventId: string, txnId?: string | undefined, - cbOrOpts?: Callback | IRedactOpts, + opts?: IRedactOpts, ): Promise; public redactEvent( roomId: string, threadId: string | null, eventId?: string, - txnId?: string | Callback | IRedactOpts, - cbOrOpts?: Callback | IRedactOpts, + txnId?: string | IRedactOpts, + opts?: IRedactOpts, ): Promise { if (!eventId?.startsWith(EVENT_ID_PREFIX)) { - cbOrOpts = txnId as (Callback | IRedactOpts); + opts = txnId as IRedactOpts; txnId = eventId; eventId = threadId; threadId = null; } - const opts = typeof (cbOrOpts) === 'object' ? cbOrOpts : {}; - const reason = opts.reason; - const callback = typeof (cbOrOpts) === 'function' ? cbOrOpts : undefined; + const reason = opts?.reason; return this.sendCompleteEvent(roomId, threadId, { type: EventType.RoomRedaction, content: { reason }, redacts: eventId, - }, txnId as string, callback); + }, txnId as string); } /** @@ -4175,7 +4116,6 @@ export class MatrixClient extends TypedEventEmitter; public sendMessage( roomId: string, threadId: string | null, content: IContent, txnId?: string, - callback?: Callback, ): Promise; public sendMessage( roomId: string, threadId: string | null | IContent, content: IContent | string, - txnId?: string | Callback, - callback?: Callback, + txnId?: string, ): Promise { if (typeof threadId !== "string" && threadId !== null) { - callback = txnId as Callback; txnId = content as string; content = threadId as IContent; threadId = null; } - if (utils.isFunction(txnId)) { - callback = txnId as any as Callback; // for legacy - txnId = undefined; - } // Populate all outbound events with Extensible Events metadata to ensure there's a // reasonably large pool of messages to parse. @@ -4254,8 +4186,7 @@ export class MatrixClient extends TypedEventEmitter; public sendTextMessage( roomId: string, threadId: string | null, body: string, txnId?: string, - callback?: Callback, ): Promise; public sendTextMessage( roomId: string, threadId: string | null, body: string, - txnId?: string | Callback, - callback?: Callback, + txnId?: string, ): Promise { if (!threadId?.startsWith(EVENT_ID_PREFIX) && threadId !== null) { - callback = txnId as Callback; txnId = body; body = threadId; threadId = null; } const content = ContentHelpers.makeTextMessage(body); - return this.sendMessage(roomId, threadId, content, txnId as string, callback); + return this.sendMessage(roomId, threadId, content, txnId); } /** @@ -4303,7 +4229,6 @@ export class MatrixClient extends TypedEventEmitter; public sendNotice( roomId: string, threadId: string | null, body: string, txnId?: string, - callback?: Callback, ): Promise; public sendNotice( roomId: string, threadId: string | null, body: string, - txnId?: string | Callback, - callback?: Callback, + txnId?: string, ): Promise { if (!threadId?.startsWith(EVENT_ID_PREFIX) && threadId !== null) { - callback = txnId as Callback; txnId = body; body = threadId; threadId = null; } const content = ContentHelpers.makeNotice(body); - return this.sendMessage(roomId, threadId, content, txnId as string, callback); + return this.sendMessage(roomId, threadId, content, txnId); } /** @@ -4342,7 +4263,6 @@ export class MatrixClient extends TypedEventEmitter; public sendEmoteMessage( roomId: string, threadId: string | null, body: string, txnId?: string, - callback?: Callback, ): Promise; public sendEmoteMessage( roomId: string, threadId: string | null, body: string, - txnId?: string | Callback, - callback?: Callback, + txnId?: string, ): Promise { if (!threadId?.startsWith(EVENT_ID_PREFIX) && threadId !== null) { - callback = txnId as Callback; txnId = body; body = threadId; threadId = null; } const content = ContentHelpers.makeEmoteMessage(body); - return this.sendMessage(roomId, threadId, content, txnId as string, callback); + return this.sendMessage(roomId, threadId, content, txnId); } /** @@ -4382,7 +4298,6 @@ export class MatrixClient extends TypedEventEmitter; public sendImageMessage( roomId: string, @@ -4399,34 +4313,27 @@ export class MatrixClient extends TypedEventEmitter; public sendImageMessage( roomId: string, threadId: string | null, url: string | IImageInfo, info?: IImageInfo | string, - text: Callback | string = "Image", - callback?: Callback, + text = "Image", ): Promise { if (!threadId?.startsWith(EVENT_ID_PREFIX) && threadId !== null) { - callback = text as Callback; text = info as string || "Image"; info = url as IImageInfo; url = threadId as string; threadId = null; } - if (utils.isFunction(text)) { - callback = text as any as Callback; // legacy - text = undefined; - } const content = { msgtype: MsgType.Image, url: url, info: info, body: text, }; - return this.sendMessage(roomId, threadId, content, undefined, callback); + return this.sendMessage(roomId, threadId, content); } /** @@ -4435,7 +4342,6 @@ export class MatrixClient extends TypedEventEmitter; public sendStickerMessage( roomId: string, @@ -4452,34 +4357,27 @@ export class MatrixClient extends TypedEventEmitter; public sendStickerMessage( roomId: string, threadId: string | null, url: string | IImageInfo, info?: IImageInfo | string, - text: Callback | string = "Sticker", - callback?: Callback, + text = "Sticker", ): Promise { if (!threadId?.startsWith(EVENT_ID_PREFIX) && threadId !== null) { - callback = text as Callback; text = info as string || "Sticker"; info = url as IImageInfo; url = threadId as string; threadId = null; } - if (utils.isFunction(text)) { - callback = text as any as Callback; // legacy - text = undefined; - } const content = { url: url, info: info, body: text, }; - return this.sendEvent(roomId, threadId, EventType.Sticker, content, undefined, callback); + return this.sendEvent(roomId, threadId, EventType.Sticker, content); } /** @@ -4487,7 +4385,6 @@ export class MatrixClient extends TypedEventEmitter; public sendHtmlMessage( roomId: string, threadId: string | null, body: string, htmlBody: string, - callback?: Callback, ): Promise; public sendHtmlMessage( roomId: string, threadId: string | null, body: string, - htmlBody: string | Callback, - callback?: Callback, + htmlBody?: string, ): Promise { if (!threadId?.startsWith(EVENT_ID_PREFIX) && threadId !== null) { - callback = htmlBody as Callback; htmlBody = body as string; body = threadId; threadId = null; } - const content = ContentHelpers.makeHtmlMessage(body, htmlBody as string); - return this.sendMessage(roomId, threadId, content, undefined, callback); + const content = ContentHelpers.makeHtmlMessage(body, htmlBody); + return this.sendMessage(roomId, threadId, content); } /** * @param {string} roomId * @param {string} body * @param {string} htmlBody - * @param {module:client.callback} callback Optional. Deprecated * @return {Promise} Resolves: to a ISendEventResponse object * @return {module:http-api.MatrixError} Rejects: with an error response. */ @@ -4533,30 +4425,26 @@ export class MatrixClient extends TypedEventEmitter; public sendHtmlNotice( roomId: string, threadId: string | null, body: string, htmlBody: string, - callback?: Callback, ): Promise; public sendHtmlNotice( roomId: string, threadId: string | null, body: string, - htmlBody: string | Callback, - callback?: Callback, + htmlBody?: string, ): Promise { if (!threadId?.startsWith(EVENT_ID_PREFIX) && threadId !== null) { - callback = htmlBody as Callback; htmlBody = body as string; body = threadId; threadId = null; } - const content = ContentHelpers.makeHtmlNotice(body, htmlBody as string); - return this.sendMessage(roomId, threadId, content, undefined, callback); + const content = ContentHelpers.makeHtmlNotice(body, htmlBody); + return this.sendMessage(roomId, threadId, content); } /** @@ -4564,7 +4452,6 @@ export class MatrixClient extends TypedEventEmitter; public sendHtmlEmote( roomId: string, threadId: string | null, body: string, htmlBody: string, - callback?: Callback, ): Promise; public sendHtmlEmote( roomId: string, threadId: string | null, body: string, - htmlBody: string | Callback, - callback?: Callback, + htmlBody?: string, ): Promise { if (!threadId?.startsWith(EVENT_ID_PREFIX) && threadId !== null) { - callback = htmlBody as Callback; htmlBody = body as string; body = threadId; threadId = null; } - const content = ContentHelpers.makeHtmlEmote(body, htmlBody as string); - return this.sendMessage(roomId, threadId, content, undefined, callback); + const content = ContentHelpers.makeHtmlEmote(body, htmlBody); + return this.sendMessage(roomId, threadId, content); } /** @@ -4604,7 +4487,6 @@ export class MatrixClient extends TypedEventEmitter { - if (typeof (body) === 'function') { - callback = body as any as Callback; // legacy - body = {}; - } - if (this.isGuest()) { return Promise.resolve({}); // guests cannot send receipts so don't bother. } @@ -4637,7 +4513,7 @@ export class MatrixClient extends TypedEventEmitter { if (!event) return; const eventId = event.getId(); @@ -4666,7 +4540,7 @@ export class MatrixClient extends TypedEventEmitter { + public getUrlPreview(url: string, ts: number): Promise { // bucket the timestamp to the nearest minute to prevent excessive spam to the server // Surely 60-second accuracy is enough for anyone. ts = Math.floor(ts / 60000) * 60000; @@ -4746,20 +4619,15 @@ export class MatrixClient extends TypedEventEmitter(Method.Get, "/preview_url", { + url, + ts: ts.toString(), + }, undefined, { + prefix: MediaPrefix.R0, + }); // TODO: Expire the URL preview cache sometimes this.urlPreviewCache[key] = resp; return resp; @@ -4769,11 +4637,10 @@ export class MatrixClient extends TypedEventEmitter { + public sendTyping(roomId: string, isTyping: boolean, timeoutMs: number): Promise<{}> { if (this.isGuest()) { return Promise.resolve({}); // guests cannot send typing notifications so don't bother. } @@ -4788,7 +4655,7 @@ export class MatrixClient extends TypedEventEmitter { - return this.membershipChange(roomId, userId, "invite", reason, callback); + public invite(roomId: string, userId: string, reason?: string): Promise<{}> { + return this.membershipChange(roomId, userId, "invite", reason); } /** * Invite a user to a room based on their email address. * @param {string} roomId The room to invite the user to. * @param {string} email The email address to invite. - * @param {module:client.callback} callback Optional. * @return {Promise} Resolves: {} an empty object. * @return {module:http-api.MatrixError} Rejects: with an error response. */ - public inviteByEmail(roomId: string, email: string, callback?: Callback): Promise<{}> { - return this.inviteByThreePid(roomId, "email", email, callback); + public inviteByEmail(roomId: string, email: string): Promise<{}> { + return this.inviteByThreePid(roomId, "email", email); } /** @@ -4898,11 +4763,10 @@ export class MatrixClient extends TypedEventEmitter { + public async inviteByThreePid(roomId: string, medium: string, address: string): Promise<{}> { const path = utils.encodeUri( "/rooms/$roomId/invite", { $roomId: roomId }, @@ -4931,17 +4795,16 @@ export class MatrixClient extends TypedEventEmitter { - return this.membershipChange(roomId, undefined, "leave", undefined, callback); + public leave(roomId: string): Promise<{}> { + return this.membershipChange(roomId, undefined, "leave"); } /** @@ -4995,28 +4858,22 @@ export class MatrixClient extends TypedEventEmitter { + return this.membershipChange(roomId, userId, "ban", reason); } /** * @param {string} roomId * @param {boolean} deleteRoom True to delete the room from the store on success. * Default: true. - * @param {module:client.callback} callback Optional. * @return {Promise} Resolves: {} an empty object. * @return {module:http-api.MatrixError} Rejects: with an error response. */ - public forget(roomId: string, deleteRoom?: boolean, callback?: Callback): Promise<{}> { - if (deleteRoom === undefined) { - deleteRoom = true; - } - const promise = this.membershipChange(roomId, undefined, "forget", undefined, - callback); + public forget(roomId: string, deleteRoom = true): Promise<{}> { + const promise = this.membershipChange(roomId, undefined, "forget"); if (!deleteRoom) { return promise; } @@ -5030,11 +4887,10 @@ export class MatrixClient extends TypedEventEmitter { + public unban(roomId: string, userId: string): Promise { // unbanning != set their state to leave: this used to be // the case, but was then changed so that leaving was always // a revoking of privilege, otherwise two people racing to @@ -5046,20 +4902,17 @@ export class MatrixClient extends TypedEventEmitter { + public kick(roomId: string, userId: string, reason?: string): Promise<{}> { const path = utils.encodeUri("/rooms/$roomId/kick", { $roomId: roomId, }); @@ -5067,9 +4920,7 @@ export class MatrixClient extends TypedEventEmitter { // API returns an empty object - if (utils.isFunction(reason)) { - callback = reason as any as Callback; // legacy - reason = undefined; - } - const path = utils.encodeUri("/rooms/$room_id/$membership", { $room_id: roomId, $membership: membership, }); return this.http.authedRequest( - callback, Method.Post, path, undefined, { + Method.Post, path, undefined, { user_id: userId, // may be undefined e.g. on leave reason: reason, }, @@ -5114,29 +4959,27 @@ export class MatrixClient extends TypedEventEmitter; - public setProfileInfo(info: "displayname", data: { displayname: string }, callback?: Callback): Promise<{}>; - public setProfileInfo(info: "avatar_url" | "displayname", data: object, callback?: Callback): Promise<{}> { + public setProfileInfo(info: "avatar_url", data: { avatar_url: string }): Promise<{}>; + public setProfileInfo(info: "displayname", data: { displayname: string }): Promise<{}>; + public setProfileInfo(info: "avatar_url" | "displayname", data: object): Promise<{}> { const path = utils.encodeUri("/profile/$userId/$info", { $userId: this.credentials.userId, $info: info, }); - return this.http.authedRequest(callback, Method.Put, path, undefined, data); + return this.http.authedRequest(Method.Put, path, undefined, data); } /** * @param {string} name - * @param {module:client.callback} callback Optional. * @return {Promise} Resolves: {} an empty object. * @return {module:http-api.MatrixError} Rejects: with an error response. */ - public async setDisplayName(name: string, callback?: Callback): Promise<{}> { - const prom = await this.setProfileInfo("displayname", { displayname: name }, callback); + public async setDisplayName(name: string): Promise<{}> { + const prom = await this.setProfileInfo("displayname", { displayname: name }); // XXX: synthesise a profile update for ourselves because Synapse is broken and won't const user = this.getUser(this.getUserId()); if (user) { @@ -5148,12 +4991,11 @@ export class MatrixClient extends TypedEventEmitter { - const prom = await this.setProfileInfo("avatar_url", { avatar_url: url }, callback); + public async setAvatarUrl(url: string): Promise<{}> { + const prom = await this.setProfileInfo("avatar_url", { avatar_url: url }); // XXX: synthesise a profile update for ourselves because Synapse is broken and won't const user = this.getUser(this.getUserId()); if (user) { @@ -5190,12 +5032,11 @@ export class MatrixClient extends TypedEventEmitter { + public setPresence(opts: IPresenceOpts): Promise { const path = utils.encodeUri("/presence/$userId/status", { $userId: this.credentials.userId, }); @@ -5208,23 +5049,20 @@ export class MatrixClient extends TypedEventEmitter { + public getPresence(userId: string): Promise { const path = utils.encodeUri("/presence/$userId/status", { $userId: userId, }); - return this.http.authedRequest(callback, Method.Get, path); + return this.http.authedRequest(Method.Get, path); } /** @@ -5238,17 +5076,12 @@ export class MatrixClient extends TypedEventEmitterRoom.oldState.paginationToken will be * null. * @return {module:http-api.MatrixError} Rejects: with an error response. */ - public scrollback(room: Room, limit = 30, callback?: Callback): Promise { - if (utils.isFunction(limit)) { - callback = limit as any as Callback; // legacy - limit = undefined; - } + public scrollback(room: Room, limit = 30): Promise { let timeToWaitMs = 0; let info = this.ongoingScrollbacks[room.roomId] || {}; @@ -5300,13 +5133,11 @@ export class MatrixClient extends TypedEventEmitter { this.ongoingScrollbacks[room.roomId] = { errorTs: Date.now(), }; - callback?.(err); reject(err); }); }); @@ -5369,7 +5200,7 @@ export class MatrixClient extends TypedEventEmitter(undefined, Method.Get, path, params); + const res = await this.http.authedRequest(Method.Get, path, params); if (!res.event) { throw new Error("'event' not in '/context' result - homeserver too old?"); } @@ -5476,7 +5307,7 @@ export class MatrixClient extends TypedEventEmitter(undefined, Method.Get, messagesPath, params); + const res = await this.http.authedRequest(Method.Get, messagesPath, params); const event = res.chunk?.[0]; if (!event) { throw new Error("No message returned from /messages when trying to construct getLatestTimeline"); @@ -5531,7 +5362,7 @@ export class MatrixClient extends TypedEventEmitter( - undefined, Method.Get, path, params, + Method.Get, path, params, ).then(async (res) => { const token = res.next_token; const matrixEvents = []; @@ -5897,7 +5728,6 @@ export class MatrixClient extends TypedEventEmitter { + public searchMessageText(opts: ISearchOpts): Promise { const roomEvents: ISearchRequestBody["search_categories"]["room_events"] = { search_term: opts.query, }; @@ -6094,7 +5924,7 @@ export class MatrixClient extends TypedEventEmitter(undefined, Method.Post, path, undefined, content) + return this.http.authedRequest(Method.Post, path, undefined, content) .then((response) => { // persist the filter const filter = Filter.fromJson(this.credentials.userId, response.filter_id, content); @@ -6292,7 +6122,7 @@ export class MatrixClient extends TypedEventEmitter(undefined, Method.Get, path).then((response) => { + return this.http.authedRequest(Method.Get, path).then((response) => { // persist the filter const filter = Filter.fromJson(userId, filterId, response); this.store.storeFilter(filter); @@ -6367,9 +6197,7 @@ export class MatrixClient extends TypedEventEmitter { @@ -6380,12 +6208,11 @@ export class MatrixClient extends TypedEventEmitter { - return this.http.authedRequest(callback, Method.Get, "/voip/turnServer"); + public turnServer(): Promise { + return this.http.authedRequest(Method.Get, "/voip/turnServer"); } /** @@ -6491,7 +6318,7 @@ export class MatrixClient extends TypedEventEmitter r['admin']); // pull out the specific boolean we want } @@ -6507,7 +6334,7 @@ export class MatrixClient extends TypedEventEmitter { @@ -6582,7 +6407,7 @@ export class MatrixClient extends TypedEventEmitter( - undefined, Method.Get, path, undefined, undefined, + Method.Get, path, undefined, undefined, { prefix: ClientPrefix.Unstable }, ); return res.joined; @@ -6599,7 +6424,6 @@ export class MatrixClient extends TypedEventEmitter( - undefined, // callback Method.Get, "/_matrix/client/versions", undefined, // queryParams undefined, // data @@ -6963,7 +6787,7 @@ export class MatrixClient extends TypedEventEmitter { return this.http.authedRequest<{ available: true }>( - undefined, Method.Get, '/register/available', { username }, + Method.Get, '/register/available', { username }, ).then((response) => { return response.available; }).catch(response => { @@ -6984,7 +6808,6 @@ export class MatrixClient extends TypedEventEmitter { // backwards compat if (bindThreepids === true) { @@ -7004,11 +6826,6 @@ export class MatrixClient extends TypedEventEmitter { // TODO: Types + public registerGuest(opts: { body?: any }): Promise { // TODO: Types opts = opts || {}; opts.body = opts.body || {}; - return this.registerRequest(opts.body, "guest", callback); + return this.registerRequest(opts.body, "guest"); } /** * @param {Object} data parameters for registration request * @param {string=} kind type of user to register. may be "guest" - * @param {module:client.callback=} callback * @return {Promise} Resolves: to the /register response * @return {module:http-api.MatrixError} Rejects: with an error response. */ - public registerRequest(data: IRegisterRequestParams, kind?: string, callback?: Callback): Promise { + public registerRequest(data: IRegisterRequestParams, kind?: string): Promise { const params: { kind?: string } = {}; if (kind) { params.kind = kind; } - return this.http.request(callback, Method.Post, "/register", params, data); + return this.http.request(Method.Post, "/register", params, data); } /** @@ -7106,7 +6921,6 @@ export class MatrixClient extends TypedEventEmitter { return this.http.authedRequest( - undefined, Method.Post, "/refresh", undefined, @@ -7119,22 +6933,20 @@ export class MatrixClient extends TypedEventEmitter} Resolves to the available login flows * @return {module:http-api.MatrixError} Rejects: with an error response. */ - public loginFlows(callback?: Callback): Promise { - return this.http.request(callback, Method.Get, "/login"); + public loginFlows(): Promise { + return this.http.request(Method.Get, "/login"); } /** * @param {string} loginType * @param {Object} data - * @param {module:client.callback} callback Optional. * @return {Promise} Resolves: TODO * @return {module:http-api.MatrixError} Rejects: with an error response. */ - public login(loginType: string, data: any, callback?: Callback): Promise { // TODO: Types + public login(loginType: string, data: any): Promise { // TODO: Types const loginData = { type: loginType, }; @@ -7142,46 +6954,41 @@ export class MatrixClient extends TypedEventEmitter { - if (response && response.access_token && response.user_id) { - this.http.opts.accessToken = response.access_token; - this.credentials = { - userId: response.user_id, - }; - } - - if (callback) { - callback(error, response); - } - }, Method.Post, "/login", undefined, loginData, - ); + return this.http.authedRequest<{ + access_token?: string; + user_id?: string; + }>(Method.Post, "/login", undefined, loginData).then(response => { + if (response.access_token && response.user_id) { + this.http.opts.accessToken = response.access_token; + this.credentials = { + userId: response.user_id, + }; + } + }); } /** * @param {string} user * @param {string} password - * @param {module:client.callback} callback Optional. * @return {Promise} Resolves: TODO * @return {module:http-api.MatrixError} Rejects: with an error response. */ - public loginWithPassword(user: string, password: string, callback?: Callback): Promise { // TODO: Types + public loginWithPassword(user: string, password: string): Promise { // TODO: Types return this.login("m.login.password", { user: user, password: password, - }, callback); + }); } /** * @param {string} relayState URL Callback after SAML2 Authentication - * @param {module:client.callback} callback Optional. * @return {Promise} Resolves: TODO * @return {module:http-api.MatrixError} Rejects: with an error response. */ - public loginWithSAML2(relayState: string, callback?: Callback): Promise { // TODO: Types + public loginWithSAML2(relayState: string): Promise { // TODO: Types return this.login("m.login.saml2", { relay_state: relayState, - }, callback); + }); } /** @@ -7223,14 +7030,13 @@ export class MatrixClient extends TypedEventEmitter { // TODO: Types + public loginWithToken(token: string): Promise { // TODO: Types return this.login("m.login.token", { token: token, - }, callback); + }); } /** @@ -7239,11 +7045,10 @@ export class MatrixClient extends TypedEventEmitter { + public async logout(stopClient = false): Promise<{}> { if (this.crypto?.backupManager?.getKeyBackupEnabled()) { try { while (await this.crypto.backupManager.backupPendingKeys(200) > 0); @@ -7259,9 +7064,7 @@ export class MatrixClient extends TypedEventEmitter { - if (typeof (erase) === 'function') { - throw new Error('deactivateAccount no longer accepts a callback parameter'); - } - const body: any = {}; if (auth) { body.auth = auth; @@ -7289,7 +7088,7 @@ export class MatrixClient extends TypedEventEmitter> { const body: UIARequest<{}> = { auth }; return this.http.authedRequest( - undefined, // no callback support Method.Post, "/org.matrix.msc3882/login/token", undefined, // no query params @@ -7340,14 +7138,10 @@ export class MatrixClient extends TypedEventEmitter{room_id: {string}} * @return {module:http-api.MatrixError} Rejects: with an error response. */ - public async createRoom( - options: ICreateRoomOpts, - callback?: Callback, - ): Promise<{ room_id: string }> { // eslint-disable-line camelcase + public async createRoom(options: ICreateRoomOpts): Promise<{ room_id: string }> { // eslint-disable-line camelcase // some valid options include: room_alias_name, visibility, invite // inject the id_access_token if inviting 3rd party addresses @@ -7366,7 +7160,7 @@ export class MatrixClient extends TypedEventEmitter { + public roomState(roomId: string): Promise { const path = utils.encodeUri("/rooms/$roomId/state", { $roomId: roomId }); - return this.http.authedRequest(callback, Method.Get, path); + return this.http.authedRequest(Method.Get, path); } /** * Get an event in a room by its event id. * @param {string} roomId * @param {string} eventId - * @param {module:client.callback} callback Optional. * * @return {Promise} Resolves to an object containing the event. * @return {module:http-api.MatrixError} Rejects: with an error response. */ - public fetchRoomEvent( - roomId: string, - eventId: string, - callback?: Callback, - ): Promise { + public fetchRoomEvent(roomId: string, eventId: string): Promise { const path = utils.encodeUri( "/rooms/$roomId/event/$eventId", { $roomId: roomId, $eventId: eventId, }, ); - return this.http.authedRequest(callback, Method.Get, path); + return this.http.authedRequest(Method.Get, path); } /** @@ -7452,7 +7240,6 @@ export class MatrixClient extends TypedEventEmitter { const queryParams: Record = {}; if (includeMembership) { @@ -7478,7 +7264,7 @@ export class MatrixClient extends TypedEventEmitter { // eslint-disable-line camelcase const path = utils.encodeUri("/rooms/$roomId/upgrade", { $roomId: roomId }); - return this.http.authedRequest( - undefined, Method.Post, path, undefined, { new_version: newVersion }, - ); + return this.http.authedRequest(Method.Post, path, undefined, { new_version: newVersion }); } /** @@ -7503,7 +7287,6 @@ export class MatrixClient extends TypedEventEmitter> { const pathParams = { $roomId: roomId, @@ -7522,9 +7304,7 @@ export class MatrixClient extends TypedEventEmitter { const pathParams = { $roomId: roomId, @@ -7552,27 +7330,21 @@ export class MatrixClient extends TypedEventEmitter { - if (utils.isFunction(limit)) { - callback = limit as any as Callback; // legacy - limit = undefined; - } - + public roomInitialSync(roomId: string, limit: number): Promise { const path = utils.encodeUri("/rooms/$roomId/initialSync", { $roomId: roomId }, ); - return this.http.authedRequest(callback, Method.Get, path, { limit: limit?.toString() ?? "30" }); + return this.http.authedRequest(Method.Get, path, { limit: limit?.toString() ?? "30" }); } /** @@ -7608,7 +7380,7 @@ export class MatrixClient extends TypedEventEmitter { const path = utils.encodeUri("/joined_rooms", {}); - return this.http.authedRequest(undefined, Method.Get, path); + return this.http.authedRequest(Method.Get, path); } /** @@ -7631,7 +7403,7 @@ export class MatrixClient extends TypedEventEmitter { - if (typeof (options) == 'function') { - callback = options; - options = {}; - } - if (options === undefined) { - options = {}; - } - + public publicRooms(options: IRoomDirectoryOptions = {}): Promise { const queryParams: any = {}; if (options.server) { queryParams.server = options.server; @@ -7663,9 +7426,9 @@ export class MatrixClient extends TypedEventEmitter { + public createAlias(alias: string, roomId: string): Promise<{}> { const path = utils.encodeUri("/directory/room/$alias", { $alias: alias, }); const data = { room_id: roomId, }; - return this.http.authedRequest(callback, Method.Put, path, undefined, data); + return this.http.authedRequest(Method.Put, path, undefined, data); } /** * Delete an alias to room ID mapping. This alias must be on your local server, * and you must have sufficient access to do this operation. * @param {string} alias The room alias to delete. - * @param {module:client.callback} callback Optional. * @return {Promise} Resolves: an empty object {}. * @return {module:http-api.MatrixError} Rejects: with an error response. */ - public deleteAlias(alias: string, callback?: Callback): Promise<{}> { + public deleteAlias(alias: string): Promise<{}> { const path = utils.encodeUri("/directory/room/$alias", { $alias: alias, }); - return this.http.authedRequest(callback, Method.Delete, path); + return this.http.authedRequest(Method.Delete, path); } /** @@ -7712,52 +7473,48 @@ export class MatrixClient extends TypedEventEmitter { const path = utils.encodeUri("/rooms/$roomId/aliases", { $roomId: roomId }); const prefix = ClientPrefix.V3; - return this.http.authedRequest(undefined, Method.Get, path, undefined, undefined, { prefix }); + return this.http.authedRequest(Method.Get, path, undefined, undefined, { prefix }); } /** * Get room info for the given alias. * @param {string} alias The room alias to resolve. - * @param {module:client.callback} callback Optional. * @return {Promise} Resolves: Object with room_id and servers. * @return {module:http-api.MatrixError} Rejects: with an error response. */ public getRoomIdForAlias( alias: string, - callback?: Callback, ): Promise<{ room_id: string, servers: string[] }> { // eslint-disable-line camelcase // TODO: deprecate this or resolveRoomAlias const path = utils.encodeUri("/directory/room/$alias", { $alias: alias, }); - return this.http.authedRequest(callback, Method.Get, path); + return this.http.authedRequest(Method.Get, path); } /** * @param {string} roomAlias - * @param {module:client.callback} callback Optional. * @return {Promise} Resolves: Object with room_id and servers. * @return {module:http-api.MatrixError} Rejects: with an error response. */ // eslint-disable-next-line camelcase - public resolveRoomAlias(roomAlias: string, callback?: Callback): Promise<{ room_id: string, servers: string[] }> { + public resolveRoomAlias(roomAlias: string): Promise<{ room_id: string, servers: string[] }> { // TODO: deprecate this or getRoomIdForAlias const path = utils.encodeUri("/directory/room/$alias", { $alias: roomAlias }); - return this.http.request(callback, Method.Get, path); + return this.http.request(Method.Get, path); } /** * Get the visibility of a room in the current HS's room directory * @param {string} roomId - * @param {module:client.callback} callback Optional. * @return {Promise} Resolves: TODO * @return {module:http-api.MatrixError} Rejects: with an error response. */ - public getRoomDirectoryVisibility(roomId: string, callback?: Callback): Promise<{ visibility: Visibility }> { + public getRoomDirectoryVisibility(roomId: string): Promise<{ visibility: Visibility }> { const path = utils.encodeUri("/directory/list/room/$roomId", { $roomId: roomId, }); - return this.http.authedRequest(callback, Method.Get, path); + return this.http.authedRequest(Method.Get, path); } /** @@ -7766,15 +7523,14 @@ export class MatrixClient extends TypedEventEmitter { + public setRoomDirectoryVisibility(roomId: string, visibility: Visibility): Promise<{}> { const path = utils.encodeUri("/directory/list/room/$roomId", { $roomId: roomId, }); - return this.http.authedRequest(callback, Method.Put, path, undefined, { visibility }); + return this.http.authedRequest(Method.Put, path, undefined, { visibility }); } /** @@ -7786,7 +7542,6 @@ export class MatrixClient extends TypedEventEmitter { // TODO: Types const path = utils.encodeUri("/directory/list/appservice/$networkId/$roomId", { $networkId: networkId, $roomId: roomId, }); - return this.http.authedRequest( - callback, Method.Put, path, undefined, { "visibility": visibility }, - ); + return this.http.authedRequest(Method.Put, path, undefined, { "visibility": visibility }); } /** @@ -7822,7 +7574,7 @@ export class MatrixClient extends TypedEventEmitter { - if (utils.isFunction(info)) { - callback = info as any as Callback; // legacy - info = undefined; - } - const path = info ? utils.encodeUri("/profile/$userId/$info", { $userId: userId, $info: info }) : utils.encodeUri("/profile/$userId", { $userId: userId }); - return this.http.authedRequest(callback, Method.Get, path); + return this.http.authedRequest(Method.Get, path); } /** - * @param {module:client.callback} callback Optional. * @return {Promise} Resolves to a list of the user's threepids. * @return {module:http-api.MatrixError} Rejects: with an error response. */ - public getThreePids(callback?: Callback): Promise<{ threepids: IThreepid[] }> { - return this.http.authedRequest(callback, Method.Get, "/account/3pid"); + public getThreePids(): Promise<{ threepids: IThreepid[] }> { + return this.http.authedRequest(Method.Get, "/account/3pid"); } /** @@ -7938,19 +7678,16 @@ export class MatrixClient extends TypedEventEmitter { // TODO: Types + public addThreePid(creds: any, bind: boolean): Promise { // TODO: Types const path = "/account/3pid"; const data = { 'threePidCreds': creds, 'bind': bind, }; - return this.http.authedRequest( - callback, Method.Post, path, undefined, data, - ); + return this.http.authedRequest(Method.Post, path, undefined, data); } /** @@ -7968,7 +7705,7 @@ export class MatrixClient extends TypedEventEmitter { const path = "/account/3pid/add"; const prefix = await this.isVersionSupported("r0.6.0") ? ClientPrefix.R0 : ClientPrefix.Unstable; - return this.http.authedRequest(undefined, Method.Post, path, undefined, data, { prefix }); + return this.http.authedRequest(Method.Post, path, undefined, data, { prefix }); } /** @@ -7988,9 +7725,7 @@ export class MatrixClient extends TypedEventEmitter { const path = "/account/3pid/bind"; const prefix = await this.isVersionSupported("r0.6.0") ? ClientPrefix.R0 : ClientPrefix.Unstable; - return this.http.authedRequest( - undefined, Method.Post, path, undefined, data, { prefix }, - ); + return this.http.authedRequest(Method.Post, path, undefined, data, { prefix }); } /** @@ -8016,7 +7751,7 @@ export class MatrixClient extends TypedEventEmitter { const path = "/account/3pid/delete"; - return this.http.authedRequest(undefined, Method.Post, path, undefined, { medium, address }); + return this.http.authedRequest(Method.Post, path, undefined, { medium, address }); } /** @@ -8041,36 +7776,14 @@ export class MatrixClient extends TypedEventEmitter; - public setPassword( - authDict: any, - newPassword: string, - logoutDevices: boolean, - callback?: Callback, - ): Promise<{}>; - public setPassword( - authDict: any, - newPassword: string, - logoutDevices?: Callback | boolean, - callback?: Callback, + logoutDevices?: boolean, ): Promise<{}> { - if (typeof logoutDevices === 'function') { - callback = logoutDevices; - } - if (typeof logoutDevices !== 'boolean') { - // Use backwards compatible behaviour of not specifying logout_devices - // This way it is left up to the server: - logoutDevices = undefined; - } - const path = "/account/password"; const data = { 'auth': authDict, @@ -8078,9 +7791,7 @@ export class MatrixClient extends TypedEventEmitter( - callback, Method.Post, path, undefined, data, - ); + return this.http.authedRequest<{}>(Method.Post, path, undefined, data); } /** @@ -8089,7 +7800,7 @@ export class MatrixClient extends TypedEventEmitter { - return this.http.authedRequest(undefined, Method.Get, "/devices"); + return this.http.authedRequest(Method.Get, "/devices"); } /** @@ -8102,7 +7813,7 @@ export class MatrixClient extends TypedEventEmitter { - const response = await this.http.authedRequest(callback, Method.Get, "/pushers"); + public async getPushers(): Promise<{ pushers: IPusher[] }> { + const response = await this.http.authedRequest<{ pushers: IPusher[] }>(Method.Get, "/pushers"); // Migration path for clients that connect to a homeserver that does not support // MSC3881 yet, see https://github.com/matrix-org/matrix-spec-proposals/blob/kerry/remote-push-toggle/proposals/3881-remote-push-notification-toggling.md#migration @@ -8191,13 +7901,12 @@ export class MatrixClient extends TypedEventEmitter { + public setPusher(pusher: IPusherRequest): Promise<{}> { const path = "/pushers/set"; - return this.http.authedRequest(callback, Method.Post, path, undefined, pusher); + return this.http.authedRequest(Method.Post, path, undefined, pusher); } /** @@ -8217,12 +7926,11 @@ export class MatrixClient extends TypedEventEmitter { - return this.http.authedRequest(callback, Method.Get, "/pushrules/").then((rules: IPushRules) => { + public getPushRules(): Promise { + return this.http.authedRequest(Method.Get, "/pushrules/").then((rules: IPushRules) => { return PushProcessor.rewriteDefaultRules(rules); }); } @@ -8232,7 +7940,6 @@ export class MatrixClient extends TypedEventEmitter, body: Pick, - callback?: Callback, ): Promise<{}> { // NB. Scope not uri encoded because devices need the '/' const path = utils.encodeUri("/pushrules/" + scope + "/$kind/$ruleId", { $kind: kind, $ruleId: ruleId, }); - return this.http.authedRequest(callback, Method.Put, path, undefined, body); + return this.http.authedRequest(Method.Put, path, undefined, body); } /** * @param {string} scope * @param {string} kind * @param {string} ruleId - * @param {module:client.callback} callback Optional. * @return {Promise} Resolves: an empty object {} * @return {module:http-api.MatrixError} Rejects: with an error response. */ @@ -8263,14 +7968,13 @@ export class MatrixClient extends TypedEventEmitter, - callback?: Callback, ): Promise<{}> { // NB. Scope not uri encoded because devices need the '/' const path = utils.encodeUri("/pushrules/" + scope + "/$kind/$ruleId", { $kind: kind, $ruleId: ruleId, }); - return this.http.authedRequest(callback, Method.Delete, path); + return this.http.authedRequest(Method.Delete, path); } /** @@ -8279,7 +7983,6 @@ export class MatrixClient extends TypedEventEmitter { const path = utils.encodeUri("/pushrules/" + scope + "/$kind/$ruleId/enabled", { $kind: kind, $ruleId: ruleId, }); - return this.http.authedRequest( - callback, Method.Put, path, undefined, { "enabled": enabled }, - ); + return this.http.authedRequest(Method.Put, path, undefined, { "enabled": enabled }); } /** @@ -8305,7 +8005,6 @@ export class MatrixClient extends TypedEventEmitter { const path = utils.encodeUri("/pushrules/" + scope + "/$kind/$ruleId/actions", { $kind: kind, $ruleId: ruleId, }); - return this.http.authedRequest( - callback, Method.Put, path, undefined, { "actions": actions }, - ); + return this.http.authedRequest(Method.Put, path, undefined, { "actions": actions }); } /** @@ -8330,19 +8026,17 @@ export class MatrixClient extends TypedEventEmitter { const queryParams: any = {}; if (opts.next_batch) { queryParams.next_batch = opts.next_batch; } - return this.http.authedRequest(callback, Method.Post, "/search", queryParams, opts.body); + return this.http.authedRequest(Method.Post, "/search", queryParams, opts.body); } /** @@ -8353,22 +8047,19 @@ export class MatrixClient extends TypedEventEmitter { - return this.http.authedRequest(callback, Method.Post, "/keys/upload", undefined, content); + return this.http.authedRequest(Method.Post, "/keys/upload", undefined, content); } public uploadKeySignatures(content: KeySignatures): Promise { return this.http.authedRequest( - undefined, Method.Post, '/keys/signatures/upload', undefined, + Method.Post, '/keys/signatures/upload', undefined, content, { prefix: ClientPrefix.Unstable, }, @@ -8388,13 +8079,7 @@ export class MatrixClient extends TypedEventEmitter { - if (utils.isFunction(opts)) { - // opts used to be 'callback'. - throw new Error('downloadKeysForUsers no longer accepts a callback parameter'); - } - opts = opts || {}; - + public downloadKeysForUsers(userIds: string[], opts: { token?: string } = {}): Promise { const content: any = { device_keys: {}, }; @@ -8405,7 +8090,7 @@ export class MatrixClient extends TypedEventEmitter { // API returns empty object const data = Object.assign({}, keys); if (auth) Object.assign(data, { auth }); return this.http.authedRequest( - undefined, Method.Post, "/keys/device_signing/upload", undefined, data, { + Method.Post, "/keys/device_signing/upload", undefined, data, { prefix: ClientPrefix.Unstable, }, ); @@ -8495,10 +8180,7 @@ export class MatrixClient extends TypedEventEmitter { // TODO: Types const params = { @@ -8541,7 +8221,7 @@ export class MatrixClient extends TypedEventEmitter { // TODO: Types const params = { @@ -8591,7 +8269,7 @@ export class MatrixClient extends TypedEventEmitter { // TODO: Types return this.http.idServerRequest( - undefined, Method.Get, "/hash_details", + Method.Get, "/hash_details", null, IdentityPrefix.V2, identityAccessToken, ); } @@ -8745,7 +8421,7 @@ export class MatrixClient extends TypedEventEmitter { // TODO: Types // Note: we're using the V2 API by calling this function, but our @@ -8793,7 +8467,6 @@ export class MatrixClient extends TypedEventEmitter p.address === address); if (!result) { - if (callback) callback(null, {}); return {}; } @@ -8809,7 +8482,6 @@ export class MatrixClient extends TypedEventEmitter { // TODO: Types return this.http.idServerRequest( - undefined, Method.Get, "/account", + Method.Get, "/account", undefined, IdentityPrefix.V2, identityAccessToken, ); } @@ -8901,7 +8573,7 @@ export class MatrixClient extends TypedEventEmitter { return this.http.authedRequest>( - undefined, Method.Get, "/thirdparty/protocols", + Method.Get, "/thirdparty/protocols", ).then((response) => { // sanity check if (!response || typeof (response) !== 'object') { @@ -8948,7 +8620,7 @@ export class MatrixClient extends TypedEventEmitter { // TODO: Types const url = this.termsUrlForService(serviceType, baseUrl); - return this.http.requestOtherUrl(undefined, Method.Get, url); + return this.http.requestOtherUrl(Method.Get, url); } public agreeToTerms( @@ -8982,7 +8654,7 @@ export class MatrixClient extends TypedEventEmitter(undefined, Method.Get, path, queryParams, undefined, { + return this.http.authedRequest(Method.Get, path, queryParams, undefined, { prefix: ClientPrefix.V1, }).catch(e => { if (e.errcode === "M_UNRECOGNIZED") { // fall back to the prefixed hierarchy API. - return this.http.authedRequest(undefined, Method.Get, path, queryParams, undefined, { + return this.http.authedRequest(Method.Get, path, queryParams, undefined, { prefix: "/_matrix/client/unstable/org.matrix.msc2946", }); } @@ -9133,7 +8805,6 @@ export class MatrixClient extends TypedEventEmitter( - undefined, Method.Post, "/sync", qps, @@ -9161,8 +8832,7 @@ export class MatrixClient extends TypedEventEmitter { const path = utils.encodeUri("/rooms/$roomid/summary", { $roomid: roomIdOrAlias }); - return this.http.authedRequest(undefined, Method.Get, path, { via }, undefined, { - qsStringifyOptions: { arrayFormat: 'repeat' }, + return this.http.authedRequest(Method.Get, path, { via }, undefined, { prefix: "/_matrix/client/unstable/im.nheko.summary", }); } @@ -9188,7 +8858,7 @@ export class MatrixClient extends TypedEventEmitter { // eslint-disable-line camelcase - return this.http.authedRequest(undefined, Method.Get, "/account/whoami"); + return this.http.authedRequest(Method.Get, "/account/whoami"); } /** @@ -9207,7 +8877,6 @@ export class MatrixClient extends TypedEventEmitter( - undefined, Method.Put, "/dehydrated_device", undefined, @@ -273,7 +272,6 @@ export class DehydrationManager { logger.log("Uploading keys to server"); await this.crypto.baseApis.http.authedRequest( - undefined, Method.Post, "/keys/upload/" + encodeURI(deviceId), undefined, diff --git a/src/http-api.ts b/src/http-api.ts index 291b6917f5a..ed0ae10435a 100644 --- a/src/http-api.ts +++ b/src/http-api.ts @@ -31,7 +31,6 @@ import * as callbacks from "./realtime-callbacks"; import { IUploadOpts } from "./@types/requests"; import { IAbortablePromise, IUsageLimit } from "./@types/partials"; import { IDeferred, sleep } from "./utils"; -import { Callback } from "./client"; import * as utils from "./utils"; import { logger } from './logger'; import { MediaPrefix } from "./http-api/prefix"; @@ -235,10 +234,6 @@ export class MatrixHttpApi { * where it defaults to true for backwards compatibility). Ignored if * opts.rawResponse is true. * - * @param {Function=} opts.callback Deprecated. Optional. The callback to - * invoke on success/failure. See the promise return values for more - * information. - * * @param {Function=} opts.progressHandler Optional. Called when a chunk of * data has been uploaded, with an object containing the fields `loaded` * (number of bytes transferred) and `total` (total size, if known). @@ -249,17 +244,8 @@ export class MatrixHttpApi { */ public uploadContent( file: FileType, - opts?: O, + opts: O = {} as O, ): IAbortablePromise> { - if (utils.isFunction(opts)) { - // opts used to be callback, backwards compatibility - opts = { - callback: opts as unknown as IUploadOpts["callback"], - } as O; - } else if (!opts) { - opts = {} as O; - } - // default opts.includeFilename to true (ignoring falsey values) const includeFilename = opts.includeFilename !== false; @@ -349,7 +335,7 @@ export class MatrixHttpApi { if (global.XMLHttpRequest) { const defer = utils.defer>(); const xhr = new global.XMLHttpRequest(); - const cb = requestCallback(defer, opts.callback, this.opts.onlyData); + const cb = requestCallback(defer, this.opts.onlyData); const timeoutFn = function() { xhr.abort(); @@ -440,7 +426,7 @@ export class MatrixHttpApi { } promise = this.authedRequest>( - opts.callback, Method.Post, "/upload", queryParams, body, { + Method.Post, "/upload", queryParams, body, { prefix: MediaPrefix.R0, headers, json: false, @@ -479,7 +465,6 @@ export class MatrixHttpApi { } public idServerRequest( - callback: Callback, method: Method, path: string, params: Record, @@ -492,12 +477,6 @@ export class MatrixHttpApi { const fullUri = this.opts.idBaseUrl + prefix + path; - if (callback !== undefined && !utils.isFunction(callback)) { - throw Error( - "Expected callback to be a function but got " + typeof callback, - ); - } - const opts = { uri: fullUri, method, @@ -518,14 +497,12 @@ export class MatrixHttpApi { } const defer = utils.defer(); - this.opts.request(opts, requestCallback(defer, callback, this.opts.onlyData)); + this.opts.request(opts, requestCallback(defer, this.opts.onlyData)); return defer.promise; } /** * Perform an authorised request to the homeserver. - * @param {Function} callback Optional. The callback to invoke on - * success/failure. See the promise return values for more information. * @param {string} method The HTTP method e.g. "GET". * @param {string} path The HTTP path after the supplied prefix e.g. * "/createRoom". @@ -557,7 +534,6 @@ export class MatrixHttpApi { * occurred. This includes network problems and Matrix-specific error JSON. */ public authedRequest = IRequestOpts>( - callback: Callback | undefined, method: Method, path: string, queryParams?: Record, @@ -588,7 +564,7 @@ export class MatrixHttpApi { queryParams.access_token = this.opts.accessToken; } - const requestPromise = this.request(callback, method, path, queryParams, data, requestOpts); + const requestPromise = this.request(method, path, queryParams, data, requestOpts); requestPromise.catch((err: MatrixError) => { if (err.errcode == 'M_UNKNOWN_TOKEN' && !requestOpts?.inhibitLogoutEmit) { @@ -605,8 +581,6 @@ export class MatrixHttpApi { /** * Perform a request to the homeserver without any credentials. - * @param {Function} callback Optional. The callback to invoke on - * success/failure. See the promise return values for more information. * @param {string} method The HTTP method e.g. "GET". * @param {string} path The HTTP path after the supplied prefix e.g. * "/createRoom". @@ -634,7 +608,6 @@ export class MatrixHttpApi { * occurred. This includes network problems and Matrix-specific error JSON. */ public request = IRequestOpts>( - callback: Callback | undefined, method: Method, path: string, queryParams?: CoreOptions["qs"], @@ -645,13 +618,11 @@ export class MatrixHttpApi { const baseUrl = opts?.baseUrl ?? this.opts.baseUrl; const fullUri = baseUrl + prefix + path; - return this.requestOtherUrl(callback, method, fullUri, queryParams, data, opts); + return this.requestOtherUrl(method, fullUri, queryParams, data, opts); } /** * Perform a request to an arbitrary URL. - * @param {Function} callback Optional. The callback to invoke on - * success/failure. See the promise return values for more information. * @param {string} method The HTTP method e.g. "GET". * @param {string} uri The HTTP URI * @@ -678,7 +649,6 @@ export class MatrixHttpApi { * occurred. This includes network problems and Matrix-specific error JSON. */ public requestOtherUrl = IRequestOpts>( - callback: Callback | undefined, method: Method, uri: string, queryParams?: CoreOptions["qs"], @@ -693,7 +663,7 @@ export class MatrixHttpApi { } as O; } - return this.doRequest(callback, method, uri, queryParams, data, requestOpts); + return this.doRequest(method, uri, queryParams, data, requestOpts); } /** @@ -718,7 +688,6 @@ export class MatrixHttpApi { /** * @private * - * @param {function} callback * @param {string} method * @param {string} uri * @param {object} queryParams @@ -745,17 +714,12 @@ export class MatrixHttpApi { * Generic O should be inferred */ private doRequest = IRequestOpts>( - callback: Callback | undefined, method: Method, uri: string, queryParams?: Record, data?: CoreOptions["body"], opts?: O, ): IAbortablePromise> { - if (callback !== undefined && !utils.isFunction(callback)) { - throw Error("Expected callback to be a function but got " + typeof callback); - } - if (this.opts.extraParams) { queryParams = { ...(queryParams || {}), @@ -840,7 +804,7 @@ export class MatrixHttpApi { } } - const handlerFn = requestCallback(defer, callback, this.opts.onlyData, bodyParser); + const handlerFn = requestCallback(defer, this.opts.onlyData, bodyParser); handlerFn(err, response, body); }, ); @@ -865,9 +829,6 @@ export class MatrixHttpApi { } } catch (ex) { defer.reject(ex); - if (callback) { - callback(ex); - } } return reqPromise; } @@ -902,7 +863,6 @@ function getStatusCode(response: XMLHttpRequest | IncomingMessage): number { */ function requestCallback( defer: IDeferred, - userDefinedCallback?: Callback, onlyData = false, bodyParser?: (body: string) => T, ): RequestCallback { @@ -935,10 +895,8 @@ function requestCallback( if (err) { defer.reject(err); - userDefinedCallback?.(err); } else if (onlyData) { defer.resolve(data as T); - userDefinedCallback?.(null, data as T); } else { const res: IResponse = { code: getStatusCode(response), @@ -951,7 +909,6 @@ function requestCallback( // XXX: the variations in caller-expected types here are horrible, // typescript doesn't do conditional types based on runtime values defer.resolve(res as any as T); - userDefinedCallback?.(null, res as any as T); } }; } diff --git a/src/sync.ts b/src/sync.ts index 7685479499a..592c870d79a 100644 --- a/src/sync.ts +++ b/src/sync.ts @@ -296,9 +296,7 @@ export class SyncApi { getFilterName(client.credentials.userId, "LEFT_ROOMS"), filter, ).then(function(filterId) { qps.filter = filterId; - return client.http.authedRequest( - undefined, Method.Get, "/sync", qps as any, undefined, localTimeoutMs, - ); + return client.http.authedRequest(Method.Get, "/sync", qps as any, undefined, localTimeoutMs); }).then(async (data) => { let leaveRooms = []; if (data.rooms?.leave) { @@ -431,7 +429,7 @@ export class SyncApi { } // FIXME: gut wrenching; hard-coded timeout values - this.client.http.authedRequest(undefined, Method.Get, "/events", { + this.client.http.authedRequest(Method.Get, "/events", { room_id: peekRoom.roomId, timeout: String(30 * 1000), from: token, @@ -899,7 +897,7 @@ export class SyncApi { private doSyncRequest(syncOptions: ISyncOptions, syncToken: string): IAbortablePromise { const qps = this.getSyncParams(syncOptions, syncToken); return this.client.http.authedRequest( - undefined, Method.Get, "/sync", qps as any, undefined, + Method.Get, "/sync", qps as any, undefined, qps.timeout + BUFFER_PERIOD_MS, ); } @@ -1492,7 +1490,6 @@ export class SyncApi { }; this.client.http.request( - undefined, // callback Method.Get, "/_matrix/client/versions", undefined, // queryParams undefined, // data