discord-amethyst

An opinionated extension for discord.py.


Keywords
discord-py, extension, plugin-system, python
License
MIT
Install
pip install discord-amethyst==2.0.0

Documentation

Discord Amethyst

An opinionated extension for discord.py. Amethyst adds a handful of features that I found myself re-implementing or wanting for many of my Discord bots such as automatic app command synchronisation and job scheduling.

Widgets

Command

The amethyst command decorator is just a wrapper around discord.py's app_commands.command decorator. Please refer to the discord.py documentation for usage.

Event

Amethyst's event decorator is a type hinted wrapper around discord.py's normal event decorator. The primary difference is that you must specify which event you wish to subscribe to. The property amethyst.events is a module containing all of the default discord.py events.

import amethyst

@amethyst.event(amethyst.events.on_ready)
async def on_ready():
    print("Bot is ready!")

Schedule

Amethyst implements a cron-like asynchronous scheduler for calling functions on a set schedule, powered by croniter.

The following is an example of a schedule that will run every day at 8 am.

import amethyst

@amethyst.schedule("0 8 * * *")
async def every_morning():
    print("Good morning!")

Dynamic Module Import

Amethyst can dynamically load python modules, powered by dynamicpy. When run, the client will automatically import and register any widgets found in the .command, .commands, .plugin and .plugins submodules. The submodules which are searched can be configured in the AmethystClient's constructor.

Lets say you have the following project structure:

my-bot/
├── __init__.py
├── main.py
└── commands/
    ├── __init__.py
    ├── foo.py
    └── bar.py

If your instance of AmethystClient is instantiated in main.py then the commands/ package will be recursively searched for widgets to register.

The searched modules can also be top-level, the only requirement is that they are at the same level as the module inside which the client was instantiated.

my-bot.py
plugins.py
commands/
├── __init__.py
├── foo.py
└── bar.py

In this example, the commands.py module and the commands/ package will be searched.

Plugin System

Amethyst has a plugin system, powered by dynamicpy and inspired by discord.py Cogs. You can create a plugin by simply defining a class that extends AmethystPlugin. If this is found by the Dynamic Module Importer then it will be automatically registered to the client, otherwise you will have to use the AmethystClient.register_plugin method.

An example plugin may look like the following:

import amethyst

class ExamplePlugin(amethyst.AmethystPlugin):

    @amethyst.event(amethyst.events.on_ready)
    async def on_ready(self):
        channel = self.client.get_channel(000000000000000000)
        await channel.send("Bot is ready!")

Plugin Dependency Injection

Amethyst plugins support dynamicpy dependency injection for their constructors. You can add dependencies to the client using the AmethystClient.add_dependency method, which will then be injected into constructor parameters when the plugin is registered.

import mysql.connector
import amethyst

client = amethyst.AmethystClient(...)
database: mysql.connector.MySQLConnection = mysql.connector.connect(...)
client.add_dependency(database)

class ExamplePlugin(amethyst.AmethystPlugin):

    def __init__(self, database: mysql.connector.MySQLConnection) -> None:
        self.database = database

Evironment Variables

Amethyst uses python-dotenv to load .env files found at the project root. This can be used to configure certain aspects of the library.

Name Default Description
AMETHYST-BOT-TOKEN None If present, token can be omitted from the AmethystClient.run and this will be used instead.
AMETHYST-AUTO-SYNC true If true, the client will synchronise app_commands if they are out of date with Discord.
AMETHYST-SYNC-GUILD None If present, app_commands will only be synchronised to specified guild id.

Roadmap

  • Context Menus
  • Hybrid Commands
  • Plugins enable/disable after initialisation
  • Debug mode featuring automatic reload