Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
A discord.py extension for using discord ui/interaction features
pip package
▪
read the docs
▪
examples
This is a discord.py ui extension made by 404kuso and RedstoneZockt for using discord's newest ui features like buttons, slash commands and context commands.
py -m pip install discord-ui
python3 -m pip install discord-ui
This project is under MIT License
If you find any issues, please report them
https://github.com/discord-py-ui/discord-ui/issues
If you want to use slash commands, in the oauth2 invite link generation,
you have to check both bot
and application.commands
fields
Example for creating a simple slash command
import discord
from discord.ext import commands
from discord_ui import UI, SlashOption
client = commands.Bot(" ")
ui = UI(client)
@ui.slash.command("hello_world", options=[SlashOption(bool, "cool", "whether this libary is cool", required=False)], guild_ids=[785567635802816595])
async def command(ctx, cool=True):
"""This is a simple slash command"""
# you can use docstrings for the slash command description too
await ctx.respond("You said this libary is " + str(cool))
client.run("your_token")
Example for creating a user-context command
import discord
from discord.ext import commands
from discurd_ui import UI
client = commands.Bot(" ")
ui = UI(client)
@ui.slash.user_command("avatar", guild_ids=[785567635802816595])
async def avatar(ctx, user: discord.Member):
"""Sends the avatar of a user"""
await ctx.respond(embed=discord.Embed(description=user.display_name).set_image(url=user.avatar_url))
client.run("your_token")
Example for autocompletion of choices
import discord
from discord_ui import UI, SlashOption, AutocompleteInteraction
async def generator(ctx: AutocompleteInteraction):
available_choices = ["hmm", "this", "is", "a", "an", "test", "testing"]
return [(x, x) for x in available_choices if x.startswith(ctx.value_query)]
@ui.slash.command("search_word", options=[SlashOption(str, "query", choice_generator=generator)])
async def search_word(ctx, query):
await ctx.send("got " + query + " for query")
client.run("your_token")
Example for sending a button and receiving it
import discord
from discord.ext import commands
from discord_ui import UI, LinkButton, Button
from asyncio import TimeoutError
client = commands.Bot(" ")
ui = UI(client)
@client.listen("on_message")
async def on_message(message: discord.Message):
if message.content == "!btn":
msg = await message.channel.send("you", components=[
[Button("press me", color="green"), LinkButton("https://discord.com", emoji="😁")],
Button(custom_id="my_custom_id")
])
try:
btn = await msg.wait_for("button", client, by=message.author, timeout=20)
await btn.respond("you pressed `" + btn.content + "`")
except TimeoutError:
await msg.delete()
client.run("your_token_here")
Example for sending Selectmenus and receiving them
import discord
from discord.ext import commands
from discord_ui import UI, SelectMenu, SelectOption
from asyncio import TimeoutError
client = commands.Bot(" ")
ui = UI(client)
@client.listen("on_message")
async def on_message(message: discord.Message):
if message.content == "!sel":
msg = await message.channel.send("you", components=[SelectMenu(options=[
SelectOption("my_value", label="test", description="this is a test"),
SelectOption("my_other_value", emoji="🤗", description="this is a test too")
], "custom_id", max_values=2)])
try:
sel = await msg.wait_for("select", client, by=message.author, timeout=20)
await sel.respond("you selected `" + str([x.content for x in sel.selected_options]) + "`")
except TimeoutError:
await msg.delete()
client.run("your_token_here")
Example for cogs
from discord.ext import commands
from discord_ui import UI
from discord_ui.cogs import slash_command, subslash_command, listening_component
bot = commands.Bot(" ")
ui = UI(bot)
class Example(commands.Cog):
def __init__(self, bot):
self.bot = bot
@slash_command(name="example", guild_ids=[785567635802816595])
async def example(self, ctx):
await ctx.respond("gotchu")
@subslash_command(base_names="example", name="command"):
async def example_command(self, ctx):
await ctx.respond("okayy")
bot.add_cog(Example(bot))
bot.run("your token")
You can find more (and better) examples here
You can contact us on discord
This will be moved to https://discord-py-ui.github.io/discord-ui/
commands.nuke
custom_id
comes now after options
SelectMenu("my_custom_id", [options...here])
# is now
SelectMenu([options...here], "my_custom_id")
Button("my_custom_id", "label")
# is now
Button("label", "my_custom_id")
slash_command
-> slash_command
, subslash_command
-> subslash_command
, context_cog
-> context_command
, listening_component
-> listening_component
Slash.edit_command
and Slash.edit_subcommand
, "moved" to Command.edit
SlashedCommand
is now SlashInteraction
, SlashedSubCommand
is now SubSlashInteraction
and SlashedContext
is now ContextInteraction
Interaction.command.
(the .command
attribute is a reference to the real command, if you change properties of the command they will be updated).component
.param
attribute is now .target
argument_type
in SlashOption is now type
ButtonStyle
value names changed: color names are now capitalized and Danger
is now Destructive
Listener.target_user
is now Listener.target_users
and can take users, members and ids as the valueBaseCommand.options
and SlashOption.options
is now of type SlashOptionCollection
, which allows you to acces options by index and namemy_command.options["option name"]
# or
my_command.options[0]
You can also use some methods like .get
, .set
(which will return itself after it set something, so SlashOption.set(key, value).set(key, value)
would work) and SlashOption.options + SlashOption.option
will add both SlashOptions together
logging.error()
discord_ui.ext.py
module into a folderon_button_press
and on_menu_select
is now on_button
and on_select
. The old event names will still work but will be removed in the next releaseActionRow.disable
commands.Bot
instances wouldn't get overriden which lead to not enabling needed debug eventsListener
could be found, the events for components events wouldn't be dispatcheddelete_after
keyword in message send override not working@discord.ext.commands.Cooldown
not working on cog slashcommands**fields
to all functions that edit the message components (like .disable_components
, .disable_component
, ...). The **fields
parameter can be used to edit other properties of the message without using .edit
again and send a "useless" request@Lister.on_error
and @Listener.wrong_user
decorators for handling Exceptions in Listeners@Listener.button
or @Listener.select
, the function will be called on every button/slectchannel_type
to SlashOption, list of discord.ChannelType
. This will restrict the shown channels for channel slash options to this list.Mentionable
type for SlashOptions# style 1
@ui.slash.command()
async def my_command(ctx, my_option, my_other_option):
"""This is my command description
my_option: `int`:
This is the description for the my_option parameter
my_other_option: `str`:
This is the description for another option
"""
...
# style 2
@ui.slash.command()
async def my_command(ctx, my_option: int, my_other_option: str):
"""This is my command description
my_option: This is the description for the my_option parameter
my_other_option: This is the description for another option
"""
...
# style 3
@ui.slash.command()
async def my_command(ctx, my_option, my_other_option: str):
"""This is my command description
`int`: This is the description for the my_option parameter
This is the description for another option
"""
...
Note: You don't have to use `type`
, you can just use type
\u200b
which is an "empty" char.options[name or index].name = "new name"
and the option will be updatedui.slash.command(options=[SlashOption(str, "my_option")])
async def my_command(ctx, my_option):
...
@my_command.options["my_option"].autocomplete_function
async def my_generator(ctx):
...
# or
@my_command.options[0].autocomplete_function
async def my_generator(ctx):
...
@ui.slash.command(...)
async my_command(ctx):
...
type(my_command) # SlashCommand
# edit
await my_command.edit(name="test")
# delete
await my_command.delete()
id
to SlashCommandcommands_synced
event which will be dispatched when all commands where synced with the api (UI.Slash.sync_commands
)BaseCommmand.update
method which updates the api command with the lcoal changesSlashSubCommand.base
, which will be shared among all subslashcommands with the same basediscord.ext.commands.Bot
override for enabling the debug event, this will be enabled when creating a UI instance from the botdefault_permission can now be of type
discord.Permissions
but the api doesn't support that yet.
some code changes to slash-http features
Context class for choice generation
choice_generator
keyword andautocomplete
keyword.autocomplete
is not needed if you pass choice_generator
You are now able to send hidden files
required is now false by default again
Required is now
True
by default
AttributeError: 'LinkButton' object has no attribute 'component_type'
The lib now doesn't decompress byte data anymore, which means everything before the dpy commit
848d752
doesn't work with this lib.message reference in discordpy discord server
TypeError: 'NoneType' object is not iterable
Could not find a matching option type for parameter '<class 'NoneType'>'
Message.wait_for
by keyword doesn't work properly
Removed the hash property from Buttons and SelectMenus due to the removal of it from the api
discord_ui.ext
A module with useful tools and decorators to use more information
BaseCommand (the superclass for all applicationcommands) has now some extra properties:
- is_chat_input
> Whether this command is a slash command
- is_message_context
> Whether this command is a message context command
- is_user_context
> Whether this command is a user context command
Added properties:
- is_alias
> Whether the invoked command is an alias or not
- aliases
> All the available aliases for the command
Listeners are something that you can use for a better processing of received components. You could see them as a cog to the message components more information
SelectInteraction.selected_values
are not the raw values that were selected,SelectMenu.selected_options
are the options of typeSlashOption
that were selected
All instance values that were
MISSING
by default are nowNone
TypeError: 'EMPTY' is not a callable object
in context commandsguild_permission
keywordThe base_names and the name will be now set to the right value
on_component
There is now an event with the name
component
that will be dispatched whenever a component was received If you useMessage.wait_for
, there is now a new event choice with the namecomponent
(message.wait_for("component", client)
)
DM issue with deleting messages
edit
Edit now takes "content" as not positional (
.edit("the content")
works now)
You are now able to set component values with the right max lenght
there was an issue with sending embeds
There was an issue with listening components that they needed two parameters but only one was passed Another issue was
TypeError: __init__() missing 1 required positional argument: 'custom_id'
?
there was an issue with sending embeds
the
delete_unused
keyword is now optional, if you don't pass a parameter,slash.delete_unused
will be used (from the__init__
function)
cannot import name 'InteractionResponseType' from 'discord.enums'
when you remove a cog the slash commands will now get deleted if you set
delete_unused
to True and setsync_on_cog
to True
you don't have to specify options in one of the slash decorators anymore. Instead, you can set them in your callback function Example
@ui.slash.command()
async def greet(ctx, user): # This will add an required option with the name "user" of type "user"
"""Greets a user
You can use multiline docstrings, because only the first line will be used for the description
"""
...
@ui.slash.command()
async def tag(ctx, target: discord.User = None): # This will add an optional option with the name "target" of type "user"
# Note: you could also use target: "user" = None or anything else you would use in SlashOption for the type
...
if you would sync the commands after the first sync, it threw an error
when trying to get slash commands in a guild with no
appication.commands
permission, it won't throw an exepction anymore
subcommand checks were wrong and this would result in errors like
In options.0.options.2: Option name 'name' is already used in these options
For some reason the voice property of the creator or the interaction would be set
They wouldn't be registered to the api
You should be able to use this package with python 3.6 or newer
Forgot to remove print statements💀
when a user was passed in an option, its guild was always None
if no name passed, the context command wouldn't take the callback name as the name of the command
You now have much more control over your slash commands!
You can update your permissions with the
Slash.update_permissions
function
You can now create slash commands without the decorator in a much more eaisier way! Check out the
Slash.add_command
function
You can edit commands in code with the
Slash.edit_command
function
You can add and remove listening components now with the
Components.add_listening_component
,Components.remove_listening_component
andComponents.remove_listening_components
functions
You can now use cog decorators like
slash_command
,subslash_command
andlistening_component
Slash commands wouldn't be updated if only
default_permission
was changed
Message.wait_for now takes
by
andcheck
as parameters andevent_name
andclient
switched place (wait_for(client, "event_name")
is nowwait_for("event_name", client)
)
You can specify listening_components now more presicely, you can add messages, users, and a check to filter
Interaction.member
is nowInteraction.author
Listening component callback functions now only take one parameter, the used component
on_button_press
and on_menu_select
These events now take a sole parameter, the used component. If you want to acces to message, use
passed_component.message
Removed ResponseMessage
SelectMenu issue when creating it from data
Message.edit
now takes aembed
parameter
Forgot to remove some
classes have now a
__repr__
function
You can now choose whether you want to override some of dpy objects and functions (default is True) (see the override module for more information) This also appeals to the
Components
class (Components(override_dpy)) note: if you don't want to create aUI
object, you can instead override dpy with theoverride_dpy
method
from discord_ui import override_dpy
override_dpy()
discord.py v2 now auto-decompresses socket data and passes a string instead of the uncompressed data.
when overriding dpy message object, the components would mix
You can now edit a ephemeral message which was created from an interaction (ex. when a button in a hidden message was pressed)
Interaction.channel
andInteraction.guild
The lib will now retry after the ratelimit reset and doesn't throw an HTTPException anymore
Got
KeyError
exception while syncing commands
When a hidden response was about to be send without defering the interaction it would thrown an error
SlashPermission
it will throw an exceptionYou can now have context commands with the same name as a normal slash command
You can use docstrings
"""docstring"""
for setting the description of a slash commmand by setting the dosctring for the callback function
auto_defer is now disabled by default
You can now disable auto_sync for slash commmands and sync them by yourself with
Slash.sync_commands(delete_unused)
Interaction._deferred
is notInteraction.deferred
andInteraction.defer()
doesn't throw an exception anymore, it will just log the error withlogging.error()
There was a try/catch in the
Interaction.respond
function that would allow the code to continue when an exception occured while responding with ninja_mode
There was an issue adding context-commands
Now, the libary only edits commands when changes were made
If you use
.respond()
, the function will try to use ninja_mode automatically
Moved git-project to https://github.com/discord-py-ui/discord-ui
responding with ninja_mode would end up in an exception
fixed another file sending issue with slash commands
AttributeError: module 'discord' has no attribute '_Components__version'
I'm really sorry for all the issues this libary got, if you still find issues, please report them in https://github.com/discord-py-ui/discord-ui/issues
There was an issue with emojis not being set in SelectOptions
There was an issue with setting the url not being set
There was an issue with creating commands that don't already exist
.values
is not.selected_values
Buttons and SelectMenus have a
.message
property for the message where their interaction was creted ResponseMessages have a.interaction
property for the received interaction
We added a
interaction_received
event for all interactions that are received
We added support for discord.py v2, so you can stay loyal to our libary and use it together with discord.py v2!
Added own Exceptions for errors
You can change the way the extension parses interaction data. You can choose between different Methods
The libary will autodefer all interactions public. If you want to change that, take a look at the documentation for this feature
Slash commands will only be edited if there were some changes, so you won't get a
invalid interaction
error in discord after starting the bot If only permissions were changed, just the permissions will be edited and not the whole command like before
I finally fixed the damn slashcommand system, it should work now
The resolving, fetching and pulling from the cache methods should all work
Context commands are now available
The project's name was changed from
discord-message-components
todiscord-ui
Extension
is now UI
You are now able to use webhooks together with message components, to send a webhook message with the components, use the
Components.send_webhook
function. The standart webhook function is also overriden with the new component function
You can now use
float
as the argument type for a slash command option
Buttons, LinkButtons and SelectOptions labels are now by default
\u200b
, which is an "empty" char
Fixed small code issues (they were already fixed in previous versions, but I just wanna list this here)
Docs are now working
Select option threw an exception if it was smaller than 1 or higher than 100
Slashcomamnd support
Slash
class for slash commandsSlash.command
, Slash.subcommand
and Slash.subcommand_groups
are available for creating slash commandsSlashedCommand
and SlashedSubCommand
are there for used slash commandsMessage
int
| range
, disable: bool
)disables (enables) component row(s) in the message
bool
)disables (enables) all componentss
overrides
Messageable.send
returns Message instead of discord.Message and takes components parameteroverride_client
function addedinteraction.send
, creates followup messages which can be hidden
Component.listening_component
A listening component with a callback function that will always be executed whenever a component with the specified custom_id was used
Message
All interaction responses work now
You can now edit messages with button support
ResponseMessage.acknowledge()
-> ResponseMessage.defer()
Changed the name of the function + changed
ResponseMessage.acknowledged
->ResponseMessage.deferred
ResponseMessage.defer()
=> await ResponseMessage.defer()
defer
(acknowledge
) is now async and needs to be awaited
You can now send responses only visible to the user
ResponseMessage.respond()
Now doesn't show a failed interaction
ResponseMessage.respond()
responding now doesn't fail after sending the message, it will now defer the interaction by it self if not already deferred and then send the message
ResponseMessage.acknowledged
Whether the message was acknowledged with the
ResponseMessage.acknowledged()
function
ResponseMessage.respond()
=> await ResponseMessage.respond()
respond() function is now async and needs to be awaited
ResponseMessage.respond() -> None
=> ResponseMessage.respond() -> Message or None
respond() now returns the sent message or None if ninja_mode is true
Button.hash
Buttons have now a custom hash property, generated by the discord api
FAQs
A disord.py extension for discord's ui/interaction features
We found that discord-ui demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.