mirror of
https://github.com/matrix-org/mjolnir.git
synced 2024-09-28 20:26:02 +00:00
Improve redaction handling
This commit is contained in:
parent
954a0e1561
commit
6f80a17558
@ -104,7 +104,7 @@ export async function handleCommand(roomId: string, event: any, mjolnir: Mjolnir
|
||||
"!mjolnir status - Print status information\n" +
|
||||
"!mjolnir ban <list shortcode> <user|room|server> <glob> [reason] - Adds an entity to the ban list\n" +
|
||||
"!mjolnir unban <list shortcode> <user|room|server> <glob> [apply] - Removes an entity from the ban list. If apply is 'true', the users matching the glob will actually be unbanned\n" +
|
||||
"!mjolnir redact <user ID> [room alias/ID] - Redacts messages by the sender in the target room (or all rooms)\n" +
|
||||
"!mjolnir redact <user ID> [room alias/ID] [limit] - Redacts messages by the sender in the target room (or all rooms), up to a maximum number of events in the backlog (default 1000)\n" +
|
||||
"!mjolnir redact <event permalink> - Redacts a message by permalink\n" +
|
||||
"!mjolnir rules - Lists the rules currently in use by Mjolnir\n" +
|
||||
"!mjolnir sync - Force updates of all lists and re-apply rules\n" +
|
||||
|
@ -18,25 +18,36 @@ import { Mjolnir } from "../Mjolnir";
|
||||
import { redactUserMessagesIn } from "../utils";
|
||||
import { Permalinks } from "matrix-bot-sdk";
|
||||
|
||||
// !mjolnir redact <user ID> [room alias]
|
||||
// !mjolnir redact <user ID> [room alias] [limit]
|
||||
export async function execRedactCommand(roomId: string, event: any, mjolnir: Mjolnir, parts: string[]) {
|
||||
const userId = parts[2];
|
||||
let roomAlias = null;
|
||||
if (parts.length > 3) {
|
||||
let limit = Number.parseInt(parts.length > 3 ? parts[3] : null); // default to NaN for later
|
||||
if (parts.length > 3 && isNaN(limit)) {
|
||||
roomAlias = await mjolnir.client.resolveRoom(parts[3]);
|
||||
if (parts.length > 4) {
|
||||
limit = Number.parseInt(parts[4]);
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure we always have a limit set
|
||||
if (isNaN(limit)) limit = 1000;
|
||||
|
||||
const processingReactionId = await mjolnir.client.unstableApis.addReactionToEvent(roomId, event['event_id'], 'In Progress');
|
||||
|
||||
if (userId[0] !== '@') {
|
||||
// Assume it's a permalink
|
||||
const parsed = Permalinks.parseUrl(parts[2]);
|
||||
const targetRoomId = await mjolnir.client.resolveRoom(parsed.roomIdOrAlias);
|
||||
await mjolnir.client.redactEvent(targetRoomId, parsed.eventId);
|
||||
await mjolnir.client.unstableApis.addReactionToEvent(roomId, event['event_id'], '✅');
|
||||
await mjolnir.client.redactEvent(roomId, processingReactionId, 'done processing command');
|
||||
return;
|
||||
}
|
||||
|
||||
const targetRoomIds = roomAlias ? [roomAlias] : Object.keys(mjolnir.protectedRooms);
|
||||
await redactUserMessagesIn(mjolnir.client, userId, targetRoomIds);
|
||||
await redactUserMessagesIn(mjolnir.client, userId, targetRoomIds, limit);
|
||||
|
||||
await mjolnir.client.unstableApis.addReactionToEvent(roomId, event['event_id'], '✅');
|
||||
await mjolnir.client.redactEvent(roomId, processingReactionId, 'done processing');
|
||||
}
|
||||
|
18
src/utils.ts
18
src/utils.ts
@ -37,11 +37,11 @@ export function isTrueJoinEvent(event: any): boolean {
|
||||
return membership === 'join' && prevMembership !== "join";
|
||||
}
|
||||
|
||||
export async function redactUserMessagesIn(client: MatrixClient, userIdOrGlob: string, targetRoomIds: string[]) {
|
||||
export async function redactUserMessagesIn(client: MatrixClient, userIdOrGlob: string, targetRoomIds: string[], limit = 1000) {
|
||||
for (const targetRoomId of targetRoomIds) {
|
||||
await logMessage(LogLevel.DEBUG, "utils#redactUserMessagesIn", `Fetching sent messages for ${userIdOrGlob} in ${targetRoomId} to redact...`);
|
||||
|
||||
const eventsToRedact = await getMessagesByUserSinceLastJoin(client, userIdOrGlob, targetRoomId);
|
||||
const eventsToRedact = await getMessagesByUserIn(client, userIdOrGlob, targetRoomId, limit);
|
||||
for (const victimEvent of eventsToRedact) {
|
||||
await logMessage(LogLevel.DEBUG, "utils#redactUserMessagesIn", `Redacting ${victimEvent['event_id']} in ${targetRoomId}`);
|
||||
if (!config.noop) {
|
||||
@ -59,20 +59,20 @@ export async function redactUserMessagesIn(client: MatrixClient, userIdOrGlob: s
|
||||
* @param {MatrixClient} client The client to use.
|
||||
* @param {string} sender The sender. Can include wildcards to match multiple people.
|
||||
* @param {string} roomId The room ID to search in.
|
||||
* @param {number} limit The maximum number of messages to search. Defaults to 1000.
|
||||
* @returns {Promise<any>} Resolves to the events sent by the user(s) prior to join.
|
||||
*/
|
||||
export async function getMessagesByUserSinceLastJoin(client: MatrixClient, sender: string, roomId: string): Promise<any[]> {
|
||||
const limit = 1000; // maximum number of events to process, regardless of outcome
|
||||
export async function getMessagesByUserIn(client: MatrixClient, sender: string, roomId: string, limit: number): Promise<any[]> {
|
||||
const filter = {
|
||||
room: {
|
||||
rooms: [roomId],
|
||||
state: {
|
||||
types: ["m.room.member"],
|
||||
// types: ["m.room.member"], // We'll redact all types of events
|
||||
rooms: [roomId],
|
||||
},
|
||||
timeline: {
|
||||
rooms: [roomId],
|
||||
types: ["m.room.message"],
|
||||
// types: ["m.room.message"], // We'll redact all types of events
|
||||
},
|
||||
ephemeral: {
|
||||
limit: 0,
|
||||
@ -131,7 +131,6 @@ export async function getMessagesByUserSinceLastJoin(client: MatrixClient, sende
|
||||
if (!response) return [];
|
||||
|
||||
const messages = [];
|
||||
const stopProcessingMembers = [];
|
||||
let processed = 0;
|
||||
|
||||
const timeline = (((response['rooms'] || {})['join'] || {})[roomId] || {})['timeline'] || {};
|
||||
@ -143,12 +142,7 @@ export async function getMessagesByUserSinceLastJoin(client: MatrixClient, sende
|
||||
if (processed >= limit) return messages; // we're done even if we don't want to be
|
||||
processed++;
|
||||
|
||||
if (stopProcessingMembers.includes(event['sender'])) continue;
|
||||
if (testUser(event['sender'])) messages.push(event);
|
||||
if (event['type'] === 'm.room.member' && testUser(event['state_key']) && isTrueJoinEvent(event)) {
|
||||
stopProcessingMembers.push(event['sender']);
|
||||
if (!isGlob) return messages; // done!
|
||||
}
|
||||
}
|
||||
|
||||
if (token) {
|
||||
|
Loading…
Reference in New Issue
Block a user