#javascript #discord #discord.js #bots #message
#javascript #Discord #discord.js #боты #Сообщение
Вопрос:
const filter = ["bad1", "bad2"];
client.on("message", message => {
var content = message.content;
var stringToCheck = content.replace(/s /g, '').toLowerCase();
for (var i = 0; i < filter.length; i ) {
if (content.includes(filter[i])){
message.delete();
break
}
}
});
Итак, мой приведенный выше код — это бот discord, который удаляет слова, когда кто-то пишет «bad1» «bad2»
(еще несколько отфильтрованных плохих слов, которые я собираюсь добавить), и, к счастью, никаких ошибок.
Но прямо сейчас бот удаляет эти слова только тогда, когда они написаны маленькими буквами без пробелов между ними или специальных символов.
Я думаю, что нашел решение, но, похоже, я не могу вставить его в свой код, я имею в виду, что я пробовал разные способы, но он либо удалял строчные слова, либо вообще не реагировал, и вместо этого я получал ошибки типа «невозможно прочитать свойство undefined» и т. Д.
var badWords = [
'bannedWord1',
'bannedWord2',
'bannedWord3',
'bannedWord4'
];
bot.on('message', message => {
var words = message.content.toLowerCase().trim().match(/w |s |[^sw] /g);
var containsBadWord = words.some(word => {
return badWords.includes(word);
});
Это то, на что я смотрю. var words
строка. в частности (/w |s |[^sw] /g);
.
В любом случае, чтобы реализовать это в моем коде const filter (top / above) или другой подход? Заранее спасибо.
Ответ №1:
Ну, я не уверен, с чем вы пытаетесь это сделать .match(/w |s |[^sw] /g)
. Это какое-то ненужное регулярное выражение только для получения массива слов и пробелов. И это даже не сработает, если кто-то разделит свое плохое слово на что-то вроде «это».
Если вы хотите, чтобы ваш фильтр не учитывал регистр и учитывал пробелы / специальные символы, лучшее решение, вероятно, потребует более одного регулярного выражения, а также отдельных проверок на разделенные буквы и обычной проверки неверных слов. И вам нужно убедиться, что ваша проверка на разделение букв верна, иначе что-то вроде «wash it» может считаться плохим словом, несмотря на пробел между словами.
Решение
Итак, вот возможное решение. Обратите внимание, что это всего лишь решение, и оно далеко не единственное. Я просто собираюсь использовать жестко запрограммированные строковые примеры вместо message.content
, чтобы позволить этому быть в рабочем фрагменте:
//Our array of bad words
var badWords = [
'bannedWord1',
'bannedWord2',
'bannedWord3',
'bannedWord4'
];
//A function that tests if a given string contains a bad word
function testProfanity(string) {
//Removes all non-letter, non-digit, and non-space chars
var normalString = string.replace(/[^a-zA-Z0-9 ]/g, "");
//Replaces all non-letter, non-digit chars with spaces
var spacerString = string.replace(/[^a-zA-Z0-9]/g, " ");
//Checks if a condition is true for at least one element in badWords
return badWords.some(swear => {
//Removes any non-letter, non-digit chars from the bad word (for normal)
var filtered = swear.replace(/W/g, "");
//Splits the bad word into a 's p a c e d' word (for spaced)
var spaced = filtered.split("").join(" ");
//Two different regexes for normal and spaced bad word checks
var checks = {
spaced: new RegExp(`\b${spaced}\b`, "gi"),
normal: new RegExp(`\b${filtered}\b`, "gi")
};
//If the normal or spaced checks are true in the string, return true
//so that '.some()' will return true for satisfying the condition
return spacerString.match(checks.spaced) || normalString.match(checks.normal);
});
}
var resu<
//Includes one banned word; expected result: true
var test1 = "I am a bannedWord1";
result = testProfanity(test1);
console.log(result);
//Includes one banned word; expected result: true
var test2 = "I am a b a N_N e d w o r d 2";
result = testProfanity(test2);
console.log(result);
//Includes one banned word; expected result: true
var test3 = "A bann_eD%word4, I am";
result = testProfanity(test3);
console.log(result);
//Includes no banned words; expected result: false
var test4 = "No banned words here";
result = testProfanity(test4);
console.log(result);
//This is a tricky one. 'bannedWord2' is technically present in this string,
//but is 'bannedWord22' really the same? This prevents something like
//"wash it" from being labeled a bad word; expected result: false
var test5 = "Banned word 22 isn't technically on the list of bad words...";
result = testProfanity(test5);
console.log(result);
Я тщательно прокомментировал каждую строку, чтобы вы понимали, что я делаю в каждой строке. И вот это снова, без комментариев или частей тестирования:
var badWords = [
'bannedWord1',
'bannedWord2',
'bannedWord3',
'bannedWord4'
];
function testProfanity(string) {
var normalString = string.replace(/[^a-zA-Z0-9 ]/g, "");
var spacerString = string.replace(/[^a-zA-Z0-9]/g, " ");
return badWords.some(swear => {
var filtered = swear.replace(/W/g, "");
var spaced = filtered.split("").join(" ");
var checks = {
spaced: new RegExp(`\b${spaced}\b`, "gi"),
normal: new RegExp(`\b${filtered}\b`, "gi")
};
return spacerString.match(checks.spaced) || normalString.match(checks.normal);
});
}
Объяснение
Как вы можете видеть, этот фильтр способен обрабатывать всевозможные знаки препинания, заглавные буквы и даже одиночные пробелы / символы между буквами плохого слова. Однако обратите внимание, что для того, чтобы избежать описанного мною сценария «промыть» (потенциально приводящего к непреднамеренному удалению чистого сообщения), я сделал так, чтобы что-то вроде «bannedWord22» не обрабатывалось так же, как «bannedWord2». Если вы хотите, чтобы он делал обратное (поэтому обрабатывая «bannedWord22» так же, как «bannedWord2»), вы должны удалить обе \b
фразы в регулярном выражении обычной проверки.
Я также объясню регулярное выражение, чтобы вы полностью понимали, что здесь происходит:
[^a-zA-Z0-9 ]
означает «выберите любой символ, не входящий в диапазоны от а до Я, от А до Я, 0-9 или пробел» (это означает, что все символы, не входящие в указанные диапазоны, будут заменены пустой строкой, по существу удаляя их из строки).W
означает «выбрать любой символ, который не является символом слова», где «символ слова» относится к символам в диапазонах от а до Я, от А до Я, 0-9 и подчеркивание.b
означает «границу слова», по сути, указывая, когда начинается или заканчивается слово. Это включает пробелы, начало строки и конец строки.b
экранируется дополнительным\b
), чтобы javascript не путал токен регулярного выражения с escape-последовательностями строк.- Флаги
g
иi
, используемые в обеих проверках регулярных выражений, указывают на «глобальный» и «нечувствительный к регистру» соответственно.
Конечно, чтобы заставить это работать с вашим ботом discord, все, что вам нужно сделать в вашем обработчике сообщений, это что-то вроде этого (и обязательно замените badWords
на свою filter
переменную в testProfanity()
):
if (testProfanity(message.content)) return message.delete();
Если вы хотите узнать больше о регулярных выражениях или хотите поработать с ним и / или протестировать его, это отличный ресурс для этого.
Комментарии:
1. Я нашел способ заставить бота удалять слова, в которых есть строчные и прописные буквы, которые вы можете найти здесь hastebin . На данный момент я мог бы просто поместить каждое слово с пробелами и специальными символами между ними в свой код для фильтра, но это заняло бы целую вечность для каждого ругательного слова. все, что мне нужно, это код, который удаляет такие слова, как «t h i s» и что-то вроде «th.at «но я еще не до конца изучил программирование, хотя и понял то, что вы так подробно объяснили (я поражен. никогда не видел этого раньше!) Не могли бы вы помочь мне, пожалуйста, если это возможно?
2. Конечно, с чем конкретно вам нужна помощь? Этот ответ уже способен удалять такие слова, как «t h i s» и «th.at «. Все, что вам нужно сделать, это добавить слова «this» и «that» к вашему массиву плохих слов (в вашем коде,
filter
массиве), и это не только удалит «this» и «that», но также учтет пробелы и специальные символы, такие как «t h i s» и «th.at «и «т а т» и «th.is «.