From 9a821ba216f57060ed6364678a7b0047dd1352e0 Mon Sep 17 00:00:00 2001 From: Nicholas Stonecipher Date: Wed, 11 Oct 2023 20:19:16 -0400 Subject: [PATCH] Add bot AutoMod --- src/main/kotlin/org/openredstone/chad/Chad.kt | 4 ++ .../kotlin/org/openredstone/chad/Config.kt | 3 ++ .../org/openredstone/chad/DiscordListener.kt | 51 +++++++++++++++++++ .../org/openredstone/chad/commands/Command.kt | 2 +- 4 files changed, 59 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/org/openredstone/chad/Chad.kt b/src/main/kotlin/org/openredstone/chad/Chad.kt index 2bcc585..d2021a8 100644 --- a/src/main/kotlin/org/openredstone/chad/Chad.kt +++ b/src/main/kotlin/org/openredstone/chad/Chad.kt @@ -142,9 +142,13 @@ fun main(args: Array) = runBlocking { logger.info("Starting listeners...") startDiscordListeners( + logger, discordApi, CommandExecutor(chadConfig.commandChar, commands), chadConfig.disableSpoilers, + chadConfig.botAutomod.enableBotAutomod, + chadConfig.botAutomod.automodChannelId, + chadConfig.botAutomod.regexes, chadConfig.welcomeChannelId, chadConfig.greetings, chadConfig.ingameBotRoleId, diff --git a/src/main/kotlin/org/openredstone/chad/Config.kt b/src/main/kotlin/org/openredstone/chad/Config.kt index 190d66a..95d87ac 100644 --- a/src/main/kotlin/org/openredstone/chad/Config.kt +++ b/src/main/kotlin/org/openredstone/chad/Config.kt @@ -21,6 +21,7 @@ data class ChadConfig( val fractalDeets: FractalConfig, val authorizedDiscordRoles: List, val logging: LoggingConfig, + val botAutomod: AutomodConfig, val greetings: List, val insults: List, ) @@ -29,6 +30,8 @@ object ChadSpec : ConfigSpec("") { val chad by required() } +data class AutomodConfig(val enableBotAutomod: Boolean, val automodChannelId: Long, val regexes: List) + data class FractalConfig(val size: Int, val maxIterations: Int, val messiness: Int, val zoom: Double) data class NotificationRoleConfig(val name: String, val role: String, val description: String) diff --git a/src/main/kotlin/org/openredstone/chad/DiscordListener.kt b/src/main/kotlin/org/openredstone/chad/DiscordListener.kt index 9158caa..e532295 100644 --- a/src/main/kotlin/org/openredstone/chad/DiscordListener.kt +++ b/src/main/kotlin/org/openredstone/chad/DiscordListener.kt @@ -4,9 +4,11 @@ import khttp.post import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.future.await import kotlinx.coroutines.launch +import mu.KLogger import mu.KotlinLogging import org.javacord.api.DiscordApi import org.javacord.api.entity.message.Message +import org.javacord.api.entity.message.embed.EmbedBuilder import org.javacord.api.entity.permission.Role import org.javacord.api.event.message.MessageCreateEvent import org.openredstone.chad.commands.CommandExecutor @@ -15,10 +17,20 @@ import org.openredstone.chad.commands.Sender val spoilerLogger = KotlinLogging.logger("Spoiler listener") +internal fun Message.getUrl(): String { + val server = this.server.toNullable()?.id ?: throw Exception("Oof") + val channel = this.channel.id + return "https://discord.com/channels/${server}/${channel}/${this.id}" +} + fun startDiscordListeners( + logger: KLogger, discordApi: DiscordApi, executor: CommandExecutor, disableSpoilers: Boolean, + botAutomod: Boolean, + automodChannelId: Long, + automodRegexes: List, welcomeChannel: Long, greetings: List, ingameBotRole: String, @@ -30,6 +42,9 @@ fun startDiscordListeners( if (disableSpoilers) { startSpoilerListener(discordApi, coroutineScope) } + if (botAutomod) { + startBotAutomod(logger, discordApi, automodChannelId, automodRegexes) + } if (greetings.isNotEmpty()) { startJoinListener(discordApi, welcomeChannel, greetings, coroutineScope) } @@ -45,6 +60,42 @@ private fun startJoinListener(discordApi: DiscordApi, welcomeChannel: Long, gree } } +private fun startBotAutomod( + logger: KLogger, + discordApi: DiscordApi, + automodChannelId: Long, + automodRegexes: List +) { + val automodChannel = + discordApi.getChannelById(automodChannelId).toNullable()?.asServerTextChannel()?.toNullable() ?: run { + logger.error { "Could not locate AutoMod channel" } + return + } + val compiledRegexes = automodRegexes.map { Regex(it, RegexOption.IGNORE_CASE) } + fun onBotMessage(event: MessageCreateEvent) { + val user = event.messageAuthor.asUser().toNullable() ?: return + if (discordApi.clientId == user.id || !user.isBot) { + return + } + val body = event.message.content + val matches = compiledRegexes.filter { it.containsMatchIn(body) } + if (matches.isNotEmpty()) { + val messageUrl = event.message.getUrl() + logger.warn("Flagged message for bot AutoMod! (Matches ${matches}) $messageUrl") + val embed = EmbedBuilder().setDescription(body) + matches.forEach { embed.addField("Matches", it.pattern) } + automodChannel.sendMessage("Flagged a message $messageUrl", embed) + } + } + discordApi.addMessageCreateListener { event -> + try { + onBotMessage(event) + } catch (e: Exception) { + logger.error(e) { "onBotMessage error" } + } + } +} + private fun startDiscordCommandListener( discordApi: DiscordApi, executor: CommandExecutor, diff --git a/src/main/kotlin/org/openredstone/chad/commands/Command.kt b/src/main/kotlin/org/openredstone/chad/commands/Command.kt index d9b82f4..ee00c8e 100644 --- a/src/main/kotlin/org/openredstone/chad/commands/Command.kt +++ b/src/main/kotlin/org/openredstone/chad/commands/Command.kt @@ -101,7 +101,7 @@ class CommandExecutor(private val commandChar: Char, private val commands: Comma if (commandResponse != null) { sql.insertHistory( name, - args.joinToString(", "), + args, commandResponse.reply, service, senderToInsert