Skip to content

Instantly share code, notes, and snippets.

@AmazingAkai
Last active July 6, 2024 10:12
Show Gist options
  • Save AmazingAkai/1f53152d3906b2db477d0babc6d8b629 to your computer and use it in GitHub Desktop.
Save AmazingAkai/1f53152d3906b2db477d0babc6d8b629 to your computer and use it in GitHub Desktop.
Discord.py button roles example.
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,
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