pythonpycord

How do I send a modal after a deferred button call in Pycord?


I'm trying to defer a button call and then send a modal afterward in Pycord. Here's a portion of my code:

class AddItemButton(Button):  # Button class from discord.ui.Button
    def __init__(self, title):
        super().__init__(style=discord.ButtonStyle.blurple, label="Add Item", emoji="➕")
        self.title = title  # Title is just something from the database to access things

    async def callback(self, interaction):
        await interaction.response.defer()  # Defer the call
        # -- Add deletion if there's one or more items in the database --
        fetch_one = itemsExistInList(title=self.title, user_id=interaction.user.id)

        if fetch_one and self.view.get_item("delete"):
            self.view.add_item(ItemDeleteSelect(title=self.title, user_id=interaction.user.id))

        await self.view.message.edit(view=self.view)
        await interaction.response.send_modal(AddItemModal(message=self.view.message, title=self.title))  
        # ^ Attempt a response

Specifically this portion:

await interaction.response.send_modal(AddItemModal(message=self.view.message, title=self.title))

When I try the above, I get the following error:

discord.errors.InteractionResponded: This interaction has already been responded to before

Because the interaction has already been responded to, I decided to use a followup. A followup in Pycord is:

Returns the followup webhook for followup interactions.

When I attempted to exchange the previous line with:

        await interaction.followup.send_modal(AddItemModal(message=self.view.message, title=self.title))

It returned:

    await interaction.followup.send_modal(AddItemModal(message=self.view.message, title=self.title))
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'Webhook' object has no attribute 'send_modal'

Solution

  • After some research, it turns out you can't send a modal after a button defer. This is because Pycord's followup returns a Webhook object which: Webhook params

    See here


    This means you can't send a modal through the webhook. The solution to this is to not defer the webhook. Code:

    class AddItemButton(Button):
        def __init__(self, title):
            super().__init__(style=discord.ButtonStyle.blurple, label="Add Item", emoji="➕")
            self.title = title
    
        async def callback(self, interaction):
            await interaction.response.send_modal(AddItemModal(message=self.view.message, title=self.title))
    
    
            await self.view.message.edit(view=self.view)```