lightbulb.client

class Client(rest: RESTClient, default_enabled_guilds: Sequence[hikari.Snowflakeish], execution_step_order: Sequence[ExecutionStep], default_locale: Locale, localization_provider: localization.LocalizationProvider, delete_unknown_commands: bool, deferred_registration_callback: lb_types.DeferredRegistrationCallback | None, hooks: Sequence[ExecutionHook])[source]

Base client implementation supporting generic application command handling.

Parameters:
  • rest – The rest client to use.

  • default_enabled_guilds – The guilds that application commands should be created in by default. Can be overridden on a per-command basis.

  • execution_step_order – The order that execution steps will be run in upon command processing.

  • default_locale – The default locale to use for command names and descriptions, as well as option names and descriptions. Has no effect if localizations are not being used.

  • localization_provider – The localization provider function to use. This will be called whenever the client needs to get the localizations for a key.

  • delete_unknown_commands – Whether to delete existing commands that the client does not have an implementation for during command syncing.

  • deferred_registration_callback – The callback to use to resolve which guilds a command should be created in if a command is registered using register_deferred(). Allows for commands to be dynamically created in guilds, for example enabled on a per-guild basis using feature flags.

  • hooks – Execution hooks that should be applied to all commands. These hooks will always run before all other hooks registered for the same step are executed.

build_autocomplete_context(interaction: AutocompleteInteraction, options: Sequence[AutocompleteInteractionOption], command_cls: type[CommandBase]) context_.AutocompleteContext[t.Any][source]

Build a context object from the given parameters.

Parameters:
  • interaction – The interaction for the autocomplete invocation.

  • options – The options supplied with the interaction.

  • command_cls – The command class that represents the command that has the option being autocompleted.

Returns:

The built context.

Return type:

AutocompleteContext

build_command_context(interaction: CommandInteraction, options: Sequence[CommandInteractionOption], command_cls: type[CommandBase]) context_.Context[source]

Build a context object from the given parameters.

Parameters:
  • interaction – The interaction for the command invocation.

  • options – The options to use to invoke the command with.

  • command_cls – The command class that represents the command that should be invoked for the interaction.

Returns:

The built context.

Return type:

Context

error_handler(*, priority: int = 0) Callable[[ErrorHandlerT], ErrorHandlerT][source]
error_handler(func: ErrorHandlerT, *, priority: int = 0) ErrorHandlerT

Register an error handler function to call when an ExecutionPipeline fails. Also enables dependency injection for the error handler function.

The function must take the exception as its first argument, which will be an instance of ExecutionPipelineFailedException. The function must return a boolean indicating whether the exception was successfully handled. Non-boolean return values will be cast to booleans.

Parameters:
  • func – The function to register as a command error handler.

  • priority – The priority that this handler should be registered at. Higher priority handlers will be executed first.

async load_extensions(*import_paths: str) None[source]

Load extensions from the given import paths. If loading of a single extension fails it will be skipped and any loaders already processed, as well as the one that caused the error will be removed.

Parameters:

*import_paths – The import paths for the extensions to be loaded.

Returns:

None

async load_extensions_from_package(package: ModuleType, *, recursive: bool = False) None[source]

Load all extension modules from the given package. Ignores any files with a name that starts with an underscore.

Parameters:
  • package – The package to load extensions from. Expects the imported module for the __init__.py file in the package.

  • recursive – Whether to recursively load extensions from subpackages. Defaults to False.

Returns:

None

Raises:

TypeError – If the given module is not for the __init__.py file of a package.

Example

Given the following file structure:

extensions/
├── __init__.py
├── extension1.py
└── extension2.py
bot.py

To load all extensions in the extensions package you should do the following:

import extensions

await client.load_extensions_from_package(extensions)
register(*, guilds: Sequence[hikari.Snowflakeish] | None = None, global_: bool | None = None) Callable[[CommandOrGroupT], CommandOrGroupT][source]
register(*, defer_guilds: Literal[True]) Callable[[CommandOrGroupT], CommandOrGroupT]
register(command: CommandOrGroupT, *, guilds: Sequence[hikari.Snowflakeish] | None = None, global_: bool | None = None) CommandOrGroupT
register(command: CommandOrGroupT, *, defer_guilds: Literal[True]) CommandOrGroupT

Register a command or group with this client instance.

Optionally, a sequence of guild ids, and/or a boolean indicating whether the command should be registered globally can be provided to make the commands created in specific guilds only - overriding the value for default enabled guilds. If you specify global_=False then you must specify either guilds=[...] in this function, or default_enabled_guilds when creating the client.

If a value is passed to guilds or you pass global_=True, then this command will not use the value you provided to default_enabled_guilds.

You may specify defer_guilds=True in order to resolve the guilds the command should be created in once the client has been started.

This method can be used as a function, or a first or second order decorator.

Parameters:
  • command – The command class or command group to register with the client.

  • guilds – The guilds to create the command or group in.

  • global – Whether the command should be registered globally.

  • defer_guilds – Whether the guilds to create this command in should be resolved when the client is started. If True, the deferred_registration_callback will be used to resolve which guilds to create the command in. You can also use this to conditionally prevent the command from being registered to any guilds.

Returns:

The registered command or group, unchanged.

Raises:

ValueError – If defer_guilds is True, and no deferred_registration_callback was set upon client creation.

Note

The signature overloads do not allow for you to pass a value for both guilds and defer_guilds. If for some reason you pass both however, then defer_guilds will take precedence.

Example

client = lightbulb.client_from_app(...)

# valid
@client.register
# also valid
@client.register(guilds=[...], global_=True)
# also valid
@client.register(defer_guilds=True)
class Example(
    lightbulb.SlashCommand,
    ...
):
    ...

# also valid
client.register(Example, guilds=[...], global_=True)
# also valid
client.register(Example, defer_guilds=True)
client = lightbulb.client_from_app(..., default_enabled_guilds=[123, 456])

# Command will be registered in:
# guilds: 123, 456
# globally: false
client.register(command)

# guilds: 123, 456
# globally: false
client.register(command, global_=False)

# guilds: 789
# globally: false
client.register(command, guilds=[789])

# guilds: none
# globally: true
client.register(command, global_=True)

# guilds: 789
# globally: true
client.register(command, guilds=[789], global_=True)

# === IF NO 'default_enabled_guilds' SET ===

# guilds: none
# globally: true
client.register(command)
async reload_extensions(*import_paths: str) None[source]

Reload extensions from the given import paths. This operation is atomic. If reloading of an extension fails, the client’s state for that extension will be restored to the previous known-working state. If a path is passed for an extension that is not loaded, it will be loaded and continue processing the remaining extensions.

Parameters:

*import_paths – The import paths for the extensions to be reloaded.

Returns:

None

remove_error_handler(func: Callable[[Concatenate[ExecutionPipelineFailedException, ...]], bool | Coroutine[Any, Any, bool]]) None[source]

Unregister a command error handler function from the client.

Parameters:

func – The function to unregister as a command error handler.

Returns:

None

remove_task(task: Task, cancel: bool = False) None[source]

Remove a task from the client. Tasks will be stopped and unregistered from the client once they complete.

Parameters:
  • task – The task to remove from the client.

  • cancel – Whether the task should be immediately cancelled instead of stopped gracefully.

Returns:

None

async start(*_: Any) None[source]

Starts the client. Ensures that commands are registered properly with the client, and that commands have been synced with discord. Also starts any tasks that were created with auto_start set to True.

Returns:

None

Raises:

RuntimeError – If the client has already been started.

async stop(*_: Any) None[source]

Stops the client. Cancelling any tasks that are running, and closing the default DI container - causing teardown methods to be called.

Returns:

None

async sync_application_commands() None[source]

Sync all application commands registered to the bot with discord. Also, properly registers any commands with localization enabled for the command name as well as any commands using deferred registration.

Returns:

None

task(trigger: tasks.Trigger, /, auto_start: bool = True, max_failures: int = 1, max_invocations: int = -1) Callable[[tasks.TaskFunc], Task][source]
task(task: Task, /) Task

Second order decorator to register a repeating task with the client. Task functions will have dependency injection enabled on them automatically. Task functions must be asynchronous.

Parameters:
  • task – The task to register with the client. If this parameter is provided then all other parameters are ignored.

  • trigger – The trigger function to use to resolve the interval between task executions.

  • auto_start – Whether the task should be started automatically. This means that if the task is added to the client upon the client being started, the task will also be started; it will also be started if being added to an already-started client.

  • max_failures – The maximum number of failed attempts to execute the task before it is cancelled. Setting this to a negative number will prevent the task from being cancelled, regardless of how often the task fails.

  • max_invocations – The maximum number of times the task can be invoked before being stopped. Setting this to a negative number will disable this behaviour, allowing unlimited invocations.

Note

This method can also be called with an existing task object to register it directly.

Example

@client.task(lightbulb.uniformtrigger(minutes=1)
async def print_hi() -> None:
    print("HI")
async unload_extensions(*import_paths: str) None[source]

Unload extensions from the given import paths. If unloading of a single extension fails an error will be raised and no further extensions will be unloaded. Attempting to unload an extensions that is not loaded will log a warning and continue with the remaining extensions.

Parameters:

*import_paths – The import paths for the extensions to be unloaded.

Returns:

None

Raises:

When an exception is thrown during removing loaders from the client for the extension being unloaded.

unregister(command: Group | type[CommandBase]) None[source]

Unregister a command with the client. This will prevent the client from handling any incoming interactions for the given command globally, or in any guild. This will not delete the command from discord and users will still be able to see it in the command menu.

Parameters:

command – The command class or command group to unregister with the client.

Returns:

None

abstract property app: RESTAware

The app that this client was created from.

property created_commands: Mapping[hikari.Snowflakeish, Collection[PartialCommand]]

Mapping of guild ID to commands that were created in that guild during command syncing.

Global commands are stored at the key lightbulb.internal.constants.GLOBAL_COMMAND_KEY.

property di: DependencyInjectionManager

The dependency injection manager used by this client.

property invokable_commands: Mapping[hikari.Snowflakeish, Mapping[tuple[str, ...], i_utils.CommandCollection]]

Mapping of guild ID to mapping of qualified command path to command(s) (slash, message, and user) that can be invoked for that command path.

Example

If the following global commands are registered:

/command
/group
├── subcommand
└── subgroup
    └── subsubcommand

This would return the following mapping:

{0: {
    ("command",): CommandCollection(slash=Command, message=None, user=None),
    ("group", "subcommand"): CommandCollection(slash=Subcommand, message=None, user=None),
    ("group", "subgroup", "subsubcommand"): CommandCollection(slash=Subsubcommand, message=None, user=None),
}}

Note

This may contain commands that have not yet been synced with discord.

property registered_commands: Sequence[lb_types.CommandOrGroup]

Sequence of the command classes and group instances registered to this client. This will not contain any subcommands or subgroups.

Note

This may contain commands that have not yet been synced with discord.

class GatewayEnabledClient(app: GatewayClientAppT, *args: Any, **kwargs: Any)[source]

Client implementation for applications that support gateway events.

Warning

This client should not be instantiated manually. Use client_from_app() instead.

Warning

This client will not be started automatically (see: start()). It is recommended that you start the client in a listener for StartedEvent. You should ensure that any commands are registered and extensions have been loaded before starting the client - otherwise command syncing may not work properly.

For example:

bot = hikari.GatewayBot(...)
client = lightbulb.client_from_app(bot, ...)

bot.subscribe(hikari.StartedEvent, client.start)
property app: GatewayClientAppT

The app that this client was created from.

class RestEnabledClient(app: RestClientAppT, *args: Any, **kwargs: Any)[source]

Client implementation for applications that support an interaction server.

Warning

This client should not be instantiated manually. Use client_from_app() instead.

Warning

This client will not be started automatically (see: start()). It is recommended that you start the client in a RESTBot startup callback. You should ensure that any commands are registered and extensions have been loaded before starting the client - otherwise command syncing may not work properly.

For example:

bot = hikari.RESTBot(...)
client = lightbulb.client_from_app(bot, ...)

bot.add_startup_callback(client.start)
property app: RestClientAppT

The app that this client was created from.

client_from_app(app: GatewayClientAppT, default_enabled_guilds: Sequence[hikari.Snowflakeish] = (), execution_step_order: Sequence[ExecutionStep] = DEFAULT_EXECUTION_STEP_ORDER, default_locale: Locale = hikari.Locale.EN_US, localization_provider: Callable[[str], Mapping[Locale, str] | Coroutine[Any, Any, Mapping[Locale, str]]] = localization.localization_unsupported, delete_unknown_commands: bool = True, deferred_registration_callback: Callable[[Group | type[CommandBase]], tuple[Iterable[Snowflake | int], bool] | None | Coroutine[Any, Any, tuple[Iterable[Snowflake | int], bool] | None]] | None = None, hooks: Sequence[ExecutionHook] = ()) GatewayEnabledClient[source]
client_from_app(app: RestClientAppT, default_enabled_guilds: Sequence[hikari.Snowflakeish] = (), execution_step_order: Sequence[ExecutionStep] = DEFAULT_EXECUTION_STEP_ORDER, default_locale: Locale = hikari.Locale.EN_US, localization_provider: Callable[[str], Mapping[Locale, str] | Coroutine[Any, Any, Mapping[Locale, str]]] = localization.localization_unsupported, delete_unknown_commands: bool = True, deferred_registration_callback: Callable[[Group | type[CommandBase]], tuple[Iterable[Snowflake | int], bool] | None | Coroutine[Any, Any, tuple[Iterable[Snowflake | int], bool] | None]] | None = None, hooks: Sequence[ExecutionHook] = ()) RestEnabledClient

Create and return the appropriate client implementation from the given application.

Parameters:
  • app – Application that either supports gateway events, or an interaction server.

  • default_enabled_guilds – The guilds that application commands should be created in by default.

  • execution_step_order – The order that execution steps will be run in upon command processing.

  • default_locale – The default locale to use for command names and descriptions, as well as option names and descriptions. Has no effect if localizations are not being used. Defaults to hikari.locales.Locale.EN_US.

  • localization_provider – The localization provider function to use. This will be called whenever the client needs to get the localizations for a key. Defaults to localization_unsupported - the client does not support localizing commands. Must be passed if you intend to support localizations.

  • delete_unknown_commands – Whether to delete existing commands that the client does not have an implementation for during command syncing. Defaults to True.

  • deferred_registration_callback – The callback to use to resolve which guilds a command should be created in if a command is registered using register_deferred(). Allows for commands to be dynamically created in guilds, for example enabled on a per-guild basis using feature flags. Defaults to None.

  • hooks – Execution hooks that should be applied to all commands. These hooks will always run before all other hooks registered for the same step are executed.

Returns:

The created client instance.

Return type:

Client

DEFAULT_EXECUTION_STEP_ORDER = (ExecutionStep(name='MAX_CONCURRENCY'), ExecutionStep(name='CHECKS'), ExecutionStep(name='COOLDOWNS'), ExecutionStep(name='PRE_INVOKE'), ExecutionStep(name='INVOKE'), ExecutionStep(name='POST_INVOKE'))

The order that execution steps will be run in if you don’t specify your own order.