我的视图类在 dpy 中响应很奇怪

问题描述 投票:0回答:1

我有一个用于确认的视图类,我在多个命令中使用它,但行为很奇怪,就像有时当我在响应消息上使用命令按钮时已经被禁用,有时当我单击/使用按钮时,即使在它调用 on_timeout 并编辑之后我的消息超时了。

这是我的视图类:

confirm = Button(label="Confirm", emoji=tick, style=discord.ButtonStyle.green, custom_id="confirm")


class ConfirmView(View):
    def __init__(self, ctx, timeout):
        self.ctx = ctx
        super().__init__(timeout=timeout)

    async def on_timeout(self) -> None:
        for i in self.children:
            i.disabled = True
        await self.message.edit(content="Timeout You took too long to respond!", view=None)

    async def interaction_check(self, interaction) -> bool:
        if interaction.user.id == self.ctx.author.id:
            return True
        await interaction.response.send_message("You cannot interact with this view.", ephemeral=True)
        return False

class Cancel(Button):
    def __init__(self):
        super().__init__(label="Cancel", emoji=cross, style=discord.ButtonStyle.red, custom_id="cancel")

    async def callback(self, interaction):
        await interaction.response.edit_message(content="Cancelled!", view=None)

cancel = Cancel()

这是我的命令示例:

@client.command()
async def my_command_1(ctx):
    
    async def callback(interaction):
        # do my stuff here

    view = ConfirmView(ctx=ctx, timeout=30)
    view.add_item(confirm)
    view.add_item(cancel)

    confirm.callback = callback
    view.message = await ctx.send("One", view=view)

@client.command()
async def my_command_2(ctx):
    
    async def callback(interaction):
        # do my stuff here

    view = ConfirmView(ctx=ctx, timeout=30)
    view.add_item(confirm)
    view.add_item(cancel)

    confirm.callback = callback
    view.message = await ctx.send("Two", view=view)

@client.command()
async def my_command_3(ctx):
    
    async def callback(interaction):
        # do my stuff here

    view = ConfirmView(ctx=ctx, timeout=30)
    view.add_item(confirm)
    view.add_item(cancel)

    confirm.callback = callback
    view.message = await ctx.send("Three", view=view)
discord.py nextcord
1个回答
0
投票

您提到的问题有两个;单击按钮后超时并且按钮被禁用。

1.即使点击按钮也超时

发生这种情况是因为视图 timeout 的工作方式。从文档来看,

在不再接受输入之前与 UI 的上次交互的超时时间(以秒为单位)。

禁用 on_timeout 事件的一种方法是使用 stop 方法一起停止监听视图中的交互事件。在您的回调中,

async def callback(self, interaction):
    self.view.stop() # <-
    await interaction.response.edit_message(content="Cancelled!", view=None)

2.超时后禁用

您的代码的逻辑似乎有点不对劲。您将所有按钮设置为禁用,然后编辑消息以使其根本没有任何按钮?

你所说的“行为怪异”其实是

假设您运行command_1,并让它超时。然后运行command_2,按钮将被禁用。但您会注意到,重新启动后它们将不再被禁用。

为了进一步理解这一点,我们必须研究面向对象编程的工作原理。

当您使用

add_item
添加这些按钮时,这些按钮将成为视图子级的一部分。在
on_timeout
中,您将所有子项设置为禁用。这意外地也导致按钮
cancel
confirm
保留属性
disabled=True

所以现在,当您再次使用该类时,按钮将被禁用,直到您重新启动代码,所有内容都会再次启用。

您可以通过添加打印语句来看到这一点。

@client.command()
async def command_2(ctx):
    async def callback(interaction):
        ...
    print(cancel.disabled) # <- prints "True"
    view = ConfirmView(ctx=ctx, timeout=5)
    view.add_item(confirm)
    view.add_item(cancel)

    confirm.callback = callback
    view.message = await ctx.send("Two", view=view)

运行 command_1,让它超时,然后运行 command_2,将显示

disabled
变量本身等于 True。
为了避免这种情况,您可以创建按钮的新实例。

cancel

© www.soinside.com 2019 - 2024. All rights reserved.