diff --git a/src/main/java/com/loki/lochat/managers/ChatColorManager.java b/src/main/java/com/loki/lochat/managers/ChatColorManager.java index 8891bb2..f2120a5 100644 --- a/src/main/java/com/loki/lochat/managers/ChatColorManager.java +++ b/src/main/java/com/loki/lochat/managers/ChatColorManager.java @@ -1,6 +1,7 @@ package com.loki.lochat.managers; import com.loki.lochat.LoChat; +import com.loki.lochat.gradient.util.FoliaUtil; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; @@ -61,9 +62,16 @@ public class ChatColorManager { } } + /** + * Асинхронное сохранение данных (для Folia совместимости) + */ + private void saveDataAsync() { + FoliaUtil.runAsync(plugin, this::saveData); + } + public void setChatColor(UUID playerId, String color) { chatColors.put(playerId, color); - saveData(); + saveDataAsync(); } public String getChatColor(UUID playerId) { @@ -77,7 +85,7 @@ public class ChatColorManager { public void removeChatColor(UUID playerId) { chatColors.remove(playerId); dataConfig.set(playerId.toString(), null); - saveData(); + saveDataAsync(); } /** diff --git a/src/main/java/com/loki/lochat/managers/FilterManager.java b/src/main/java/com/loki/lochat/managers/FilterManager.java index c0c9eec..9ee1db6 100644 --- a/src/main/java/com/loki/lochat/managers/FilterManager.java +++ b/src/main/java/com/loki/lochat/managers/FilterManager.java @@ -20,18 +20,49 @@ public class FilterManager { WARNED } + /** + * Проверяет сообщение на наличие запрещенных слов + */ public FilterResult checkMessage(String message) { if (!plugin.getConfigManager().isFilterEnabled()) { return FilterResult.ALLOWED; } + if (message == null || message.trim().isEmpty()) { + return FilterResult.ALLOWED; + } + List badWords = plugin.getConfigManager().getFilterWords(); - String lowerMessage = message.toLowerCase(); + if (badWords == null || badWords.isEmpty()) { + return FilterResult.ALLOWED; + } + + // Нормализуем сообщение (убираем обход фильтра) + String normalizedMessage = normalizeMessage(message); + String lowerMessage = normalizedMessage.toLowerCase(); for (String word : badWords) { - if (lowerMessage.contains(word.toLowerCase())) { + if (word == null || word.trim().isEmpty()) { + continue; + } + + String lowerWord = word.toLowerCase().trim(); + + // Проверяем точное совпадение слова (с границами слов) + Pattern wordPattern = Pattern.compile("\\b" + Pattern.quote(lowerWord) + "\\b", Pattern.CASE_INSENSITIVE); + if (wordPattern.matcher(normalizedMessage).find()) { String action = plugin.getConfigManager().getFilterAction(); - return switch (action) { + return switch (action.toLowerCase()) { + case "block" -> FilterResult.BLOCKED; + case "warn" -> FilterResult.WARNED; + default -> FilterResult.CENSORED; + }; + } + + // Также проверяем как подстроку (для частичных совпадений типа "пизд") + if (lowerMessage.contains(lowerWord)) { + String action = plugin.getConfigManager().getFilterAction(); + return switch (action.toLowerCase()) { case "block" -> FilterResult.BLOCKED; case "warn" -> FilterResult.WARNED; default -> FilterResult.CENSORED; @@ -42,20 +73,89 @@ public class FilterManager { return FilterResult.ALLOWED; } + /** + * Цензурирует сообщение, заменяя запрещенные слова + */ public String censorMessage(String message) { if (!plugin.getConfigManager().isFilterEnabled()) { return message; } + if (message == null || message.trim().isEmpty()) { + return message; + } + List badWords = plugin.getConfigManager().getFilterWords(); + if (badWords == null || badWords.isEmpty()) { + return message; + } + String replacement = plugin.getConfigManager().getFilterReplacement(); + if (replacement == null) { + replacement = "***"; + } + String result = message; + String normalizedMessage = normalizeMessage(message); for (String word : badWords) { - Pattern pattern = Pattern.compile("(?i)" + Pattern.quote(word)); - result = pattern.matcher(result).replaceAll(replacement); + if (word == null || word.trim().isEmpty()) { + continue; + } + + String lowerWord = word.toLowerCase().trim(); + + // Заменяем точные совпадения слов + Pattern wordPattern = Pattern.compile("\\b" + Pattern.quote(word) + "\\b", Pattern.CASE_INSENSITIVE); + result = wordPattern.matcher(result).replaceAll(replacement); + + // Также заменяем как подстроку (для частичных совпадений) + Pattern substringPattern = Pattern.compile("(?i)" + Pattern.quote(word)); + result = substringPattern.matcher(result).replaceAll(replacement); } return result; } + + /** + * Нормализует сообщение, убирая попытки обхода фильтра + * Заменяет специальные символы на обычные буквы + */ + private String normalizeMessage(String message) { + if (message == null) { + return ""; + } + + // Заменяем символы обхода на буквы (для обнаружения х*й, х_уй и т.д.) + String normalized = message; + + // Заменяем символы обхода на буквы + normalized = normalized.replace('*', 'а'); + normalized = normalized.replace('_', 'а'); + normalized = normalized.replace('-', 'а'); + normalized = normalized.replace('.', 'а'); + normalized = normalized.replace(',', 'а'); + normalized = normalized.replace('|', 'и'); + normalized = normalized.replace('1', 'и'); + normalized = normalized.replace('!', 'и'); + normalized = normalized.replace('0', 'о'); + normalized = normalized.replace('3', 'з'); + normalized = normalized.replace('4', 'ч'); + normalized = normalized.replace('5', 'с'); + normalized = normalized.replace('6', 'б'); + normalized = normalized.replace('7', 'т'); + normalized = normalized.replace('8', 'в'); + normalized = normalized.replace('9', 'д'); + normalized = normalized.replace('@', 'а'); + normalized = normalized.replace('#', 'х'); + normalized = normalized.replace('$', 'с'); + normalized = normalized.replace('%', 'о'); + normalized = normalized.replace('^', 'х'); + normalized = normalized.replace('&', 'а'); + + // Убираем множественные пробелы + normalized = normalized.replaceAll("\\s+", " "); + + return normalized; + } } diff --git a/src/main/java/com/loki/lochat/managers/IgnoreManager.java b/src/main/java/com/loki/lochat/managers/IgnoreManager.java index 1ab0262..90d2ab8 100644 --- a/src/main/java/com/loki/lochat/managers/IgnoreManager.java +++ b/src/main/java/com/loki/lochat/managers/IgnoreManager.java @@ -1,6 +1,7 @@ package com.loki.lochat.managers; import com.loki.lochat.LoChat; +import com.loki.lochat.gradient.util.FoliaUtil; import org.bukkit.configuration.file.YamlConfiguration; import java.io.File; @@ -69,7 +70,7 @@ public class IgnoreManager { public boolean addIgnore(UUID player, UUID target) { Set ignored = ignoreMap.computeIfAbsent(player, k -> ConcurrentHashMap.newKeySet()); boolean added = ignored.add(target); - if (added) save(); + if (added) saveAsync(); return added; } @@ -77,7 +78,7 @@ public class IgnoreManager { Set ignored = ignoreMap.get(player); if (ignored == null) return false; boolean removed = ignored.remove(target); - if (removed) save(); + if (removed) saveAsync(); return removed; } @@ -92,6 +93,13 @@ public class IgnoreManager { public void clearIgnores(UUID player) { ignoreMap.remove(player); - save(); + saveAsync(); + } + + /** + * Асинхронное сохранение данных (для Folia совместимости) + */ + private void saveAsync() { + FoliaUtil.runAsync(plugin, this::save); } }