mirror of
https://github.com/the-draupnir-project/Draupnir.git
synced 2026-03-31 11:25:39 +00:00
We have a lot of verbose headers, and i think now is the best opportunity we have to become reuse compliant given that we just did two other similar maintenance changes (prettier, typescirpt5 & eslint9 & typescript-eslint). * synapse_antispam resuse headers. * delete old unused tslint.json. * Add REUSE to pre-commit config. * reuse info for config directory.
296 lines
9.7 KiB
TypeScript
296 lines
9.7 KiB
TypeScript
// Copyright 2022 - 2024 Gnuxie <Gnuxie@protonmail.com>
|
|
// Copyright 2021 The Matrix.org Foundation C.I.C.
|
|
//
|
|
// SPDX-License-Identifier: AFL-3.0 AND Apache-2.0
|
|
//
|
|
// SPDX-FileAttributionText: <text>
|
|
// This modified file incorporates work from mjolnir
|
|
// https://github.com/matrix-org/mjolnir
|
|
// </text>
|
|
|
|
import { strict as assert } from "assert";
|
|
import { newTestUser } from "../clientHelper";
|
|
import { getMessagesByUserIn } from "../../../src/utils";
|
|
import { LogService } from "matrix-bot-sdk";
|
|
import { getFirstReaction } from "./commandUtils";
|
|
import {
|
|
draupnirClient,
|
|
draupnirSafeEmitter,
|
|
DraupnirTestContext,
|
|
} from "../mjolnirSetupUtils";
|
|
import { MatrixClient } from "matrix-bot-sdk";
|
|
|
|
interface RedactionTestContext extends DraupnirTestContext {
|
|
moderator?: MatrixClient;
|
|
}
|
|
|
|
describe("Test: The redaction command", function () {
|
|
// If a test has a timeout while awaitng on a promise then we never get given control back.
|
|
afterEach(function () {
|
|
this.moderator?.stop();
|
|
});
|
|
|
|
it(
|
|
"Mjölnir redacts all of the events sent by a spammer when instructed to by giving their id and a room id.",
|
|
async function (this: RedactionTestContext) {
|
|
this.timeout(60000);
|
|
// Create a few users and a room.
|
|
const badUser = await newTestUser(this.config.homeserverUrl, {
|
|
name: { contains: "spammer-needs-redacting" },
|
|
});
|
|
const badUserId = await badUser.getUserId();
|
|
const draupnirMatrixClient = draupnirClient();
|
|
const draupnir = this.draupnir;
|
|
if (draupnirMatrixClient === null || draupnir === undefined) {
|
|
throw new TypeError(`Test isn't setup correctly`);
|
|
}
|
|
const mjolnirUserId = await draupnirMatrixClient.getUserId();
|
|
const moderator = await newTestUser(this.config.homeserverUrl, {
|
|
name: { contains: "moderator" },
|
|
});
|
|
this.moderator = moderator;
|
|
await moderator.joinRoom(this.config.managementRoom);
|
|
const targetRoom = await moderator.createRoom({
|
|
invite: [await badUser.getUserId(), mjolnirUserId],
|
|
});
|
|
await moderator.setUserPowerLevel(mjolnirUserId, targetRoom, 100);
|
|
await badUser.joinRoom(targetRoom);
|
|
await getFirstReaction(
|
|
draupnirSafeEmitter(),
|
|
draupnir.managementRoomID,
|
|
"✅",
|
|
async () => {
|
|
return moderator.sendMessage(draupnir.managementRoomID, {
|
|
msgtype: "m.text",
|
|
body: `!draupnir rooms add ${targetRoom}`,
|
|
});
|
|
}
|
|
);
|
|
LogService.debug(
|
|
"redactionTest",
|
|
`targetRoom: ${targetRoom}, managementRoom: ${this.config.managementRoom}`
|
|
);
|
|
// Sandwich irrelevant messages in bad messages.
|
|
await badUser.sendMessage(targetRoom, {
|
|
msgtype: "m.text",
|
|
body: "Very Bad Stuff",
|
|
});
|
|
await Promise.all(
|
|
[...Array(50).keys()].map((i) =>
|
|
moderator.sendMessage(targetRoom, {
|
|
msgtype: "m.text",
|
|
body: `Irrelevant Message #${i}`,
|
|
})
|
|
)
|
|
);
|
|
for (let i = 0; i < 5; i++) {
|
|
await badUser.sendMessage(targetRoom, {
|
|
msgtype: "m.text",
|
|
body: "Very Bad Stuff",
|
|
});
|
|
}
|
|
await Promise.all(
|
|
[...Array(50).keys()].map((i) =>
|
|
moderator.sendMessage(targetRoom, {
|
|
msgtype: "m.text",
|
|
body: `Irrelevant Message #${i}`,
|
|
})
|
|
)
|
|
);
|
|
await badUser.sendMessage(targetRoom, {
|
|
msgtype: "m.text",
|
|
body: "Very Bad Stuff",
|
|
});
|
|
|
|
await getFirstReaction(
|
|
draupnirSafeEmitter(),
|
|
draupnir.managementRoomID,
|
|
"✅",
|
|
async () => {
|
|
return await moderator.sendMessage(draupnir.managementRoomID, {
|
|
msgtype: "m.text",
|
|
body: `!draupnir redact ${badUserId} --room ${targetRoom}`,
|
|
});
|
|
}
|
|
);
|
|
|
|
await getMessagesByUserIn(
|
|
moderator,
|
|
badUserId,
|
|
targetRoom,
|
|
1000,
|
|
function (events) {
|
|
events.map((e) => {
|
|
if (e.type === "m.room.member") {
|
|
assert.equal(
|
|
Object.keys(e.content).length,
|
|
1,
|
|
"Only membership should be left on the membership even when it has been redacted."
|
|
);
|
|
} else if (Object.keys(e.content).length !== 0) {
|
|
throw new Error(
|
|
`This event should have been redacted: ${JSON.stringify(e, null, 2)}`
|
|
);
|
|
}
|
|
});
|
|
}
|
|
);
|
|
} as unknown as Mocha.AsyncFunc
|
|
);
|
|
|
|
it(
|
|
"Mjölnir redacts all of the events sent by a spammer when instructed to by giving their id in multiple rooms.",
|
|
async function (this: RedactionTestContext) {
|
|
this.timeout(60000);
|
|
// Create a few users and a room.
|
|
const badUser = await newTestUser(this.config.homeserverUrl, {
|
|
name: { contains: "spammer-needs-redacting" },
|
|
});
|
|
const badUserId = await badUser.getUserId();
|
|
const draupnir = this.draupnir;
|
|
if (draupnir === undefined) {
|
|
throw new TypeError(`Test isn't setup correctly`);
|
|
}
|
|
const mjolnirUserId = await draupnir.client.getUserId();
|
|
const moderator = await newTestUser(this.config.homeserverUrl, {
|
|
name: { contains: "moderator" },
|
|
});
|
|
this.moderator = moderator;
|
|
await moderator.joinRoom(this.config.managementRoom);
|
|
const targetRooms: string[] = [];
|
|
for (let i = 0; i < 5; i++) {
|
|
const targetRoom = await moderator.createRoom({
|
|
invite: [await badUser.getUserId(), mjolnirUserId],
|
|
});
|
|
await moderator.setUserPowerLevel(mjolnirUserId, targetRoom, 100);
|
|
await badUser.joinRoom(targetRoom);
|
|
await moderator.sendMessage(draupnir.managementRoomID, {
|
|
msgtype: "m.text",
|
|
body: `!draupnir rooms add ${targetRoom}`,
|
|
});
|
|
targetRooms.push(targetRoom);
|
|
|
|
// Sandwich irrelevant messages in bad messages.
|
|
await badUser.sendMessage(targetRoom, {
|
|
msgtype: "m.text",
|
|
body: "Very Bad Stuff",
|
|
});
|
|
await Promise.all(
|
|
[...Array(50).keys()].map((j) =>
|
|
moderator.sendMessage(targetRoom, {
|
|
msgtype: "m.text",
|
|
body: `Irrelevant Message #${j}`,
|
|
})
|
|
)
|
|
);
|
|
for (let j = 0; j < 5; j++) {
|
|
await badUser.sendMessage(targetRoom, {
|
|
msgtype: "m.text",
|
|
body: "Very Bad Stuff",
|
|
});
|
|
}
|
|
await Promise.all(
|
|
[...Array(50).keys()].map((j) =>
|
|
moderator.sendMessage(targetRoom, {
|
|
msgtype: "m.text",
|
|
body: `Irrelevant Message #${j}`,
|
|
})
|
|
)
|
|
);
|
|
await badUser.sendMessage(targetRoom, {
|
|
msgtype: "m.text",
|
|
body: "Very Bad Stuff",
|
|
});
|
|
}
|
|
|
|
await getFirstReaction(
|
|
draupnirSafeEmitter(),
|
|
draupnir.managementRoomID,
|
|
"✅",
|
|
async () => {
|
|
return await moderator.sendMessage(draupnir.managementRoomID, {
|
|
msgtype: "m.text",
|
|
body: `!draupnir redact ${badUserId}`,
|
|
});
|
|
}
|
|
);
|
|
|
|
await Promise.all(
|
|
targetRooms.map(async (targetRoom) => {
|
|
await getMessagesByUserIn(
|
|
moderator,
|
|
badUserId,
|
|
targetRoom,
|
|
1000,
|
|
function (events) {
|
|
events.map((e) => {
|
|
if (e.type === "m.room.member") {
|
|
assert.equal(
|
|
Object.keys(e.content).length,
|
|
1,
|
|
"Only membership should be left on the membership even when it has been redacted."
|
|
);
|
|
} else if (Object.keys(e.content).length !== 0) {
|
|
throw new Error(
|
|
`This event should have been redacted: ${JSON.stringify(e, null, 2)}`
|
|
);
|
|
}
|
|
});
|
|
}
|
|
);
|
|
})
|
|
);
|
|
} as unknown as Mocha.AsyncFunc
|
|
);
|
|
it("Redacts a single event when instructed to.", async function (
|
|
this: RedactionTestContext
|
|
) {
|
|
this.timeout(60000);
|
|
// Create a few users and a room.
|
|
const badUser = await newTestUser(this.config.homeserverUrl, {
|
|
name: { contains: "spammer-needs-redacting" },
|
|
});
|
|
const draupnir = this.draupnir;
|
|
if (draupnir === undefined) {
|
|
throw new TypeError(`Test isn't setup correctly`);
|
|
}
|
|
const moderator = await newTestUser(this.config.homeserverUrl, {
|
|
name: { contains: "moderator" },
|
|
});
|
|
this.moderator = moderator;
|
|
await moderator.joinRoom(this.config.managementRoom);
|
|
const targetRoom = await moderator.createRoom({
|
|
invite: [await badUser.getUserId(), draupnir.clientUserID],
|
|
});
|
|
await moderator.setUserPowerLevel(draupnir.clientUserID, targetRoom, 100);
|
|
await badUser.joinRoom(targetRoom);
|
|
await moderator.sendMessage(draupnir.managementRoomID, {
|
|
msgtype: "m.text",
|
|
body: `!draupnir rooms add ${targetRoom}`,
|
|
});
|
|
const eventToRedact = await badUser.sendMessage(targetRoom, {
|
|
msgtype: "m.text",
|
|
body: "Very Bad Stuff",
|
|
});
|
|
|
|
await getFirstReaction(
|
|
draupnirSafeEmitter(),
|
|
draupnir.managementRoomID,
|
|
"✅",
|
|
async () => {
|
|
return await moderator.sendMessage(draupnir.managementRoomID, {
|
|
msgtype: "m.text",
|
|
body: `!draupnir redact https://matrix.to/#/${encodeURIComponent(targetRoom)}/${encodeURIComponent(eventToRedact)}`,
|
|
});
|
|
}
|
|
);
|
|
|
|
const redactedEvent = await moderator.getEvent(targetRoom, eventToRedact);
|
|
assert.equal(
|
|
Object.keys(redactedEvent.content).length,
|
|
0,
|
|
"This event should have been redacted"
|
|
);
|
|
} as unknown as Mocha.AsyncFunc);
|
|
});
|