diff --git a/backend/utils/profanityFilter.js b/backend/utils/profanityFilter.js index 2fbd674..674df45 100644 --- a/backend/utils/profanityFilter.js +++ b/backend/utils/profanityFilter.js @@ -70,11 +70,27 @@ class ProfanityFilter { */ generateWordPatterns(words) { this.wordPatterns = words - .filter(word => word && word.length >= 4) // Берем только слова длиннее 3 символов для производных + .filter(word => word && word.length >= 3) // Снижаем минимальную длину до 3 символов .map(word => { - // Создаем шаблон для каждого слова: допускает изменение окончаний и вставку символов - const baseWord = word.replace(/[еёо]/g, '[еёо]'); // Учитываем замену е/ё/о - return new RegExp(`\\b${baseWord}[а-яёa-z]*\\b`, 'i'); + // Создаем шаблон с учетом возможных разделителей и замен символов + const baseWord = word + .replace(/[еёо]/g, '[еёо]') // Учитываем замену е/ё/о + .replace(/а/g, '[аa@]') // Учитываем замену а на a латинскую или @ + .replace(/о/g, '[оo0]') // Учитываем замену о на o латинскую или 0 + .replace(/е/g, '[еe]') // Учитываем замену е на e латинскую + .replace(/с/g, '[сc]') // Учитываем замену с на c латинскую + .replace(/р/g, '[рp]') // Учитываем замену р на p латинскую + .replace(/х/g, '[хx]') // Учитываем замену х на x латинскую + .replace(/у/g, '[уy]') // Учитываем замену у на y латинскую + .replace(/и/g, '[иi]'); // Учитываем замену и на i + + // Создаем регулярку, которая учитывает: + // - возможные разделители между буквами (точки, пробелы, дефисы) + // - возможные окончания слов + const chars = baseWord.split(''); + const patternWithSeparators = chars.join('[\\s\\._\\-]*'); + + return new RegExp(`\\b${patternWithSeparators}[а-яёa-z]*\\b`, 'i'); }); } @@ -86,14 +102,17 @@ class ProfanityFilter { hasProfanity(text) { if (!text) return false; + // Нормализуем текст, убирая лишние символы и разделители + const normalizedText = text.toLowerCase() + .replace(/[\s\._\-]+/g, ''); // Удаляем пробелы, точки, подчеркивания, дефисы + // Проверяем сначала стандартным методом библиотеки bad-words - if (this.filter.isProfane(text.toLowerCase())) { + if (this.filter.isProfane(normalizedText) || this.filter.isProfane(text.toLowerCase())) { return true; } // Дополнительная проверка на производные слова через регулярные выражения - const normalizedText = text.toLowerCase(); - return this.wordPatterns.some(pattern => pattern.test(normalizedText)); + return this.wordPatterns.some(pattern => pattern.test(text.toLowerCase())); } /** diff --git a/src/views/RegisterView.vue b/src/views/RegisterView.vue index b29bc76..f9a93cf 100644 --- a/src/views/RegisterView.vue +++ b/src/views/RegisterView.vue @@ -173,6 +173,28 @@ import { ref, onMounted, onUnmounted, computed } from 'vue'; import { useAuth } from '@/auth'; import russianCities from '@/assets/russian-cities.json'; +// Слова для базовой проверки на клиентской стороне +// (меньше, чем в полной библиотеке на сервере, но достаточно для основных случаев) +const badWords = [ + 'блядь', 'хуй', 'пизда', 'ебать', 'ебал', 'ебло', 'хуесос', 'пидор', 'пидорас', + 'мудак', 'говно', 'залупа', 'хер', 'шлюха', 'соска', 'шалава', 'дебил', 'дрочить', + 'сука', 'гандон', 'гондон' +]; + +// Функция для проверки на нецензурную лексику (упрощенная версия, основная проверка на сервере) +const hasProfanity = (text) => { + if (!text) return false; + + const normalizedText = text.toLowerCase() + .replace(/[\s\._\-]+/g, '') // Удаляем пробелы, точки, подчеркивания, дефисы + .replace(/[еёo]/g, 'е') // Приводим похожие символы к общему виду + .replace(/[аa]/g, 'а') + .replace(/[оo0]/g, 'о'); + + // Проверяем на запрещенные слова + return badWords.some(word => normalizedText.includes(word.toLowerCase())); +}; + const name = ref(''); const email = ref(''); const birthdate = ref(''); @@ -271,6 +293,13 @@ const handleRegister = async () => { return; } + // Проверка имени на запрещенные слова + if (hasProfanity(name.value)) { + errorMessage.value = 'Имя содержит запрещенные слова или выражения. Пожалуйста, используйте другое имя.'; + loading.value = false; + return; + } + try { const userData = { name: name.value,