Registering Commands
Registering Commands¶
We've created the command, we'll need to register the command with Discord.
Info
All methods for editing, deleting, registering, and getting commands share the same method for globally and guild only.
You will need an initialized Dispike
object.
from dispike import Dispike
bot = Dispike(
client_public_key="..",
bot_token="..",
application_id=".."
)
bot.register(command_to_be_created)
¶
components
¶
ActionRow
¶
Represents a action row component
__init__(self, components)
special
¶
Parameters:
Name | Type | Description | Default |
---|---|---|---|
components |
List[Union[dispike.creating.components.Button, dispike.creating.components.LinkButton, dispike.creating.components.SelectMenu]] |
Components for this action row. You cannot combine buttons and select menus |
required |
Source code in dispike/creating/components.py
def __init__(
self, components: typing.List[typing.Union[Button, LinkButton, SelectMenu]]
):
"""
Args:
components (typing.List[typing.Union[Button, LinkButton, SelectMenu]]): Components for this action row. You cannot combine buttons and select menus
"""
self.type = ComponentTypes.ACTION_ROW
# Do a heap of stuff to figure out if a select menu is being combined with a button
contains_button = False
contains_select_menu = False
for component in components:
if isinstance(component, (Button, LinkButton)):
contains_button = True
elif isinstance(component, SelectMenu):
contains_select_menu = True
else:
# raise error if neither.
raise InvalidComponentError(type(component))
if contains_button and contains_select_menu:
raise ComponentCombinationError(
"You cannot combine buttons and select menus"
)
self.components = components
Button
¶
Represents a partial Discord emoji
__init__(self, label=None, custom_id=None, disabled=False, style=<ButtonStyles.PRIMARY: 1>, emoji=None)
special
¶
Parameters:
Name | Type | Description | Default |
---|---|---|---|
label |
str |
label of the button. |
None |
custom_id |
str |
custom id of the button. |
None |
disabled |
bool |
bool specifying if this button should be disabled. |
False |
style |
ButtonStyles |
style of the button. Cannot be LINK |
<ButtonStyles.PRIMARY: 1> |
emoji |
PartialEmoji |
a partial emoji. |
None |
Source code in dispike/creating/components.py
def __init__(
self,
label: str = None,
custom_id: str = None,
disabled: bool = False,
style: ButtonStyles = ButtonStyles.PRIMARY,
emoji: PartialEmoji = None,
):
"""
Args:
label (str): label of the button.
custom_id (str, optional): custom id of the button.
disabled (bool, optional): bool specifying if this button should be disabled.
style (ButtonStyles, optional): style of the button. Cannot be LINK
emoji (PartialEmoji, optional): a partial emoji.
"""
self.type = ComponentTypes.BUTTON
if style == ButtonStyles.LINK:
raise TypeError("style cannot be type Link")
if not label:
raise TypeError("label cannot be None")
if not custom_id:
raise TypeError("custom_id cannot be None")
self.style = style
self.label = label
self.custom_id = custom_id
self.disabled = disabled
self.emoji = emoji
ButtonStyles
¶
Easy access to button styles.
Attributes:
Name | Type | Description |
---|---|---|
PRIMARY |
int |
Represents Style 1 |
SECONDARY |
int |
Represents Style 2 |
SUCCESS |
int |
Represents Style 3 |
DANGER |
int |
Represents Style 4 |
LINK |
int |
Represents Style 5 |
ComponentTypes
¶
Easy access to component types.
Attributes:
Name | Type | Description |
---|---|---|
ACTION_ROW |
int |
Represents Type 1 |
BUTTON |
int |
Represents Type 2 |
SELECT_MENU |
int |
Represents Type 3 |
LinkButton
¶
Represents a partial Discord emoji
__init__(self, label=None, url=None, disabled=False)
special
¶
Parameters:
Name | Type | Description | Default |
---|---|---|---|
label |
str |
Label of the button. |
None |
url |
str |
Url of the link button. |
None |
disabled |
bool |
bool Specifying if this button should be disabled. |
False |
Source code in dispike/creating/components.py
def __init__(self, label: str = None, url: str = None, disabled: bool = False):
"""
Args:
label (str): Label of the button.
url (str): Url of the link button.
disabled (bool, optional): bool Specifying if this button should be disabled.
"""
self.type = ComponentTypes.BUTTON
self.style = ButtonStyles.LINK
if not url:
raise TypeError("url cannot be None")
if not label:
raise TypeError("label cannot be None")
self.label = label
self.url = url
self.disabled = disabled
PartialEmoji
¶
Represents a partial Discord emoji
__init__(self, name, id=None, animated=None)
special
¶
Parameters:
Name | Type | Description | Default |
---|---|---|---|
name |
str |
The emojis name, or unicode symbol. |
required |
id |
str |
id of the emoji, if not a unicode one. |
None |
animated |
bool |
bool Specifying if this emoji should be animated, if not a unicode one. |
None |
Source code in dispike/creating/components.py
def __init__(self, name: str, id: str = None, animated: bool = None):
"""
Args:
name (str): The emojis name, or unicode symbol.
id (str, optional): id of the emoji, if not a unicode one.
animated (bool, options): bool Specifying if this emoji should be animated, if not a unicode one.
"""
self.name = name
self.id = id
self.animated = animated
SelectMenu
¶
Represents a Discord select menu
SelectMenuOption
¶
Represents a Discord select menu option
__init__(self, label=None, value=None, description=None, emoji=None, default=False)
special
¶
Parameters:
Name | Type | Description | Default |
---|---|---|---|
label |
str |
Label of the option. |
None |
value |
str |
Internal value of the option. |
None |
description |
str |
Description of the option. |
None |
emoji |
PartialEmoji |
A partial emoji |
None |
default |
bool |
Whether or not this option should be the default. |
False |
Source code in dispike/creating/components.py
def __init__(
self,
label: str = None,
value: str = None,
description: str = None,
emoji: PartialEmoji = None,
default: bool = False,
):
"""
Args:
label (str): Label of the option.
value (str): Internal value of the option.
description (str): Description of the option.
emoji (PartialEmoji, optional): A partial emoji
default (bool): Whether or not this option should be the default.
"""
if not label:
raise TypeError("label cannot be None")
if not value:
raise TypeError("value cannot be None")
self.label = label
self.value = value
self.description = description
self.emoji = emoji
self.default = default
__init__(self, custom_id, options, placeholder, min_values, max_values, disabled)
special
¶
Parameters:
Name | Type | Description | Default |
---|---|---|---|
custom_id |
str |
Custom id of the menu. |
required |
options |
List[dispike.creating.components.SelectMenu.SelectMenuOption] |
List of SelectMenu.SelectMenuOption's |
required |
placeholder |
str |
Text that's shown before a user selects anything. |
required |
min_values |
int |
The minimum amount of values a user can select. Cannot be lower than 0 |
required |
max_values |
int |
The maximum amount of values a user can select. Cannot be higher than the amount of options. |
required |
disabled |
False |
Whether to disable menu |
required |
Source code in dispike/creating/components.py
def __init__(
self,
custom_id: str,
options: typing.List[SelectMenuOption],
placeholder: str,
min_values: int,
max_values: int,
disabled: False,
):
"""
Args:
custom_id (str): Custom id of the menu.
options (SelectMenu.SelectMenuOption): List of SelectMenu.SelectMenuOption's
placeholder (str, optional): Text that's shown before a user selects anything.
min_values (int): The minimum amount of values a user can select. Cannot be lower than 0
max_values (int): The maximum amount of values a user can select. Cannot be higher than the amount of options.
disabled (bool, optional): Whether to disable menu
"""
self.type = ComponentTypes.SELECT_MENU
self.options = options
for option in options:
if not isinstance(option, SelectMenu.SelectMenuOption):
raise SelectMenuOptionError(f"{option} is not type SelectMenuOption")
if not placeholder:
raise TypeError("placeholder cannot be None")
if not custom_id:
raise TypeError("custom_id cannot be None")
self.placeholder = placeholder
self.custom_id = custom_id
if not min_values or not max_values:
raise TypeError("min_values or max_values must not be None")
if max_values > len(options):
raise TypeError(
"max_values cannot be larger than how many options you have"
)
if min_values < 1:
raise TypeError("min_values cannot be less than 0")
self.min_values = min_values
self.max_values = max_values
self.disabled = disabled
models
special
¶
options
¶
CommandChoice
pydantic-model
¶
Represents a key-value command choice.
Attributes:
Name | Type | Description |
---|---|---|
name |
str |
Name of the choice. |
value |
str |
Value of the choice. |
CommandOption
pydantic-model
¶
Represents a standard command option (not a subcommand).
Attributes:
Name | Type | Description |
---|---|---|
name |
str |
Name of the option. |
description |
str |
Description of the option. |
type |
OptionTypes |
The option type. |
required |
bool |
Whether or not this option is required. |
choices |
Union[List[dict], List[CommandChoice]] |
Possible choices for this option for the user to pick from. |
options |
Union[List[CommandChoice], List] |
If the option is a subcommand or subcommand group type, this nested options will be the parameters. |
CommandTypes
¶
Easy access to command types.
Attributes:
Name | Type | Description |
---|---|---|
SLASH |
int |
Represents Type 1 |
USER |
int |
Represents Type 2 |
MESSAGE |
int |
Represents Type 3 |
DiscordCommand
pydantic-model
¶
Represents a discord command.
Attributes:
Name | Type | Description |
---|---|---|
id |
int |
Id of this command. |
name |
str |
Name of this command. |
description |
str |
Description of this command. |
options |
List[Union[SubcommandOption, CommandOption]] |
Options for this command. |
default_permission |
boolean |
whether the command is enabled by default when the app is added to a guild. Defaults to True. |
type |
Union[CommandTypes, int] |
The type of command. This defaults to SLASH |
OptionTypes
¶
Easy access to option types.
Attributes:
Name | Type | Description |
---|---|---|
BOOLEAN |
int |
Represents Type 5 |
CHANNEL |
int |
Represents Type 7 |
INTEGER |
int |
Represents Type 4 |
ROLE |
int |
Represents Type 8 |
STRING |
int |
Represents Type 3 |
SUB_COMMAND |
int |
Represents Type 1 |
SUB_COMMAND_GROUP |
int |
Represents Type 2 |
USER |
int |
Represents Type 6 |
MENTIONABLE |
int |
Represents Type 9 |
NUMBER |
int |
Represents Type 10 |
SubcommandOption
pydantic-model
¶
Represents a subcommand group usually you would put this as an option in a DiscordCommand
Attributes:
Name | Type | Description |
---|---|---|
name |
str |
Name of this group. |
description |
str |
Description of this group. |
options |
List[CommandOption] |
Options for this group. |
permissions
¶
registrator
¶
RegisterCommands
¶
This object contains methods to help registering a command to Discord. While you shouldn't need to import this directly, it's still accessible if you prefer not to initalize a Dispike object.
Important to remember all methods are not async.
bot_token
property
writable
¶
You cannot view the bot_token directly, but you can still 'update' it.
Exceptions:
Type | Description |
---|---|
PermissionError |
If you attempt to view the bot token without a new value |
request_headers
property
readonly
¶
Return a valid header for authorization
Returns:
Type | Description |
---|---|
dict |
a valid header for authorization |
__init__(self, application_id, bot_token)
special
¶
Initalize object provided with application_id and a bot token
Parameters:
Name | Type | Description | Default |
---|---|---|---|
application_id |
str |
Client ID |
required |
bot_token |
str |
Bot user Token |
required |
Source code in dispike/creating/registrator.py
def __init__(self, application_id: str, bot_token: str):
"""Initalize object provided with application_id and a bot token
Args:
application_id (str): Client ID
bot_token (str): Bot user Token
"""
self.__bot_token = bot_token
self._application_id = application_id
self._client = Client(
base_url=f"https://discord.com/api/v8/applications/{self._application_id}/",
event_hooks={
"response": [dispike_httpx_event_hook_incoming_request],
"request": [dispike_httpx_event_hook_outgoing_request],
},
)
bulk_overwrite_commands(self, commands, guild_only=False, guild_to_target=None)
¶
Bulk OVERWRITE commands to specific guilds or globally.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
commands |
List[dispike.creating.models.options.DiscordCommand] |
List of new commands (these commands will be overwritten) |
required |
guild_only |
bool |
Default to set global mode (True). Set to False to let the function know to expect a guild_id |
False |
guild_to_target |
int |
A guild Id if guild_only is set to True. |
None |
Source code in dispike/creating/registrator.py
@logger.catch(reraise=True, message="Issue with bulk overrwriting commands")
def bulk_overwrite_commands(
self,
commands: typing.List[DiscordCommand],
guild_only: bool = False,
guild_to_target: int = None,
):
"""Bulk OVERWRITE commands to specific guilds or globally.
Args:
commands (typing.List[DiscordCommand]): List of new commands (these commands will be overwritten)
guild_only (bool, optional): Default to set global mode (True). Set to False to let the function know to expect a guild_id
guild_to_target (int, optional): A guild Id if guild_only is set to True.
"""
if guild_only == True:
if guild_to_target is None:
raise TypeError(
"if guild_only is set to true, a guild id must be provided."
)
logger.info(f"Targeting a specific guild -> {guild_to_target}")
_request_url = f"guilds/{guild_to_target}/commands"
else:
_request_url = f"commands"
_commands_to_json = [command.dict(exclude_none=True) for command in commands]
_send_request = self._client.put(
url=_request_url, json=_commands_to_json, headers=self.request_headers
)
if _send_request.status_code == 200:
logger.info(
f"Overwritten {len(_send_request.json())} commands.. Recieved ({len(_commands_to_json)}"
)
return True
else:
logger.debug(
f"BULK Overwrite failed ({guild_only} = {guild_to_target}): Body: {_commands_to_json}.. Status code: {_send_request.status_code}"
)
raise DiscordAPIError(_send_request.status_code, _send_request.text)
register(self, command, guild_only=False, guild_to_target=None)
¶
Register a completed DiscordCommand
model to Discord API.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
command |
DiscordCommand |
A properly configured DiscordCommand |
required |
guild_only |
bool |
Default to set global mode (True). Set to False to let the function know to expect a guild_id |
False |
guild_to_target |
int |
A guild Id if guild_only is set to True. |
None |
Source code in dispike/creating/registrator.py
def register(
self, command: DiscordCommand, guild_only=False, guild_to_target: int = None
):
"""Register a completed `DiscordCommand` model to Discord API.
Args:
command (DiscordCommand): A properly configured DiscordCommand
guild_only (bool, optional): Default to set global mode (True). Set to False to let the function know to expect a guild_id
guild_to_target (int, optional): A guild Id if guild_only is set to True.
"""
if guild_only == True:
if guild_to_target is None:
raise TypeError(
"if guild_only is set to true, a guild id must be provided."
)
logger.info(f"Targeting a specific guild -> {guild_to_target}")
_request_url = f"guilds/{guild_to_target}/commands"
else:
_request_url = f"commands"
try:
_command_to_json = command.dict(exclude_none=True)
_send_request = self._client.post(
_request_url, headers=self.request_headers, json=_command_to_json
)
if _send_request.status_code in [200, 201]:
return True
raise DiscordAPIError(_send_request.status_code, _send_request.text)
except Exception:
raise