Wrap MatrixClient into something that displays nicer error messages

This commit is contained in:
David Teller 2021-12-21 15:10:25 +01:00 committed by David Teller
parent 1592440bc9
commit 57746f7fb4
3 changed files with 60 additions and 3 deletions

View File

@ -42,6 +42,7 @@ import { EventRedactionQueue, RedactUserInRoom } from "./queues/EventRedactionQu
import * as htmlEscape from "escape-html";
import { ReportManager } from "./report/ReportManager";
import { WebAPIs } from "./webapis/WebAPIs";
import { makeClientWithSanerExceptions } from "./utils";
export const STATE_NOT_STARTED = "not_started";
export const STATE_CHECKING_PERMISSIONS = "checking_permissions";
@ -54,7 +55,7 @@ const PROTECTED_ROOMS_EVENT_TYPE = "org.matrix.mjolnir.protected_rooms";
const WARN_UNPROTECTED_ROOM_EVENT_PREFIX = "org.matrix.mjolnir.unprotected_room_warning.for.";
export class Mjolnir {
public readonly client: MatrixClient;
private displayName: string;
private localpart: string;
private currentState: string = STATE_NOT_STARTED;
@ -153,11 +154,12 @@ export class Mjolnir {
}
constructor(
public readonly client: MatrixClient,
client: MatrixClient,
public readonly protectedRooms: { [roomId: string]: string },
private banLists: BanList[],
) {
this.explicitlyProtectedRoomIds = Object.keys(this.protectedRooms);
this.client = makeClientWithSanerExceptions(client);
for (const reason of config.automaticallyRedactForReasons) {
this.automaticRedactionReasons.push(new MatrixGlob(reason.toLowerCase()));

View File

@ -28,6 +28,7 @@ import {
import { logMessage } from "./LogProxy";
import config from "./config";
import * as htmlEscape from "escape-html";
import { ClientRequest, IncomingMessage } from "http";
export function setToArray<T>(set: Set<T>): T[] {
const arr: T[] = [];
@ -201,3 +202,56 @@ export async function replaceRoomIdsWithPills(client: MatrixClient, text: string
return content;
}
export function makeClientWithSanerExceptions(client: MatrixClient): MatrixClient {
let result = new Proxy(client, {
get: function (obj, key) {
let value = obj[key];
if (!(typeof value == "function")) {
return value;
}
return function (...args) {
let result = value.apply(client, args);
if (!(result instanceof Promise)) {
// We're only interested in watching async code.
return result;
}
return result.catch(reason => {
if (!(reason instanceof IncomingMessage)) {
// In most cases, we're happy with the result.
throw reason;
}
// However, MatrixClient has a tendency of throwing
// instances of `IncomingMessage` instead of instances
// of `Error`. The former take ~800 lines of log and
// provide no stack trace, which makes them typically
// useless.
let method: string | null = null;
let path: string = '';
let body: string | null = null;
if (reason.method) {
method = reason.method;
}
if (reason.url) {
path = reason.url;
}
if ("req" in reason && (reason as any).req instanceof ClientRequest) {
if (!method) {
method = (reason as any).req.method;
}
if (!path) {
path = (reason as any).req.path;
}
}
if ("body" in reason) {
body = JSON.stringify((reason as any).body);
}
let error = new Error(`Error during MatrixClient request ${method} ${path}: ${reason.statusCode} ${reason.statusMessage} -- ${body}`);
//(error as any).message = reason;
throw error;
});
}
}
});
return result;
}

View File

@ -2,6 +2,7 @@ import axios from "axios";
import { HmacSHA1 } from "crypto-js";
import { LogService, MatrixClient, MemoryStorageProvider, PantalaimonClient } from "matrix-bot-sdk";
import config from "../../src/config";
import { makeClientWithSanerExceptions } from "../../src/utils";
/**
* Register a user using the synapse admin api that requires the use of a registration secret rather than an admin user.
@ -67,7 +68,7 @@ export async function registerNewTestUser(isAdmin: boolean, label: string = "")
export async function newTestUser(isAdmin: boolean = false, label: string = ""): Promise<MatrixClient> {
const username = await registerNewTestUser(isAdmin, label);
const pantalaimon = new PantalaimonClient(config.homeserverUrl, new MemoryStorageProvider());
return await pantalaimon.createClientWithCredentials(username, username);
return makeClientWithSanerExceptions(await pantalaimon.createClientWithCredentials(username, username));
}
/**