mirror of
https://github.com/matrix-org/mjolnir.git
synced 2024-10-01 01:36:06 -04:00
Since command: adding the ability to mute (#272)
This commit is contained in:
parent
a88fc64a07
commit
74d8caa7e7
@ -157,7 +157,7 @@ export async function handleCommand(roomId: string, event: { content: { body: st
|
||||
"!mjolnir alias add <room alias> <target room alias/ID> - Adds <room alias> to <target room>\n" +
|
||||
"!mjolnir alias remove <room alias> - Deletes the room alias from whatever room it is attached to\n" +
|
||||
"!mjolnir resolve <room alias> - Resolves a room alias to a room ID\n" +
|
||||
"!mjolnir since <date>/<duration> <action> <limit> [rooms...] [reason] - Apply an action (kick, ban or just show) to all users who joined a room since a given date (up to <limit> users)\n" +
|
||||
"!mjolnir since <date>/<duration> <action> <limit> [rooms...] [reason] - Apply an action ('kick', 'ban', 'mute', 'unmute' or 'show') to all users who joined a room since <date>/<duration> (up to <limit> users)\n" +
|
||||
"!mjolnir shutdown room <room alias/ID> [message] - Uses the bot's account to shut down a room, preventing access to the room on this server\n" +
|
||||
"!mjolnir powerlevel <user ID> <power level> [room alias/ID] - Sets the power level of the user in the specified room (or all protected rooms)\n" +
|
||||
"!mjolnir make admin <room alias> [user alias/ID] - Make the specified user or the bot itself admin of the room\n" +
|
||||
|
@ -19,6 +19,7 @@ import { LogLevel, LogService, RichReply } from "matrix-bot-sdk";
|
||||
import { htmlEscape, parseDuration } from "../utils";
|
||||
import { ParseEntry } from "shell-quote";
|
||||
import { HumanizeDurationLanguage, HumanizeDuration } from "humanize-duration-ts";
|
||||
import { Join } from "../RoomMembers";
|
||||
|
||||
const HUMANIZE_LAG_SERVICE: HumanizeDurationLanguage = new HumanizeDurationLanguage();
|
||||
const HUMANIZER: HumanizeDuration = new HumanizeDuration(HUMANIZE_LAG_SERVICE);
|
||||
@ -26,11 +27,16 @@ const HUMANIZER: HumanizeDuration = new HumanizeDuration(HUMANIZE_LAG_SERVICE);
|
||||
enum Action {
|
||||
Kick = "kick",
|
||||
Ban = "ban",
|
||||
Mute = "mute",
|
||||
Unmute = "unmute",
|
||||
Show = "show"
|
||||
}
|
||||
|
||||
type Result<T> = {ok: T} | {error: string};
|
||||
|
||||
type userId = string;
|
||||
type Summary = { succeeded: userId[], failed: userId[] };
|
||||
|
||||
/**
|
||||
* Attempt to parse a `ParseEntry`, as provided by the shell-style parser, using a parsing function.
|
||||
*
|
||||
@ -104,6 +110,15 @@ export async function execSinceCommand(destinationRoomId: string, event: any, mj
|
||||
}
|
||||
}
|
||||
|
||||
function formatResult(action: string, targetRoomId: string, recentJoins: Join[], summary: Summary): {html: string, text: string} {
|
||||
const html = `Attempted to ${action} ${recentJoins.length} users from room ${targetRoomId}.<br/>Succeeded ${summary.succeeded.length}: <ul>${summary.succeeded.map(x => `<li>${htmlEscape(x)}</li>`).join("\n")}</ul>.<br/> Failed ${summary.failed.length}: <ul>${summary.succeeded.map(x => `<li>${htmlEscape(x)}</li>`).join("\n")}</ul>`;
|
||||
const text = `Attempted to ${action} ${recentJoins.length} users from room ${targetRoomId}.\nSucceeded ${summary.succeeded.length}: ${summary.succeeded.map(x => `*${htmlEscape(x)}`).join("\n")}\n Failed ${summary.failed.length}:\n${summary.succeeded.map(x => ` * ${htmlEscape(x)}`).join("\n")}`;
|
||||
return {
|
||||
html,
|
||||
text
|
||||
};
|
||||
}
|
||||
|
||||
// Implementation of `execSinceCommand`, counts on caller to print errors.
|
||||
//
|
||||
// This method:
|
||||
@ -209,46 +224,78 @@ async function execSinceCommandAux(destinationRoomId: string, event: any, mjolni
|
||||
|
||||
for (let targetRoomId of rooms) {
|
||||
let {html, text} = await (async () => {
|
||||
let results: Summary = { succeeded: [], failed: []};
|
||||
const recentJoins = mjolnir.roomJoins.getUsersInRoom(targetRoomId, minDate, maxEntries);
|
||||
|
||||
switch (action) {
|
||||
case Action.Show: {
|
||||
return makeJoinStatus(mjolnir, targetRoomId, maxEntries, minDate, maxAgeMS);
|
||||
return makeJoinStatus(mjolnir, targetRoomId, maxEntries, minDate, maxAgeMS, recentJoins);
|
||||
}
|
||||
case Action.Kick: {
|
||||
const joins = mjolnir.roomJoins.getUsersInRoom(targetRoomId, minDate, maxEntries);
|
||||
let results = { good: 0, bad: 0};
|
||||
for (let join of joins) {
|
||||
for (let join of recentJoins) {
|
||||
try {
|
||||
await mjolnir.client.kickUser(join.userId, targetRoomId, reason);
|
||||
results.good += 1;
|
||||
results.succeeded.push(join.userId);
|
||||
} catch (ex) {
|
||||
LogService.warn("SinceCommand", "Error while attempting to kick user", ex);
|
||||
results.bad += 1;
|
||||
results.failed.push(join.userId);
|
||||
}
|
||||
}
|
||||
const text_ = `Attempted to kick ${joins.length} users from room ${targetRoomId}, ${results.good} kicked, ${results.bad} failures`;
|
||||
return {
|
||||
html: text_,
|
||||
text: text_,
|
||||
}
|
||||
|
||||
return formatResult("kick", targetRoomId, recentJoins, results);
|
||||
}
|
||||
case Action.Ban: {
|
||||
const joins = mjolnir.roomJoins.getUsersInRoom(targetRoomId, minDate, maxEntries);
|
||||
|
||||
let results = { good: 0, bad: 0};
|
||||
for (let join of joins) {
|
||||
for (let join of recentJoins) {
|
||||
try {
|
||||
await mjolnir.client.banUser(join.userId, targetRoomId, reason);
|
||||
results.good += 1;
|
||||
results.succeeded.push(join.userId);
|
||||
} catch (ex) {
|
||||
LogService.warn("SinceCommand", "Error while attempting to ban user", ex);
|
||||
results.bad += 1;
|
||||
results.failed.push(join.userId);
|
||||
}
|
||||
}
|
||||
const text_ = `Attempted to ban ${joins.length} users from room ${targetRoomId}, ${results.good} kicked, ${results.bad} failures`;
|
||||
return {
|
||||
html: text_,
|
||||
text: text_
|
||||
|
||||
return formatResult("ban", targetRoomId, recentJoins, results);
|
||||
}
|
||||
case Action.Mute: {
|
||||
const powerLevels = await mjolnir.client.getRoomStateEvent(targetRoomId, "m.room.power_levels", "") as {users: Record</* userId */ string, number>};
|
||||
|
||||
for (let join of recentJoins) {
|
||||
powerLevels.users[join.userId] = -1;
|
||||
}
|
||||
try {
|
||||
await mjolnir.client.sendStateEvent(targetRoomId, "m.room.power_levels", "", powerLevels);
|
||||
for (let join of recentJoins) {
|
||||
results.succeeded.push(join.userId);
|
||||
}
|
||||
} catch (ex) {
|
||||
LogService.warn("SinceCommand", "Error while attempting to mute users", ex);
|
||||
for (let join of recentJoins) {
|
||||
results.failed.push(join.userId);
|
||||
}
|
||||
}
|
||||
|
||||
return formatResult("mute", targetRoomId, recentJoins, results);
|
||||
}
|
||||
case Action.Unmute: {
|
||||
const powerLevels = await mjolnir.client.getRoomStateEvent(targetRoomId, "m.room.power_levels", "") as {users: Record</* userId */ string, number>, users_default?: number};
|
||||
for (let join of recentJoins) {
|
||||
// Restore default powerlevel.
|
||||
delete powerLevels.users[join.userId];
|
||||
}
|
||||
try {
|
||||
await mjolnir.client.sendStateEvent(targetRoomId, "m.room.power_levels", "", powerLevels);
|
||||
for (let join of recentJoins) {
|
||||
results.succeeded.push(join.userId);
|
||||
}
|
||||
} catch (ex) {
|
||||
LogService.warn("SinceCommand", "Error while attempting to unmute users", ex);
|
||||
for (let join of recentJoins) {
|
||||
results.failed.push(join.userId);
|
||||
}
|
||||
}
|
||||
|
||||
return formatResult("unmute", targetRoomId, recentJoins, results);
|
||||
}
|
||||
}
|
||||
})();
|
||||
@ -262,7 +309,7 @@ async function execSinceCommandAux(destinationRoomId: string, event: any, mjolni
|
||||
return {ok: undefined};
|
||||
}
|
||||
|
||||
function makeJoinStatus(mjolnir: Mjolnir, targetRoomId: string, maxEntries: number, minDate: Date, maxAgeMS: number): {html: string, text: string} {
|
||||
function makeJoinStatus(mjolnir: Mjolnir, targetRoomId: string, maxEntries: number, minDate: Date, maxAgeMS: number, recentJoins: Join[]): {html: string, text: string} {
|
||||
const HUMANIZER_OPTIONS = {
|
||||
// Reduce "1 day" => "1day" to simplify working with CSV.
|
||||
spacer: "",
|
||||
@ -270,16 +317,15 @@ function makeJoinStatus(mjolnir: Mjolnir, targetRoomId: string, maxEntries: numb
|
||||
largest: 1,
|
||||
};
|
||||
const maxAgeHumanReadable = HUMANIZER.humanize(maxAgeMS);
|
||||
const joins = mjolnir.roomJoins.getUsersInRoom(targetRoomId, minDate, maxEntries);
|
||||
const htmlFragments = [];
|
||||
const textFragments = [];
|
||||
for (let join of joins) {
|
||||
for (let join of recentJoins) {
|
||||
const durationHumanReadable = HUMANIZER.humanize(Date.now() - join.timestamp, HUMANIZER_OPTIONS);
|
||||
htmlFragments.push(`<li>${htmlEscape(join.userId)}: ${durationHumanReadable}</li>`);
|
||||
textFragments.push(`- ${join.userId}: ${durationHumanReadable}`);
|
||||
}
|
||||
return {
|
||||
html: `${joins.length} recent joins (cut at ${maxAgeHumanReadable} ago / ${maxEntries} entries): <ul> ${htmlFragments.join()} </ul>`,
|
||||
text: `${joins.length} recent joins (cut at ${maxAgeHumanReadable} ago / ${maxEntries} entries):\n${textFragments.join("\n")}`
|
||||
html: `${recentJoins.length} recent joins (cut at ${maxAgeHumanReadable} ago / ${maxEntries} entries): <ul> ${htmlFragments.join()} </ul>`,
|
||||
text: `${recentJoins.length} recent joins (cut at ${maxAgeHumanReadable} ago / ${maxEntries} entries):\n${textFragments.join("\n")}`
|
||||
}
|
||||
}
|
||||
|
@ -403,7 +403,7 @@ describe("Test: Testing RoomMemberManager", function() {
|
||||
// Create and protect rooms.
|
||||
// - room 0 remains unprotected, as witness;
|
||||
// - room 1 is protected but won't be targeted directly, also as witness.
|
||||
const NUMBER_OF_ROOMS = 14;
|
||||
const NUMBER_OF_ROOMS = 18;
|
||||
const roomIds: string[] = [];
|
||||
const roomAliases: string[] = [];
|
||||
const mjolnirUserId = await this.mjolnir.client.getUserId();
|
||||
@ -460,121 +460,195 @@ describe("Test: Testing RoomMemberManager", function() {
|
||||
|
||||
enum Method {
|
||||
kick,
|
||||
ban
|
||||
ban,
|
||||
mute,
|
||||
unmute,
|
||||
}
|
||||
const WITNESS_UNPROTECTED_ROOM_ID = roomIds[0];
|
||||
const WITNESS_ROOM_ID = roomIds[1];
|
||||
const EXPERIMENTS = [
|
||||
class Experiment {
|
||||
// A human-readable name for the command.
|
||||
readonly name: string;
|
||||
// If `true`, this command should affect room `WITNESS_ROOM_ID`.
|
||||
// Defaults to `false`.
|
||||
readonly shouldAffectWitnessRoom: boolean;
|
||||
// The actual command-line.
|
||||
readonly command: (roomId: string, roomAlias: string) => string;
|
||||
// The number of responses we expect to this command.
|
||||
// Defaults to `1`.
|
||||
readonly n: number;
|
||||
// How affected users should leave the room.
|
||||
readonly method: Method;
|
||||
|
||||
// If `true`, should this experiment look at the same room as the previous one.
|
||||
// Defaults to `false`.
|
||||
readonly isSameRoomAsPrevious: boolean;
|
||||
|
||||
roomIndex: number | undefined;
|
||||
|
||||
constructor({name, shouldAffectWitnessRoom, command, n, method, sameRoom}: {name: string, command: (roomId: string, roomAlias: string) => string, shouldAffectWitnessRoom?: boolean, n?: number, method: Method, sameRoom?: boolean}) {
|
||||
this.name = name;
|
||||
this.shouldAffectWitnessRoom = typeof shouldAffectWitnessRoom === "undefined" ? false : shouldAffectWitnessRoom;
|
||||
this.command = command;
|
||||
this.n = typeof n === "undefined" ? 1 : n;
|
||||
this.method = method;
|
||||
this.isSameRoomAsPrevious = typeof sameRoom === "undefined" ? false : sameRoom;
|
||||
}
|
||||
|
||||
addTo(experiments: Experiment[]) {
|
||||
if (this.isSameRoomAsPrevious) {
|
||||
this.roomIndex = experiments[experiments.length - 1].roomIndex;
|
||||
} else if (experiments.length === 0) {
|
||||
this.roomIndex = 0;
|
||||
} else {
|
||||
this.roomIndex = experiments[experiments.length - 1].roomIndex! + 1;
|
||||
}
|
||||
experiments.push(this);
|
||||
}
|
||||
}
|
||||
const EXPERIMENTS: Experiment[] = [];
|
||||
for (let experiment of [
|
||||
// Kick bad users in one room, using duration syntax, no reason.
|
||||
{
|
||||
// A human-readable name for the command.
|
||||
new Experiment({
|
||||
name: "kick with duration",
|
||||
// The actual command-line.
|
||||
command: (roomId: string) => `!mjolnir since ${Date.now() - cutDate.getTime()}ms kick 100 ${roomId}`,
|
||||
// If `true`, this command should affect room `WITNESS_ROOM_ID`.
|
||||
shouldAffectWitnessRoom: false,
|
||||
// The number of responses we expect to this command.
|
||||
n: 1,
|
||||
// How affected users should leave the room.
|
||||
method: Method.kick,
|
||||
},
|
||||
}),
|
||||
// Ban bad users in one room, using duration syntax, no reason.
|
||||
{
|
||||
new Experiment({
|
||||
name: "ban with duration",
|
||||
command: (roomId: string) => `!mjolnir since ${Date.now() - cutDate.getTime()}ms ban 100 ${roomId}`,
|
||||
shouldAffectWitnessRoom: false,
|
||||
n: 1,
|
||||
method: Method.ban,
|
||||
},
|
||||
}),
|
||||
// Mute bad users in one room, using duration syntax, no reason.
|
||||
new Experiment({
|
||||
name: "mute with duration",
|
||||
command: (roomId: string) => `!mjolnir since ${Date.now() - cutDate.getTime()}ms mute 100 ${roomId}`,
|
||||
method: Method.mute,
|
||||
}),
|
||||
new Experiment({
|
||||
name: "unmute with duration",
|
||||
command: (roomId: string) => `!mjolnir since ${Date.now() - cutDate.getTime()}ms unmute 100 ${roomId}`,
|
||||
method: Method.unmute,
|
||||
sameRoom: true,
|
||||
}),
|
||||
// Kick bad users in one room, using date syntax, no reason.
|
||||
{
|
||||
new Experiment({
|
||||
name: "kick with date",
|
||||
command: (roomId: string) => `!mjolnir since "${cutDate}" kick 100 ${roomId}`,
|
||||
shouldAffectWitnessRoom: false,
|
||||
n: 1,
|
||||
method: Method.kick,
|
||||
},
|
||||
}),
|
||||
// Ban bad users in one room, using date syntax, no reason.
|
||||
{
|
||||
new Experiment({
|
||||
name: "ban with date",
|
||||
command: (roomId: string) => `!mjolnir since "${cutDate}" ban 100 ${roomId}`,
|
||||
shouldAffectWitnessRoom: false,
|
||||
n: 1,
|
||||
method: Method.ban,
|
||||
},
|
||||
}),
|
||||
// Mute bad users in one room, using date syntax, no reason.
|
||||
new Experiment({
|
||||
name: "mute with date",
|
||||
command: (roomId: string) => `!mjolnir since "${cutDate}" mute 100 ${roomId}`,
|
||||
method: Method.mute,
|
||||
}),
|
||||
new Experiment({
|
||||
name: "unmute with date",
|
||||
command: (roomId: string) => `!mjolnir since "${cutDate}" unmute 100 ${roomId}`,
|
||||
method: Method.unmute,
|
||||
sameRoom: true,
|
||||
}),
|
||||
|
||||
// Kick bad users in one room, using duration syntax, with reason.
|
||||
{
|
||||
new Experiment({
|
||||
name: "kick with duration and reason",
|
||||
command: (roomId: string) => `!mjolnir since ${Date.now() - cutDate.getTime()}ms kick 100 ${roomId} bad, bad user`,
|
||||
shouldAffectWitnessRoom: false,
|
||||
n: 1,
|
||||
method: Method.kick,
|
||||
},
|
||||
}),
|
||||
// Ban bad users in one room, using duration syntax, with reason.
|
||||
{
|
||||
new Experiment({
|
||||
name: "ban with duration and reason",
|
||||
command: (roomId: string) => `!mjolnir since ${Date.now() - cutDate.getTime()}ms ban 100 ${roomId} bad, bad user`,
|
||||
shouldAffectWitnessRoom: false,
|
||||
n: 1,
|
||||
method: Method.ban,
|
||||
},
|
||||
}),
|
||||
// Mute bad users in one room, using duration syntax, with reason.
|
||||
new Experiment({
|
||||
name: "mute with duration and reason",
|
||||
command: (roomId: string) => `!mjolnir since ${Date.now() - cutDate.getTime()}ms mute 100 ${roomId} bad, bad user`,
|
||||
method: Method.mute,
|
||||
}),
|
||||
new Experiment({
|
||||
name: "unmute with duration and reason",
|
||||
command: (roomId: string) => `!mjolnir since ${Date.now() - cutDate.getTime()}ms unmute 100 ${roomId} bad, bad user`,
|
||||
method: Method.unmute,
|
||||
sameRoom: true,
|
||||
}),
|
||||
|
||||
// Kick bad users in one room, using date syntax, with reason.
|
||||
{
|
||||
new Experiment({
|
||||
name: "kick with date and reason",
|
||||
command: (roomId: string) => `!mjolnir since "${cutDate}" kick 100 ${roomId} bad, bad user`,
|
||||
shouldAffectWitnessRoom: false,
|
||||
n: 1,
|
||||
method: Method.kick,
|
||||
},
|
||||
}),
|
||||
// Ban bad users in one room, using date syntax, with reason.
|
||||
{
|
||||
new Experiment({
|
||||
name: "ban with date and reason",
|
||||
command: (roomId: string) => `!mjolnir since "${cutDate}" ban 100 ${roomId} bad, bad user`,
|
||||
shouldAffectWitnessRoom: false,
|
||||
n: 1,
|
||||
method: Method.ban,
|
||||
},
|
||||
}),
|
||||
// Mute bad users in one room, using date syntax, with reason.
|
||||
new Experiment({
|
||||
name: "mute with date and reason",
|
||||
command: (roomId: string) => `!mjolnir since "${cutDate}" mute 100 ${roomId} bad, bad user`,
|
||||
method: Method.mute,
|
||||
}),
|
||||
new Experiment({
|
||||
name: "unmute with date and reason",
|
||||
command: (roomId: string) => `!mjolnir since "${cutDate}" unmute 100 ${roomId} bad, bad user`,
|
||||
method: Method.unmute,
|
||||
sameRoom: true,
|
||||
}),
|
||||
|
||||
// Kick bad users in one room, using duration syntax, without reason, using alias.
|
||||
{
|
||||
new Experiment({
|
||||
name: "kick with duration, no reason, alias",
|
||||
command: (_: string, roomAlias: string) => `!mjolnir since ${Date.now() - cutDate.getTime()}ms kick 100 ${roomAlias}`,
|
||||
shouldAffectWitnessRoom: false,
|
||||
n: 1,
|
||||
method: Method.kick,
|
||||
},
|
||||
|
||||
}),
|
||||
// Kick bad users in one room, using duration syntax, with reason, using alias.
|
||||
{
|
||||
new Experiment({
|
||||
name: "kick with duration, reason and alias",
|
||||
command: (_: string, roomAlias: string) => `!mjolnir since ${Date.now() - cutDate.getTime()}ms kick 100 ${roomAlias} for some reason`,
|
||||
shouldAffectWitnessRoom: false,
|
||||
n: 1,
|
||||
method: Method.kick,
|
||||
},
|
||||
}),
|
||||
|
||||
// Kick bad users everywhere, no reason
|
||||
{
|
||||
new Experiment({
|
||||
name: "kick with date everywhere",
|
||||
command: () => `!mjolnir since "${cutDate}" kick 100 * bad, bad user`,
|
||||
shouldAffectWitnessRoom: true,
|
||||
n: NUMBER_OF_ROOMS - 1,
|
||||
method: Method.kick,
|
||||
}
|
||||
];
|
||||
}),
|
||||
]) {
|
||||
experiment.addTo(EXPERIMENTS);
|
||||
}
|
||||
for (let i = 0; i < EXPERIMENTS.length; ++i) {
|
||||
const experiment = EXPERIMENTS[i];
|
||||
const roomId = roomIds[i + 2];
|
||||
const roomAlias = roomAliases[i + 2];
|
||||
const index = experiment.roomIndex! + 1;
|
||||
const roomId = roomIds[index];
|
||||
const roomAlias = roomAliases[index];
|
||||
const joined = this.mjolnir.roomJoins.getUsersInRoom(roomId, start, 100);
|
||||
assert.ok(joined.length >= 2 * SAMPLE_SIZE, `We should have seen ${2 * SAMPLE_SIZE} users, saw ${joined.length}`);
|
||||
assert.ok(joined.length >= 2 * SAMPLE_SIZE, `In experiment ${experiment.name}, we should have seen ${2 * SAMPLE_SIZE} users, saw ${joined.length}`);
|
||||
|
||||
// Run experiment.
|
||||
await getNthReply(this.mjolnir.client, this.mjolnir.managementRoomId, experiment.n, async () => {
|
||||
const command = experiment.command(roomId, roomAlias);
|
||||
let result = await this.moderator.sendMessage(this.mjolnir.managementRoomId, { msgtype: 'm.text', body: command });
|
||||
return result;
|
||||
});
|
||||
|
||||
// Check post-conditions.
|
||||
const usersInRoom = await this.mjolnir.client.getJoinedRoomMembers(roomId);
|
||||
const usersInUnprotectedWitnessRoom = await this.mjolnir.client.getJoinedRoomMembers(WITNESS_UNPROTECTED_ROOM_ID);
|
||||
const usersInWitnessRoom = await this.mjolnir.client.getJoinedRoomMembers(WITNESS_ROOM_ID);
|
||||
@ -583,18 +657,38 @@ describe("Test: Testing RoomMemberManager", function() {
|
||||
assert.ok(usersInWitnessRoom.includes(userId), `After a ${experiment.name}, good user ${userId} should still be in witness room`);
|
||||
assert.ok(usersInUnprotectedWitnessRoom.includes(userId), `After a ${experiment.name}, good user ${userId} should still be in unprotected witness room`);
|
||||
}
|
||||
for (let userId of badUserIds) {
|
||||
assert.ok(!usersInRoom.includes(userId), `After a ${experiment.name}, bad user ${userId} should NOT be in affected room`);
|
||||
assert.equal(usersInWitnessRoom.includes(userId), !experiment.shouldAffectWitnessRoom, `After a ${experiment.name}, bad user ${userId} should ${experiment.shouldAffectWitnessRoom ? "NOT" : "still"} be in witness room`);
|
||||
assert.ok(usersInUnprotectedWitnessRoom.includes(userId), `After a ${experiment.name}, bad user ${userId} should still be in unprotected witness room`);
|
||||
const leaveEvent = await this.mjolnir.client.getRoomStateEvent(roomId, "m.room.member", userId);
|
||||
switch (experiment.method) {
|
||||
case Method.kick:
|
||||
assert.equal(leaveEvent.membership, "leave");
|
||||
break;
|
||||
case Method.ban:
|
||||
assert.equal(leaveEvent.membership, "ban");
|
||||
break;
|
||||
if (experiment.method === Method.mute) {
|
||||
for (let userId of goodUserIds) {
|
||||
let canSpeak = await this.mjolnir.client.userHasPowerLevelFor(userId, roomId, "m.message", false);
|
||||
assert.ok(canSpeak, `After a ${experiment.name}, good user ${userId} should still be allowed to speak in the room`);
|
||||
}
|
||||
for (let userId of badUserIds) {
|
||||
let canSpeak = await this.mjolnir.client.userHasPowerLevelFor(userId, roomId, "m.message", false);
|
||||
assert.ok(!canSpeak, `After a ${experiment.name}, bad user ${userId} should NOT be allowed to speak in the room`);
|
||||
}
|
||||
} else if (experiment.method === Method.unmute) {
|
||||
for (let userId of goodUserIds) {
|
||||
let canSpeak = await this.mjolnir.client.userHasPowerLevelFor(userId, roomId, "m.message", false);
|
||||
assert.ok(canSpeak, `After a ${experiment.name}, good user ${userId} should still be allowed to speak in the room`);
|
||||
}
|
||||
for (let userId of badUserIds) {
|
||||
let canSpeak = await this.mjolnir.client.userHasPowerLevelFor(userId, roomId, "m.message", false);
|
||||
assert.ok(canSpeak, `After a ${experiment.name}, bad user ${userId} should AGAIN be allowed to speak in the room`);
|
||||
}
|
||||
} else {
|
||||
for (let userId of badUserIds) {
|
||||
assert.ok(!usersInRoom.includes(userId), `After a ${experiment.name}, bad user ${userId} should NOT be in affected room`);
|
||||
assert.equal(usersInWitnessRoom.includes(userId), !experiment.shouldAffectWitnessRoom, `After a ${experiment.name}, bad user ${userId} should ${experiment.shouldAffectWitnessRoom ? "NOT" : "still"} be in witness room`);
|
||||
assert.ok(usersInUnprotectedWitnessRoom.includes(userId), `After a ${experiment.name}, bad user ${userId} should still be in unprotected witness room`);
|
||||
const leaveEvent = await this.mjolnir.client.getRoomStateEvent(roomId, "m.room.member", userId);
|
||||
switch (experiment.method) {
|
||||
case Method.kick:
|
||||
assert.equal(leaveEvent.membership, "leave");
|
||||
break;
|
||||
case Method.ban:
|
||||
assert.equal(leaveEvent.membership, "ban");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user