154 lines
6.7 KiB
JavaScript
154 lines
6.7 KiB
JavaScript
![]() |
// Утилита для фильтрации нежелательного контента
|
|||
|
const Filter = require('bad-words');
|
|||
|
const fs = require('fs');
|
|||
|
const path = require('path');
|
|||
|
|
|||
|
// Список русских нецензурных слов и других запрещенных слов
|
|||
|
const russianBadWords = [
|
|||
|
'блядь', 'хуй', 'пизда', 'ебать', 'ебал', 'ебло', 'хуесос', 'пидор', 'пидорас',
|
|||
|
'мудак', 'говно', 'залупа', 'хер', 'манда', 'спермоед', 'шлюха', 'соска', 'шалава',
|
|||
|
'дебил', 'дрочить', 'дрочка', 'ебанутый', 'выродок', 'шмара', 'сука', 'членосос',
|
|||
|
'гандон', 'гондон', 'гнида', 'вагина', 'хуи', 'жопа', 'шлюхи', 'проститутка'
|
|||
|
];
|
|||
|
|
|||
|
// Список запрещенных слов и фраз для дейтинг-приложения
|
|||
|
const datingAppBadWords = [
|
|||
|
'проститутка', 'интим', 'секс за деньги', 'эскорт', 'интим услуги',
|
|||
|
'заплачу', 'заплати', 'минет', 'массаж с интимом'
|
|||
|
];
|
|||
|
|
|||
|
/**
|
|||
|
* Загружает список запрещенных слов из файла
|
|||
|
* @param {string} filePath - Путь к файлу со списком запрещенных слов
|
|||
|
* @return {Array<string>} - Массив запрещенных слов
|
|||
|
*/
|
|||
|
function loadBadWordsFromFile(filePath) {
|
|||
|
try {
|
|||
|
if (fs.existsSync(filePath)) {
|
|||
|
const content = fs.readFileSync(filePath, 'utf8');
|
|||
|
const words = content.split('\n')
|
|||
|
.map(word => word.trim())
|
|||
|
.filter(word => word && !word.startsWith('//') && word.length >= 3);
|
|||
|
console.log(`Загружено ${words.length} запрещенных слов из файла ${filePath}`);
|
|||
|
return words;
|
|||
|
}
|
|||
|
} catch (error) {
|
|||
|
console.error(`Ошибка при загрузке слов из файла ${filePath}:`, error.message);
|
|||
|
}
|
|||
|
return [];
|
|||
|
}
|
|||
|
|
|||
|
class ProfanityFilter {
|
|||
|
constructor() {
|
|||
|
// Создаем экземпляр фильтра с английскими словами по умолчанию
|
|||
|
this.filter = new Filter({ placeHolder: '*' });
|
|||
|
|
|||
|
// Загружаем слова из файлов
|
|||
|
const russianFileWords = loadBadWordsFromFile(path.join(__dirname, 'words.txt'));
|
|||
|
const englishFileWords = loadBadWordsFromFile(path.join(__dirname, 'en.txt'));
|
|||
|
|
|||
|
// Объединяем все источники запрещенных слов
|
|||
|
const allBadWords = [
|
|||
|
...russianBadWords,
|
|||
|
...datingAppBadWords,
|
|||
|
...russianFileWords,
|
|||
|
...englishFileWords
|
|||
|
];
|
|||
|
|
|||
|
// Добавляем все слова в фильтр
|
|||
|
this.filter.addWords(...allBadWords);
|
|||
|
|
|||
|
// Создаем регулярные выражения для проверки производных слов
|
|||
|
this.generateWordPatterns(allBadWords);
|
|||
|
|
|||
|
console.log(`Всего загружено ${allBadWords.length} запрещенных слов`);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Создает регулярные выражения для проверки производных слов
|
|||
|
* @param {Array<string>} words - Список базовых запрещённых слов
|
|||
|
*/
|
|||
|
generateWordPatterns(words) {
|
|||
|
this.wordPatterns = words
|
|||
|
.filter(word => word && word.length >= 4) // Берем только слова длиннее 3 символов для производных
|
|||
|
.map(word => {
|
|||
|
// Создаем шаблон для каждого слова: допускает изменение окончаний и вставку символов
|
|||
|
const baseWord = word.replace(/[еёо]/g, '[еёо]'); // Учитываем замену е/ё/о
|
|||
|
return new RegExp(`\\b${baseWord}[а-яёa-z]*\\b`, 'i');
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Проверяет, содержит ли текст запрещенные слова или их производные
|
|||
|
* @param {string} text - Текст для проверки
|
|||
|
* @return {boolean} - true, если текст содержит запрещенные слова, иначе false
|
|||
|
*/
|
|||
|
hasProfanity(text) {
|
|||
|
if (!text) return false;
|
|||
|
|
|||
|
// Проверяем сначала стандартным методом библиотеки bad-words
|
|||
|
if (this.filter.isProfane(text.toLowerCase())) {
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
// Дополнительная проверка на производные слова через регулярные выражения
|
|||
|
const normalizedText = text.toLowerCase();
|
|||
|
return this.wordPatterns.some(pattern => pattern.test(normalizedText));
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Проверяет, содержит ли объект запрещенные слова в указанных полях
|
|||
|
* @param {Object} obj - Объект для проверки
|
|||
|
* @param {Array<string>} fields - Массив имен полей для проверки
|
|||
|
* @return {Object} - Объект с результатами проверки { isProfane: boolean, field: string|null }
|
|||
|
*/
|
|||
|
validateObject(obj, fields) {
|
|||
|
for (const field of fields) {
|
|||
|
if (obj[field] && this.hasProfanity(obj[field])) {
|
|||
|
return { isProfane: true, field };
|
|||
|
}
|
|||
|
}
|
|||
|
return { isProfane: false, field: null };
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Заменяет запрещенные слова в тексте на звездочки
|
|||
|
* @param {string} text - Исходный текст
|
|||
|
* @return {string} - Очищенный текст
|
|||
|
*/
|
|||
|
clean(text) {
|
|||
|
if (!text) return '';
|
|||
|
|
|||
|
// Сначала используем стандартный метод библиотеки
|
|||
|
let cleanedText = this.filter.clean(text);
|
|||
|
|
|||
|
// Затем проверяем на производные слова и заменяем их
|
|||
|
this.wordPatterns.forEach(pattern => {
|
|||
|
cleanedText = cleanedText.replace(pattern, match => '*'.repeat(match.length));
|
|||
|
});
|
|||
|
|
|||
|
return cleanedText;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Добавляет новое запрещенное слово в фильтр
|
|||
|
* @param {string|Array<string>} words - Слово или массив слов для добавления
|
|||
|
*/
|
|||
|
addWords(words) {
|
|||
|
// Добавляем слова в стандартный фильтр
|
|||
|
this.filter.addWords(words);
|
|||
|
|
|||
|
// Если слова переданы как массив
|
|||
|
if (Array.isArray(words)) {
|
|||
|
this.generateWordPatterns(words);
|
|||
|
} else {
|
|||
|
// Если передано одно слово
|
|||
|
this.generateWordPatterns([words]);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Экспортируем экземпляр фильтра для использования в приложении
|
|||
|
const profanityFilter = new ProfanityFilter();
|
|||
|
|
|||
|
module.exports = profanityFilter;
|