mirror of
https://github.com/matrix-org/mjolnir.git
synced 2024-10-01 01:36:06 -04:00
Update log handling for debugging
This commit is contained in:
parent
05aedcafb7
commit
84135c5ff5
36
src/LogProxy.ts
Normal file
36
src/LogProxy.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2019 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { LogLevel, LogService } from "matrix-bot-sdk";
|
||||||
|
import config from "./config";
|
||||||
|
|
||||||
|
const levelToFn = {
|
||||||
|
[LogLevel.DEBUG.toString()]: LogService.debug,
|
||||||
|
[LogLevel.INFO.toString()]: LogService.info,
|
||||||
|
[LogLevel.WARN.toString()]: LogService.warn,
|
||||||
|
[LogLevel.ERROR.toString()]: LogService.error,
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function logMessage(level: LogLevel, module: string, message: string | any) {
|
||||||
|
if (config.RUNTIME.client && (config.verboseLogging || LogLevel.INFO.includes(level))) {
|
||||||
|
let clientMessage = message;
|
||||||
|
if (level === LogLevel.WARN) clientMessage = `⚠ | ${message}`;
|
||||||
|
if (level === LogLevel.ERROR) clientMessage = `‼ | ${message}`;
|
||||||
|
await config.RUNTIME.client.sendNotice(config.managementRoom, clientMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
levelToFn[level.toString()](module, message);
|
||||||
|
}
|
@ -14,13 +14,14 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { LogService, MatrixClient, Permalinks } from "matrix-bot-sdk";
|
import { LogLevel, LogService, MatrixClient, Permalinks } from "matrix-bot-sdk";
|
||||||
import BanList, { ALL_RULE_TYPES } from "./models/BanList";
|
import BanList, { ALL_RULE_TYPES } from "./models/BanList";
|
||||||
import { applyServerAcls } from "./actions/ApplyAcl";
|
import { applyServerAcls } from "./actions/ApplyAcl";
|
||||||
import { RoomUpdateError } from "./models/RoomUpdateError";
|
import { RoomUpdateError } from "./models/RoomUpdateError";
|
||||||
import { COMMAND_PREFIX, handleCommand } from "./commands/CommandHandler";
|
import { COMMAND_PREFIX, handleCommand } from "./commands/CommandHandler";
|
||||||
import { applyUserBans } from "./actions/ApplyBan";
|
import { applyUserBans } from "./actions/ApplyBan";
|
||||||
import config from "./config";
|
import config from "./config";
|
||||||
|
import { logMessage } from "./LogProxy";
|
||||||
|
|
||||||
export const STATE_NOT_STARTED = "not_started";
|
export const STATE_NOT_STARTED = "not_started";
|
||||||
export const STATE_CHECKING_PERMISSIONS = "checking_permissions";
|
export const STATE_CHECKING_PERMISSIONS = "checking_permissions";
|
||||||
@ -37,14 +38,13 @@ export class Mjolnir {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public readonly client: MatrixClient,
|
public readonly client: MatrixClient,
|
||||||
public readonly managementRoomId: string,
|
|
||||||
public readonly protectedRooms: { [roomId: string]: string },
|
public readonly protectedRooms: { [roomId: string]: string },
|
||||||
private banLists: BanList[],
|
private banLists: BanList[],
|
||||||
) {
|
) {
|
||||||
client.on("room.event", this.handleEvent.bind(this));
|
client.on("room.event", this.handleEvent.bind(this));
|
||||||
|
|
||||||
client.on("room.message", async (roomId, event) => {
|
client.on("room.message", async (roomId, event) => {
|
||||||
if (roomId !== managementRoomId) return;
|
if (roomId !== config.managementRoom) return;
|
||||||
if (!event['content']) return;
|
if (!event['content']) return;
|
||||||
|
|
||||||
const content = event['content'];
|
const content = event['content'];
|
||||||
@ -55,6 +55,7 @@ export class Mjolnir {
|
|||||||
|
|
||||||
// rewrite the event body to make the prefix uniform (in case the bot has spaces in its display name)
|
// rewrite the event body to make the prefix uniform (in case the bot has spaces in its display name)
|
||||||
event['content']['body'] = COMMAND_PREFIX + content['body'].substring(prefixUsed.length);
|
event['content']['body'] = COMMAND_PREFIX + content['body'].substring(prefixUsed.length);
|
||||||
|
LogService.info("Mjolnir", `Command being run by ${event['sender']}: ${event['content']['body']}`);
|
||||||
|
|
||||||
await client.sendReadReceipt(roomId, event['event_id']);
|
await client.sendReadReceipt(roomId, event['event_id']);
|
||||||
return handleCommand(roomId, event, this);
|
return handleCommand(roomId, event, this);
|
||||||
@ -83,25 +84,19 @@ export class Mjolnir {
|
|||||||
return this.client.start().then(async () => {
|
return this.client.start().then(async () => {
|
||||||
this.currentState = STATE_CHECKING_PERMISSIONS;
|
this.currentState = STATE_CHECKING_PERMISSIONS;
|
||||||
if (config.verifyPermissionsOnStartup) {
|
if (config.verifyPermissionsOnStartup) {
|
||||||
if (config.verboseLogging) {
|
await logMessage(LogLevel.INFO, "Mjolnir@startup", "Checking permissions...");
|
||||||
await this.client.sendNotice(this.managementRoomId, "Checking permissions...");
|
|
||||||
}
|
|
||||||
await this.verifyPermissions(config.verboseLogging);
|
await this.verifyPermissions(config.verboseLogging);
|
||||||
}
|
}
|
||||||
}).then(async () => {
|
}).then(async () => {
|
||||||
this.currentState = STATE_SYNCING;
|
this.currentState = STATE_SYNCING;
|
||||||
if (config.syncOnStartup) {
|
if (config.syncOnStartup) {
|
||||||
if (config.verboseLogging) {
|
await logMessage(LogLevel.INFO, "Mjolnir@startup", "Syncing lists...");
|
||||||
await this.client.sendNotice(this.managementRoomId, "Syncing lists...");
|
|
||||||
}
|
|
||||||
await this.buildWatchedBanLists();
|
await this.buildWatchedBanLists();
|
||||||
await this.syncLists(config.verboseLogging);
|
await this.syncLists(config.verboseLogging);
|
||||||
}
|
}
|
||||||
}).then(async () => {
|
}).then(async () => {
|
||||||
this.currentState = STATE_RUNNING;
|
this.currentState = STATE_RUNNING;
|
||||||
if (config.verboseLogging) {
|
await logMessage(LogLevel.INFO, "Mjolnir@startup", "Startup complete. Now monitoring rooms.");
|
||||||
await this.client.sendNotice(this.managementRoomId, "Startup complete.");
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,7 +176,7 @@ export class Mjolnir {
|
|||||||
if (!hadErrors && verbose) {
|
if (!hadErrors && verbose) {
|
||||||
const html = `<font color="#00cc00">All permissions look OK.</font>`;
|
const html = `<font color="#00cc00">All permissions look OK.</font>`;
|
||||||
const text = "All permissions look OK.";
|
const text = "All permissions look OK.";
|
||||||
await this.client.sendMessage(this.managementRoomId, {
|
await this.client.sendMessage(config.managementRoom, {
|
||||||
msgtype: "m.notice",
|
msgtype: "m.notice",
|
||||||
body: text,
|
body: text,
|
||||||
format: "org.matrix.custom.html",
|
format: "org.matrix.custom.html",
|
||||||
@ -257,7 +252,7 @@ export class Mjolnir {
|
|||||||
if (!hadErrors && verbose) {
|
if (!hadErrors && verbose) {
|
||||||
const html = `<font color="#00cc00">Done updating rooms - no errors</font>`;
|
const html = `<font color="#00cc00">Done updating rooms - no errors</font>`;
|
||||||
const text = "Done updating rooms - no errors";
|
const text = "Done updating rooms - no errors";
|
||||||
await this.client.sendMessage(this.managementRoomId, {
|
await this.client.sendMessage(config.managementRoom, {
|
||||||
msgtype: "m.notice",
|
msgtype: "m.notice",
|
||||||
body: text,
|
body: text,
|
||||||
format: "org.matrix.custom.html",
|
format: "org.matrix.custom.html",
|
||||||
@ -285,7 +280,7 @@ export class Mjolnir {
|
|||||||
if (!hadErrors) {
|
if (!hadErrors) {
|
||||||
const html = `<font color="#00cc00"><b>Done updating rooms - no errors</b></font>`;
|
const html = `<font color="#00cc00"><b>Done updating rooms - no errors</b></font>`;
|
||||||
const text = "Done updating rooms - no errors";
|
const text = "Done updating rooms - no errors";
|
||||||
await this.client.sendMessage(this.managementRoomId, {
|
await this.client.sendMessage(config.managementRoom, {
|
||||||
msgtype: "m.notice",
|
msgtype: "m.notice",
|
||||||
body: text,
|
body: text,
|
||||||
format: "org.matrix.custom.html",
|
format: "org.matrix.custom.html",
|
||||||
@ -302,7 +297,7 @@ export class Mjolnir {
|
|||||||
const url = this.protectedRooms[roomId];
|
const url = this.protectedRooms[roomId];
|
||||||
let html = `Power levels changed in <a href="${url}">${roomId}</a> - checking permissions...`;
|
let html = `Power levels changed in <a href="${url}">${roomId}</a> - checking permissions...`;
|
||||||
let text = `Power levels changed in ${url} - checking permissions...`;
|
let text = `Power levels changed in ${url} - checking permissions...`;
|
||||||
await this.client.sendMessage(this.managementRoomId, {
|
await this.client.sendMessage(config.managementRoom, {
|
||||||
msgtype: "m.notice",
|
msgtype: "m.notice",
|
||||||
body: text,
|
body: text,
|
||||||
format: "org.matrix.custom.html",
|
format: "org.matrix.custom.html",
|
||||||
@ -313,7 +308,7 @@ export class Mjolnir {
|
|||||||
if (!hadErrors) {
|
if (!hadErrors) {
|
||||||
html = `<font color="#00cc00">All permissions look OK.</font>`;
|
html = `<font color="#00cc00">All permissions look OK.</font>`;
|
||||||
text = "All permissions look OK.";
|
text = "All permissions look OK.";
|
||||||
await this.client.sendMessage(this.managementRoomId, {
|
await this.client.sendMessage(config.managementRoom, {
|
||||||
msgtype: "m.notice",
|
msgtype: "m.notice",
|
||||||
body: text,
|
body: text,
|
||||||
format: "org.matrix.custom.html",
|
format: "org.matrix.custom.html",
|
||||||
@ -358,7 +353,7 @@ export class Mjolnir {
|
|||||||
format: "org.matrix.custom.html",
|
format: "org.matrix.custom.html",
|
||||||
formatted_body: html,
|
formatted_body: html,
|
||||||
};
|
};
|
||||||
await this.client.sendMessage(this.managementRoomId, message);
|
await this.client.sendMessage(config.managementRoom, message);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,8 @@ import { ServerAcl } from "../models/ServerAcl";
|
|||||||
import { RoomUpdateError } from "../models/RoomUpdateError";
|
import { RoomUpdateError } from "../models/RoomUpdateError";
|
||||||
import { Mjolnir } from "../Mjolnir";
|
import { Mjolnir } from "../Mjolnir";
|
||||||
import config from "../config";
|
import config from "../config";
|
||||||
|
import { LogLevel } from "matrix-bot-sdk";
|
||||||
|
import { logMessage } from "../LogProxy";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies the server ACLs represented by the ban lists to the provided rooms, returning the
|
* Applies the server ACLs represented by the ban lists to the provided rooms, returning the
|
||||||
@ -40,35 +42,31 @@ export async function applyServerAcls(lists: BanList[], roomIds: string[], mjoln
|
|||||||
|
|
||||||
if (config.verboseLogging) {
|
if (config.verboseLogging) {
|
||||||
// We specifically use sendNotice to avoid having to escape HTML
|
// We specifically use sendNotice to avoid having to escape HTML
|
||||||
await mjolnir.client.sendNotice(mjolnir.managementRoomId, `Constructed server ACL:\n${JSON.stringify(finalAcl, null, 2)}`);
|
await mjolnir.client.sendNotice(config.managementRoom, `Constructed server ACL:\n${JSON.stringify(finalAcl, null, 2)}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const errors: RoomUpdateError[] = [];
|
const errors: RoomUpdateError[] = [];
|
||||||
for (const roomId of roomIds) {
|
for (const roomId of roomIds) {
|
||||||
try {
|
try {
|
||||||
if (config.verboseLogging) {
|
await logMessage(LogLevel.DEBUG, "ApplyAcl", `Checking ACLs for ${roomId}`);
|
||||||
await mjolnir.client.sendNotice(mjolnir.managementRoomId, `Checking ACLs for ${roomId}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const currentAcl = await mjolnir.client.getRoomStateEvent(roomId, "m.room.server_acl", "");
|
const currentAcl = await mjolnir.client.getRoomStateEvent(roomId, "m.room.server_acl", "");
|
||||||
if (acl.matches(currentAcl)) {
|
if (acl.matches(currentAcl)) {
|
||||||
if (config.verboseLogging) {
|
await logMessage(LogLevel.DEBUG, "ApplyAcl", `Skipping ACLs for ${roomId} because they are already the right ones`);
|
||||||
await mjolnir.client.sendNotice(mjolnir.managementRoomId, `Skipping ACLs for ${roomId} because they are already the right ones`);
|
|
||||||
}
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// ignore - assume no ACL
|
// ignore - assume no ACL
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.verboseLogging) {
|
// We specifically use sendNotice to avoid having to escape HTML
|
||||||
// We specifically use sendNotice to avoid having to escape HTML
|
await logMessage(LogLevel.DEBUG, "ApplyAcl", `Applying ACL in ${roomId}`);
|
||||||
await mjolnir.client.sendNotice(mjolnir.managementRoomId, `Applying ACL in ${roomId}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!config.noop) {
|
if (!config.noop) {
|
||||||
await mjolnir.client.sendStateEvent(roomId, "m.room.server_acl", "", finalAcl);
|
await mjolnir.client.sendStateEvent(roomId, "m.room.server_acl", "", finalAcl);
|
||||||
|
} else {
|
||||||
|
await logMessage(LogLevel.WARN, "ApplyAcl", `Tried to apply ACL in ${roomId} but Mjolnir is running in no-op mode`);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
errors.push({roomId, errorMessage: e.message || (e.body ? e.body.error : '<no message>')});
|
errors.push({roomId, errorMessage: e.message || (e.body ? e.body.error : '<no message>')});
|
||||||
|
@ -18,6 +18,8 @@ import BanList from "../models/BanList";
|
|||||||
import { RoomUpdateError } from "../models/RoomUpdateError";
|
import { RoomUpdateError } from "../models/RoomUpdateError";
|
||||||
import { Mjolnir } from "../Mjolnir";
|
import { Mjolnir } from "../Mjolnir";
|
||||||
import config from "../config";
|
import config from "../config";
|
||||||
|
import { logMessage } from "../LogProxy";
|
||||||
|
import { LogLevel } from "matrix-bot-sdk";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies the member bans represented by the ban lists to the provided rooms, returning the
|
* Applies the member bans represented by the ban lists to the provided rooms, returning the
|
||||||
@ -32,10 +34,8 @@ export async function applyUserBans(lists: BanList[], roomIds: string[], mjolnir
|
|||||||
let bansApplied = 0;
|
let bansApplied = 0;
|
||||||
for (const roomId of roomIds) {
|
for (const roomId of roomIds) {
|
||||||
try {
|
try {
|
||||||
if (config.verboseLogging) {
|
// We specifically use sendNotice to avoid having to escape HTML
|
||||||
// We specifically use sendNotice to avoid having to escape HTML
|
await logMessage(LogLevel.DEBUG, "ApplyBan", `Updating member bans in ${roomId}`);
|
||||||
await mjolnir.client.sendNotice(mjolnir.managementRoomId, `Updating member bans in ${roomId}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const state = await mjolnir.client.getRoomState(roomId);
|
const state = await mjolnir.client.getRoomState(roomId);
|
||||||
const members = state.filter(s => s['type'] === 'm.room.member' && !!s['state_key']);
|
const members = state.filter(s => s['type'] === 'm.room.member' && !!s['state_key']);
|
||||||
@ -54,13 +54,13 @@ export async function applyUserBans(lists: BanList[], roomIds: string[], mjolnir
|
|||||||
if (userRule.isMatch(member['state_key'])) {
|
if (userRule.isMatch(member['state_key'])) {
|
||||||
// User needs to be banned
|
// User needs to be banned
|
||||||
|
|
||||||
if (config.verboseLogging) {
|
// We specifically use sendNotice to avoid having to escape HTML
|
||||||
// We specifically use sendNotice to avoid having to escape HTML
|
await logMessage(LogLevel.DEBUG, "ApplyBan", `Banning ${member['state_key']} in ${roomId} for: ${userRule.reason}`);
|
||||||
await mjolnir.client.sendNotice(mjolnir.managementRoomId, `Banning ${member['state_key']} in ${roomId} for: ${userRule.reason}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!config.noop) {
|
if (!config.noop) {
|
||||||
await mjolnir.client.banUser(member['state_key'], roomId, userRule.reason);
|
await mjolnir.client.banUser(member['state_key'], roomId, userRule.reason);
|
||||||
|
} else {
|
||||||
|
await logMessage(LogLevel.WARN, "ApplyBan", `Tried to ban ${member['state_key']} in ${roomId} but Mjolnir is running in no-op mode`);
|
||||||
}
|
}
|
||||||
|
|
||||||
bansApplied++;
|
bansApplied++;
|
||||||
@ -79,7 +79,7 @@ export async function applyUserBans(lists: BanList[], roomIds: string[], mjolnir
|
|||||||
if (bansApplied > 0) {
|
if (bansApplied > 0) {
|
||||||
const html = `<font color="#00cc00"><b>Banned ${bansApplied} people</b></font>`;
|
const html = `<font color="#00cc00"><b>Banned ${bansApplied} people</b></font>`;
|
||||||
const text = `Banned ${bansApplied} people`;
|
const text = `Banned ${bansApplied} people`;
|
||||||
await this.client.sendMessage(mjolnir.managementRoomId, {
|
await this.client.sendMessage(config.managementRoom, {
|
||||||
msgtype: "m.notice",
|
msgtype: "m.notice",
|
||||||
body: text,
|
body: text,
|
||||||
format: "org.matrix.custom.html",
|
format: "org.matrix.custom.html",
|
||||||
|
@ -83,6 +83,6 @@ export async function handleCommand(roomId: string, event: any, mjolnir: Mjolnir
|
|||||||
const text = "There was an error processing your command - see console/log for details";
|
const text = "There was an error processing your command - see console/log for details";
|
||||||
const reply = RichReply.createFor(roomId, event, text, text);
|
const reply = RichReply.createFor(roomId, event, text, text);
|
||||||
reply["msgtype"] = "m.notice";
|
reply["msgtype"] = "m.notice";
|
||||||
return mjolnir.client.sendMessage(roomId, reply);
|
return await mjolnir.client.sendMessage(roomId, reply);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ import { Mjolnir } from "../Mjolnir";
|
|||||||
import { RichReply } from "matrix-bot-sdk";
|
import { RichReply } from "matrix-bot-sdk";
|
||||||
import { RECOMMENDATION_BAN, recommendationToStable } from "../models/ListRule";
|
import { RECOMMENDATION_BAN, recommendationToStable } from "../models/ListRule";
|
||||||
import { RULE_SERVER, RULE_USER, ruleTypeToStable } from "../models/BanList";
|
import { RULE_SERVER, RULE_USER, ruleTypeToStable } from "../models/BanList";
|
||||||
|
import config from "../config";
|
||||||
|
|
||||||
// !mjolnir import <room ID> <shortcode>
|
// !mjolnir import <room ID> <shortcode>
|
||||||
export async function execImportCommand(roomId: string, event: any, mjolnir: Mjolnir, parts: string[]) {
|
export async function execImportCommand(roomId: string, event: any, mjolnir: Mjolnir, parts: string[]) {
|
||||||
@ -42,7 +43,7 @@ export async function execImportCommand(roomId: string, event: any, mjolnir: Mjo
|
|||||||
if (content['membership'] === 'ban') {
|
if (content['membership'] === 'ban') {
|
||||||
const reason = content['reason'] || '<no reason>';
|
const reason = content['reason'] || '<no reason>';
|
||||||
|
|
||||||
await mjolnir.client.sendNotice(mjolnir.managementRoomId, `Adding user ${stateEvent['state_key']} to ban list`);
|
await mjolnir.client.sendNotice(config.managementRoom, `Adding user ${stateEvent['state_key']} to ban list`);
|
||||||
|
|
||||||
const recommendation = recommendationToStable(RECOMMENDATION_BAN);
|
const recommendation = recommendationToStable(RECOMMENDATION_BAN);
|
||||||
const ruleContent = {
|
const ruleContent = {
|
||||||
@ -60,7 +61,7 @@ export async function execImportCommand(roomId: string, event: any, mjolnir: Mjo
|
|||||||
for (const server of content['deny']) {
|
for (const server of content['deny']) {
|
||||||
const reason = "<no reason>";
|
const reason = "<no reason>";
|
||||||
|
|
||||||
await mjolnir.client.sendNotice(mjolnir.managementRoomId, `Adding server ${server} to ban list`);
|
await mjolnir.client.sendNotice(config.managementRoom, `Adding server ${server} to ban list`);
|
||||||
|
|
||||||
const recommendation = recommendationToStable(RECOMMENDATION_BAN);
|
const recommendation = recommendationToStable(RECOMMENDATION_BAN);
|
||||||
const ruleContent = {
|
const ruleContent = {
|
||||||
|
@ -17,6 +17,8 @@ limitations under the License.
|
|||||||
import { Mjolnir } from "../Mjolnir";
|
import { Mjolnir } from "../Mjolnir";
|
||||||
import { getMessagesByUserSinceLastJoin } from "../utils";
|
import { getMessagesByUserSinceLastJoin } from "../utils";
|
||||||
import config from "../config";
|
import config from "../config";
|
||||||
|
import { logMessage } from "../LogProxy";
|
||||||
|
import { LogLevel } from "matrix-bot-sdk";
|
||||||
|
|
||||||
// !mjolnir redact <user ID> [room alias]
|
// !mjolnir redact <user ID> [room alias]
|
||||||
export async function execRedactCommand(roomId: string, event: any, mjolnir: Mjolnir, parts: string[]) {
|
export async function execRedactCommand(roomId: string, event: any, mjolnir: Mjolnir, parts: string[]) {
|
||||||
@ -28,17 +30,15 @@ export async function execRedactCommand(roomId: string, event: any, mjolnir: Mjo
|
|||||||
|
|
||||||
const targetRoomIds = roomAlias ? [roomAlias] : Object.keys(mjolnir.protectedRooms);
|
const targetRoomIds = roomAlias ? [roomAlias] : Object.keys(mjolnir.protectedRooms);
|
||||||
for (const targetRoomId of targetRoomIds) {
|
for (const targetRoomId of targetRoomIds) {
|
||||||
if (config.verboseLogging) {
|
await logMessage(LogLevel.DEBUG, "RedactCommand", `Fetching sent messages for ${userId} in ${targetRoomId} to redact...`);
|
||||||
await mjolnir.client.sendNotice(mjolnir.managementRoomId, `Fetching sent messages for ${userId} in ${targetRoomId} to redact...`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const eventsToRedact = await getMessagesByUserSinceLastJoin(mjolnir.client, userId, targetRoomId);
|
const eventsToRedact = await getMessagesByUserSinceLastJoin(mjolnir.client, userId, targetRoomId);
|
||||||
for (const victimEvent of eventsToRedact) {
|
for (const victimEvent of eventsToRedact) {
|
||||||
if (config.verboseLogging) {
|
await logMessage(LogLevel.DEBUG, "RedactCommand", `Redacting ${victimEvent['event_id']} in ${targetRoomId}`);
|
||||||
await mjolnir.client.sendNotice(mjolnir.managementRoomId, `Redacting ${victimEvent['event_id']} in ${targetRoomId}`);
|
|
||||||
}
|
|
||||||
if (!config.noop) {
|
if (!config.noop) {
|
||||||
await mjolnir.client.redactEvent(targetRoomId, victimEvent['event_id']);
|
await mjolnir.client.redactEvent(targetRoomId, victimEvent['event_id']);
|
||||||
|
} else {
|
||||||
|
await logMessage(LogLevel.WARN, "RedactCommand", `Tried to redact ${victimEvent['event_id']} in ${targetRoomId} but Mjolnir is running in no-op mode`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,10 +16,11 @@ limitations under the License.
|
|||||||
|
|
||||||
import { Mjolnir } from "../Mjolnir";
|
import { Mjolnir } from "../Mjolnir";
|
||||||
import { RULE_ROOM, RULE_SERVER, RULE_USER, ruleTypeToStable, USER_RULE_TYPES } from "../models/BanList";
|
import { RULE_ROOM, RULE_SERVER, RULE_USER, ruleTypeToStable, USER_RULE_TYPES } from "../models/BanList";
|
||||||
import { RichReply } from "matrix-bot-sdk";
|
import { LogLevel, RichReply } from "matrix-bot-sdk";
|
||||||
import { RECOMMENDATION_BAN, recommendationToStable } from "../models/ListRule";
|
import { RECOMMENDATION_BAN, recommendationToStable } from "../models/ListRule";
|
||||||
import { MatrixGlob } from "matrix-bot-sdk/lib/MatrixGlob";
|
import { MatrixGlob } from "matrix-bot-sdk/lib/MatrixGlob";
|
||||||
import config from "../config";
|
import config from "../config";
|
||||||
|
import { logMessage } from "../LogProxy";
|
||||||
|
|
||||||
function parseBits(parts: string[]): { listShortcode: string, entityType: string, ruleType: string, glob: string, reason: string } {
|
function parseBits(parts: string[]): { listShortcode: string, entityType: string, ruleType: string, glob: string, reason: string } {
|
||||||
const shortcode = parts[2].toLowerCase();
|
const shortcode = parts[2].toLowerCase();
|
||||||
@ -98,7 +99,7 @@ export async function execUnbanCommand(roomId: string, event: any, mjolnir: Mjol
|
|||||||
|
|
||||||
if (USER_RULE_TYPES.includes(bits.ruleType) && parts.length > 5 && parts[5] === 'true') {
|
if (USER_RULE_TYPES.includes(bits.ruleType) && parts.length > 5 && parts[5] === 'true') {
|
||||||
const rule = new MatrixGlob(bits.glob);
|
const rule = new MatrixGlob(bits.glob);
|
||||||
await mjolnir.client.sendNotice(mjolnir.managementRoomId, "Unbanning users that match glob: " + bits.glob);
|
await logMessage(LogLevel.INFO, "UnbanBanCommand", "Unbanning users that match glob: " + bits.glob);
|
||||||
let unbannedSomeone = false;
|
let unbannedSomeone = false;
|
||||||
for (const protectedRoomId of Object.keys(mjolnir.protectedRooms)) {
|
for (const protectedRoomId of Object.keys(mjolnir.protectedRooms)) {
|
||||||
const members = await mjolnir.client.getMembers(protectedRoomId, null, ['ban'], null);
|
const members = await mjolnir.client.getMembers(protectedRoomId, null, ['ban'], null);
|
||||||
@ -106,21 +107,21 @@ export async function execUnbanCommand(roomId: string, event: any, mjolnir: Mjol
|
|||||||
const victim = member['state_key'];
|
const victim = member['state_key'];
|
||||||
if (!member['content'] || member['content']['membership'] !== 'ban') continue;
|
if (!member['content'] || member['content']['membership'] !== 'ban') continue;
|
||||||
if (rule.test(victim)) {
|
if (rule.test(victim)) {
|
||||||
if (config.verboseLogging) {
|
await logMessage(LogLevel.DEBUG, "UnbanBanCommand", `Unbanning ${victim} in ${protectedRoomId}`);
|
||||||
await mjolnir.client.sendNotice(mjolnir.managementRoomId, `Unbanning ${victim} in ${protectedRoomId}`);
|
|
||||||
}
|
|
||||||
if (!config.noop) {
|
if (!config.noop) {
|
||||||
await mjolnir.client.unbanUser(victim, protectedRoomId);
|
await mjolnir.client.unbanUser(victim, protectedRoomId);
|
||||||
|
} else {
|
||||||
|
await logMessage(LogLevel.WARN, "UnbanBanCommand", `Attempted to unban ${victim} in ${protectedRoomId} but Mjolnir is running in no-op mode`);
|
||||||
}
|
}
|
||||||
|
|
||||||
unbannedSomeone = true;
|
unbannedSomeone = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unbannedSomeone) {
|
if (unbannedSomeone) {
|
||||||
if (config.verboseLogging) {
|
await logMessage(LogLevel.DEBUG, "UnbanBanCommand", `Syncing lists to ensure no users were accidentally unbanned`);
|
||||||
await mjolnir.client.sendNotice(mjolnir.managementRoomId, `Syncing lists to ensure no users were accidentally unbanned`);
|
|
||||||
}
|
|
||||||
await mjolnir.syncLists(config.verboseLogging);
|
await mjolnir.syncLists(config.verboseLogging);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ limitations under the License.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import * as config from "config";
|
import * as config from "config";
|
||||||
|
import { MatrixClient } from "matrix-bot-sdk";
|
||||||
|
|
||||||
interface IConfig {
|
interface IConfig {
|
||||||
homeserverUrl: string;
|
homeserverUrl: string;
|
||||||
@ -33,6 +34,14 @@ interface IConfig {
|
|||||||
verifyPermissionsOnStartup: boolean;
|
verifyPermissionsOnStartup: boolean;
|
||||||
noop: boolean;
|
noop: boolean;
|
||||||
protectedRooms: string[]; // matrix.to urls
|
protectedRooms: string[]; // matrix.to urls
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Config options only set at runtime. Try to avoid using the objects
|
||||||
|
* here as much as possible.
|
||||||
|
*/
|
||||||
|
RUNTIME: {
|
||||||
|
client: MatrixClient;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default <IConfig>config;
|
export default <IConfig>config;
|
||||||
|
11
src/index.ts
11
src/index.ts
@ -28,6 +28,9 @@ import {
|
|||||||
import config from "./config";
|
import config from "./config";
|
||||||
import BanList from "./models/BanList";
|
import BanList from "./models/BanList";
|
||||||
import { Mjolnir } from "./Mjolnir";
|
import { Mjolnir } from "./Mjolnir";
|
||||||
|
import { logMessage } from "./LogProxy";
|
||||||
|
|
||||||
|
config.RUNTIME = {client: null};
|
||||||
|
|
||||||
LogService.setLogger(new RichConsoleLogger());
|
LogService.setLogger(new RichConsoleLogger());
|
||||||
LogService.setLevel(LogLevel.fromString(config.logLevel, LogLevel.DEBUG));
|
LogService.setLevel(LogLevel.fromString(config.logLevel, LogLevel.DEBUG));
|
||||||
@ -45,6 +48,8 @@ LogService.info("index", "Starting bot...");
|
|||||||
client = new MatrixClient(config.homeserverUrl, config.accessToken, storage);
|
client = new MatrixClient(config.homeserverUrl, config.accessToken, storage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
config.RUNTIME.client = client;
|
||||||
|
|
||||||
if (config.autojoin) {
|
if (config.autojoin) {
|
||||||
AutojoinRoomsMixin.setupOnClient(client);
|
AutojoinRoomsMixin.setupOnClient(client);
|
||||||
}
|
}
|
||||||
@ -68,9 +73,9 @@ LogService.info("index", "Starting bot...");
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ensure we're also in the management room
|
// Ensure we're also in the management room
|
||||||
const managementRoomId = await client.joinRoom(config.managementRoom);
|
config.managementRoom = await client.joinRoom(config.managementRoom);
|
||||||
await client.sendNotice(managementRoomId, "Mjolnir is starting up. Use !mjolnir to query status.");
|
await logMessage(LogLevel.INFO, "index", "Mjolnir is starting up. Use !mjolnir to query status.");
|
||||||
|
|
||||||
const bot = new Mjolnir(client, managementRoomId, protectedRooms, banLists);
|
const bot = new Mjolnir(client, protectedRooms, banLists);
|
||||||
await bot.start();
|
await bot.start();
|
||||||
})();
|
})();
|
||||||
|
Loading…
Reference in New Issue
Block a user