diff --git a/README.md b/README.md index 70816820..4e16b665 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Phase 2: * [x] More useful spam in management room * [x] Command to import ACLs, etc from rooms * [x] Vet rooms on startup option -* [ ] Command to actually unban users (instead of leaving them stuck) +* [x] Command to actually unban users (instead of leaving them stuck) * [x] Support multiple lists Phase 3: diff --git a/package.json b/package.json index fbb65535..f87c86a6 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,6 @@ "config": "^3.2.2", "escape-html": "^1.0.3", "js-yaml": "^3.13.1", - "matrix-bot-sdk": "^0.4.0-beta.7" + "matrix-bot-sdk": "^0.4.0-beta.8" } } diff --git a/src/commands/CommandHandler.ts b/src/commands/CommandHandler.ts index 50ad50d5..45976d6b 100644 --- a/src/commands/CommandHandler.ts +++ b/src/commands/CommandHandler.ts @@ -62,7 +62,7 @@ export async function handleCommand(roomId: string, event: any, mjolnir: Mjolnir "!mjolnir - Print status information\n" + "!mjolnir status - Print status information\n" + "!mjolnir ban [reason] - Adds an entity to the ban list\n" + - "!mjolnir unban - Removes an entity from the ban list\n" + + "!mjolnir unban [apply] - Removes an entity from the ban list. If apply is 'true', the users matching the glob will actually be unbanned\n" + "!mjolnir redact [room alias/ID] - Redacts messages by the sender in the target room (or all rooms)\n" + "!mjolnir rules - Lists the rules currently in use by Mjolnir\n" + "!mjolnir sync - Force updates of all lists and re-apply rules\n" + diff --git a/src/commands/UnbanBanCommand.ts b/src/commands/UnbanBanCommand.ts index dcfe521a..ea0d69e4 100644 --- a/src/commands/UnbanBanCommand.ts +++ b/src/commands/UnbanBanCommand.ts @@ -15,9 +15,11 @@ limitations under the License. */ import { Mjolnir } from "../Mjolnir"; -import { RULE_ROOM, RULE_SERVER, RULE_USER, ruleTypeToStable } from "../models/BanList"; +import { RULE_ROOM, RULE_SERVER, RULE_USER, ruleTypeToStable, USER_RULE_TYPES } from "../models/BanList"; import { RichReply } from "matrix-bot-sdk"; import { RECOMMENDATION_BAN, recommendationToStable } from "../models/ListRule"; +import { MatrixGlob } from "matrix-bot-sdk/lib/MatrixGlob"; +import config from "../config"; function parseBits(parts: string[]): { listShortcode: string, entityType: string, ruleType: string, glob: string, reason: string } { const shortcode = parts[2].toLowerCase(); @@ -41,7 +43,7 @@ function parseBits(parts: string[]): { listShortcode: string, entityType: string return {listShortcode: shortcode, entityType, ruleType: rule, glob, reason}; } -// !mjolnir ban [reason] +// !mjolnir ban [reason] export async function execBanCommand(roomId: string, event: any, mjolnir: Mjolnir, parts: string[]) { const bits = parseBits(parts); if (!bits.ruleType) { @@ -71,7 +73,7 @@ export async function execBanCommand(roomId: string, event: any, mjolnir: Mjolni await mjolnir.client.unstableApis.addReactionToEvent(roomId, event['event_id'], '✅'); } -// !mjolnir unban +// !mjolnir unban [apply:t/f] export async function execUnbanCommand(roomId: string, event: any, mjolnir: Mjolnir, parts: string[]) { const bits = parseBits(parts); if (!bits.ruleType) { @@ -93,5 +95,35 @@ export async function execUnbanCommand(roomId: string, event: any, mjolnir: Mjol } await mjolnir.client.sendStateEvent(list.roomId, bits.ruleType, stateKey, ruleContent); + + if (USER_RULE_TYPES.includes(bits.ruleType) && parts.length > 5 && parts[5] === 'true') { + const rule = new MatrixGlob(bits.glob); + await mjolnir.client.sendNotice(mjolnir.managementRoomId, "Unbanning users that match glob: " + bits.glob); + let unbannedSomeone = false; + for (const protectedRoomId of Object.keys(mjolnir.protectedRooms)) { + const members = await mjolnir.client.getMembers(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)) { + if (config.verboseLogging) { + await mjolnir.client.sendNotice(mjolnir.managementRoomId, `Unbanning ${victim} in ${protectedRoomId}`); + } + if (!config.noop) { + await mjolnir.client.unbanUser(victim, protectedRoomId); + } + unbannedSomeone = true; + } + } + } + + if (unbannedSomeone) { + if (config.verboseLogging) { + await mjolnir.client.sendNotice(mjolnir.managementRoomId, `Syncing lists to ensure no users were accidentally unbanned`); + } + await mjolnir.syncLists(config.verboseLogging); + } + } + await mjolnir.client.unstableApis.addReactionToEvent(roomId, event['event_id'], '✅'); } diff --git a/yarn.lock b/yarn.lock index fb559936..dec850cc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -701,10 +701,10 @@ lru-cache@^5.1.1: dependencies: yallist "^3.0.2" -matrix-bot-sdk@^0.4.0-beta.7: - version "0.4.0-beta.7" - resolved "https://registry.yarnpkg.com/matrix-bot-sdk/-/matrix-bot-sdk-0.4.0-beta.7.tgz#fa2db6fafe5386d11cdf0fe54ab4b1c87db08764" - integrity sha512-pVU6vr4P8s/mYynM2harZ3swyX5XtzmG6RspIhfF+iMCOKNkOXIYSYYLZtifpkkFxWAToVyY7l1Gj8Wz+pHyew== +matrix-bot-sdk@^0.4.0-beta.8: + version "0.4.0-beta.8" + resolved "https://registry.yarnpkg.com/matrix-bot-sdk/-/matrix-bot-sdk-0.4.0-beta.8.tgz#625f192dac4e8dc96de8ce965671f819c633b177" + integrity sha512-dtUZ3rKApi9MVbg+RggBJi0xz2xK21tvzLceB0kmmVdZLdNqixYSvxoUuinaW66rTjlpxEQNdz+NWuVW4ImQnQ== dependencies: "@types/node" "^10.14.9" bluebird "^3.5.5"