From ac240c6166b3f23693ca7efc886457e5e6e4419d Mon Sep 17 00:00:00 2001 From: justADeni Date: Mon, 14 Jul 2025 00:37:01 +0200 Subject: [PATCH 1/3] feat: Added a config option to automatically convert message to lowercase, if there are too many capital letters --- .../configuration/PluginConfiguration.java | 6 +++ .../plugin/core/capitals/CapitalsService.java | 48 +++++++++++++++++++ .../playerchat/PlayerChatFormatRenderer.java | 5 +- 3 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 src/main/java/de/rexlmanu/fairychat/plugin/core/capitals/CapitalsService.java diff --git a/src/main/java/de/rexlmanu/fairychat/plugin/configuration/PluginConfiguration.java b/src/main/java/de/rexlmanu/fairychat/plugin/configuration/PluginConfiguration.java index cef2df8..c666758 100644 --- a/src/main/java/de/rexlmanu/fairychat/plugin/configuration/PluginConfiguration.java +++ b/src/main/java/de/rexlmanu/fairychat/plugin/configuration/PluginConfiguration.java @@ -109,6 +109,12 @@ public class PluginConfiguration { @Comment("How similar the messages have to be to be considered a duplicate.") private double similarityPercentage = 0.75; + @Comment("Prevent excessive capital letters being used.") + private boolean preventExcessiveCapitals = false; + + @Comment("How much of the message has to be in capital letters to be considered excessive.") + private double capitalPercentage = 0.75; + @Comment({ "The similarity algorithm that should be used.", "Supported algorithms:", diff --git a/src/main/java/de/rexlmanu/fairychat/plugin/core/capitals/CapitalsService.java b/src/main/java/de/rexlmanu/fairychat/plugin/core/capitals/CapitalsService.java new file mode 100644 index 0000000..c869737 --- /dev/null +++ b/src/main/java/de/rexlmanu/fairychat/plugin/core/capitals/CapitalsService.java @@ -0,0 +1,48 @@ +package de.rexlmanu.fairychat.plugin.core.capitals; + +import com.google.inject.Inject; +import com.google.inject.Provider; +import com.google.inject.Singleton; +import de.rexlmanu.fairychat.plugin.configuration.PluginConfiguration; +import lombok.RequiredArgsConstructor; +import net.kyori.adventure.platform.bukkit.BukkitAudiences; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.minimessage.MiniMessage; + +@Singleton +@RequiredArgsConstructor(onConstructor = @__(@Inject)) +public class CapitalsService { + private final Provider configurationProvider; + private final MiniMessage miniMessage; + private final BukkitAudiences bukkitAudiences; + + public Component checkCapitals(Component message) { + + if (!this.configurationProvider.get().preventExcessiveCapitals()) { + return message; + } + + String miniTextMessage = this.miniMessage.serialize(message); + int count = 0, len = miniTextMessage.length(); + for (int i = 0; i < len; i++) { + char c = miniTextMessage.charAt(i); + if (c >= 'A' && c <= 'Z') count++; + } + double percentageCapitals = len == 0 ? 0.0 : (double) count / len; + + if (percentageCapitals < this.configurationProvider.get().capitalPercentage()) { + return message; + } + + StringBuilder sb = new StringBuilder(len); + for (int i = 0; i < len; i++) { + char c = miniTextMessage.charAt(i); + if (c >= 'A' && c <= 'Z') { + sb.append((char)(c + 32)); + } else { + sb.append(c); + } + } + return this.miniMessage.deserialize(sb.toString()); + } +} diff --git a/src/main/java/de/rexlmanu/fairychat/plugin/core/playerchat/PlayerChatFormatRenderer.java b/src/main/java/de/rexlmanu/fairychat/plugin/core/playerchat/PlayerChatFormatRenderer.java index faac012..869fb31 100644 --- a/src/main/java/de/rexlmanu/fairychat/plugin/core/playerchat/PlayerChatFormatRenderer.java +++ b/src/main/java/de/rexlmanu/fairychat/plugin/core/playerchat/PlayerChatFormatRenderer.java @@ -5,6 +5,7 @@ import com.google.inject.Singleton; import com.google.inject.name.Named; import de.rexlmanu.fairychat.plugin.configuration.PluginConfiguration; +import de.rexlmanu.fairychat.plugin.core.capitals.CapitalsService; import de.rexlmanu.fairychat.plugin.core.ignore.UserIgnoreService; import de.rexlmanu.fairychat.plugin.core.mentions.MentionService; import de.rexlmanu.fairychat.plugin.integration.IntegrationRegistry; @@ -33,6 +34,7 @@ public class PlayerChatFormatRenderer implements DefaultChatRenderer { private final MiniMessage miniMessage; private final PermissionProvider permissionProvider; private final MentionService mentionService; + private final CapitalsService capitalsService; private final IntegrationRegistry registry; private final UserIgnoreService userIgnoreService; @@ -53,7 +55,8 @@ public class PlayerChatFormatRenderer implements DefaultChatRenderer { if (this.userIgnoreService.isIgnored(player.getUniqueId(), source.getUniqueId())) { return formattedMessage; } - return this.mentionService.checkMentions(player, formattedMessage); + return this.mentionService.checkMentions(player, + this.capitalsService.checkCapitals(formattedMessage)); } @NotNull From b1ab7a769ee8a8e9afc271dea60aac9b85d123d0 Mon Sep 17 00:00:00 2001 From: justADeni Date: Mon, 14 Jul 2025 01:13:21 +0200 Subject: [PATCH 2/3] fix: removed unused imports, moved capital detection before minimessage formatting --- .../plugin/core/capitals/CapitalsService.java | 17 ++++++++--------- .../playerchat/PlayerChatFormatRenderer.java | 7 ++++--- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main/java/de/rexlmanu/fairychat/plugin/core/capitals/CapitalsService.java b/src/main/java/de/rexlmanu/fairychat/plugin/core/capitals/CapitalsService.java index c869737..1668ed6 100644 --- a/src/main/java/de/rexlmanu/fairychat/plugin/core/capitals/CapitalsService.java +++ b/src/main/java/de/rexlmanu/fairychat/plugin/core/capitals/CapitalsService.java @@ -5,7 +5,6 @@ import com.google.inject.Singleton; import de.rexlmanu.fairychat.plugin.configuration.PluginConfiguration; import lombok.RequiredArgsConstructor; -import net.kyori.adventure.platform.bukkit.BukkitAudiences; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.minimessage.MiniMessage; @@ -14,28 +13,27 @@ public class CapitalsService { private final Provider configurationProvider; private final MiniMessage miniMessage; - private final BukkitAudiences bukkitAudiences; public Component checkCapitals(Component message) { if (!this.configurationProvider.get().preventExcessiveCapitals()) { return message; } - String miniTextMessage = this.miniMessage.serialize(message); - int count = 0, len = miniTextMessage.length(); - for (int i = 0; i < len; i++) { + int count = 0; + for (int i = 0; i < miniTextMessage.length(); i++) { char c = miniTextMessage.charAt(i); - if (c >= 'A' && c <= 'Z') count++; + if (c >= 'A' && c <= 'Z') + count++; } - double percentageCapitals = len == 0 ? 0.0 : (double) count / len; + double percentageCapitals = (double) count / miniTextMessage.length(); if (percentageCapitals < this.configurationProvider.get().capitalPercentage()) { return message; } - StringBuilder sb = new StringBuilder(len); - for (int i = 0; i < len; i++) { + StringBuilder sb = new StringBuilder(miniTextMessage.length()); + for (int i = 0; i < miniTextMessage.length(); i++) { char c = miniTextMessage.charAt(i); if (c >= 'A' && c <= 'Z') { sb.append((char)(c + 32)); @@ -43,6 +41,7 @@ public Component checkCapitals(Component message) { sb.append(c); } } + return this.miniMessage.deserialize(sb.toString()); } } diff --git a/src/main/java/de/rexlmanu/fairychat/plugin/core/playerchat/PlayerChatFormatRenderer.java b/src/main/java/de/rexlmanu/fairychat/plugin/core/playerchat/PlayerChatFormatRenderer.java index 869fb31..6dee95f 100644 --- a/src/main/java/de/rexlmanu/fairychat/plugin/core/playerchat/PlayerChatFormatRenderer.java +++ b/src/main/java/de/rexlmanu/fairychat/plugin/core/playerchat/PlayerChatFormatRenderer.java @@ -55,8 +55,7 @@ public class PlayerChatFormatRenderer implements DefaultChatRenderer { if (this.userIgnoreService.isIgnored(player.getUniqueId(), source.getUniqueId())) { return formattedMessage; } - return this.mentionService.checkMentions(player, - this.capitalsService.checkCapitals(formattedMessage)); + return this.mentionService.checkMentions(player, formattedMessage); } @NotNull @@ -72,7 +71,9 @@ public Component formatMessage(@NotNull Player source, @NotNull Component messag if (this.configurationProvider.get().legacyColorSupport()) { serializer = LegacyComponentSerializer.legacyAmpersand()::serialize; } - final String textMessage = this.resolveMessageModifiers(source, serializer.apply(message)); + final String textMessage = this.resolveMessageModifiers(source, serializer.apply( + this.capitalsService.checkCapitals(message)) + ); // Check if the player has the permission to use mini message if (source.hasPermission("fairychat.feature.minimessage")) { From 225c0a239838d812baa6f19bed31f43fa1d0980f Mon Sep 17 00:00:00 2001 From: justADeni Date: Mon, 14 Jul 2025 01:21:15 +0200 Subject: [PATCH 3/3] feat: added a bypass permission --- README.md | 1 + .../plugin/core/playerchat/PlayerChatFormatRenderer.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 856f60e..3e8600d 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,7 @@ You can find the documentation for FairyChat [here](https://github.com/rexlManu/ | `/fairychat` | | Show information about FairyChat | | `/fairychat reload` | `fairychat.command.fairychat.reload` | Reload the configuration | | | `fairychat.bypass.similarity` | Bypass the similarity check for last message | +| | `fairychat.bypass.capitals` | Bypass the capital letters check | | | `fairychat.bypass.cooldown` | Bypass the chat cooldown | | | `fairychat.feature.displayitem` | Allow players to show the item in and with | | | `fairychat.messages.join.ignore` | The join message will not be sent | diff --git a/src/main/java/de/rexlmanu/fairychat/plugin/core/playerchat/PlayerChatFormatRenderer.java b/src/main/java/de/rexlmanu/fairychat/plugin/core/playerchat/PlayerChatFormatRenderer.java index 6dee95f..c942ccc 100644 --- a/src/main/java/de/rexlmanu/fairychat/plugin/core/playerchat/PlayerChatFormatRenderer.java +++ b/src/main/java/de/rexlmanu/fairychat/plugin/core/playerchat/PlayerChatFormatRenderer.java @@ -72,7 +72,7 @@ public Component formatMessage(@NotNull Player source, @NotNull Component messag serializer = LegacyComponentSerializer.legacyAmpersand()::serialize; } final String textMessage = this.resolveMessageModifiers(source, serializer.apply( - this.capitalsService.checkCapitals(message)) + source.hasPermission("fairychat.bypass.capitals") ? message : this.capitalsService.checkCapitals(message)) ); // Check if the player has the permission to use mini message