使用后禁用按钮

disable a button after being used

最近我决定重写我的 discord 机器人并添加按钮。 到目前为止,我遇到的主要问题是,我无法在按下按钮后 禁用按钮 人们告诉我 button.disabled=True 实际上,它会禁用按钮, 但它只是将其发送为禁用状态,因此永远不能按下它。我想要的是能够单击它并执行它,然后禁用它。

作为参考,我会放一些代码

我使用 disnake,一个 discord.py 分支,它的语法确实与 dpy 相同,但我们有按钮和斜杠命令、下拉菜单等

class BlurpleButton(Button):
    def __init__(self, label, emoji=None):
        super().__init__(label=label, style=discord.ButtonStyle.blurple, emoji=emoji)

这是为了更方便地使用按钮,我创建了一个模板,我可以在任何命令上使用它

class CustomView(View):
    def __init__(self, member: disnake.Member):
        self.member = member
        super().__init__(timeout=180)

    async def interaction_check(self, inter: disnake.MessageInteraction) -> bool:
        if inter.author != self.member:
            await inter.response.send_message(content="You don't have permission to press this button.", ephemeral=True)
            return False
        return True

这是为了让按钮只能由提到的成员按下,例如如果我这样做 /test @member(由于不一致的新特权意图,我迁移到斜线命令)只有成员能够按下它,没有其他人。

到目前为止一切正常,现在我们在命令中“assemble”之后

@commands.slash_command(description='test')
    async def test(self, inter):

         (do stuff in there)
         . . .
        button1 = BlurpleButton("Button name")
        view=CustomView(member)
        view.add_item(button1)

        async def button_callback(inter):
            await inter.send(embed=embedname2)

        button1.callback = button_callback
        await inter.send(embed=embed1, view=view)

再一次,这段代码正在做它打算做的事情,发送一个嵌入(让我们只说我放在哪里......是几个嵌入)并附加到我们有的嵌入 button1当它被点击时,它会发送 embedname2 并且有些地方不再工作了,我在发送 embedname2 之后继续以任何方式尝试,如果我添加,该按钮会通过单击一次来禁用自身button1.disabled=True 在回调中,按钮将被禁用而不会被点击。我将回调放在命令中的主要原因是当按钮触发时能够使用嵌入,如果我把它放在子类按钮或视图中我不能再这样做了。

所以这就是我的全部问题,如果您知道更好的解决方法,包括使用嵌入,并且只有成员可以按下按钮,请告诉我,我花了一个多星期的时间来解决这个问题,我可以'没弄对

我倾向于并建议为每个视图回调创建新的 classes。这样我就可以更轻松地处理多个按钮,并且更易于阅读。随意相应地编辑我的代码,我会留下评论作为指导

首先,给您的 BlurpleButton 一个自定义 ID,或者让用户在 class

中定义一个
(label=label, style=discord.ButtonStyle.blurple, emoji=emoji, custom_id="bttn1") # bttn1 is your custom ID, you'll use it to select this button from the view when disabling it or modifying its contents

在你的回调中,试试这个代码:

b = [x for x in self.children if x.custom_id == "bttn1"][0] # Selects the blurpleButton from the view's buttons based on the custom_id
b.disabled = True # Disable

然后通过使用此新视图编辑您的消息来完成它

await inter.response.edit_message(view=self) # Edit that the buttons are attached to, but replacing the view with the new one containing our edits (disabling the button)

我使用 Pycord,而不是 Disnake,但这应该可以。您可能必须在此处或按钮回调中更改确切的方法调用。

async def interaction_check(self, inter: disnake.MessageInteraction) -> bool:
    if inter.author != self.member:
        await inter.response.send_message(content="You don't have permission to press this button.", ephemeral=True)
        return False

    # The interaction is allowed, so let's disable the button.
    # Interactions have a data field that stores the custom ID of the
    # component sent the interaction. We will use this to find our button
    # in the view.

    button_id = iter.data["custom_id"]
    [child for child in self.children if child.custom_id == button_id][0].disabled = True
    await inter.edit_original_message(view=self)

    # From this point on, you will be dealing with inter.followup, since
    # an interaction can only be responded to once.
    
    return True

说明

您可以通过在按钮的回调中将 button.disabled 设置为 True 来完成此操作。然后,您还需要编辑原始邮件以反映此更改。

代码

    @commands.slash_command(description='test')
    async def test(self, slash_inter: disnake.ApplicationCommandInteraction, member: disnake.Member):

        view = CustomView(member)
        button1 = BlurpleButton("TEST")
        view.add_item(button1)

        async def button_callback(button_inter: disnake.MessageInteraction):
            button1.disabled = True
            await button_inter.send(embed=embedname2)
            await slash_inter.edit_original_message(view=view)

        button1.callback = button_callback

        await slash_inter.send(embed=embed1, view=view)

注意:要使 /test @member 正常工作,您需要在斜杠命令中添加一个 disnake.Member 参数。

参考

disnake.MessageInteraction

disnake.ui.Button.callback

disnake slash commands