Note: Before we go any further. Let me make this real clear that the following gist uses the OFFICIAL discord.py
library and not forks like discord_components
, nextcord
, etc... So when your using this code but a different library and fuck up don't comment something mean or go to a help channel in the server and say "this gist is misleading" or "bad gist who wrote this" when your at fault, trust me I'm going to fuck you up😅
Just a reminder^^
Related Links:
Buttons are a new feature added to discord in the brand new 2.0.0a
update.
Read more about it here(in the discord.py
server)
How can I install discord.py v2
?
It's pretty simple all you have to do it go to your console/terminal and say the following:
pip install -U git+https://github.com/Rapptz/discord.py
Note: You need to have Git BASH
and a python version higher than or equal to 3.8.0
. Get it at python.org/downloads
Now let's get started shall we? First of let me show you the bad way to make buttons
@client.command(brief="Send a message with a button!") # Create a command inside a cog
async def button(self, ctx):
view = discord.ui.View() # Establish an instance of the discord.ui.View class
style = discord.ButtonStyle.gray # The button will be gray in color
item = discord.ui.Button(style=style, label="Read the docs!", url="https://discordpy.readthedocs.io/en/master") # Create an item to pass into the view class.
view.add_item(item=item) # Add that item into the view class
await ctx.send("This message has buttons!", view=view) # Send your message with a button.
This example is shown when you say ?tag button example
in any channel in the official dpy
server but this is wrong!
Why? you may ask
Reason: It's because the button style doesn't work perfectly and all butttons are url buttons.
So what's the good/better way to make buttons?
I never said the method provided above was wrong but it just isn't feasible of sorts.
But, the better way is to sub-class the buttons isn't a view class(discord.ui.View
) like follows:
Code:
import discord
from discord.ext import commands
client=commands.Bot(command_prefix=".")
class Buttons(discord.ui.View):
def __init__(self, *, timeout=180):
super().__init__(timeout=timeout)
@discord.ui.button(label="Button",style=discord.ButtonStyle.gray)
async def gray_button(self,button:discord.ui.Button,interaction:discord.Interaction):
await interaction.response.edit_message(content=f"This is an edited button response!")
@client.command()
async def button(ctx):
await ctx.send("This message has buttons!",view=Buttons())
token=""
client.run(token)
Response:
Response - On Click:
Let me explain what happened just happened.
First we delared the bot(client=commands.Bot()
), then we made a class called Buttons()
and it was a simple view
(discord.ui.View
) class
Then we declared the view as self
, and timeout as 180
seconds in the def __init__():
right after that we added the timeout to the view in the super().__init__()
Right after we added an @discord.ui.button
decorator which declares a button and in the decorator we declared the label
and style
a lot more things can be declared in there which will be shown later on in the gist.
Then we called our button as gray_button
inside an asynchronous function(basically the button's asynchronous callback function) and inside that we declared our:
(a)
view
asself
(b)discord.ui.Button
asbutton
(c)discord.Interaction
asinteraction
Right after that we opened up the funtion and added in a await interaction.response.edit_message()
and added some content to it.
After that we delcared a command(button
), added one argument to it(ctx
) and sent a primary/base message with the content
as "This message has buttons!", and, then added in the view class we defined earlier(Button()
) as view=Buttons()
Then ran the bot
Now that I gave you the a small summary of what just happened in the above code, let me tell you the various attributes of the @discord.ui.button
decorator.
Taken from the API.
Reference Link: ui.Button
Basic Required Attributes:
label
This is the button's label, basically what's shown when the message is sent.
style
This is the button's style, basically what the button looks like when the message is sent. Various Styles:
Again taken from the
API
In your
@discord.ui.button
decorator add in astyle
parameter and do something like below
How do I change the button style on click?
That's actually a better question that pops up in someone's head because they've seen buttons change styles on click and let me tell you it's pretty easy to do. Take an example of the code below.
Code:
# Note: This is just an "improved" code of what's shown above and that's how it's going to work throughout the gist the above code is going to be refined over and over again.
import discord
from discord.ext import commands
client=commands.Bot(command_prefix=".")
class Buttons(discord.ui.View):
def __init__(self, *, timeout=180):
super().__init__(timeout=timeout)
@discord.ui.button(label="Button",style=discord.ButtonStyle.gray)
async def blurple_button(self,button:discord.ui.Button,interaction:discord.Interaction):
button.style=discord.ButtonStyle.green
await interaction.response.edit_message(content=f"This is an edited button response!",view=self)
@client.command()
async def button(ctx):
await ctx.send("This message has buttons!",view=Buttons())
token=""
client.run(token)
Initial Response:
Response - On Click:
When changing anything in your button all you have to do is add in a view=self
in your interaction.response.edit_message()
But, if you'd like to change the style on the click on a interaction.response.send_message()
, the following would be your output with the above shown code, but, with the await interaction.response.edit_message(...,view=self)
, replaced, with await interaction.response.send_message(...,ephemeral=False)
you may make it True
if you'd like too
Response(s):
That would be your response and if you had ephemeral
as True
then all responses would only be able to be seen by the button clicker and not the command user.
If you'd like to add an interaction_check
funtion, and send a message when the interaction user isn't the command user it's shown below or futher in the gist(don't fret!)
Let's get back to the main topic - components of a button
emoji
This is basically the emoji that pops up on the left-side of the button. So, how can I use these emojis? You may use the emojis in the below format. To get this "format" just add a
\
before the emoji name regardless if it's a discord default, unicode, or, discord custom(statis or animated) and the emoji ID is what's going to pop up as: (a)<:[emoji_name]:[emoji_id]>
for a static emoji (b)<a:[emoji_name]:[emoji_id]>
for an animated emojiFor getting the unicode character(s) of the entered text(as shown in the below picture) go to the
discord.py
server and say?charinfo <chracter(s)>
and the bot'll respond with the related information
Code:
import discord
from discord.ext import commands
client=commands.Bot(command_prefix=".")
class Buttons(discord.ui.View):
def __init__(self, *, timeout=180):
super().__init__(timeout=timeout)
@discord.ui.button(label="Blurple Button",style=discord.ButtonStyle.blurple,emoji="🎁") # or .primary
async def blurple_button(self,button:discord.ui.Button,interaction:discord.Interaction):
button.disabled=True
await interaction.response.edit_message(view=self)
@discord.ui.button(label="Gray Button",style=discord.ButtonStyle.gray,emoji="\U0001f974") # or .secondary/.grey
async def gray_button(self,button:discord.ui.Button,interaction:discord.Interaction):
button.disabled=True
await interaction.response.edit_message(view=self)
@discord.ui.button(label="Green Button",style=discord.ButtonStyle.green,emoji="<:FD_pepeyay:878854266012438549>") # or .success
async def green_button(self,button:discord.ui.Button,interaction:discord.Interaction):
button.disabled=True
await interaction.response.edit_message(view=self)
@discord.ui.button(label="Red Button",style=discord.ButtonStyle.red,emoji="<a:PomRun:869781523971317811>") # or .danger
async def red_button(self,button:discord.ui.Button,interaction:discord.Interaction):
button.disabled=True
await interaction.response.edit_message(view=self)
@client.command()
async def button(ctx):
view=Buttons()
view.add_item(discord.ui.Button(label="URL Button",style=discord.ButtonStyle.link,url="https://github.com/lykn",emoji="<a:kannaWink:909791444661850132>"))
await ctx.send("This message has buttons!",view=view)
token=""
client.run(token)
Response:
Those were the basic componenets that are required to make a good button. Below I'm going to show you the code and response to the code where all the button styles are shown
Code:
# Note: In the below code the buttons get disabled on click.
""" Note: The last button is a URL button which takes in a `url` param and has to be added via declaring the view in a variable and then adding a the item in the view through the variable """
import discord
from discord.ext import commands
client=commands.Bot(command_prefix=".")
class Buttons(discord.ui.View):
def __init__(self, *, timeout=180):
super().__init__(timeout=timeout)
@discord.ui.button(label="Blurple Button",style=discord.ButtonStyle.blurple) # or .primary
async def blurple_button(self,button:discord.ui.Button,interaction:discord.Interaction):
button.disabled=True
await interaction.response.edit_message(view=self)
@discord.ui.button(label="Gray Button",style=discord.ButtonStyle.gray) # or .secondary/.grey
async def gray_button(self,button:discord.ui.Button,interaction:discord.Interaction):
button.disabled=True
await interaction.response.edit_message(view=self)
@discord.ui.button(label="Green Button",style=discord.ButtonStyle.green) # or .success
async def green_button(self,button:discord.ui.Button,interaction:discord.Interaction):
button.disabled=True
await interaction.response.edit_message(view=self)
@discord.ui.button(label="Red Button",style=discord.ButtonStyle.red) # or .danger
async def red_button(self,button:discord.ui.Button,interaction:discord.Interaction):
button.disabled=True
await interaction.response.edit_message(view=self)
@client.command()
async def button(ctx):
view=Buttons()
view.add_item(discord.ui.Button(label="URL Button",style=discord.ButtonStyle.link,url="https://github.com/lykn"))
await ctx.send("This message has buttons!",view=view)
token=""
client.run(token)
Response:
Dark Mode
Light Mode
Heads Up!
URL Buttons can't be added into the button's class, aka, a button's callback funtion in a class, but, to have such a button you need to make a
discord.ui.View
class(a simple view class) and then name you variable in your command, let's call this variablev
. The, you have to do something like what's shown below
@client.command()
async def button(ctx):
v=Buttons()
v.add_item(discord.ui.Button(label="URL Button",style=discord.ButtonStyle.link,url="https://github.com/lykn"))
await ctx.send("This message has buttons!",view=v)
Functions Inside Button Callback
All the parameters that can be added inside the
@discord.ui.Button
decorator can be passed in an individual button's callback by declaring thediscord.ui.Button
as a positinal arguement yourasync def button_name(self,_____:discord.ui.Button)
function(button callback)
Let's make a code where on the click of a button all the other buttons get disabled!
Note: This is just a smol code to show you how to use for
loops inside a button's callback
Code:
We are going to be for
looping a "child" in self.children
(i.e, the button's view
components)
import discord
from discord.ext import commands
from discord.ui import view
client=commands.Bot(command_prefix=".")
class Buttons(discord.ui.View):
def __init__(self, *, timeout=180):
super().__init__(timeout=timeout)
@discord.ui.button(label="Blurple Button",style=discord.ButtonStyle.blurple) # or .primary
async def blurple_button(self,button:discord.ui.Button,interaction:discord.Interaction):
button.disabled=True
await interaction.response.edit_message(view=self)
@discord.ui.button(label="Gray Button",style=discord.ButtonStyle.gray) # or .secondary/.grey
async def gray_button(self,button:discord.ui.Button,interaction:discord.Interaction):
button.disabled=True
await interaction.response.edit_message(view=self)
@discord.ui.button(label="Green Button",style=discord.ButtonStyle.green) # or .success
async def green_button(self,button:discord.ui.Button,interaction:discord.Interaction):
button.disabled=True
await interaction.response.edit_message(view=self)
@discord.ui.button(label="Red Button",style=discord.ButtonStyle.red) # or .danger
async def red_button(self,button:discord.ui.Button,interaction:discord.Interaction):
button.disabled=True
await interaction.response.edit_message(view=self)
@discord.ui.button(label="Change All",style=discord.ButtonStyle.success)
async def color_changing_button(self,child:discord.ui.Button,interaction:discord.Interaction):
for child in self.children:
child.disabled=True
await interaction.response.edit_message(view=self)
@client.command()
async def button(ctx):
view=Buttons()
view.add_item(discord.ui.Button(label="URL Button",style=discord.ButtonStyle.link,url="https://github.com/lykn"))
await ctx.send("This message has buttons!",view=view)
token=""
client.run(token)
Response:
Required Button:
Response - On Click:
And as all good things come to an end, I have come to the last few lines of this gist.
Firstly I'd like to thank everyone at the discord.py
server who have helped me figure out how to make buttons on the whole you guys are amazing(Includes Umbra#9999
if he reads this, that is😆)!
A special thanks goes to LeoCx1000#9999
, veyron#1741
,Jeyy#6639
, Hay#7860
, Ender2K89#9999
, SHERLOCK#7309
and Nyanaka#1224
for helping me with all the patience in this world!
Thanks to everyone reading this! If you feel something is wrong/needs correction or just need some help then drop a comment down below
This is Lykn signing off.
I am getting the same error