首页 > 解决方案 > Discord 按钮全部同时触发。不和谐.py

问题描述

我正在尝试在我的不和谐机器人上创建审核,将单词标记为不恰当,然后允许审核团队轻松禁止/超时用户,而无需在活动期间在场。所有的审核都有效,但前提是我运行了一次代码。如果有多个按钮组,当其中一个被按下时,它们都会同时触发。例如,如果我在一条消息上按下了禁止按钮,它将禁止所有发言不当的用户,而不仅仅是禁止一个人。

我该如何解决?

编辑:我设法解决了我的所有按钮都被一次按下的问题,并且遇到了一个新按钮。现在,当按下一个按钮时,如果按下其余按钮,它们就会失败。很明显,代码正在解析 button_cxt 的所有实例,但我不确定如何防止或解决它。

更新代码:

@bot.event
async def on_profanity(message, word):

    try:
        guildID = message.guild.id
        guild = bot.get_guild(guildID)
        channel = discord.utils.get(guild.text_channels, name="moderation-logs")
        channel_id = channel.id
    except:
        return None

    channel = bot.get_channel(channel_id) 
    embed = discord.Embed(title="Profanity Alert!", description=f"{message.author.name} just said ||{message.content}||. The bad word was: ||{word}||", color=discord.Color.blurple()) # Let's make an embed!
    await channel.send(embed=embed)

    buttons = [
            manage_components.create_button(
                style=ButtonStyle.red,
                label="Ban!",
                custom_id="ban"
            ),
            manage_components.create_button(
                style=ButtonStyle.gray,
                label="Give them a Warning",
                custom_id="warning"
            ),
            manage_components.create_button(
                style=ButtonStyle.green,
                label="Nope!",
                custom_id="noBan"
            ),
          ]

    ActionRow = manage_components.create_actionrow(*buttons)

    if "warning" in [y.name.lower() for y in message.author.roles]:
        botMessage = await channel.send("They have already been warned. Do you wish to ban them?", components=[ActionRow])
    else:
        botMessage = await channel.send("Do you wish to ban them?", components=[ActionRow])


    button_ctx: ComponentContext = await manage_components.wait_for_component(bot, components=ActionRow)
    origin_id = button_ctx.origin_message.id

    if (botMessage.id == origin_id):
        await botMessage.delete()
        if button_ctx.custom_id == "ban":    
            await channel.send("The deed has been done.")
            bot.dispatch('ban', message, guild)

        elif button_ctx.custom_id == "warning":
            await channel.send("The warning has been sent!")
            bot.dispatch('warning', message, guild, channel)

        elif button_ctx.custom_id == "noBan":
            await channel.send("No action taken")

标签: discord.py

解决方案


所以我花了很长时间,有些思考,但我终于解决了这个问题。问题在于这两个部分:

button_ctx: ComponentContext = await manage_components.wait_for_component(bot, components=ActionRow)

按钮上下文正在侦听具有组件 ActionRow 的任何按钮,这是我所有按钮的所有组件。因此,所有按钮都会立即触发它们的函数实例。我的小检查意味着只有按下的那个才起作用,但它并没有阻止其余按钮触发该事件侦听器。

因此,我想到的解决方法是递归地重新启动所有侦听器,如果它们没有被按下的话。执行按下按钮的操作,然后重新启动其余功能。因此,我现在运行的代码如下所示:

@bot.event
async def on_profanity(message, word):

    try:
        guildID = message.guild.id
        guild = bot.get_guild(guildID)
        channel = discord.utils.get(guild.text_channels, name="moderation-logs")
        channel_id = channel.id
    except:
        return None

    channel = bot.get_channel(channel_id) 
    embed = discord.Embed(title="Profanity Alert!", description=f"{message.author.name} just said ||{message.content}||. The bad word was: ||{word}||", color=discord.Color.blurple())
    await channel.send(embed=embed)

    buttons = [
        manage_components.create_button(
            style=ButtonStyle.red,
            label="Ban!",
            custom_id="ban"
            ),
        manage_components.create_button(
            style=ButtonStyle.gray,
            label="Give them a Warning",
            custom_id="warning"
            ),
        manage_components.create_button(
            style=ButtonStyle.green,
            label="Nope!",
            custom_id="noBan"
            ),
          ]

    ActionRow = manage_components.create_actionrow(*buttons)

    if "warning" in [y.name.lower() for y in message.author.roles]:
        botMessage = await channel.send("They have already been warned. Do you wish to ban them?", components=[ActionRow])
    else:
        botMessage = await channel.send("Do you wish to ban them?", components=[ActionRow])

    await modButtons(guild, message, channel, botMessage, ActionRow)



async def modButtons(guild, message, channel, botMessage, ActionRow):

    button_ctx: ComponentContext = await manage_components.wait_for_component(bot, components=ActionRow)
    origin_id = button_ctx.origin_message.id

    if (botMessage.id == origin_id):
        await botMessage.delete()
        if button_ctx.custom_id == "ban":    
            #await channel.send("The deed has been done.")
            bot.dispatch('ban', message, guild)

        elif button_ctx.custom_id == "warning":
            #await channel.send("The warning has been sent!")
            bot.dispatch('warning', message, guild, channel)

        elif button_ctx.custom_id == "noBan":
            await channel.send(f"No action taken for {message.author.name}")

    else:
        await modButtons(guild, message, channel, botMessage, ActionRow) #recursion HERE!

推荐阅读