Skip to content

Instantly share code, notes, and snippets.

@lykn
Last active April 16, 2024 05:39
Show Gist options
  • Star 55 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save lykn/bac99b06d45ff8eed34c2220d86b6bf4 to your computer and use it in GitHub Desktop.
Save lykn/bac99b06d45ff8eed34c2220d86b6bf4 to your computer and use it in GitHub Desktop.
A gist which shows/tells you how to make buttons using discord.py v2(version 2.0.0a)

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:

DPY's Docs

Discord's Docs

Code(GitHub)

Python

Python(Downloads)

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)

image

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:

image

Response - On Click:

image

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 as self (b) discord.ui.Button as button (c) discord.Interaction as interaction

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

image

Basic Required Attributes:

  1. label

This is the button's label, basically what's shown when the message is sent.

  1. style

This is the button's style, basically what the button looks like when the message is sent. Various Styles: image Again taken from the API

image How can I change the button style?

In your @discord.ui.button decorator add in a style parameter and do something like below

image

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:

image

Response - On Click:

image

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):

image

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

  1. 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 emoji

For 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

image

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:

image

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

image

Light Mode

image

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 variable v. 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 the discord.ui.Button as a positinal arguement your async 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:

image

Required Button:

image

Response - On Click:

image

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.

@kem008
Copy link

kem008 commented Jan 24, 2024

this is not working.

@fish0117
Copy link

Thanks! Very useful:)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment