当前位置: 首页 > 知识库问答 >
问题:

Discord机器人添加并等待测验游戏的反应

戚哲
2023-03-14

我正在使用discordpy编写一个discord测验机器人。机器人发送一条包含问题和4个可能答案的消息。机器人还使用表情符号1为其信息添加反应️⃣, 2.️⃣, 3.️⃣ 四,️⃣. 这个想法是,机器人等待30秒,让人们点击其中一个反应。如果单击的反应是正确/错误的答案,则bot会回答正确或错误。一旦有人回答,机器人也应该停止等待新的反应。Aka:一旦有人点击了4个反应表情中的一个,机器人就会回复,而不会处理对该消息的任何未来反应。

目前,我让机器人发送消息(嵌入),并将反应表情添加到其中。然而,从人民那里获得结果是我的问题所在。

首先,由于某种原因,机器人似乎仍然会被自己的反应触发,即使我在check函数中排除了这一点。(至少我是这么想的)。

总的来说,我希望有一个结构良好的方法来解决这个问题。我熟悉所有的api调用/事件,例如message()上的和reaction\u add()上的,但我很难将所有内容正确地组合在一起。

这是我到目前为止所拥有的:

@commands.command(name="quiz")
    async def on_command_quiz(ctx):

        #if ctx.message.author.bot:
        #    return   

        print("Quiz command!")
        quiz = QuizGame()

        # Send quiz
        reply = await ctx.message.channel.send(embed=quiz.format())

        # Add reply emojis
        for x in range(0, len(quiz.quiz_answers)):
            await reply.add_reaction(Utils.get_number_emoji_by_number(x + 1))
        print("Correct Answer:", quiz.quiz_correct_answer)

        # Evaluate replies
        async def check_answer(reaction, user):        
            emojis = ["1️⃣","2️⃣","3️⃣","4️⃣"]
            return user != ctx.message.author and str(reaction.emoji) in emojis

        # Wait for replies
        try:
            reaction, user = await bot.wait_for('reaction_add', timeout=30.0, check=check_answer)
        except asyncio.TimeoutError:
            print("Timeout")
        else:
            if user != ctx.message.author:
                if str(reaction.emoji) == "1️⃣":
                    print("1")
                elif str(reaction.emoji) == "2️⃣":
                    print("2")
                elif str(reaction.emoji) == "3️⃣":
                    print("3")
                elif str(reaction.emoji) == "4️⃣":
                    print("4")
                else:
                    print("Unknown reaction")

我怎样才能做到这一点?


共有2个答案

施誉
2023-03-14

你并没有真正忽略机器人的反应,至少从代码中我可以看到。可以试试以下方法:

            try:
                reaction, user = await self.bot.wait_for('reaction_add', timeout=15)
                while user == self.bot.user:
                    reaction, user = await self.bot.wait_for('reaction_add', timeout=15)
                if str(reaction.emoji) == "YourEmoji":

检查功能可以是:

        reactions = "YourReactions"

        def check1(reaction, user):
            return user == ctx.author and str(reaction.emoji) in [reactions]

这里我们检查反应是否来自命令的作者,还检查表情符号是否在反应列表中。

宰父俊彦
2023-03-14

您的代码中有几个错误和一些不准确之处;首先我将列出它们,然后我将向您展示我认为设置这种类型命令的最佳方法。请注意,以下一些不是实际的修复,而是组织代码的更有效方法。

-您应该使用decorator来定义bot命令,而不是使用像on_command这样的函数

@bot.command()
async def quiz(ctx)

-ctx类已经提供了channel属性,因此ctx.message.channel有点冗余,请改用ctx.channel

同样适用于ctx.message.author

-如果答案的数量总是相同的,那么您可以使用非常简单的for循环添加数字表情(也不需要调用Utils来获取相关表情):

for emoji in ["1️⃣","2️⃣","3️⃣","4️⃣"]:
    reply.add_reaction(emoji)

+check_answer函数也是多余的,逻辑上也是错误的。

它是多余的,因为不需要验证反应表情符号是4个可用表情符号中的一个,因为它将在稍后的try块中确定。

它在逻辑上是错误的,因为如果添加反应的用户与命令的作者匹配,它应该返回True,而不是相反(您会注意到这也将防止机器人被自己的反应触发)。

那么,函数就没有必要异步了。

def check_answer(reaction, user):
    return user == ctx.author

-最后,整个try-except-else块在这里并不真正起作用。为了使bot保持响应,直到特定用户的第一个反应或30秒超时过期,您应该将try-except块集成到无限while循环中:

while True:
    try:
        reaction, user = await bot.wait_for("reaction_add", timeout=30, check=check_answer)
    
        # The following line is optional: it removes the reaction added by the user 
        # to let them react again with the same emoji; not really necessary in your case, 
        # but very helpful if your bot would still be responsive after the first reaction.
        await reply.remove_reaction(reaction, user) 

        # Here goes the if-else block of reactions.

    except asyncio.TimeoutError:
        print("Timeout")

请记住,在try块的某个地方,当操作完成时,必须使用break语句停止循环,否则它将无限期地继续。

我正在开发一个Discord机器人,而且还是一个初学者,所以我希望我能够很好地解释。总之,下面是我个人如何实现该命令的一个示例:

@bot.command()
async def quiz(ctx):

    print("Quiz command!")
    quiz = QuizGame()

    reply = await ctx.send(embed=quiz.format())

    emojis = ["1️⃣","2️⃣","3️⃣","4️⃣"]
    for emoji in emojis:
        await reply.add_reaction(emoji)

    def check_answer(reaction, user):
        return user == ctx.author

    while True:
        try:
            reaction, user = await bot.wait_for("reaction_add", timeout=30, check=check_answer)
            await reply.remove_reaction(reaction, user)

            # Shorter representation of that if-else block.
            if reaction.emoji in emojis:
                print(emojis.index(reaction.emoji) + 1)
                break
            else:
                print("Unknown reaction")

        except asyncio.TimeoutError:
            print("Timeout")

然后你当然应该定义如何识别正确答案以及如何通知用户。如果你需要澄清我写的内容,请随时评论这个答案,我很乐意回答你。

 类似资料:
  • 我想测试我的代码是否正确地从API下载数据(使用改装),并在RecyclerView中显示它们。为了做到这一点,我创建了一个模拟API的拦截器(基于此解决方案),并创建了一个测试(使用Robolectric): 问题是测试有时通过,有时失败。我已经调试了代码,我知道这是因为MyListFragment中的数据是使用Reformation的enqueue()方法加载到rv\U fruits中的。如何

  • 有没有可能让我的不和谐机器人发送消息,而不必在不和谐中键入命令?相反,我想从我的应用程序内部触发它。 上面的代码给出了一个属性错误:'NoneType'对象没有属性'send'

  • 直到最近,我的Discord机器人一直工作得很好,我没有对代码做任何更改,它与工作时处于相同的状态。但是出于某种原因,现在当我尝试通过控制台启动bot时(在我的情况下): 节点my-discord-bot.js 它什么也不做,没有错误,只是空白,我应该收到一个确认,说‘准备好了!’我的机器人应该上线,但这一切都不会发生。 下面是我用来启动我的bot(直到最近才开始工作)的代码: 我真的不知道问题出

  • 1.自我介绍 2.为什么投游戏测试岗位? 3.对游戏测试工作有什么了解? 4.游戏测试都需要做什么? 5.平时玩什么游戏 6.一天会花多长时间在游戏 7.最近玩了什么游戏 8.端游呢? 9.对我们公司有什么了解? 10.对工作的计划? 11.linux操作命令 12.对数据库的增删改查了解吗?删除是什么? 13.sql插入语句 14.能接受加班吗? 15.反问

  • 每2个玩家,服务器将创建1个房间(我的游戏是PvP,一对一) 每个房间处理游戏逻辑 我将使用作为我的游戏循环 服务器FPS=5 每个房间都可以处理玩家的移动和一些物理操作 关于实际问题: 基于下面的点数,我应该使用什么样的游戏循环?下面每种类型的游戏循环的利弊是什么。 null

  • 我对Javascript了解不多,所以请耐心听我说。 所以,我想为我的不和谐机器人发出命令。基本上,我想发生的是,当你发布“!记录”,我想让机器人发送一个RichEmbed与2个选项,你可以选择。 我已经把那部分搞定了。这正是我想要的。它发送带有两个选项的RichEmbed。 接下来我想做的是,当您发送“1”或“2”时,我希望Bot回复正确的记录。这是我不能理解的部分。以下是所有代码: 有人能概括