Переделал фильтр чата: слова теперь в JSON, добавлен поиск по фрагментам, улучшена защита от обхода фильтра
This commit is contained in:
parent
2292137986
commit
cb60c29e91
4 changed files with 796 additions and 27 deletions
|
|
@ -3,7 +3,7 @@ plugins {
|
|||
}
|
||||
|
||||
group = 'com.loki'
|
||||
version = '1.5.3'
|
||||
version = '1.5.4'
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
|
|
@ -17,6 +17,7 @@ dependencies {
|
|||
compileOnly 'me.clip:placeholderapi:2.11.6'
|
||||
compileOnly 'org.black_ixx:playerpoints:3.2.7'
|
||||
compileOnly 'net.luckperms:api:5.4'
|
||||
implementation 'com.google.code.gson:gson:2.10.1'
|
||||
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.10.0'
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.10.0'
|
||||
|
|
@ -42,7 +43,7 @@ test {
|
|||
}
|
||||
|
||||
jar {
|
||||
archiveFileName = 'LoChat-1.5.3.jar'
|
||||
archiveFileName = 'LoChat-1.5.4.jar'
|
||||
from {
|
||||
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -126,6 +126,9 @@ public final class LoChat extends JavaPlugin {
|
|||
if (customCommandManager != null) {
|
||||
customCommandManager.reload();
|
||||
}
|
||||
if (filterManager != null) {
|
||||
filterManager.reload();
|
||||
}
|
||||
}
|
||||
|
||||
public static LoChat getInstance() {
|
||||
|
|
|
|||
|
|
@ -1,16 +1,111 @@
|
|||
package com.loki.lochat.managers;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.loki.lochat.LoChat;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class FilterManager {
|
||||
|
||||
private final LoChat plugin;
|
||||
private List<String> badWords = new ArrayList<>();
|
||||
private List<String> fragments = new ArrayList<>();
|
||||
|
||||
public FilterManager(LoChat plugin) {
|
||||
this.plugin = plugin;
|
||||
loadFilterWords();
|
||||
}
|
||||
|
||||
/**
|
||||
* Загружает плохие слова из JSON файла
|
||||
*/
|
||||
private void loadFilterWords() {
|
||||
badWords.clear();
|
||||
fragments.clear();
|
||||
|
||||
try {
|
||||
// Сначала пытаемся загрузить из data folder (если есть кастомный)
|
||||
File customFile = new File(plugin.getDataFolder(), "filter-words.json");
|
||||
if (customFile.exists()) {
|
||||
try (FileReader reader = new FileReader(customFile, StandardCharsets.UTF_8)) {
|
||||
JsonObject json = JsonParser.parseReader(reader).getAsJsonObject();
|
||||
loadFromJsonObject(json);
|
||||
plugin.getLogger().info("Загружены плохие слова из filter-words.json (data folder): " + badWords.size() + " слов, " + fragments.size() + " фрагментов");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Если кастомного нет, копируем из ресурсов
|
||||
plugin.saveResource("filter-words.json", false);
|
||||
|
||||
// Теперь загружаем из data folder
|
||||
if (customFile.exists()) {
|
||||
try (FileReader reader = new FileReader(customFile, StandardCharsets.UTF_8)) {
|
||||
JsonObject json = JsonParser.parseReader(reader).getAsJsonObject();
|
||||
loadFromJsonObject(json);
|
||||
plugin.getLogger().info("Загружено " + badWords.size() + " плохих слов и " + fragments.size() + " фрагментов из filter-words.json");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback на старый способ из config.yml
|
||||
List<String> configWords = plugin.getConfigManager().getFilterWords();
|
||||
if (configWords != null && !configWords.isEmpty()) {
|
||||
badWords.addAll(configWords);
|
||||
plugin.getLogger().warning("Используются слова из config.yml (filter-words.json не найден)");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
plugin.getLogger().severe("Ошибка загрузки filter-words.json: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
// Fallback на старый способ
|
||||
List<String> configWords = plugin.getConfigManager().getFilterWords();
|
||||
if (configWords != null && !configWords.isEmpty()) {
|
||||
badWords.addAll(configWords);
|
||||
plugin.getLogger().info("Используются слова из config.yml (fallback)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Загружает данные из JSON объекта
|
||||
*/
|
||||
private void loadFromJsonObject(JsonObject json) {
|
||||
if (json.has("words")) {
|
||||
JsonArray wordsArray = json.getAsJsonArray("words");
|
||||
for (JsonElement element : wordsArray) {
|
||||
String word = element.getAsString();
|
||||
if (word != null && !word.trim().isEmpty()) {
|
||||
badWords.add(word.trim().toLowerCase());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (json.has("fragments")) {
|
||||
JsonArray fragmentsArray = json.getAsJsonArray("fragments");
|
||||
for (JsonElement element : fragmentsArray) {
|
||||
String fragment = element.getAsString();
|
||||
if (fragment != null && !fragment.trim().isEmpty()) {
|
||||
fragments.add(fragment.trim().toLowerCase());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Перезагружает список плохих слов
|
||||
*/
|
||||
public void reload() {
|
||||
loadFilterWords();
|
||||
}
|
||||
|
||||
public enum FilterResult {
|
||||
|
|
@ -32,15 +127,16 @@ public class FilterManager {
|
|||
return FilterResult.ALLOWED;
|
||||
}
|
||||
|
||||
List<String> badWords = plugin.getConfigManager().getFilterWords();
|
||||
if (badWords == null || badWords.isEmpty()) {
|
||||
if (badWords.isEmpty() && fragments.isEmpty()) {
|
||||
return FilterResult.ALLOWED;
|
||||
}
|
||||
|
||||
// Нормализуем сообщение (убираем обход фильтра)
|
||||
String normalizedMessage = normalizeMessage(message);
|
||||
String lowerMessage = normalizedMessage.toLowerCase();
|
||||
String originalLower = message.toLowerCase();
|
||||
|
||||
// Проверяем полные слова
|
||||
for (String word : badWords) {
|
||||
if (word == null || word.trim().isEmpty()) {
|
||||
continue;
|
||||
|
|
@ -50,29 +146,45 @@ public class FilterManager {
|
|||
|
||||
// Проверяем точное совпадение слова (с границами слов)
|
||||
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.toLowerCase()) {
|
||||
case "block" -> FilterResult.BLOCKED;
|
||||
case "warn" -> FilterResult.WARNED;
|
||||
default -> FilterResult.CENSORED;
|
||||
};
|
||||
if (wordPattern.matcher(normalizedMessage).find() || wordPattern.matcher(originalLower).find()) {
|
||||
return getFilterResult();
|
||||
}
|
||||
|
||||
// Также проверяем как подстроку (для частичных совпадений типа "пизд")
|
||||
if (lowerMessage.contains(lowerWord)) {
|
||||
String action = plugin.getConfigManager().getFilterAction();
|
||||
return switch (action.toLowerCase()) {
|
||||
case "block" -> FilterResult.BLOCKED;
|
||||
case "warn" -> FilterResult.WARNED;
|
||||
default -> FilterResult.CENSORED;
|
||||
};
|
||||
// Также проверяем как подстроку
|
||||
if (lowerMessage.contains(lowerWord) || originalLower.contains(lowerWord)) {
|
||||
return getFilterResult();
|
||||
}
|
||||
}
|
||||
|
||||
// Проверяем фрагменты (поиск по фрагментам типа "пизд" найдет "пизда", "пиздец" и т.д.)
|
||||
for (String fragment : fragments) {
|
||||
if (fragment == null || fragment.trim().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String lowerFragment = fragment.toLowerCase().trim();
|
||||
|
||||
// Ищем фрагмент в нормализованном сообщении
|
||||
if (lowerMessage.contains(lowerFragment) || originalLower.contains(lowerFragment)) {
|
||||
return getFilterResult();
|
||||
}
|
||||
}
|
||||
|
||||
return FilterResult.ALLOWED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает результат фильтрации на основе настроек
|
||||
*/
|
||||
private FilterResult getFilterResult() {
|
||||
String action = plugin.getConfigManager().getFilterAction();
|
||||
return switch (action.toLowerCase()) {
|
||||
case "block" -> FilterResult.BLOCKED;
|
||||
case "warn" -> FilterResult.WARNED;
|
||||
default -> FilterResult.CENSORED;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Цензурирует сообщение, заменяя запрещенные слова
|
||||
*/
|
||||
|
|
@ -85,8 +197,7 @@ public class FilterManager {
|
|||
return message;
|
||||
}
|
||||
|
||||
List<String> badWords = plugin.getConfigManager().getFilterWords();
|
||||
if (badWords == null || badWords.isEmpty()) {
|
||||
if (badWords.isEmpty() && fragments.isEmpty()) {
|
||||
return message;
|
||||
}
|
||||
|
||||
|
|
@ -98,38 +209,53 @@ public class FilterManager {
|
|||
String result = message;
|
||||
String normalizedMessage = normalizeMessage(message);
|
||||
|
||||
// Заменяем полные слова
|
||||
for (String word : badWords) {
|
||||
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);
|
||||
}
|
||||
|
||||
// Заменяем фрагменты (находим слова содержащие фрагмент и заменяем их)
|
||||
for (String fragment : fragments) {
|
||||
if (fragment == null || fragment.trim().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ищем слова содержащие фрагмент и заменяем весь фрагмент
|
||||
Pattern fragmentPattern = Pattern.compile("(?i)" + Pattern.quote(fragment));
|
||||
result = fragmentPattern.matcher(result).replaceAll(replacement);
|
||||
|
||||
// Также заменяем слова начинающиеся с фрагмента
|
||||
Pattern wordStartPattern = Pattern.compile("\\b" + Pattern.quote(fragment) + "\\w*", Pattern.CASE_INSENSITIVE);
|
||||
result = wordStartPattern.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('-', 'а');
|
||||
|
|
@ -146,12 +272,27 @@ public class FilterManager {
|
|||
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.replace('&', 'а');
|
||||
normalized = normalized.replace('~', 'а');
|
||||
normalized = normalized.replace('`', 'а');
|
||||
normalized = normalized.replace('=', 'а');
|
||||
normalized = normalized.replace('+', 'а');
|
||||
normalized = normalized.replace('[', 'а');
|
||||
normalized = normalized.replace(']', 'а');
|
||||
normalized = normalized.replace('{', 'а');
|
||||
normalized = normalized.replace('}', 'а');
|
||||
normalized = normalized.replace('(', 'а');
|
||||
normalized = normalized.replace(')', 'а');
|
||||
normalized = normalized.replace('/', 'а');
|
||||
normalized = normalized.replace('\\', 'а');
|
||||
normalized = normalized.replace('?', 'а');
|
||||
normalized = normalized.replace('<', 'а');
|
||||
normalized = normalized.replace('>', 'а');
|
||||
|
||||
// Убираем множественные пробелы
|
||||
normalized = normalized.replaceAll("\\s+", " ");
|
||||
|
|
|
|||
624
src/main/resources/filter-words.json
Normal file
624
src/main/resources/filter-words.json
Normal file
|
|
@ -0,0 +1,624 @@
|
|||
{
|
||||
"words": [
|
||||
"хуй",
|
||||
"хуя",
|
||||
"хуе",
|
||||
"хуи",
|
||||
"хую",
|
||||
"хуё",
|
||||
"пизд",
|
||||
"пизда",
|
||||
"пиздец",
|
||||
"пизду",
|
||||
"пизды",
|
||||
"пиздо",
|
||||
"блять",
|
||||
"блядь",
|
||||
"бля",
|
||||
"бляд",
|
||||
"ебать",
|
||||
"ебал",
|
||||
"ебало",
|
||||
"ебать",
|
||||
"ебет",
|
||||
"ебут",
|
||||
"ебу",
|
||||
"ебё",
|
||||
"ебан",
|
||||
"сука",
|
||||
"суки",
|
||||
"суке",
|
||||
"суку",
|
||||
"сукой",
|
||||
"суко",
|
||||
"ебан",
|
||||
"ебана",
|
||||
"ебану",
|
||||
"ебань",
|
||||
"ебля",
|
||||
"ебли",
|
||||
"ебло",
|
||||
"ебля",
|
||||
"ебут",
|
||||
"ебуть",
|
||||
"ебёшь",
|
||||
"ебёт",
|
||||
"ебём",
|
||||
"ебёте",
|
||||
"ебут",
|
||||
"ебаный",
|
||||
"ебаная",
|
||||
"ебаное",
|
||||
"ебаные",
|
||||
"ебаного",
|
||||
"ебаной",
|
||||
"ебаному",
|
||||
"ебаным",
|
||||
"ебаных",
|
||||
"ебаным",
|
||||
"ебаные",
|
||||
"ебаными",
|
||||
"ебаных",
|
||||
"ебанный",
|
||||
"ебанная",
|
||||
"ебанное",
|
||||
"ебанные",
|
||||
"ебанного",
|
||||
"ебанной",
|
||||
"ебанному",
|
||||
"ебанным",
|
||||
"ебанных",
|
||||
"ебанным",
|
||||
"ебанные",
|
||||
"ебанными",
|
||||
"ебанных",
|
||||
"заеб",
|
||||
"заеба",
|
||||
"заебе",
|
||||
"заеби",
|
||||
"заебу",
|
||||
"заебё",
|
||||
"уеб",
|
||||
"уеба",
|
||||
"уебе",
|
||||
"уеби",
|
||||
"уебу",
|
||||
"уебё",
|
||||
"выеб",
|
||||
"выеба",
|
||||
"выебе",
|
||||
"выеби",
|
||||
"выебу",
|
||||
"выебё",
|
||||
"проеб",
|
||||
"проеба",
|
||||
"проебе",
|
||||
"проеби",
|
||||
"проебу",
|
||||
"проебё",
|
||||
"долбоеб",
|
||||
"долбоеба",
|
||||
"долбоебе",
|
||||
"долбоеби",
|
||||
"долбоебу",
|
||||
"долбоебё",
|
||||
"мудак",
|
||||
"мудака",
|
||||
"мудаке",
|
||||
"мудаки",
|
||||
"мудаку",
|
||||
"мудаком",
|
||||
"мудаки",
|
||||
"мудаков",
|
||||
"мудакам",
|
||||
"мудаками",
|
||||
"мудаках",
|
||||
"мудила",
|
||||
"мудилы",
|
||||
"мудиле",
|
||||
"мудилу",
|
||||
"мудилой",
|
||||
"мудило",
|
||||
"гандон",
|
||||
"гондон",
|
||||
"гандона",
|
||||
"гондона",
|
||||
"гандону",
|
||||
"гондону",
|
||||
"гандоном",
|
||||
"гондоном",
|
||||
"гандоне",
|
||||
"гондоне",
|
||||
"гандонов",
|
||||
"гондонов",
|
||||
"гандонам",
|
||||
"гондонам",
|
||||
"гандонами",
|
||||
"гондонами",
|
||||
"гандонах",
|
||||
"гондонах",
|
||||
"пидор",
|
||||
"пидора",
|
||||
"пидору",
|
||||
"пидором",
|
||||
"пидоре",
|
||||
"пидоры",
|
||||
"пидоров",
|
||||
"пидорам",
|
||||
"пидорами",
|
||||
"пидорах",
|
||||
"пидарас",
|
||||
"пидараса",
|
||||
"пидарасу",
|
||||
"пидарасом",
|
||||
"пидарасе",
|
||||
"пидарасы",
|
||||
"пидарасов",
|
||||
"пидарасам",
|
||||
"пидарасами",
|
||||
"пидарасах",
|
||||
"педик",
|
||||
"педика",
|
||||
"педику",
|
||||
"педиком",
|
||||
"педике",
|
||||
"педики",
|
||||
"педиков",
|
||||
"педикам",
|
||||
"педиками",
|
||||
"педиках",
|
||||
"гомик",
|
||||
"гомика",
|
||||
"гомику",
|
||||
"гомиком",
|
||||
"гомике",
|
||||
"гомики",
|
||||
"гомиков",
|
||||
"гомикам",
|
||||
"гомиками",
|
||||
"гомиках",
|
||||
"шлюха",
|
||||
"шлюхи",
|
||||
"шлюхе",
|
||||
"шлюху",
|
||||
"шлюхой",
|
||||
"шлюхо",
|
||||
"шлюх",
|
||||
"блядина",
|
||||
"блядины",
|
||||
"блядине",
|
||||
"блядину",
|
||||
"блядиной",
|
||||
"блядино",
|
||||
"блядин",
|
||||
"шлюшка",
|
||||
"шлюшки",
|
||||
"шлюшке",
|
||||
"шлюшку",
|
||||
"шлюшкой",
|
||||
"шлюшко",
|
||||
"шлюшек",
|
||||
"проститутка",
|
||||
"проститутки",
|
||||
"проститутке",
|
||||
"проститутку",
|
||||
"проституткой",
|
||||
"проститутко",
|
||||
"проституток",
|
||||
"проституткам",
|
||||
"проститутками",
|
||||
"проститутках",
|
||||
"еблан",
|
||||
"еблана",
|
||||
"еблану",
|
||||
"ебланом",
|
||||
"еблане",
|
||||
"ебланы",
|
||||
"ебланов",
|
||||
"ебланам",
|
||||
"ебланами",
|
||||
"ебланах",
|
||||
"ебанутый",
|
||||
"ебанутого",
|
||||
"ебанутому",
|
||||
"ебанутым",
|
||||
"ебанутом",
|
||||
"ебанутая",
|
||||
"ебанутой",
|
||||
"ебанутую",
|
||||
"ебанутое",
|
||||
"ебанутые",
|
||||
"ебанутых",
|
||||
"ебанутым",
|
||||
"ебанутыми",
|
||||
"ебанутых",
|
||||
"ебанутый",
|
||||
"ебанутого",
|
||||
"ебанутому",
|
||||
"ебанутым",
|
||||
"ебанутом",
|
||||
"ебанутая",
|
||||
"ебанутой",
|
||||
"ебанутую",
|
||||
"ебанутое",
|
||||
"ебанутые",
|
||||
"ебанутых",
|
||||
"ебанутым",
|
||||
"ебанутыми",
|
||||
"ебанутых",
|
||||
"уебан",
|
||||
"уебана",
|
||||
"уебану",
|
||||
"уебаном",
|
||||
"уебане",
|
||||
"уебаны",
|
||||
"уебанов",
|
||||
"уебанам",
|
||||
"уебанами",
|
||||
"уебанах",
|
||||
"долбоёб",
|
||||
"долбоёба",
|
||||
"долбоёбу",
|
||||
"долбоёбом",
|
||||
"долбоёбе",
|
||||
"долбоёбы",
|
||||
"долбоёбов",
|
||||
"долбоёбам",
|
||||
"долбоёбами",
|
||||
"долбоёбах",
|
||||
"долбоеб",
|
||||
"долбоеба",
|
||||
"долбоебу",
|
||||
"долбоебом",
|
||||
"долбоебе",
|
||||
"долбоебы",
|
||||
"долбоебов",
|
||||
"долбоебам",
|
||||
"долбоебами",
|
||||
"долбоебах",
|
||||
"еблан",
|
||||
"еблана",
|
||||
"еблану",
|
||||
"ебланом",
|
||||
"еблане",
|
||||
"ебланы",
|
||||
"ебланов",
|
||||
"ебланам",
|
||||
"ебланами",
|
||||
"ебланах",
|
||||
"залупа",
|
||||
"залупы",
|
||||
"залупе",
|
||||
"залупу",
|
||||
"залупой",
|
||||
"залупо",
|
||||
"залуп",
|
||||
"залупка",
|
||||
"залупки",
|
||||
"залупке",
|
||||
"залупку",
|
||||
"залупкой",
|
||||
"залупко",
|
||||
"залупок",
|
||||
"залупкам",
|
||||
"залупками",
|
||||
"залупках",
|
||||
"мразь",
|
||||
"мрази",
|
||||
"мрази",
|
||||
"мразью",
|
||||
"мразь",
|
||||
"мразей",
|
||||
"мразям",
|
||||
"мразями",
|
||||
"мразях",
|
||||
"мразота",
|
||||
"мразоты",
|
||||
"мразоте",
|
||||
"мразоту",
|
||||
"мразотой",
|
||||
"мразото",
|
||||
"мразот",
|
||||
"мразотой",
|
||||
"мразотам",
|
||||
"мразотами",
|
||||
"мразотах",
|
||||
"ублюдок",
|
||||
"ублюдка",
|
||||
"ублюдку",
|
||||
"ублюдком",
|
||||
"ублюдке",
|
||||
"ублюдки",
|
||||
"ублюдков",
|
||||
"ублюдкам",
|
||||
"ублюдками",
|
||||
"ублюдках",
|
||||
"выблядок",
|
||||
"выблядка",
|
||||
"выблядку",
|
||||
"выблядком",
|
||||
"выблядке",
|
||||
"выблядки",
|
||||
"выблядков",
|
||||
"выблядкам",
|
||||
"выблядками",
|
||||
"выблядках",
|
||||
"падла",
|
||||
"падлы",
|
||||
"падле",
|
||||
"падлу",
|
||||
"падлой",
|
||||
"падло",
|
||||
"падл",
|
||||
"падлюга",
|
||||
"падлюги",
|
||||
"падлюге",
|
||||
"падлюгу",
|
||||
"падлюгой",
|
||||
"падлюго",
|
||||
"падлюг",
|
||||
"падлюгам",
|
||||
"падлюгами",
|
||||
"падлюгах",
|
||||
"гад",
|
||||
"гада",
|
||||
"гаду",
|
||||
"гадом",
|
||||
"гаде",
|
||||
"гады",
|
||||
"гадов",
|
||||
"гадам",
|
||||
"гадами",
|
||||
"гадах",
|
||||
"гадина",
|
||||
"гадины",
|
||||
"гадине",
|
||||
"гадину",
|
||||
"гадиной",
|
||||
"гадино",
|
||||
"гадин",
|
||||
"гадинам",
|
||||
"гадинами",
|
||||
"гадинах",
|
||||
"тварь",
|
||||
"твари",
|
||||
"твари",
|
||||
"тварью",
|
||||
"тварь",
|
||||
"тварей",
|
||||
"тварям",
|
||||
"тварями",
|
||||
"тварях",
|
||||
"тварина",
|
||||
"тварины",
|
||||
"тварине",
|
||||
"тварину",
|
||||
"твариной",
|
||||
"тварино",
|
||||
"тварин",
|
||||
"тваринам",
|
||||
"тваринами",
|
||||
"тваринах",
|
||||
"сволочь",
|
||||
"сволочи",
|
||||
"сволочи",
|
||||
"сволочью",
|
||||
"сволочь",
|
||||
"сволочей",
|
||||
"сволочам",
|
||||
"сволочами",
|
||||
"сволочах",
|
||||
"сволочка",
|
||||
"сволочки",
|
||||
"сволочке",
|
||||
"сволочку",
|
||||
"сволочкой",
|
||||
"сволочко",
|
||||
"сволочек",
|
||||
"сволочкам",
|
||||
"сволочками",
|
||||
"сволочках",
|
||||
"скотина",
|
||||
"скотины",
|
||||
"скотине",
|
||||
"скотину",
|
||||
"скотиной",
|
||||
"скотино",
|
||||
"скотин",
|
||||
"скотинам",
|
||||
"скотинами",
|
||||
"скотинах",
|
||||
"скотиняка",
|
||||
"скотиняки",
|
||||
"скотиняке",
|
||||
"скотиняку",
|
||||
"скотинякой",
|
||||
"скотиняко",
|
||||
"скотиняк",
|
||||
"скотинякам",
|
||||
"скотиняками",
|
||||
"скотиняках",
|
||||
"козел",
|
||||
"козла",
|
||||
"козлу",
|
||||
"козлом",
|
||||
"козле",
|
||||
"козлы",
|
||||
"козлов",
|
||||
"козлам",
|
||||
"козлами",
|
||||
"козлах",
|
||||
"козлина",
|
||||
"козлины",
|
||||
"козлине",
|
||||
"козлину",
|
||||
"козлиной",
|
||||
"козлино",
|
||||
"козлин",
|
||||
"козлинам",
|
||||
"козлинами",
|
||||
"козлинах",
|
||||
"козлище",
|
||||
"козлища",
|
||||
"козлищу",
|
||||
"козлищем",
|
||||
"козлище",
|
||||
"козлищ",
|
||||
"козлищам",
|
||||
"козлищами",
|
||||
"козлищах",
|
||||
"козёл",
|
||||
"козла",
|
||||
"козлу",
|
||||
"козлом",
|
||||
"козле",
|
||||
"козлы",
|
||||
"козлов",
|
||||
"козлам",
|
||||
"козлами",
|
||||
"козлах",
|
||||
"козлина",
|
||||
"козлины",
|
||||
"козлине",
|
||||
"козлину",
|
||||
"козлиной",
|
||||
"козлино",
|
||||
"козлин",
|
||||
"козлинам",
|
||||
"козлинами",
|
||||
"козлинах",
|
||||
"козлище",
|
||||
"козлища",
|
||||
"козлищу",
|
||||
"козлищем",
|
||||
"козлище",
|
||||
"козлищ",
|
||||
"козлищам",
|
||||
"козлищами",
|
||||
"козлищах",
|
||||
"козёл",
|
||||
"козла",
|
||||
"козлу",
|
||||
"козлом",
|
||||
"козле",
|
||||
"козлы",
|
||||
"козлов",
|
||||
"козлам",
|
||||
"козлами",
|
||||
"козлах",
|
||||
"козлина",
|
||||
"козлины",
|
||||
"козлине",
|
||||
"козлину",
|
||||
"козлиной",
|
||||
"козлино",
|
||||
"козлин",
|
||||
"козлинам",
|
||||
"козлинами",
|
||||
"козлинах",
|
||||
"козлище",
|
||||
"козлища",
|
||||
"козлищу",
|
||||
"козлищем",
|
||||
"козлище",
|
||||
"козлищ",
|
||||
"козлищам",
|
||||
"козлищами",
|
||||
"козлищах"
|
||||
],
|
||||
"fragments": [
|
||||
"хуй",
|
||||
"хуя",
|
||||
"хуе",
|
||||
"хуи",
|
||||
"хую",
|
||||
"хуё",
|
||||
"пизд",
|
||||
"бля",
|
||||
"бляд",
|
||||
"еб",
|
||||
"еба",
|
||||
"ебе",
|
||||
"еби",
|
||||
"ебу",
|
||||
"ебё",
|
||||
"ебан",
|
||||
"ебал",
|
||||
"ебан",
|
||||
"ебля",
|
||||
"ебли",
|
||||
"ебло",
|
||||
"ебут",
|
||||
"ебуть",
|
||||
"ебёшь",
|
||||
"ебёт",
|
||||
"ебём",
|
||||
"ебёте",
|
||||
"ебут",
|
||||
"ебаный",
|
||||
"ебаная",
|
||||
"ебаное",
|
||||
"ебаные",
|
||||
"ебаного",
|
||||
"ебаной",
|
||||
"ебаному",
|
||||
"ебаным",
|
||||
"ебаных",
|
||||
"ебаным",
|
||||
"ебаные",
|
||||
"ебаными",
|
||||
"ебаных",
|
||||
"ебанный",
|
||||
"ебанная",
|
||||
"ебанное",
|
||||
"ебанные",
|
||||
"ебанного",
|
||||
"ебанной",
|
||||
"ебанному",
|
||||
"ебанным",
|
||||
"ебанных",
|
||||
"ебанным",
|
||||
"ебанные",
|
||||
"ебанными",
|
||||
"ебанных",
|
||||
"заеб",
|
||||
"уеб",
|
||||
"выеб",
|
||||
"проеб",
|
||||
"долбоеб",
|
||||
"мудак",
|
||||
"мудил",
|
||||
"гандон",
|
||||
"гондон",
|
||||
"пидор",
|
||||
"пидарас",
|
||||
"педик",
|
||||
"гомик",
|
||||
"шлюх",
|
||||
"блядин",
|
||||
"проститутк",
|
||||
"еблан",
|
||||
"ебанут",
|
||||
"уебан",
|
||||
"долбоёб",
|
||||
"долбоеб",
|
||||
"залуп",
|
||||
"мраз",
|
||||
"мразот",
|
||||
"ублюдок",
|
||||
"выблядок",
|
||||
"падл",
|
||||
"падлюг",
|
||||
"гад",
|
||||
"гадин",
|
||||
"твар",
|
||||
"тварин",
|
||||
"сволоч",
|
||||
"скотин",
|
||||
"козел",
|
||||
"козл",
|
||||
"козёл",
|
||||
"козлищ"
|
||||
]
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue