用 Python 编写的简单 Discord 聊天机器人,用作具有多个数据源的字典

Simple Discord chatbot written in Python that serves as a dictionary with multiple data sources

提问人:smithmarci 提问时间:10/8/2023 最后编辑:smithmarci 更新时间:10/21/2023 访问量:54

问:

我想用一个聊天机器人来帮助我在 Discord 上的翻译社区,该聊天机器人可以用作字典、词汇数据库,但词库的大小将是巨大的,我想将数据源拆分为几个单独的文件,就像他们在印刷词典中处理首字母的字母索引一样。我有一个基本程序代码,它已经适用于一个文件,但我不知道如何实现多文件查找和评估方法。对不起,我的英语不好(显然,这不是我的母语)!另外,请耐心等待,因为我是编程菜鸟! 你能帮我解决这个问题吗?

这些是我的文件。它旨在仅回复私人消息并在 DM 中进行交流。

我的数据源 #1 pool0_help.py

def get_response(message: str) -> str:
    p_message = message.lower()
    
    #HELP MESSAGE
    #------------

    if p_message == '?help':
        return 'Type in any name or phrase that comes to your mind, and I will tell you what its equivalent is in your language.\r\n \r\nTo see all phrases under index B, type: poolB'

    #FALLBACK
    #--------

    return 'I am not sure I understood it correctly!'

我的潜在数据源 #3 pool2_B.py

def get_response(message: str) -> str:
    p_message = message.lower()
    
    #INDEX B
    #-------
    
    poolB = [
        "**baldur\'s gate**" , 
        "**baldur\'s mouth gazette**" , 
        "**beastlands**" , 
        "**blighted village**" , 
        "**blushing mermaid**"
    ]
    
    if p_message == "b-index":
        return '? *B* ::\r\n> ' + str(poolB)

    if p_message == 'baldur\'s gate':
        return '? *' + p_message + '*\r\n= **Baldurkapuja**'

    if p_message == 'baldur\'s mouth gazette':
        return '? *' + p_message + '*\r\n= **Baldur Szája Hírmondó**'

    if p_message == 'beastlands':
        return '? *' + p_message + '*\r\n= **Fenevadföld**'

    if p_message == 'blighted village':
        return '? *' + p_message + '*\r\n= **Felégetett falu**'

    if p_message == 'blushing mermaid':
        return '? *' + p_message + '*\r\n= **Piruló sellő**'

    #FALLBACK
    #--------

    return 'There is no such word, name or pharse in my database, sorry!'

bot.py

import discord
import pool0_help
import pool1_A
import pool2_B
import pool3_C

async def send_message(message, user_message, is_private):
    try:
        response = pool0_help.get_response(user_message)
        await message.author.send(response) if is_private else await message.author.send(response)

    except Exception as e:
        print(e)

def run_discord_bot():
    TOKEN = 'my Discord token'
    intents = discord.Intents.default()
    intents.members = True
    #intents.message_content = True
    client = discord.Client(intents=intents)

    @client.event
    async def on_ready():
        print(f'{client.user} is now running!')
    
    @client.event
    async def on_message(message):
        if message.author == client.user:
            return
        
        username = str(message.author)
        user_message = str(message.content)
        channel = str(message.channel)

        print(f'{username} said: "{user_message}" in ({channel})')

        if user_message[0] == '!':
            user_message = user_message[1:]
            await send_message(message, user_message, is_private=True)
        else:
            await send_message(message, user_message, is_private=True)

    client.run(TOKEN)

main.py

import bot

if __name__ == '__main__':
    bot.run_discord_bot()

正如我之前提到的,它按预期与一个数据源(在本例中为“pool0_help.py”)一起工作。但无论我如何尝试,我都无法让它处理更多文件。

存储起来很不方便,编辑一个包含数百个单词的文件也很麻烦,这就是为什么我想将其拆分为更小的词池。

请您告诉我要修改什么以及如何使这本词典工作吗?这对我们来说将是一个巨大的帮助!任何帮助将不胜感激!先谢谢你!

python 拆分 数据源 聊天机器人

评论

0赞 David 10/10/2023
您好,欢迎来到 Stack Overflow!您能否编辑您的答案并使用确切的错误消息(以 开头的行)进行更新?谢谢!Traceback (most recent call last):
0赞 David 10/10/2023
或者,没有错误吗?在这种情况下,预期结果是什么,实际结果是什么?
0赞 smithmarci 10/13/2023
你好大卫,当我使用一个导入的源文件(“pool0_help.py”)运行脚本时,它根本没有给出任何错误,它按应有的方式工作。我的问题是,我缺乏必要的技能来添加其他(或更多)来源,并找到一个可行的解决方案。这应该如下:当有人使用以字母“A”开头的单词进行查询时,程序应从相应的文件(“pool1_A.py”)中选择答案,并忽略所有其他回退。当一个人使用“B”字进行查询时,他们应该从其他词库('pool2_B.py)中得到答案。依此类推。
0赞 David 10/13/2023
我在下面发布了您问题的答案。
1赞 smithmarci 10/17/2023
先生,方法 #2 就像一个魅力!我不得不在方法 #1 中添加一行才能使其工作,因为如果没有它,我只从第一个池文件中得到“答案”,而没有从其他文件中得到“答案”。对于第一个导入文件中没有的每个单词,我都收到以下错误消息:“400 错误请求(错误代码:50006):无法发送空消息”。因此,我进行了一些挖掘,并找到了一个解决方案,该解决方案在第一个“await”命令(?)之前使用“if response:”。通过此添加,方法 #1 也按照您在答案中的描述工作。我真的很感谢你的帮助!我的问题解决了,多亏了你!

答:

0赞 David 10/13/2023 #1

您需要以某种方式确定需要为每条传入消息使用哪个消息。在这里,您有两种选择:要么尝试每个池,直到其中一个池正常工作,要么创建一些事先确定池的逻辑。pool


方法一:尝试每个池,直到它起作用

要尝试每个池,您可以将池放入一个,然后调用直到您得到一些东西。如果选择此选项,则如果响应不匹配,池中的函数应返回(即 no return 语句)。例如:listget_responseget_responseNone

# pool0_help.py
def get_response(message: str) -> str:
    p_message = message.lower()

    if p_message == '?help':
        return 'Type in any name or phrase that comes to your mind, and I will tell you what its equivalent is in your language.\r\n \r\nTo see all phrases under index B, type: poolB'
# pool2_B.py
def get_response(message: str) -> str:
    p_message = message.lower()

    poolB = [
        "**baldur\'s gate**" , 
        "**baldur\'s mouth gazette**" , 
        "**beastlands**" , 
        "**blighted village**" , 
        "**blushing mermaid**"
    ]
    
    if p_message == "b-index":
        return '? *B* ::\r\n> ' + str(poolB)

    # a bunch more `if`s...
# bot.py
import pool0_help
import pool1_A
import pool2_B
import pool3_C

POOLS = [pool0_help, pool1_A, pool2_B, pool3_C, ...]

async def send_message(message, user_message, is_private):
    try:
        for pool in POOLS:
            response = pool.get_response(user_message)
            if not response:
                continue
            await message.author.send(response) if is_private else await message.author.send(response)
            return
        await message.author.send('Unknown message') if is_private else await message.author.send('Unknown message')
    except Exception as e:
        print(e)

# ... rest of your code ...

方法二:使用首字母对应的池

要事先检查要使用的池,可以创建一个 从第一个字母到模块对象。您的可能看起来像:dictpoolbot.py

# bot.py
import pool0_help
import pool1_A
import pool2_B
import pool3_C

POOLS = {'?': pool0_help, 'a': pool1_A, 'b': pool2_B, 'c': pool3_C, ...}

async def send_message(message, user_message, is_private):
    try:
        ch = user_message[0]
        if ch not in POOLS:
            await message.author.send('Unknown message') if is_private else await message.author.send('Unknown message')
        response = POOLS[ch].get_response(user_message)
        await message.author.send(response) if is_private else await message.author.send(response)
    except Exception as e:
        print(e)

# ... rest of your code ...