From 7c32bbfd2d725e7d87f1b52eec9fbd30ccc728c1 Mon Sep 17 00:00:00 2001 From: duckietm Date: Wed, 3 Jun 2026 10:39:44 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=86=99=20=20wordfilter=20to=20set=20speci?= =?UTF-8?q?fic=20settings=20to=20prefix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ntions.sql => 009_mentions_wordfilter.sql} | 5 ++++ .../commands/FilterWordCommand.java | 29 ++++++++++++++----- .../habbo/habbohotel/modtool/WordFilter.java | 15 ++++++---- .../habbohotel/modtool/WordFilterWord.java | 15 ++++++++++ 4 files changed, 52 insertions(+), 12 deletions(-) rename Database Updates/{009_mentions.sql => 009_mentions_wordfilter.sql} (82%) diff --git a/Database Updates/009_mentions.sql b/Database Updates/009_mentions_wordfilter.sql similarity index 82% rename from Database Updates/009_mentions.sql rename to Database Updates/009_mentions_wordfilter.sql index d9b72c56..e7bad426 100644 --- a/Database Updates/009_mentions.sql +++ b/Database Updates/009_mentions_wordfilter.sql @@ -19,3 +19,8 @@ INSERT IGNORE INTO `emulator_settings` (`key`, `value`) VALUES ('mentions.max.targets', '50'), ('mentions.cooldown.ms', '3000'), ('mentions.store.limit', '50'); + + +ALTER TABLE `wordfilter` +ADD COLUMN `prefix_only` ENUM('0','1') NOT NULL DEFAULT '0' +COMMENT 'When 1, this word only applies to custom prefixes, not to chat/motto/guild.' AFTER `mute`; \ No newline at end of file diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/commands/FilterWordCommand.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/commands/FilterWordCommand.java index 9e208a0a..9363589a 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/commands/FilterWordCommand.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/commands/FilterWordCommand.java @@ -4,6 +4,7 @@ import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.gameclients.GameClient; import com.eu.habbo.habbohotel.modtool.WordFilter; import com.eu.habbo.habbohotel.modtool.WordFilterWord; +import com.eu.habbo.habbohotel.rooms.RoomChatMessageBubbles; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -21,30 +22,44 @@ public class FilterWordCommand extends Command { @Override public boolean handle(GameClient gameClient, String[] params) throws Exception { if (params.length < 2) { - gameClient.getHabbo().whisper(Emulator.getTexts().getValue("commands.error.cmd_filterword.missing_word")); + gameClient.getHabbo().whisper(Emulator.getTexts().getValue("commands.error.cmd_filterword.missing_word"), RoomChatMessageBubbles.ALERT); return true; } String word = params[1]; + // Optional trailing "prefix" keyword marks the word as prefix-only (blocks + // custom prefixes but not chat/motto/guild). Usage: + // :filterword -> everywhere, default replacement + // :filterword -> everywhere + // :filterword prefix -> prefix-only, default replacement + // :filterword prefix -> prefix-only + boolean prefixOnly = false; String replacement = WordFilter.DEFAULT_REPLACEMENT; - if (params.length == 3) { - replacement = params[2]; + + if (params.length >= 3) { + if (params[params.length - 1].equalsIgnoreCase("prefix")) { + prefixOnly = true; + if (params.length >= 4) replacement = params[2]; + } else { + replacement = params[2]; + } } - WordFilterWord wordFilterWord = new WordFilterWord(word, replacement); + WordFilterWord wordFilterWord = new WordFilterWord(word, replacement, prefixOnly); - try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("INSERT INTO wordfilter (`key`, `replacement`) VALUES (?, ?)")) { + try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("INSERT INTO wordfilter (`key`, `replacement`, `prefix_only`) VALUES (?, ?, ?)")) { statement.setString(1, word); statement.setString(2, replacement); + statement.setString(3, prefixOnly ? "1" : "0"); statement.execute(); } catch (SQLException e) { LOGGER.error("Caught SQL exception", e); - gameClient.getHabbo().whisper(Emulator.getTexts().getValue("commands.error.cmd_filterword.error")); + gameClient.getHabbo().whisper(Emulator.getTexts().getValue("commands.error.cmd_filterword.error"), RoomChatMessageBubbles.ALERT); return true; } - gameClient.getHabbo().whisper(Emulator.getTexts().getValue("commands.succes.cmd_filterword.added").replace("%word%", word).replace("%replacement%", replacement)); + gameClient.getHabbo().whisper(Emulator.getTexts().getValue("commands.succes.cmd_filterword.added").replace("%word%", word).replace("%replacement%", replacement) + (prefixOnly ? " [prefix-only]" : ""), RoomChatMessageBubbles.ALERT); Emulator.getGameEnvironment().getWordFilter().addWord(wordFilterWord); return true; diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/modtool/WordFilter.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/modtool/WordFilter.java index 521a4551..ee8f3eab 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/modtool/WordFilter.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/modtool/WordFilter.java @@ -23,7 +23,6 @@ public class WordFilter { private static final Logger LOGGER = LoggerFactory.getLogger(WordFilter.class); private static final Pattern DIACRITICS_AND_FRIENDS = Pattern.compile("[\\p{InCombiningDiacriticalMarks}\\p{IsLm}\\p{IsSk}]+"); - //Configuration. Loaded from database & updated accordingly. public static boolean ENABLED_FRIENDCHAT = true; public static String DEFAULT_REPLACEMENT = "bobba"; protected THashSet autoReportWords = new THashSet<>(); @@ -63,10 +62,12 @@ public class WordFilter { continue; } - if (word.autoReport) - this.autoReportWords.add(word); - else if (word.hideMessage) - this.hideMessageWords.add(word); + if (!word.prefixOnly) { + if (word.autoReport) + this.autoReportWords.add(word); + else if (word.hideMessage) + this.hideMessageWords.add(word); + } this.words.add(word); } @@ -146,6 +147,8 @@ public class WordFilter { while (iterator.hasNext()) { WordFilterWord word = (WordFilterWord) iterator.next(); + if (word.prefixOnly) continue; + if (StringUtils.containsIgnoreCase(filteredMessage, word.key)) { if (habbo != null) { if (Emulator.getPluginManager().fireEvent(new UserTriggerWordFilterEvent(habbo, word)).isCancelled()) @@ -179,6 +182,8 @@ public class WordFilter { while (iterator.hasNext()) { WordFilterWord word = (WordFilterWord) iterator.next(); + if (word.prefixOnly) continue; + if (StringUtils.containsIgnoreCase(message, word.key)) { if (habbo != null) { if (Emulator.getPluginManager().fireEvent(new UserTriggerWordFilterEvent(habbo, word)).isCancelled()) diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/modtool/WordFilterWord.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/modtool/WordFilterWord.java index 0f8420a3..98ee8e98 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/modtool/WordFilterWord.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/modtool/WordFilterWord.java @@ -9,6 +9,7 @@ public class WordFilterWord { public final boolean hideMessage; public final boolean autoReport; public final int muteTime; + public final boolean prefixOnly; public WordFilterWord(ResultSet set) throws SQLException { this.key = set.getString("key"); @@ -16,13 +17,27 @@ public class WordFilterWord { this.hideMessage = set.getInt("hide") == 1; this.autoReport = set.getInt("report") == 1; this.muteTime = set.getInt("mute"); + this.prefixOnly = readBooleanColumn(set, "prefix_only"); } public WordFilterWord(String key, String replacement) { + this(key, replacement, false); + } + + public WordFilterWord(String key, String replacement, boolean prefixOnly) { this.key = key; this.replacement = replacement; this.hideMessage = false; this.autoReport = false; this.muteTime = 0; + this.prefixOnly = prefixOnly; + } + + private static boolean readBooleanColumn(ResultSet set, String column) { + try { + return set.getInt(column) == 1; + } catch (SQLException e) { + return false; + } } }