How to make a discord button work ONLY for command user?

5.7k Views Asked by At

Here's an example basic button:

button = Button(label="This is a button", style=discord.ButtonStyle.blurple)
async def button_callback(interaction):
    await interaction.response.edit_message(embed=some_embed)
button.callback = button_callback

But a button like this can be used by anyone, which is not what I want. I know a method to allow only the command user to use button, which is this one:

button = Button(label="BACK", style=discord.ButtonStyle.blurple)
async def button_callback(interaction):
   if interaction.user == ctx.author:   
      await interaction.response.edit_message(embed=some_embed)
   else:
      await ctx.send("that is not your button") 
back_button.callback = button_callback

We use an if statement to check if the button-clicker is the ctx.author (or command user) but I do not want others to be able to click the button. I want the button to be disabled for other people. If you do not know a method to disable the button for other people, is there at least a better way to do this than just send "that is not your button"?

2

There are 2 best solutions below

0
On

I am not sure if you are using a third party package to do this, but with the official discord.py 2.0 alpha version you can override the interaction check in the View class, like this:

async def interaction_check(self, interaction: discord.Interaction):
    return interaction.user.id == ctx.author.id

For that, you should subclass the Button into its own View class, something like this will work:

class MyButton(discord.ui.View):
    def __init__(self, author):
        self.author = author
        super().__init__()

    @discord.ui.button(label="Back", style=discord.ButtonStyle.blurple)
    async def back(self, interaction: discord.Interaction, button: discord.ui.Button):
        print("button pressed")
        # do whatever here

    async def interaction_check(self, interaction: discord.Interaction):
        return interaction.user.id == self.author.id


[...]

@bot.command()
async def button_test(ctx):
    view = MyButton(ctx.author)
    await ctx.send(view=view)

https://discordpy.readthedocs.io/en/master/interactions/api.html?highlight=interaction%20check#discord.ui.View.interaction_check

0
On

you would want to subclass the view to achieve this and overwrite the interaction_check like :

class MyView(View):
def __init__(self, author: typing.Union[discord.Member, discord.User]):
    self.author = author
    super().__init__()

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

now, inside your command, you need to define your View you will attach later

view = MyView(ctx.author) # or inter.author if you use slash commands. 

so you will want to have something like :

button = Button(label="This is a button", style=discord.ButtonStyle.blurple)
view.add_item(button) # we defined the view above.