Source code for discohook.command

import asyncio
from typing import Any, Dict, List, Optional, Union

from .component import Interactable
from .enums import (ApplicationCommandOptionType, ApplicationCommandType,
                    ApplicationIntegrationType, InteractionContextType)
from .option import Option
from .permission import Permission
from .utils import Handler, find_description


[docs]class SubCommand: """ A class representing a discord application command subcommand. Parameters ---------- name: str The name of the subcommand. description: str The description of the subcommand. options: List[Option] | None The options of the subcommand. callback: `AsyncCallable` | None The callback of the subcommand. """ def __init__( self, name: str, description: str, options: Optional[List[Option]] = None, *, callback: Optional[Handler] = None, ): self.name = name self.options = options self.callback = callback self.description = description self.autocompletion_handler: Optional[Handler] = None def __call__(self, *args, **kwargs): if not self.callback: raise RuntimeWarning( f"subcommand `{self.name}` of command " f"`{args[0].data['name']}` (id: {args[0].data['id']}) has no callback" ) return self.callback(*args, **kwargs)
[docs] def on_autocomplete(self, coro: Handler): """ A decorator to register a callback for the subcommand's autocomplete options. """ self.autocompletion_handler = coro return coro
[docs] def to_dict(self) -> Dict[str, Any]: payload = { "type": ApplicationCommandOptionType.subcommand, "name": self.name, "description": self.description, } if self.options: payload["options"] = [option.to_dict() for option in self.options] return payload
class SubCommandGroup: pass # noinspection PyShadowingBuiltins
[docs]class ApplicationCommand(Interactable): """ A class representing a discord application command. Parameters ---------- name: str The name of the command. description: str | None The description of the command. Does not apply to user & message commands. options: List[Option] | None The options of the command. Does not apply to user & message commands. nsfw: bool Whether the command is age restricted. Defaults to False. permissions: List[Permission] | None The default permissions of the command. type: ApplicationCommandType The category of the command. Defaults to slash commands. integration_types: List[ApplicationIntegrationType] | None Installation context(s) where the command is available. only for globally-scoped commands. contexts: List[InteractionContextType] | None Interaction context(s) where the command can be used, only for globally-scoped commands. """ def __init__( self, name: str, *, description: Optional[str] = None, options: Optional[List[Option]] = None, nsfw: bool = False, integration_types: Optional[List[ApplicationIntegrationType]] = None, contexts: Optional[List[InteractionContextType]] = None, permissions: Optional[List[Permission]] = None, type: ApplicationCommandType = ApplicationCommandType.slash, guild_id: Optional[str] = None, callback: Handler, ): super().__init__() self.name = name if not guild_id: self.key = f"{name}:{type.value}" else: self.key = f"{name}:{guild_id}:{type.value}" self.description = description self.options: List[Union[Option, SubCommand]] = options self.nsfw = nsfw self.application_id = None self.type = type self.contexts = [InteractionContextType.guild] if contexts is None else contexts self.integration_types = ( [ApplicationIntegrationType.guild] if integration_types is None else integration_types ) self.permissions = permissions self.guild_id = guild_id self.callback: Handler = callback self.data: Dict[str, Any] = {} self.subcommands: Dict[str, SubCommand] = {} self.autocompletion_handler: Optional[Handler] = None def __call__(self, *args, **kwargs): if not self.callback: raise RuntimeWarning(f"command `{self.key}` has no callback") return self.callback(*args, **kwargs)
[docs] def on_autocomplete(self, coro: Handler): """ A decorator to register a callback for the command's autocomplete options. """ self.autocompletion_handler = coro return coro
[docs] def subcommand( self, name: Optional[str] = None, description: Optional[str] = None, *, options: Optional[List[Option]] = None, ): """ A decorator to register a subcommand for the command. Parameters ---------- name: str The name of the subcommand. description: str The description of the subcommand. options: Optional[List[Option]] The options of the subcommand. Returns ------- SubCommand The subcommand object. Raises ------ TypeError If the callback is not a coroutine. """ def decorator(coro: Handler): subcommand = SubCommand(name, description, options, callback=coro) if self.options: self.options.append(subcommand) else: self.options = [subcommand] if not asyncio.iscoroutinefunction(coro): raise TypeError("subcommand callback must be a coroutine") self.subcommands[name] = subcommand return subcommand return decorator
[docs] def to_dict(self) -> Dict[str, Any]: """ Converts the command to a dictionary. This is used to send the command to the Discord API. Not intended for use by end-users. Returns ------- Dict[str, Any] """ self.data["name"] = self.name self.data["type"] = self.type if self.description: self.data["description"] = self.description if self.type == ApplicationCommandType.slash: if self.options: self.data["options"] = [option.to_dict() for option in self.options] if self.permissions: base = 0 for permission in self.permissions: base |= permission.value self.data["default_member_permissions"] = str(base) if self.nsfw: self.data["nsfw"] = self.nsfw self.data["integration_types"] = self.integration_types self.data["contexts"] = self.contexts return self.data
def slash( name: Optional[str] = None, *, description: Optional[str] = None, options: Optional[List[Option]] = None, nsfw: bool = False, permissions: Optional[List[Permission]] = None, guild_id: Optional[str] = None, integration_types: Optional[List[ApplicationIntegrationType]] = None, contexts: Optional[List[InteractionContextType]] = None, ): """ A decorator to register a slash command with its callback. """ def decorator(coro: Handler): return ApplicationCommand( name or coro.__name__, description=find_description(name, description, coro), options=options, nsfw=nsfw, permissions=permissions, guild_id=guild_id, integration_types=integration_types, contexts=contexts, callback=coro, ) return decorator def user( name: Optional[str] = None, *, nsfw: bool = False, permissions: Optional[List[Permission]] = None, guild_id: Optional[str] = None, integration_types: Optional[List[ApplicationIntegrationType]] = None, contexts: Optional[List[InteractionContextType]] = None, ): """ A decorator to register a user command with its callback. """ def decorator(coro: Handler): return ApplicationCommand( name or coro.__name__, nsfw=nsfw, permissions=permissions, guild_id=guild_id, type=ApplicationCommandType.user, integration_types=integration_types, contexts=contexts, callback=coro, ) return decorator def message( name: Optional[str] = None, *, nsfw: bool = False, permissions: Optional[List[Permission]] = None, guild_id: Optional[str] = None, integration_types: Optional[List[ApplicationIntegrationType]] = None, contexts: Optional[List[InteractionContextType]] = None, ): """ A decorator to register a message command with its callback. """ def decorator(coro: Handler): return ApplicationCommand( name or coro.__name__, nsfw=nsfw, permissions=permissions, guild_id=guild_id, type=ApplicationCommandType.message, integration_types=integration_types, contexts=contexts, callback=coro, ) return decorator