From c1e27c0e0080e847f3b32ae9aa18aeb0a1631823 Mon Sep 17 00:00:00 2001 From: Jan Bayer Date: Tue, 5 Dec 2023 20:43:02 +0100 Subject: [PATCH] Implement embed URL blocking --- .../astralbot/config/AstralBotConfig.kt | 41 +++++++++++-- .../astralbot/handlers/MinecraftHandler.kt | 57 ++++++++++++++----- 2 files changed, 79 insertions(+), 19 deletions(-) diff --git a/common/src/main/kotlin/dev/erdragh/astralbot/config/AstralBotConfig.kt b/common/src/main/kotlin/dev/erdragh/astralbot/config/AstralBotConfig.kt index 075e392..74a9df3 100644 --- a/common/src/main/kotlin/dev/erdragh/astralbot/config/AstralBotConfig.kt +++ b/common/src/main/kotlin/dev/erdragh/astralbot/config/AstralBotConfig.kt @@ -1,6 +1,9 @@ package dev.erdragh.astralbot.config +import dev.erdragh.astralbot.LOGGER import net.minecraftforge.common.ForgeConfigSpec +import java.net.URL +import java.net.URLDecoder /** * Config for the AstralBot mod. This uses Forge's config system @@ -54,6 +57,8 @@ object AstralBotConfig { */ val CLICKABLE_EMBEDS: ForgeConfigSpec.BooleanValue + val URL_BLOCKLIST: ForgeConfigSpec.ConfigValue> + init { val builder = ForgeConfigSpec.Builder() @@ -68,12 +73,40 @@ object AstralBotConfig { DISCORD_GUILD = builder.comment("Guild (server) ID where the chat messages etc. are synced") .define("discordGuild", (-1).toLong()) - CLICKABLE_MESSAGES = builder.comment("Whether to make messages sent into the Minecraft chat open the Discord chat when clicked") - .define("clickableMessages", true) + CLICKABLE_MESSAGES = + builder.comment("Whether to make messages sent into the Minecraft chat open the Discord chat when clicked") + .define("clickableMessages", true) HANDLE_EMBEDS = builder.comment("Whether to display embeds and attached files on messages") .define("handleEmbeds", true) - CLICKABLE_EMBEDS = builder.comment("Whether to add click events opening URLs that may be associated with embeds") - .define("clickableEmbeds", true) + CLICKABLE_EMBEDS = + builder.comment("Whether to add click events opening URLs that may be associated with embeds") + .define("clickableEmbeds", true) + + URL_BLOCKLIST = builder.comment("URLs that don't get turned into clickable links") + .defineList( + "urlBlocklist", + ArrayList( + listOf( + "https://pornhub.com", + "https://xhamster.com", + "https://xvideos.com", + "https://rule34.xyz" + ) + ) + ) { + if (it !is String) { + LOGGER.warn("$it is URL blocklist is not a String") + return@defineList false + } + // TODO: Replace with better way to check for URL + try { + URL(it) + return@defineList true + } catch (e: Exception) { + LOGGER.warn("Failed to parse URL on blocklist: $it", e) + return@defineList false + } + } SPEC = builder.build() } diff --git a/common/src/main/kotlin/dev/erdragh/astralbot/handlers/MinecraftHandler.kt b/common/src/main/kotlin/dev/erdragh/astralbot/handlers/MinecraftHandler.kt index 8919389..2992efa 100644 --- a/common/src/main/kotlin/dev/erdragh/astralbot/handlers/MinecraftHandler.kt +++ b/common/src/main/kotlin/dev/erdragh/astralbot/handlers/MinecraftHandler.kt @@ -1,6 +1,7 @@ package dev.erdragh.astralbot.handlers import com.mojang.authlib.GameProfile +import dev.erdragh.astralbot.LOGGER import dev.erdragh.astralbot.config.AstralBotConfig import dev.erdragh.astralbot.guild import dev.erdragh.astralbot.textChannel @@ -107,34 +108,60 @@ class MinecraftHandler(private val server: MinecraftServer) : ListenerAdapter() } comp.append(actualMessage) if (AstralBotConfig.HANDLE_EMBEDS.get()) { - if (message.embeds.size > 0 && message.attachments.size > 0 && message.contentDisplay.isNotBlank()) comp.append("\n ") + if (message.embeds.size + message.attachments.size > 0 && message.contentDisplay.isNotBlank()) comp.append("\n ") var i = 0 message.embeds.forEach { if (i++ != 0) comp.append(", ") - val embedComponent = Component.literal(it.title ?: "embed${i}") - if (AstralBotConfig.CLICKABLE_EMBEDS.get()) { - embedComponent.withStyle { style -> - it.url?.let { url -> - style.withColor(ChatFormatting.BLUE).withUnderlined(true) - .withClickEvent(ClickEvent(ClickEvent.Action.OPEN_URL, url)) + if (urlAllowed(it.url)) { + val embedComponent = Component.literal(it.title ?: "embed${i}") + if (AstralBotConfig.CLICKABLE_EMBEDS.get()) { + embedComponent.withStyle { style -> + it.url?.let { url -> + style.withColor(ChatFormatting.BLUE).withUnderlined(true) + .withClickEvent(ClickEvent(ClickEvent.Action.OPEN_URL, url)) + } } } + comp.append(embedComponent) + } else { + comp.append(Component.literal("URL BLOCKED").withStyle(ChatFormatting.RED)) } - comp.append(embedComponent) } message.attachments.forEach { - if (i != 0) comp.append(", ") - val embedComponent = Component.literal(it.fileName) - if (AstralBotConfig.CLICKABLE_EMBEDS.get()) { - embedComponent.withStyle { style -> - style.withColor(ChatFormatting.BLUE).withUnderlined(true) - .withClickEvent(ClickEvent(ClickEvent.Action.OPEN_URL, it.url)) + if (i != 0) { + comp.append(", ") + } else { + i++ + } + if (urlAllowed(it.url)) { + val embedComponent = Component.literal(it.fileName) + if (AstralBotConfig.CLICKABLE_EMBEDS.get()) { + embedComponent.withStyle { style -> + style.withColor(ChatFormatting.BLUE).withUnderlined(true) + .withClickEvent(ClickEvent(ClickEvent.Action.OPEN_URL, it.url)) + } } + comp.append(embedComponent) + } else { + comp.append(Component.literal("URL BLOCKED").withStyle(ChatFormatting.RED)) } - comp.append(embedComponent) } } return comp } + + private fun urlAllowed(url: String?): Boolean { + if (url == null) return true + try { + val parsedURL = URL(url) + for (blockedURL in AstralBotConfig.URL_BLOCKLIST.get()) { + if (parsedURL.host.equals(URL(blockedURL).host)) return false + } + } catch (e: Exception) { + LOGGER.warn("URL $url", e) + return false + } + return true + } } \ No newline at end of file