使用discord.py过滤掉坏词,其他命令都不行

Using discord.py to filter out bad words, no other commands will work

我正在尝试使用 discord.py 在我的 discord bot 上创建一个过滤不良词的过滤器。到目前为止,这是我的代码:

with open('badwords.txt') as file:
    file = file.read().split()
@bot.event
async def on_message(message):

    channel = bot.get_channel(my_log_channel)
    mybot = bot.get_user(my_bot_id)
    #.. some custom embed ..

    if message.author is mybot:
        return

    for badword in file:
        if badword in message.content.lower():
            await message.delete()
            await channel.send(embed=embed)

目前主要有两个问题。更大的是不会执行其他命令。

我试过添加

    else:
        await bot.process_commands(message)

到第二个 if 语句的末尾,但是每个命令都被执行了两次。

我遇到的第二个问题是,如果我想将“ass”这个词列入黑名单,它也会自动删除“pass”等词。我想避免这种情况。

我真的很感谢这方面的帮助,我对 discord 机器人有点陌生,我被困在这里了。 提前致谢!

如果您的文件中没有任何内容,那么它甚至不会进入 for 循环。此外,如果消息中不存在该特定的坏词,它将调用剩余的命令并转到下一个词,这就是重复调用您的命令的原因。

所以,试试这个:

with open('badwords.txt') as file:
    file = file.read().split()

@bot.event
async def on_message(message):
    channel = bot.get_channel(my_log_channel)
    mybot = bot.get_user(my_bot_id)
    #.. some custom embed ..

    if message.author is mybot:
        return

    flag = False
    for badword in file:
        if badword in message.content.lower():
            await message.delete()
            flag = True

    if not flag:
        await bot.process_commands(message)

虽然使用简单的 for 循环来查找坏词是有效的,但人们会变得有创意并且可能会使用空格仍然说出它们,例如,v e r y b a d w o r d。你的机器人不会检测到它,也无法删除它。

代码

import re
import string

separators = string.punctuation+string.digits+string.whitespace
excluded = string.ascii_letters

word = "badword"
formatted_word = f"[{separators}]*".join(list(word))
regex_true = re.compile(fr"{formatted_word}", re.IGNORECASE)
regex_false = re.compile(fr"([{excluded}]+{word})|({word}[{excluded}]+)", re.IGNORECASE)

profane = False
if regex_true.search(message.content) is not None\
    and regex_false.search(message.content) is None:
    profane = True

分析

separators 包含可插入禁用词字母之间但仍被标记为亵渎的字符。

excluded 包含可以插入到禁用词的字母之间并被标记为不亵渎的字符。

separatorsexcluded 可以根据应该或不应该允许哪些字符来划分亵渎词来修改。

word 是一个示例坏词,将对其进行测试以确定正则表达式的有效性。

formatted_word 是一个包含字符集,它匹配 separators

中的零个或多个字符

regex_true return 如果在单词的字母之间检测到 separators 中的任何字符检测到禁用单词,则为匹配对象。请注意,分隔每个字母的字符数与其他字母无关,因此如果 'word' 是禁用词,'w!o@#r$%^d' 将 return 匹配。

regex_false return 当检测到禁用词本身且 excluded 中的一个字符位于该词之前或之后时,它是一个匹配对象。这意味着该词实际上是另一个词的一部分,例如'ass' 在 'pass'.

如果 regex_true return 是匹配对象而 regex_false 不是,则根据上述条件,检测到的匹配应被视为包含禁用词。

示例

鉴于word = "word"并且使用了上面的代码,下面是各种测试消息的结果。请记住,如果 regex_true 有匹配集而 regex_false 没有匹配集,则 profane = True.

>>> regex_true.search("word")
<re.Match object; span=(0, 4), match='word'>
>>> regex_false.search("word")
>>> #profane=True
>>> regex_true.search("aworda")
<re.Match object; span=(1, 5), match='word'>
>>> regex_false.search("aworda")
<re.Match object; span=(0, 5), match='aworda'>
>>> #profane=False
>>> regex_true.search("w1o~r d")
<re.Match object; span=(0, 7), match='w1o~r d'>
>>> regex_false.search("w1o~r d")
>>> #profane=True

我没有使用文本文件,我制作了一个过滤词列表,这是我的代码:

filtered_words = ["Example1","Example 2","ex 3"]

@bot.event
async def on_message(msg):
    for word in filtered_words:
        if word in msg.content:
         await msg.delete()

    await bot.process_commands(msg)