Package: discord-amethyst
Discord AmethystAn opinionated extension fordiscord.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.WidgetsCommandThe amethyst command decorator is just a wrapper around discord.py'sapp_commands.commanddecorator. Please refer to thediscord.py documentationfor usage.EventAmethyst's event decorator is a type hinted wrapper arounddiscord.py's normal event decorator. The primary difference is that you must specify which event you wish to subscribe to. The propertyamethyst.eventsis a module containing all of thedefault discord.py events.importamethyst@amethyst.event(amethyst.events.on_ready)asyncdefon_ready():print("Bot is ready!")ScheduleAmethyst implements acron-likeasynchronous scheduler for calling functions on a set schedule, powered bycroniter.The following is an example of a schedule that will run every day at 8 am.importamethyst@amethyst.schedule("0 8 * * *")asyncdefevery_morning():print("Good morning!")Dynamic Module ImportAmethyst can dynamically load python modules, powered bydynamicpy. When run, the client will automatically import and register any widgets found in the.command,.commands,.pluginand.pluginssubmodules. The submodules which are searched can be configured in theAmethystClient's constructor.Lets say you have the following project structure:my-bot/
├── __init__.py
├── main.py
└── commands/
    ├── __init__.py
    ├── foo.py
    └── bar.pyIf your instance ofAmethystClientis instantiated inmain.pythen thecommands/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.pyIn this example, thecommands.pymodule and thecommands/package will be searched.Plugin SystemAmethyst has a plugin system, powered bydynamicpyand inspired bydiscord.py Cogs. You can create a plugin by simply defining a class that extendsAmethystPlugin. If this is found by theDynamic Module Importerthen it will be automatically registered to the client, otherwise you will have to use theAmethystClient.register_pluginmethod.An example plugin may look like the following:importamethystclassExamplePlugin(amethyst.AmethystPlugin):@amethyst.event(amethyst.events.on_ready)asyncdefon_ready(self):channel=self.client.get_channel(000000000000000000)awaitchannel.send("Bot is ready!")Plugin Dependency InjectionAmethyst plugins supportdynamicpy dependency injectionfor their constructors. You can add dependencies to the client using theAmethystClient.add_dependencymethod, which will then be injected into constructor parameters when the plugin is registered.importmysql.connectorimportamethystclient=amethyst.AmethystClient(...)database:mysql.connector.MySQLConnection=mysql.connector.connect(...)client.add_dependency(database)classExamplePlugin(amethyst.AmethystPlugin):def__init__(self,database:mysql.connector.MySQLConnection)->None:self.database=databaseEvironment VariablesAmethyst usespython-dotenvto load.envfiles found at the project root. This can be used to configure certain aspects of the library.NameDefaultDescriptionAMETHYST_BOT_TOKENNoneIf present,tokencan be omitted from theAmethystClient.runand this will be used instead.AMETHYST_AUTO_SYNCtrueIftrue, the client will synchronise app_commands if they are out of date with Discord.AMETHYST_SYNC_GUILDNoneIf present, app_commands will only be synchronised to specified guild id.RoadmapContext MenusHybrid CommandsPlugins enable/disable after initialisationDebug mode featuring automatic reload