Creating Commands#

You’re using a command handler library so naturally you’ll probably be wanting to make some commands for your bot.

If you haven’t made your first command yet, it is recommended that you read the Getting Started page before continuing.

Note

You should note that the order that the decorators are applied is rather important. The lightbulb.implements decorator should always be on the bottom of the stack, followed by the lightbulb.command decorator on top of it. The bot.command decorator must always be on the top of the stack if you are using it.


The Implements Decorator#

lightbulb.decorators.implements(*command_types: Type[Command]) Callable[[CommandCallbackT], CommandCallbackT][source]

Second order decorator that defines the command types that a given callback function will implement.

Parameters:

*command_types (Type[Command]) – Command types that the function will implement.

This decorator acts as the base for every command you will make using Lightbulb.

It defines the type or multiple types of commands that the decorated callback function will implement.

For example:

import lightbulb

@lightbulb.implements(lightbulb.PrefixCommand)
async def foo(ctx: lightbulb.Context) -> None:
    # This command will be invoked using the command prefix(es) that the bot recognises.
    ...

@lightbulb.implements(lightbulb.SlashCommand)
async def bar(ctx: lightbulb.Context) -> None:
    # This command will be created as a slash command.
    ...

@lightbulb.implements(lightbulb.PrefixCommand, lightbulb.SlashCommand)
async def baz(ctx: lightbulb.Context) -> None:
    # This command will be able to be invoked both using the bot's command prefix(es),
    # and as a slash command using interactions.
    ...

The Command Decorator#

lightbulb.decorators.command(name: str, description: str, *, cls: ~typing.Type[~lightbulb.commands.base.CommandLike] = <class 'lightbulb.commands.base.CommandLike'>, **kwargs: ~typing.Any) Callable[[CommandCallbackT], CommandLike][source]

Second order decorator that converts the decorated function into a CommandLike object.

Parameters:
  • name (str) – The name of the command .

  • description (str) – The description of the command.

Keyword Arguments:
  • error_handler (Optional[ListenerT]) – The function to register as the command’s error handler. Defaults to None. This can also be set with the set_error_handler decorator.

  • aliases (Sequence[str]) – Aliases for the command. This will only affect prefix commands. Defaults to an empty list.

  • guilds (Sequence[int]) – The guilds that the command will be created in. This will only affect application commands. Defaults to an empty list.

  • parser (BaseParser) – The argument parser to use for prefix commands. Defaults to Parser.

  • auto_defer (bool) – Whether to automatically defer the response when the command is invoked. If True, the bot will send an initial response of type DEFERRED_MESSAGE_CREATE for interactions, and for prefix commands, typing will be triggered in the invocation channel.

  • ephemeral (bool) – Whether to send responses from the invocation of this command as ephemeral by default. If True then all responses from the command will use the flag hikari.MessageFlags.EPHEMERAL. This will not affect prefix commands as responses from prefix commands cannot be ephemeral.

  • hidden (bool) – Whether to hide the command from the help command. Defaults to False.

  • inherit_checks (bool) – Whether or not the command should inherit checks from the parent group. Only affects subcommands. Defaults to False.

  • pass_options (bool) – Whether the command will have its options passed as keyword arguments when invoked.

  • name_localizations (Mapping[Union[hikari.locales.Locale, str], str]) – A mapping of locale to name localizations for this command. Defaults to an empty dictionary.

  • description_localizations (Mapping[Union[hikari.locales.Locale, str], str]) – A mapping of locale to description localizations for this command. Defaults to an empty dictionary.

  • nsfw (bool) – Whether the command should only be enabled in NSFW channels. For prefix commands, this will add an NSFW-channel only check to the command automatically. For slash commands, this will behave as specified in the Discord documentation.

  • cls (Type[CommandLike]) – CommandLike class to instantiate from this decorator. Defaults to CommandLike.

New in version 2.1.0: cls kwarg.

New in version 2.2.1: pass_options kwarg.

New in version 2.3.0: name_localizations and description_localizations kwargs.

This decorator converts the decorated function into a lightbulb.commands.base.CommandLike object. This object can be coerced into any of the command classes that Lightbulb supports.

Given the fundamental differences between slash commands and prefix commands, not all kwargs will affect all of the command types that can be created.

For example:

import lightbulb

@lightbulb.command("foo", "test command", aliases=["bar", "baz"])
@lightbulb.implements(lightbulb.PrefixCommand)
async def foo(ctx: lightbulb.Context) -> None:
    ...

@lightbulb.command("foo", "test slash command", guilds=[123453463456, 34569827369])
@lightbulb.implements(lightbulb.SlashCommand)
async def _foo(ctx: lightbulb.Context) -> None:
    ...

The Option Decorator#

Basic commands that respond with set messages are cool, but sometimes you might want to take input from the user to allow you to create more complex commands and more complex flows.

Lightbulb provides the lightbulb.decorators.option decorator for this purpose.

lightbulb.decorators.option(name: str, description: str, type: ~typing.Any = <class 'str'>, *, required: bool | ~hikari.undefined.UndefinedType = UNDEFINED, choices: ~typing.Sequence[str | int | float | ~hikari.commands.CommandChoice] | None = None, channel_types: ~typing.Sequence[~hikari.channels.ChannelType] | None = None, default: ~typing.Any | ~hikari.undefined.UndefinedType = UNDEFINED, modifier: ~lightbulb.commands.base.OptionModifier = OptionModifier.NONE, min_value: float | int | None = None, max_value: float | int | None = None, min_length: int | None = None, max_length: int | None = None, autocomplete: bool | ~typing.Callable[[~hikari.interactions.command_interactions.CommandInteractionOption, ~hikari.interactions.command_interactions.AutocompleteInteraction], ~typing.Coroutine[~typing.Any, ~typing.Any, str | ~hikari.api.special_endpoints.AutocompleteChoiceBuilder | ~typing.Sequence[str | ~hikari.api.special_endpoints.AutocompleteChoiceBuilder]]] = False, cls: ~typing.Type[~lightbulb.commands.base.OptionLike] = <class 'lightbulb.commands.base.OptionLike'>, **kwargs: ~typing.Any) Callable[[CommandLike], CommandLike][source]

Second order decorator that adds an option to the decorated CommandLike object.

Parameters:
  • name (str) – The name of the option.

  • description (str) – The description of the option.

  • type (Any) – The type of the option. This will be used as the converter for prefix commands.

Keyword Arguments:
  • required (UndefinedOr[bool]) – Whether this option is required. This will be inferred from whether a default value for the option was specified if not otherwise specified.

  • choices (Optional[Sequence[Union[str, int, float, CommandChoice]]]) – The choices for the option. This will only affect slash commands. Defaults to None.

  • channel_types (Optional[Sequence[hikari.channels.ChannelType]]) – The channel types allowed for the option. This will only affect slash commands. Defaults to None.

  • default (UndefinedOr[Any]) – The default value for the option. Defaults to UNDEFINED.

  • modifier (OptionModifier) – Modifier controlling how the option should be parsed. Defaults to OptionModifier.NONE.

  • min_value (Optional[Union[float, int]]) – The minimum value permitted for this option (inclusive). Only available if the option type is numeric (integer or float). Defaults to None.

  • max_value (Optional[Union[float, int]]) – The maximum value permitted for this option (inclusive). Only available if the option type is numeric (integer or float). Defaults to None.

  • min_length (Optional[int]) – The minimum length permitted for this option. Only available if this option is string type.

  • max_length (Optional[int]) – The maximum length permitted for this option. Only available if this option is string type.

  • autocomplete (Union[bool, AutocompleteCallbackT]) – Boolean representing whether the option will use autocomplete or the callback to use for autocomplete for this option. This will only affect slash commands. Defaults to False.

  • name_localizations (Mapping[Union[hikari.locales.Locale, str], str]) – A mapping of locale to name localizations for this option. Defaults to an empty dictionary.

  • description_localizations (Mapping[Union[hikari.locales.Locale, str], str]) – A mapping of locale to description localizations for this option. Defaults to an empty dictionary.

  • cls (Type[OptionLike]) – OptionLike class to instantiate from this decorator. Defaults to OptionLike.

New in version 2.1.0: cls kwarg.

New in version 2.1.3: min_value and max_value kwargs.

New in version 2.3.2: min_length and max_length kwargs.

For example:

import lightbulb

@lightbulb.option("text", "text to repeat", modifier=lightbulb.OptionModifier.CONSUME_REST)
@lightbulb.command("echo", "repeats the given text")
@lightbulb.implements(lightbulb.PrefixCommand)
async def echo(ctx: lightbulb.Context) -> None:
    await ctx.respond(ctx.options.text)

Converters and Slash Command Option Types#

Below is a list of all the acceptable types that you can pass into the type argument of the option decorator. On the left is the type to pass in, the right side is the converter that the type is mapped to, or for slash commands, the hikari OptionType that the type is mapped to.

Prefix command converter mapping:

Acceptable primitives: str, int, float

Slash command option type mapping:

  • str - hikari.OptionType.STRING

  • int - hikari.OptionType.INTEGER

  • float - hikari.OptionType.FLOAT

  • bool - hikari.OptionType.BOOLEAN

  • hikari.User - hikari.OptionType.USER

  • hikari.Member - hikari.OptionType.USER

  • hikari.GuildChannel - hikari.OptionType.CHANNEL

  • hikari.TextableGuildChannel - hikari.OptionType.CHANNEL

  • hikari.TextableChannel - hikari.OptionType.CHANNEL

  • hikari.GuildCategory - hikari.OptionType.CHANNEL

  • hikari.GuildVoiceChannel - hikari.OptionType.CHANNEL

  • hikari.Role - hikari.OptionType.ROLE

  • hikari.Emoji - hikari.OptionType.STRING

  • hikari.Guild - hikari.OptionType.STRING

  • hikari.Message - hikari.OptionType.STRING

  • hikari.Invite - hikari.OptionType.STRING

  • hikari.Colour - hikari.OptionType.STRING

  • hikari.Color - hikari.OptionType.STRING

  • hikari.Snowflake - hikari.OptionType.STRING

  • datetime.datetime - hikari.OptionType.STRING

  • hikari.Attachment - hikari.OptionType.ATTACHMENT

Note

Slash command options that resolve to type hikari.OptionType.STRING will also have the appropriate converter run upon invocation. If this causes the command to take too long to run then you can pass auto_defer=True to the lightbulb.command decorator. The deferral will be processed prior to the conversion of options.


Adding Checks to Commands#

Checks prevent commands from being invoked if the user invoking the command does not meet the specified criteria. For example, you can prevent commands from being used in DMs, restrict them to only the owner of the bot, or restrict commands to only users that have specific permissions.

See Checks API Reference for all of the checks that are provided by Lightbulb.

To add checks to a command, you need to use the lightbulb.decorators.add_checks decorator. The decorator takes an arbitrary number of lightbulb.checks.Check objects and will add all of them to the command.

For example:

import lightbulb

@lightbulb.add_checks(lightbulb.owner_only)
@lightbulb.command("foo", "test command")
@lightbulb.implements(lightbulb.PrefixCommand)
async def foo(ctx: lightbulb.Context) -> None:
    await ctx.respond("You are the owner of this bot.")

You can also create custom checks by creating your own instance of the lightbulb.checks.Check class and passing in your custom check function to the constructor. A check function should take a single argument, which will be the Context instance for the command that is attempting to be invoked. Your check should either raise an error or return False on failure and must return True if it passes. Your check may be a syncronous or asyncronous function.

For example:

import lightbulb

# OPTIONAL: Converting the check function into a Check object
@lightbulb.Check
# Defining the custom check function
def check_author_is_me(context: lightbulb.Context) -> bool:
    # Returns True if the author's ID is the same as the given one
    return context.author.id == 1455657467

# Adding the check to a command
@lightbulb.add_checks(check_author_is_me)
# Or if you do not use the @lightbulb.Check decorator
@lightbulb.add_checks(lightbulb.Check(check_author_is_me))

Adding Commands to the Bot#

To add commands to the bot, you need to use the lightbulb.app.BotApp.command method, either as a decorator, or by calling it with the lightbulb.commands.base.CommandLike object to add to the bot as a command.

This method instantiates the different command objects for the given CommandLike object and registers them to the correct bot attribute.

For example:

import lightbulb

bot = lightbulb.BotApp(...)

@bot.command  # valid
@lightbulb.command("foo", "test command")
@lightbulb.implements(lightbulb.PrefixCommand)
async def foo(ctx: lightbulb.Context) -> None:
    ...

@bot.command()  # also valid
@lightbulb.command("bar", "test command")
@lightbulb.implements(lightbulb.PrefixCommand)
async def bar(ctx: lightbulb.Context) -> None:
    ...

@lightbulb.command("baz", "test command")
@lightbulb.implements(lightbulb.PrefixCommand)
async def baz(ctx: lightbulb.Context) -> None:
    ...

bot.command(baz)  # also valid