Plugins & Extensions#
Plugins#
Plugins are a way to group commands and related functionality together. This can then be combined with extensions to allow for easy code modularization.
plugin = arc.GatewayPlugin("plugin name")
@plugin.include
@arc.slash_command("name", "description")
async def plugin_cmd(ctx: arc.GatewayContext) -> None:
...
@plugin.include
@arc.slash_command("other-name", "description")
async def other_plugin_cmd(ctx: arc.GatewayContext) -> None:
...
client.add_plugin(plugin)
plugin = arc.RESTPlugin("plugin name")
@plugin.include
@arc.slash_command("name", "description")
async def plugin_cmd(ctx: arc.RESTContext) -> None:
...
@plugin.include
@arc.slash_command("other-name", "description")
async def other_plugin_cmd(ctx: arc.RESTContext) -> None:
...
client.add_plugin(plugin)
In the snippet above, we define a new plugin, add two commands to it, then add the plugin to the client. This in turn adds all commands added to the plugin to the client as well.
Tip
Anything that can be used with @client.include
can also be used with @plugin.include
as well. Plugins also define methods commonly found on the client such as .include_slash_group() or .walk_commands().
The benefit of grouping commands together into a plugin is that you can define custom behaviour at the plugin level which applies to all commands added to the plugin. Hooks, error handling, concurrency limiting and more can all be added to the plugin itself, additionally, you can also set attributes such as autodefer=
or default_permissions=
, and they will be applied to all commands that belong to the plugin.
For example, to make all commands in a plugin require MANAGE_GUILD
permissions by default, you may use the following snippet:
Extensions#
Extensions allow arc
to load additional modules and pass your client instance to them. They can be loaded & unloaded dynamically during runtime. An extension is valid from arc
's perspective if it has a function decorated with @arc.loader
. A loader function should take a client as it's sole parameter. You may optionally also define an @arc.unloader
function, however keep in mind if that no unloader is defined, the extension cannot be unloaded.
Note
It is not required to use plugins in conjunction with extensions, the two features can be used seperately, however it is recommended for simplicity's sake to make one extension contain one plugin.
Let's suppose you have the following folder structure:
import arc
plugin = arc.GatewayPlugin("foo")
@plugin.include
@arc.slash_command("foo", "Foo command")
async def foo_cmd(
ctx: arc.GatewayContext,
) -> None:
await ctx.respond(f"Foo!")
# This will run when the extension is loaded
# If there is no loader, the extension cannot be loaded!
@arc.loader
def loader(client: arc.GatewayClient) -> None:
client.add_plugin(plugin)
# If you add an unloader, the extension can also be unloaded at runtime!
# Adding an unloader is optional.
@arc.unloader
def unloader(client: arc.GatewayClient) -> None:
client.remove_plugin(plugin)
import arc
plugin = arc.GatewayPlugin("bar")
@plugin.include
@arc.slash_command("bar", "Bar command")
async def bar_cmd(
ctx: arc.GatewayContext,
) -> None:
await ctx.respond(f"Bar!")
@arc.loader
def loader(client: arc.GatewayClient) -> None:
client.add_plugin(plugin)
@arc.unloader
def unloader(client: arc.GatewayClient) -> None:
client.remove_plugin(plugin)
import arc
plugin = arc.RESTPlugin("foo")
@plugin.include
@arc.slash_command("foo", "Foo command")
async def foo_cmd(
ctx: arc.RESTContext,
) -> None:
await ctx.respond(f"Foo!")
# This will run when the extension is loaded
# If there is no loader, the extension cannot be loaded!
@arc.loader
def loader(client: arc.RESTClient) -> None:
client.add_plugin(plugin)
# If you add an unloader, the extension can also be unloaded at runtime!
# Adding an unloader is optional.
@arc.unloader
def unloader(client: arc.RESTClient) -> None:
client.remove_plugin(plugin)
import arc
plugin = arc.RESTPlugin("bar")
@plugin.include
@arc.slash_command("bar", "Bar command")
async def bar_cmd(
ctx: arc.RESTContext,
) -> None:
await ctx.respond(f"Bar!")
@arc.loader
def loader(client: arc.RESTClient) -> None:
client.add_plugin(plugin)
@arc.unloader
def unloader(client: arc.RESTClient) -> None:
client.remove_plugin(plugin)
To load foo.py
into the client before execution, you can use Client.load_extension
Or to load all extensions from the extensions
folder, you can use Client.load_extensions_from
: