Last active
January 23, 2025 11:35
-
-
Save amazingakai/1f53152d3906b2db477d0babc6d8b629 to your computer and use it in GitHub Desktop.
Discord.py button roles example.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from __future__ import annotations | |
import re | |
from typing import Optional | |
import discord | |
from discord.ext import commands | |
# Role IDs to labels mapping. | |
# role_id: label | |
ROLES = { | |
123456789: "Announcements", | |
987654321: "Giveaways", | |
} | |
class RoleButton( | |
discord.ui.DynamicItem[discord.ui.Button], template=r"roles:(?P<role_id>\d+)" | |
): | |
def __init__(self, role_id: int, label: Optional[str] = None) -> None: | |
self.role_id = role_id | |
super().__init__( | |
discord.ui.Button( | |
label=label, | |
custom_id=f"roles:{role_id}", | |
) | |
) | |
@classmethod | |
async def from_custom_id( | |
cls, | |
interaction: discord.Interaction, | |
item: discord.ui.Button, | |
match: re.Match[str], | |
): | |
role_id = int(match["role_id"]) | |
return cls(role_id) | |
async def interaction_check(self, interaction: discord.Interaction) -> bool: | |
# Restricts the button roles to ROLES dict, | |
# you can also use a database if you want. | |
return self.role_id in ROLES | |
async def callback(self, interaction: discord.Interaction) -> None: | |
# Check if the interaction is in a guild. | |
if interaction.guild is None: | |
await interaction.response.send_message( | |
"Role button can only be used in a guild.", ephemeral=True | |
) | |
return | |
# Only for type checkers, you can remove this line. | |
# It will always be `True`. | |
assert isinstance(interaction.user, discord.Member) | |
message = None | |
role = interaction.guild.get_role(self.role_id) | |
# Check if role still exists. | |
if role is None: | |
await interaction.response.send_message( | |
"Role not found. Was it deleted?", ephemeral=True | |
) | |
return | |
try: | |
# Check if the user has the role | |
if role in interaction.user.roles: | |
message = f"Removed {role.mention} from you." | |
await interaction.user.remove_roles(role) | |
else: | |
message = f"Added {role.mention} to you." | |
await interaction.user.add_roles(role) | |
except ( | |
discord.HTTPException | |
): # Handle missing permissions or other HTTP errors. | |
await interaction.response.send_message( | |
"I do not have permissions to add/remove that role.", ephemeral=True | |
) | |
return | |
await interaction.response.send_message(message, ephemeral=True) | |
class RoleBot(commands.Bot): | |
def __init__(self) -> None: | |
intents = discord.Intents.default() | |
intents.message_content = True | |
super().__init__(command_prefix="?", intents=intents) | |
async def setup_hook(self) -> None: | |
# Register the dynamic item. | |
self.add_dynamic_items(RoleButton) | |
bot = RoleBot() | |
@bot.command() | |
async def role_buttons(ctx: commands.Context) -> None: | |
"""Sends a message with button roles.""" | |
view = discord.ui.View(timeout=None) # Disabling the timeout is required. | |
for role_id, label in ROLES.items(): | |
view.add_item(RoleButton(role_id, label)) | |
await ctx.send("Click the buttons to get roles!", view=view) | |
bot.run("token") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment