Search code examples
pythondiscorddiscord.pydiscord-buttons

How do I set a button that can only be pressed with a specific role?


This is the code:

class SimpleView(discord.ui.View):
    def __init__(self):
         self.start_time = None
         self.stop_time = None
         super().__init__(timeout=None)
        
        



    @discord.ui.button(label="𝑬𝑡𝑻𝑹𝑨𝑻𝑨⬆️", style=discord.ButtonStyle.green, custom_id="1")
    @commands.has_role("πŸ™β€β™‚οΈ FUORI SERVIZIO")
    async def entrata(self, interaction: discord.Interaction, button: discord.ui.Button):
            
            orario_it = datetime.now(pytz.timezone('Europe/Rome'))
            orario = orario_it.strftime('%H:%M')


            SimpleView.start_time = time.time()

            channel = bot.get_channel(1214495527924928522)           
            embed=discord.Embed(color=0x23a559)
            embed.set_thumbnail(url="https://shft.cl/img/c/cdn.discordapp.com-101395680655364460.webp")
            embed.add_field(name="⬆️𝑬𝑡𝑻𝑹𝑨𝑻𝑨⬆️", value="", inline=False)                                 #BOTTONE ENTRATA
            embed.add_field(name="NOME:", value=f"{interaction.user.mention}", inline=True)
            embed.add_field(name="", value="", inline=True)
            embed.add_field(name="", value="", inline=False)
            embed.add_field(name="", value="", inline=False)
            embed.add_field(name="DATA:", value=f"{data}", inline=True)
            embed.add_field(name="ORARIO:", value=f"{orario}", inline=True)
            embed.set_footer(text="ARMERIA200")
            await channel.send(embed=embed)
            await interaction.response.send_message(f"***SEI ENTRATO IN SERVIZIO ALLE: {orario}.***", ephemeral=True)


    @discord.ui.button(label="𝑼𝑺π‘ͺ𝑰𝑻𝑨⬇️", style=discord.ButtonStyle.red, custom_id="2")
    @commands.has_role("πŸ™‹β€β™‚οΈ IN SERVIZIO")
    async def uscita(self, interaction: discord.Interaction, button: discord.ui.Button):
            
            orario_it = datetime.now(pytz.timezone('Europe/Rome'))
            orario = orario_it.strftime('%H:%M')

            
            SimpleView.stop_time = time.time()
            elapsed_time = SimpleView.stop_time - SimpleView.start_time
            time_d = timedelta(seconds=int(elapsed_time))

            channel = bot.get_channel(1215061241270374400)           
            embed=discord.Embed(color=0xda373c)
            embed.set_thumbnail(url="https://shft.cl/img/c/cdn.discordapp.com-101395680655364460.webp")
            embed.add_field(name="⬇️𝑼𝑺π‘ͺ𝑰𝑻𝑨⬇️", value="", inline=False)
            embed.add_field(name="NOME:", value=f"{interaction.user.mention}", inline=True)                                        #BOTTONE USCITA
            embed.add_field(name="", value="", inline=True)
            embed.add_field(name="", value="", inline=False)
            embed.add_field(name="", value="", inline=False)
            embed.add_field(name="DATA:", value=f"{data}", inline=True)
            embed.add_field(name="ORARIO:", value=f"{orario}", inline=True)
            embed.add_field(name="TEMPO IN SERVIZIO:", value=f"{time_d}", inline=True)
            embed.set_footer(text="ARMERIA200")
            await channel.send(embed=embed)
            await interaction.response.send_message(f"***SEI USCITO DI SERVIZIO ALLE: {orario}, DOPO: {time_d}***", ephemeral=True)

I want these two buttons to be able to be pressed only by those who have the "πŸ™‹β€β™‚οΈ IN SERVIZIO" and "πŸ™β€β™‚οΈ FUORI SERVIZIO" roles, I can't figure out how to do that. I tried looking for different solutions but I can't find anything useful. Help me please πŸ₯Ί


Solution

  • Youβ€˜re currently using a decorator that is ONLY designed for the commands extension of discord.py, remove it.

    For making the button only available for a certain role:

    Get the ID of the role you want to check for via Discords Developer settings.

    Then check if the user has the roles and run the rest of the code only when he does, otherwise defer the interaction.

    role = interaction.guild.get_role({id here})
    if role in interaction.user.roles:
       # code here
    else:
       await interaction.response.defer()