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:
Selects 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
Let's get started shall we?
First let me remind you that again please don't use 3rd party libs because there's more for selects that for buttons or anything in v2
(2.0.0a
)
You may find an example for dropdowns in the main repository with the filename as dropdown.py
in the views
folder
But I urge you to read this gist as I'm going to explain everything what I'm going to be doing in a linewise manner.
You'll understand what I mean we dive furthere into the gist.
So make to the topic - How do I make dropdowns?
You need classes for such a venture let me show you what I mean.
Code:
import discord
from discord.ext import commands
client=commands.Bot(command_prefix=commands.when_mentioned_or("."))
class Select(discord.ui.Select):
def __init__(self):
options=[
discord.SelectOption(label="Option 1",emoji="👌",description="This is option 1!"),
discord.SelectOption(label="Option 2",emoji="✨",description="This is option 2!"),
discord.SelectOption(label="Option 3",emoji="🎭",description="This is option 3!")
]
super().__init__(placeholder="Select an option",max_values=1,min_values=1,options=options)
token=""
client.run(token)
Line-wise Explanation:
- Imports
discord
- Imports
commands
fromdiscord.ext
- We declared our
client
. . - We defined our
discord.ui.Select
class asSelect
- Declared our
def __init__()
- Made a variable called
options
and made it into a list of options with the method asdiscord.SelectOption
. . . - Added a
super().__init__()
and declared ourplaceholder
(what's shown when no option is selected),max_values
(how many values can be selected at once),min_values
(how many values can be selected when you select it for the first time -max_values
andmin_values
are together when the values are1
it signifies that only one option can be selected at a time) andoptions
(declares the options in the dropdown by calling theoptions
variable declared inLine 8
) . . - Declared the
token
- Ran the code - Started the bot
Response:
None
You guys right now: What the fu-
Let me explain When we added in the token and ran the bot did you guys find something fishy?
Probably yes if your good with discord.py
, it's that I didn't add in a command!
So let's do that real quick.
Code:
import discord
from discord.ext import commands
client=commands.Bot(command_prefix=commands.when_mentioned_or("."))
class Select(discord.ui.Select):
def __init__(self):
options=[
discord.SelectOption(label="Option 1",emoji="👌",description="This is option 1!"),
discord.SelectOption(label="Option 2",emoji="✨",description="This is option 2!"),
discord.SelectOption(label="Option 3",emoji="🎭",description="This is option 3!")
]
super().__init__(placeholder="Select an option",max_values=1,min_values=1,options=options)
@client.command()
async def menu(ctx):
await ctx.send("Menus!",view=Select())
token=""
client.run(token)
Response: A very keen programmer who would actually like to learn something from this gist would find out another deliberate mistake. There's an error!
Error:
Ignoring exception in command menu:
Traceback (most recent call last):
File "C:\Python310\lib\site-packages\discord\ext\commands\core.py", line 167, in wrapped
ret = await coro(*args, **kwargs)
File "c:\Users\ADMIN\Desktop\r.lykn\code.py", line 18, in menu
await ctx.send("Menus!",view=Select())
File "C:\Python310\lib\site-packages\discord\abc.py", line 1368, in send
raise InvalidArgument(f'view parameter must be View not {view.__class__!r}')
discord.errors.InvalidArgument: view parameter must be View not <class '__main__.Select'>
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "C:\Python310\lib\site-packages\discord\ext\commands\bot.py", line 994, in invoke
await ctx.command.invoke(ctx)
File "C:\Python310\lib\site-packages\discord\ext\commands\core.py", line 894, in invoke
await injected(*ctx.args, **ctx.kwargs)
File "C:\Python310\lib\site-packages\discord\ext\commands\core.py", line 176, in wrapped
raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: InvalidArgument: view parameter must be View not <class '__main__.Select'>
What does this mean???
Answer: It means that there isn't a
view
class where we can actually "view" the selects. TheSelect
class is actually just a class defining the selects and the view! So how do we add the view? Answer: You need to declare another class(in our caseSelectView
) and add theSelect
class(the dropdown menu) into the view class and add the view class as our message view.
Code:
import discord
from discord.ext import commands
client=commands.Bot(command_prefix=commands.when_mentioned_or("."))
class Select(discord.ui.Select):
def __init__(self):
options=[
discord.SelectOption(label="Option 1",emoji="👌",description="This is option 1!"),
discord.SelectOption(label="Option 2",emoji="✨",description="This is option 2!"),
discord.SelectOption(label="Option 3",emoji="🎭",description="This is option 3!")
]
super().__init__(placeholder="Select an option",max_values=1,min_values=1,options=options)
class SelectView(discord.ui.View):
def __init__(self, *, timeout = 180):
super().__init__(timeout=timeout)
self.add_item(Select())
@client.command()
async def menu(ctx):
await ctx.send("Menus!",view=Select())
token=""
client.run(token)
Response:
Options:
If you used the above code and tried to select something, the view wouldn't do anything.
To make the options respond to something you see to add in a asynchronus fucntion called callback
How do I do so?
It's pretty simple lol.
Note: You have to know this before going any further, the value we select is know as self.values[0]
.
Code:
import discord
from discord.ext import commands
client=commands.Bot(command_prefix=commands.when_mentioned_or("."))
class Select(discord.ui.Select):
def __init__(self):
options=[
discord.SelectOption(label="Option 1",emoji="👌",description="This is option 1!"),
discord.SelectOption(label="Option 2",emoji="✨",description="This is option 2!"),
discord.SelectOption(label="Option 3",emoji="🎭",description="This is option 3!")
]
super().__init__(placeholder="Select an option",max_values=1,min_values=1,options=options)
async def callback(self, interaction: discord.Interaction):
await interaction.response.send_message(content=f"Your choice is {self.values[0]}!",ephemeral=True)
class SelectView(discord.ui.View):
def __init__(self, *, timeout = 180):
super().__init__(timeout=timeout)
self.add_item(Select())
@client.command()
async def menu(ctx):
await ctx.send("Menus!",view=SelectView())
token=""
client.run(token)
Response:
Now this response is preset and can't be changed, i.e., the option names are what's being displayed in when self.values[0]
is being called, How do I make it something custom and make the bot respond different things to the three different values?
That's also easy lol.
So in the above note I said that the value selected is self.values[0]
, and, if you are a person with a mind that's a little too much into coding or just with a taste towards logic you'd know that you'll have to add relations statements to this part of the code.
New Question: How do I do so?
That's even easy lol
Code:
The following code will show examples for all the types of messages that can be passed inside the interaction.response.________()
import discord
from discord.ext import commands
client=commands.Bot(command_prefix=commands.when_mentioned_or("."))
class Select(discord.ui.Select):
def __init__(self):
options=[
discord.SelectOption(label="Option 1",emoji="👌",description="This is option 1!"),
discord.SelectOption(label="Option 2",emoji="✨",description="This is option 2!"),
discord.SelectOption(label="Option 3",emoji="🎭",description="This is option 3!")
]
super().__init__(placeholder="Select an option",max_values=1,min_values=1,options=options)
async def callback(self, interaction: discord.Interaction):
if self.values[0] == "Option 1":
await interaction.response.edit_message(content="This is the first option from the entire list!")
elif self.values[0] == "Option 2":
await interaction.response.send_message("This is the second option from the list entire wooo!",ephemeral=False)
elif self.values[0] == "Option 3":
await interaction.response.send_message("Third One!",ephemeral=True)
class SelectView(discord.ui.View):
def __init__(self, *, timeout = 180):
super().__init__(timeout=timeout)
self.add_item(Select())
@client.command()
async def menu(ctx):
await ctx.send("Menus!",view=SelectView())
token=""
client.run(token)
Response:
Everything works perfectly.
Tip: A Small tip when passing positional arguments inside the interaction.response
is to always include what type of response it is, i.e., if it is just content
or an embed
, file
, etc...
InteractionResponse.send_message
InteractionResponse.edit_message
It isn't as stringent forsend_message
bcause it's a new message, but, foredit_message
programming without adding an attribute your bound to get an error.
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.
is there a way to disable drop downs at the moment? eg: after 15 seconds of no user input it gets greyed out, or no