Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
const ruleContent = {}; // empty == clear/unban
const stateKey = `rule:${bits.entity}`;
await mjolnir.client.sendStateEvent(bits.list.roomId, bits.ruleType, stateKey, ruleContent);
if (USER_RULE_TYPES.includes(bits.ruleType) && parts.length > 5 && parts[5] === 'true') {
const rule = new MatrixGlob(bits.entity);
await logMessage(LogLevel.INFO, "UnbanBanCommand", "Unbanning users that match glob: " + bits.entity);
let unbannedSomeone = false;
for (const protectedRoomId of Object.keys(mjolnir.protectedRooms)) {
const members = await mjolnir.client.getRoomMembers(protectedRoomId, null, ['ban'], null);
for (const member of members) {
const victim = member['state_key'];
if (!member['content'] || member['content']['membership'] !== 'ban') continue;
if (rule.test(victim)) {
await logMessage(LogLevel.DEBUG, "UnbanBanCommand", `Unbanning ${victim} in ${protectedRoomId}`);
if (!config.noop) {
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;
}
}
}
if (unbannedSomeone) {
await logMessage(LogLevel.DEBUG, "UnbanBanCommand", `Syncing lists to ensure no users were accidentally unbanned`);
await mjolnir.syncLists(config.verboseLogging);
}
});
}
for (const member of members) {
if (member.membership === 'ban') {
continue; // user already banned
}
let banned = false;
for (const list of lists) {
for (const userRule of list.userRules) {
if (userRule.isMatch(member.userId)) {
// User needs to be banned
// We specifically use sendNotice to avoid having to escape HTML
await logMessage(LogLevel.DEBUG, "ApplyBan", `Banning ${member.userId} in ${roomId} for: ${userRule.reason}`);
if (!config.noop) {
// Always prioritize redactions above bans
if (mjolnir.automaticRedactGlobs.find(g => g.test(userRule.reason.toLowerCase()))) {
await redactUserMessagesIn(mjolnir.client, member.userId, [roomId]);
}
await mjolnir.client.banUser(member.userId, roomId, userRule.reason);
} else {
await logMessage(LogLevel.WARN, "ApplyBan", `Tried to ban ${member.userId} in ${roomId} but Mjolnir is running in no-op mode`);
}
bansApplied++;
banned = true;
break;
}
export async function applyUserBans(lists: BanList[], roomIds: string[], mjolnir: Mjolnir): Promise {
// We can only ban people who are not already banned, and who match the rules.
const errors: RoomUpdateError[] = [];
let bansApplied = 0;
for (const roomId of roomIds) {
try {
// We specifically use sendNotice to avoid having to escape HTML
await logMessage(LogLevel.DEBUG, "ApplyBan", `Updating member bans in ${roomId}`);
let members: { userId: string, membership: string }[];
if (config.fasterMembershipChecks) {
const memberIds = await mjolnir.client.getJoinedRoomMembers(roomId);
members = memberIds.map(u => {
return {userId: u, membership: "join"};
});
} else {
const state = await mjolnir.client.getRoomState(roomId);
members = state.filter(s => s['type'] === 'm.room.member' && !!s['state_key']).map(s => {
return {userId: s['state_key'], membership: s['content'] ? s['content']['membership'] : 'leave'};
});
}
for (const member of members) {
export async function redactUserMessagesIn(client: MatrixClient, userIdOrGlob: string, targetRoomIds: string[]) {
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);
for (const victimEvent of eventsToRedact) {
await logMessage(LogLevel.DEBUG, "utils#redactUserMessagesIn", `Redacting ${victimEvent['event_id']} in ${targetRoomId}`);
if (!config.noop) {
await client.redactEvent(targetRoomId, victimEvent['event_id']);
} else {
await logMessage(LogLevel.WARN, "utils#redactUserMessagesIn", `Tried to redact ${victimEvent['event_id']} in ${targetRoomId} but Mjolnir is running in no-op mode`);
}
}
}
}
export async function redactUserMessagesIn(client: MatrixClient, userIdOrGlob: string, targetRoomIds: string[]) {
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);
for (const victimEvent of eventsToRedact) {
await logMessage(LogLevel.DEBUG, "utils#redactUserMessagesIn", `Redacting ${victimEvent['event_id']} in ${targetRoomId}`);
if (!config.noop) {
await client.redactEvent(targetRoomId, victimEvent['event_id']);
} else {
await logMessage(LogLevel.WARN, "utils#redactUserMessagesIn", `Tried to redact ${victimEvent['event_id']} in ${targetRoomId} but Mjolnir is running in no-op mode`);
}
}
}
}