Initial commit: LoChat v1.0.0 with Gradient module
This commit is contained in:
commit
252b0a60db
86 changed files with 8922 additions and 0 deletions
128
src/main/java/com/loki/lochat/managers/AntiSpamManager.java
Normal file
128
src/main/java/com/loki/lochat/managers/AntiSpamManager.java
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
package com.loki.lochat.managers;
|
||||
|
||||
import com.loki.lochat.LoChat;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class AntiSpamManager {
|
||||
|
||||
private final LoChat plugin;
|
||||
private final Map<UUID, String> lastMessages = new ConcurrentHashMap<>();
|
||||
private final Map<UUID, Long> lastMessageTime = new ConcurrentHashMap<>();
|
||||
|
||||
public AntiSpamManager(LoChat plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public enum SpamResult {
|
||||
ALLOWED,
|
||||
TOO_MANY_CAPS,
|
||||
REPEAT_CHARS,
|
||||
SIMILAR_MESSAGE
|
||||
}
|
||||
|
||||
public SpamResult checkMessage(UUID player, String message) {
|
||||
if (!plugin.getConfigManager().isAntiSpamEnabled()) {
|
||||
return SpamResult.ALLOWED;
|
||||
}
|
||||
|
||||
// Проверка CAPS
|
||||
if (hasTooManyCaps(message)) {
|
||||
return SpamResult.TOO_MANY_CAPS;
|
||||
}
|
||||
|
||||
// Проверка повторяющихся символов
|
||||
if (hasRepeatChars(message)) {
|
||||
return SpamResult.REPEAT_CHARS;
|
||||
}
|
||||
|
||||
// Проверка похожих сообщений
|
||||
if (isSimilarMessage(player, message)) {
|
||||
return SpamResult.SIMILAR_MESSAGE;
|
||||
}
|
||||
|
||||
// Сохраняем сообщение
|
||||
lastMessages.put(player, message.toLowerCase());
|
||||
lastMessageTime.put(player, System.currentTimeMillis());
|
||||
|
||||
return SpamResult.ALLOWED;
|
||||
}
|
||||
|
||||
private boolean hasTooManyCaps(String message) {
|
||||
if (message.length() < 5) return false;
|
||||
|
||||
int maxPercent = plugin.getConfigManager().getMaxCapsPercent();
|
||||
long upperCount = message.chars().filter(Character::isUpperCase).count();
|
||||
long letterCount = message.chars().filter(Character::isLetter).count();
|
||||
|
||||
if (letterCount == 0) return false;
|
||||
|
||||
int percent = (int) ((upperCount * 100) / letterCount);
|
||||
return percent > maxPercent;
|
||||
}
|
||||
|
||||
private boolean hasRepeatChars(String message) {
|
||||
int maxRepeat = plugin.getConfigManager().getMaxRepeatChars();
|
||||
int count = 1;
|
||||
char lastChar = 0;
|
||||
|
||||
for (char c : message.toCharArray()) {
|
||||
if (c == lastChar) {
|
||||
count++;
|
||||
if (count > maxRepeat) return true;
|
||||
} else {
|
||||
count = 1;
|
||||
lastChar = c;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isSimilarMessage(UUID player, String message) {
|
||||
String lastMsg = lastMessages.get(player);
|
||||
Long lastTime = lastMessageTime.get(player);
|
||||
|
||||
if (lastMsg == null || lastTime == null) return false;
|
||||
|
||||
int delay = plugin.getConfigManager().getSimilarMessageDelay();
|
||||
long elapsed = (System.currentTimeMillis() - lastTime) / 1000;
|
||||
|
||||
if (elapsed > delay) return false;
|
||||
|
||||
// Проверка схожести (простая)
|
||||
return message.toLowerCase().equals(lastMsg) ||
|
||||
similarity(message.toLowerCase(), lastMsg) > 0.8;
|
||||
}
|
||||
|
||||
private double similarity(String s1, String s2) {
|
||||
int maxLen = Math.max(s1.length(), s2.length());
|
||||
if (maxLen == 0) return 1.0;
|
||||
|
||||
int distance = levenshteinDistance(s1, s2);
|
||||
return 1.0 - ((double) distance / maxLen);
|
||||
}
|
||||
|
||||
private int levenshteinDistance(String s1, String s2) {
|
||||
int[][] dp = new int[s1.length() + 1][s2.length() + 1];
|
||||
|
||||
for (int i = 0; i <= s1.length(); i++) dp[i][0] = i;
|
||||
for (int j = 0; j <= s2.length(); j++) dp[0][j] = j;
|
||||
|
||||
for (int i = 1; i <= s1.length(); i++) {
|
||||
for (int j = 1; j <= s2.length(); j++) {
|
||||
int cost = s1.charAt(i - 1) == s2.charAt(j - 1) ? 0 : 1;
|
||||
dp[i][j] = Math.min(Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1), dp[i - 1][j - 1] + cost);
|
||||
}
|
||||
}
|
||||
|
||||
return dp[s1.length()][s2.length()];
|
||||
}
|
||||
|
||||
public void clearPlayer(UUID player) {
|
||||
lastMessages.remove(player);
|
||||
lastMessageTime.remove(player);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue