Hybrid commands
attrs
class
HybridCommand (SlashCommand)
¶
A subclass of SlashCommand that handles the logic for hybrid commands.
Attr attributes:
Name | Type | Description |
---|---|---|
extension |
Any |
The extension this command belongs to |
enabled |
bool |
Whether this can be run at all |
checks |
list |
Any checks that must be checked before the command can run |
cooldown |
Cooldown |
An optional cooldown to apply to the command |
max_concurrency |
MaxConcurrency |
An optional maximum number of concurrent instances to apply to the command |
error_callback |
Callable[..., Coroutine] |
The coroutine to be called when an error occurs |
pre_run_callback |
Callable[..., Coroutine] |
The coroutine to be called before the command is executed, but after the checks |
post_run_callback |
Callable[..., Coroutine] |
The coroutine to be called after the command has executed |
scopes |
List[Snowflake_Type] |
The scopes of this interaction. Global or guild ids |
default_member_permissions |
Optional[Permissions] |
What permissions members need to have by default to use this command |
dm_permission |
bool |
Whether this command is enabled in DMs |
cmd_id |
Dict[str, Snowflake_Type] |
The unique IDs of this commands |
callback |
Callable[..., Coroutine] |
The coroutine to call when this interaction is received |
auto_defer |
AutoDefer |
A system to automatically defer this command after a set duration |
nsfw |
bool |
This command should only work in NSFW channels |
Source code in naff/models/naff/hybrid_commands.py
@define()
class HybridCommand(SlashCommand):
"""A subclass of SlashCommand that handles the logic for hybrid commands."""
async def __call__(self, context: InteractionContext, *args, **kwargs) -> None:
new_ctx = context.bot.hybrid_context.from_interaction_context(context)
return await super().__call__(new_ctx, *args, **kwargs)
def group(self, name: str = None, description: str = "No Description Set") -> "HybridCommand":
return HybridCommand(
name=self.name,
description=self.description,
group_name=name,
group_description=description,
scopes=self.scopes,
)
def subcommand(
self,
sub_cmd_name: LocalisedName | str,
group_name: LocalisedName | str = None,
sub_cmd_description: Absent[LocalisedDesc | str] = MISSING,
group_description: Absent[LocalisedDesc | str] = MISSING,
options: list[SlashCommandOption | dict] = None,
nsfw: bool = False,
) -> Callable[..., "HybridCommand"]:
def wrapper(call: Callable[..., Coroutine]) -> "HybridCommand":
nonlocal sub_cmd_description
if not asyncio.iscoroutinefunction(call):
raise TypeError("Subcommand must be coroutine")
if sub_cmd_description is MISSING:
sub_cmd_description = call.__doc__ or "No Description Set"
return HybridCommand(
name=self.name,
description=self.description,
group_name=group_name or self.group_name,
group_description=group_description or self.group_description,
sub_cmd_name=sub_cmd_name,
sub_cmd_description=sub_cmd_description,
default_member_permissions=self.default_member_permissions,
dm_permission=self.dm_permission,
options=options,
callback=call,
scopes=self.scopes,
nsfw=nsfw,
)
return wrapper
async
inherited
method
call_with_binding(self, callback, *args, **kwargs)
¶
Call a given method using this objects _binding.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
callback |
Callable[..., Coroutine[Any, Any, Any]] |
The callback to call. |
required |
Source code in naff/models/naff/hybrid_commands.py
async def call_with_binding(self, callback: Callable[..., Coroutine[Any, Any, Any]], *args, **kwargs) -> Any:
"""
Call a given method using this objects _binding.
Args:
callback: The callback to call.
"""
if self._binding:
return await callback(self._binding, *args, **kwargs)
return await callback(*args, **kwargs)
inherited
method
update_from_dict(self, data)
¶
Updates object attribute(s) with new json data received from discord api.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
data |
Dict[str, Any] |
The json data received from discord api. |
required |
Returns:
Type | Description |
---|---|
~T |
The updated object class instance. |
Source code in naff/models/naff/hybrid_commands.py
def update_from_dict(self: Type[const.T], data: Dict[str, Any]) -> const.T:
"""
Updates object attribute(s) with new json data received from discord api.
Args:
data: The json data received from discord api.
Returns:
The updated object class instance.
"""
data = self._process_dict(data)
for key, value in self._filter_kwargs(data, self._get_keys()).items():
# todo improve
setattr(self, key, value)
return self
inherited
method
mention(self, scope)
¶
Returns a string that would mention the interaction.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
scope |
Optional[Snowflake_Type] |
If the command is available in multiple scope, specify which scope to get the mention for. Defaults to the first available one if not specified. |
None |
Returns:
Type | Description |
---|---|
str |
The markdown mention. |
Source code in naff/models/naff/hybrid_commands.py
def mention(self, scope: Optional["Snowflake_Type"] = None) -> str:
"""
Returns a string that would mention the interaction.
Args:
scope: If the command is available in multiple scope, specify which scope to get the mention for. Defaults to the first available one if not specified.
Returns:
The markdown mention.
"""
if scope:
cmd_id = self.get_cmd_id(scope=scope)
else:
cmd_id = list(self.cmd_id.values())[0]
return f"</{self.resolved_name}:{cmd_id}>"
inherited
method
error(self, call)
¶
A decorator to declare a coroutine as one that will be run upon an error.
Source code in naff/models/naff/hybrid_commands.py
def error(self, call: Callable[..., Coroutine]) -> Callable[..., Coroutine]:
"""A decorator to declare a coroutine as one that will be run upon an error."""
if not asyncio.iscoroutinefunction(call):
raise TypeError("Error handler must be coroutine")
self.error_callback = call
return call
inherited
method
pre_run(self, call)
¶
A decorator to declare a coroutine as one that will be run before the command.
Source code in naff/models/naff/hybrid_commands.py
def pre_run(self, call: Callable[..., Coroutine]) -> Callable[..., Coroutine]:
"""A decorator to declare a coroutine as one that will be run before the command."""
if not asyncio.iscoroutinefunction(call):
raise TypeError("pre_run must be coroutine")
self.pre_run_callback = call
return call
inherited
method
post_run(self, call)
¶
A decorator to declare a coroutine as one that will be run after the command has.
Source code in naff/models/naff/hybrid_commands.py
def post_run(self, call: Callable[..., Coroutine]) -> Callable[..., Coroutine]:
"""A decorator to declare a coroutine as one that will be run after the command has."""
if not asyncio.iscoroutinefunction(call):
raise TypeError("post_run must be coroutine")
self.post_run_callback = call
return call
inherited
property
readonly
resolved_name: str
¶
A representation of this interaction's name.
inherited
method
to_dict(self)
¶
Exports object into dictionary representation, ready to be sent to discord api.
Returns:
Type | Description |
---|---|
dict |
The exported dictionary. |
Source code in naff/models/naff/hybrid_commands.py
def to_dict(self) -> dict:
data = super().to_dict()
if self.is_subcommand:
data["name"] = str(self.sub_cmd_name)
data["description"] = str(self.sub_cmd_description)
data["name_localizations"] = self.sub_cmd_name.to_locale_dict()
data["description_localizations"] = self.sub_cmd_description.to_locale_dict()
data.pop("default_member_permissions", None)
data.pop("dm_permission", None)
data.pop("nsfw", None)
else:
data["name_localizations"] = self.name.to_locale_dict()
data["description_localizations"] = self.description.to_locale_dict()
return data
inherited
method
autocomplete(self, option_name)
¶
A decorator to declare a coroutine as an option autocomplete.
Source code in naff/models/naff/hybrid_commands.py
def autocomplete(self, option_name: str) -> Callable[..., Coroutine]:
"""A decorator to declare a coroutine as an option autocomplete."""
def wrapper(call: Callable[..., Coroutine]) -> Callable[..., Coroutine]:
if not asyncio.iscoroutinefunction(call):
raise TypeError("autocomplete must be coroutine")
self.autocomplete_callbacks[option_name] = call
# automatically set the option's autocomplete attribute to True
for opt in self.options:
if isinstance(opt, dict) and str(opt["name"]) == option_name:
opt["autocomplete"] = True
elif isinstance(opt, SlashCommandOption) and str(opt.name) == option_name:
opt.autocomplete = True
return call
option_name = option_name.lower()
return wrapper
function
hybrid_command(name, *, description, scopes, options, default_member_permissions, dm_permission, sub_cmd_name, group_name, sub_cmd_description, group_description, nsfw)
¶
A decorator to declare a coroutine as a hybrid command.
Hybrid commands are a slash command that can also function as a prefixed command. These use a HybridContext instead of an InteractionContext, but otherwise are mostly identical to normal slash commands.
Note that hybrid commands do not support autocompletes. They also only partially support attachments, allowing one attachment option for a command.
Note
While the base and group descriptions aren't visible in the discord client, currently. We strongly advise defining them anyway, if you're using subcommands, as Discord has said they will be visible in one of the future ui updates. They are also visible as the description for their prefixed command counterparts.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
name |
str | naff.models.naff.application_commands.LocalisedName |
1-32 character name of the command |
required |
description |
Union[naff.models.naff.application_commands.LocalisedDesc, str, naff.client.const.Missing] |
1-100 character description of the command |
Missing |
scopes |
Union[list['Snowflake_Type'], naff.client.const.Missing] |
The scope this command exists within |
Missing |
options |
Optional[list[naff.models.naff.application_commands.SlashCommandOption | dict]] |
The parameters for the command, max 25 |
None |
default_member_permissions |
Optional[Permissions] |
What permissions members need to have by default to use this command. |
None |
dm_permission |
bool |
Should this command be available in DMs. |
True |
sub_cmd_name |
str | naff.models.naff.application_commands.LocalisedName |
1-32 character name of the subcommand |
None |
sub_cmd_description |
str | naff.models.naff.application_commands.LocalisedDesc |
1-100 character description of the subcommand |
'No Description Set' |
group_name |
str | naff.models.naff.application_commands.LocalisedName |
1-32 character name of the group |
None |
group_description |
str | naff.models.naff.application_commands.LocalisedDesc |
1-100 character description of the group |
'No Description Set' |
nsfw |
bool |
This command should only work in NSFW channels |
False |
Returns:
Type | Description |
---|---|
Callable[[Callable[..., Coroutine]], naff.models.naff.hybrid_commands.HybridCommand] |
HybridCommand Object |
Source code in naff/models/naff/hybrid_commands.py
def hybrid_command(
name: str | LocalisedName,
*,
description: Absent[str | LocalisedDesc] = MISSING,
scopes: Absent[list["Snowflake_Type"]] = MISSING,
options: Optional[list[SlashCommandOption | dict]] = None,
default_member_permissions: Optional["Permissions"] = None,
dm_permission: bool = True,
sub_cmd_name: str | LocalisedName = None,
group_name: str | LocalisedName = None,
sub_cmd_description: str | LocalisedDesc = "No Description Set",
group_description: str | LocalisedDesc = "No Description Set",
nsfw: bool = False,
) -> Callable[[Callable[..., Coroutine]], HybridCommand]:
"""
A decorator to declare a coroutine as a hybrid command.
Hybrid commands are a slash command that can also function as a prefixed command.
These use a HybridContext instead of an InteractionContext, but otherwise are mostly identical to normal slash commands.
Note that hybrid commands do not support autocompletes.
They also only partially support attachments, allowing one attachment option for a command.
note:
While the base and group descriptions aren't visible in the discord client, currently.
We strongly advise defining them anyway, if you're using subcommands, as Discord has said they will be visible in
one of the future ui updates.
They are also visible as the description for their prefixed command counterparts.
Args:
name: 1-32 character name of the command
description: 1-100 character description of the command
scopes: The scope this command exists within
options: The parameters for the command, max 25
default_member_permissions: What permissions members need to have by default to use this command.
dm_permission: Should this command be available in DMs.
sub_cmd_name: 1-32 character name of the subcommand
sub_cmd_description: 1-100 character description of the subcommand
group_name: 1-32 character name of the group
group_description: 1-100 character description of the group
nsfw: This command should only work in NSFW channels
Returns:
HybridCommand Object
"""
def wrapper(func: Callable[..., Coroutine]) -> HybridCommand:
if not asyncio.iscoroutinefunction(func):
raise ValueError("Commands must be coroutines")
perm = default_member_permissions
if hasattr(func, "default_member_permissions"):
if perm:
perm = perm | func.default_member_permissions
else:
perm = func.default_member_permissions
_description = description
if _description is MISSING:
_description = func.__doc__ or "No Description Set"
return HybridCommand(
name=name,
group_name=group_name,
group_description=group_description,
sub_cmd_name=sub_cmd_name,
sub_cmd_description=sub_cmd_description,
description=_description,
scopes=scopes or [GLOBAL_SCOPE],
default_member_permissions=perm,
dm_permission=dm_permission,
callback=func,
options=options,
nsfw=nsfw,
)
return wrapper
function
hybrid_subcommand(base, *, subcommand_group, name, description, base_description, base_desc, base_default_member_permissions, base_dm_permission, subcommand_group_description, sub_group_desc, scopes, options, nsfw)
¶
A decorator specifically tailored for creating hybrid subcommands.
See the hybrid_command decorator for more information.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
base |
str | naff.models.naff.application_commands.LocalisedName |
The name of the base command |
required |
subcommand_group |
Union[str, naff.models.naff.application_commands.LocalisedName] |
The name of the subcommand group, if any. |
None |
name |
Union[str, naff.models.naff.application_commands.LocalisedName] |
The name of the subcommand, defaults to the name of the coroutine. |
None |
description |
Union[naff.models.naff.application_commands.LocalisedDesc, str, naff.client.const.Missing] |
The description of the subcommand |
Missing |
base_description |
Union[str, naff.models.naff.application_commands.LocalisedDesc] |
The description of the base command |
None |
base_desc |
Union[str, naff.models.naff.application_commands.LocalisedDesc] |
An alias of |
None |
base_default_member_permissions |
Optional[Permissions] |
What permissions members need to have by default to use this command. |
None |
base_dm_permission |
bool |
Should this command be available in DMs. |
True |
subcommand_group_description |
Union[str, naff.models.naff.application_commands.LocalisedDesc] |
Description of the subcommand group |
None |
sub_group_desc |
Union[str, naff.models.naff.application_commands.LocalisedDesc] |
An alias for |
None |
scopes |
list |
The scopes of which this command is available, defaults to GLOBAL_SCOPE |
None |
options |
list |
The options for this command |
None |
nsfw |
bool |
This command should only work in NSFW channels |
False |
Returns:
Type | Description |
---|---|
Callable[[Coroutine], naff.models.naff.hybrid_commands.HybridCommand] |
A HybridCommand object |
Source code in naff/models/naff/hybrid_commands.py
def hybrid_subcommand(
base: str | LocalisedName,
*,
subcommand_group: Optional[str | LocalisedName] = None,
name: Optional[str | LocalisedName] = None,
description: Absent[str | LocalisedDesc] = MISSING,
base_description: Optional[str | LocalisedDesc] = None,
base_desc: Optional[str | LocalisedDesc] = None,
base_default_member_permissions: Optional["Permissions"] = None,
base_dm_permission: bool = True,
subcommand_group_description: Optional[str | LocalisedDesc] = None,
sub_group_desc: Optional[str | LocalisedDesc] = None,
scopes: list["Snowflake_Type"] = None,
options: list[dict] = None,
nsfw: bool = False,
) -> Callable[[Coroutine], HybridCommand]:
"""
A decorator specifically tailored for creating hybrid subcommands.
See the hybrid_command decorator for more information.
Args:
base: The name of the base command
subcommand_group: The name of the subcommand group, if any.
name: The name of the subcommand, defaults to the name of the coroutine.
description: The description of the subcommand
base_description: The description of the base command
base_desc: An alias of `base_description`
base_default_member_permissions: What permissions members need to have by default to use this command.
base_dm_permission: Should this command be available in DMs.
subcommand_group_description: Description of the subcommand group
sub_group_desc: An alias for `subcommand_group_description`
scopes: The scopes of which this command is available, defaults to GLOBAL_SCOPE
options: The options for this command
nsfw: This command should only work in NSFW channels
Returns:
A HybridCommand object
"""
def wrapper(func) -> HybridCommand:
if not asyncio.iscoroutinefunction(func):
raise ValueError("Commands must be coroutines")
_description = description
if _description is MISSING:
_description = func.__doc__ or "No Description Set"
return HybridCommand(
name=base,
description=(base_description or base_desc) or "No Description Set",
group_name=subcommand_group,
group_description=(subcommand_group_description or sub_group_desc) or "No Description Set",
sub_cmd_name=name,
sub_cmd_description=_description,
default_member_permissions=base_default_member_permissions,
dm_permission=base_dm_permission,
scopes=scopes or [GLOBAL_SCOPE],
callback=func,
options=options,
nsfw=nsfw,
)
return wrapper