Package: discord-hero
discord-hero is an asynchronous, fully modular Discord bot framework that comes with
batteries included, allowing you to write powerfulDiscordapplications easily and quickly. It is intended for:developers interested in aneasy way to develop a powerful public
or private Discord botwith a clean, readable, pythonic,
persistent storage solution and easy-to-use cachingmanagers of Discord communities who want toautomate tasks on
Discordin a highly customizable way and/or without relying on
external botsbeginner and intermediate level developers who are interested in
asynchronous concurrency with Python using asyncioany developer who’s interested in trying something new and
wants to give this project a chance!Although discord-hero iseasy to get started with, it comes with all
the tools experienced developers enjoy using to build production-ready
applications for communities, games or companies on Discord:aDiscord botbuilt on top ofdiscord.py[TODO] aWeb APIpowered byFastAPIafamiliar asynchronous ORMbased onDjangoaneasy-to-use cache system, optionally powered by Redis, viaaiocacheandaioredisfull modularity thanks to a clever Extension systemYou might think that with all these dependencies Discord Hero will perform badly,
but so far that has actually not been the case at all! Continue reading
if you want to give it a test run.Getting startedNote:In this section, the content of every code block is intended
to be entered in a terminal / command prompt.RequirementsYou needPython 3.7 or above,Git,cookiecutterandpipenv.
On Windows you may also need theVisual C++ Build Toolsif you run into errors when trying to install discord-hero.
Installcookiecutterandpipenvif you haven’t yet:Linux / Mac:python3 install --user -U cookiecutter
python3 install --user -U --pre pipenvWindows:py -3 -m pip install -U cookiecutter
py -3 -m pip install -U --pre pipenvIf you’re just testing things out, it’s probably fine to just use the
default database and cache solutions (SQLite3 and simple memory cache).
However, if you want to use discord-hero for a production application,
it is recommended to run it on a Linux VPS, dedicated
server or something equally powerful, and use PostgreSQL for storing
data and Redis for caching. To do the latter two changes, check your.envfile and make the following changes:export DB_TYPE=postgres
export CACHE_TYPE=redisYou will be promped for further configuration details the next time
you run your bot in production mode (--prod).Note:mysqlis also an option forDB_TYPE, however it is not
officially supported.InstallationReplace<your_directory_name>with the project name you will have
entered by then.cookiecutter https://github.com/monospacedmagic/discord-hero-cookiecutter.git
cd <your_directory_name>
pipenv install --threeFor production applications:pipenv install discord-hero[postgresql,redis]Run discord-hero in test mode:cd <your_project_path>
pipenv run hero --testRun discord-hero in production mode:cd <your_project_path>
pipenv run hero --prodNote:You have the option to enter completely different configuration
details for test mode and production mode, including your bot token,
meaning you can test with a different bot account, out of the box.FeaturesCoreThe central control unit that exposes all extensions and connects all
the moving parts of the application. Inherits from`discord.ext.commands.Bot<https://discordpy.readthedocs.io/en/latest/ext/commands/api.html#discord.ext.commands.Bot>`_.ExtensionsExtensions are discord-hero’s plug-ins. They can be disabled, enabled,
installed and uninstalled at runtime (TODO).CogsCogs are the main building blocks of an extension. They are essentially
simple classes that inherit fromhero.Cog. By inheriting fromhero.Cog, the class is automatically added to theCore’s cogs
unless the extension it belongs to is disabled.
discord-hero Cogs are based on discord.py Cogs, thus they inherit
all of their functionalities. For a documentation on discord.py Cogs,check here.CommandsDecorate aCog’s coroutine method withhero.command(**options)to create aCommand.@hero.command()
@hero.guild_only()  # A check ensuring that the command can only be invoked on a Discord server (Guild)
async def set_channel_name(self, ctx: hero.Context, name: str, channel: hero.Channel=None):
    # !set channel name <new name> [channel]
    # TODO actually set the channel name
    passEvent listenersDecorate a Cog’s async method withhero.listener()to turn it into an event
listener. Valid listener names and parameters can be looked uphere.@hero.listener()
async def on_message(self, message: discord.Message):
    # essentially be a stereotypical parrot
    if message.author != self.bot.user:
        await message.channel.send(message.content)Controllersdiscord-hero encourages the Model-View-Controller pattern by
automatically adding an Extension’s Controller to its Cogs.
To make that happen, you just need to subclasshero.Controllerin your Extension’scontrollermodule.ModelsStructure your data by writing subclasses ofhero.models.Model. This will
automatically set up your database schema when discord-hero launches or
when the extension the cog belongs to is installed. If you’re coming
from Django, you might already be familiar with the basic API.# Every Guild can have their own currency
class Currency(models.Model):
    guild = fields.GuildField(pk=True, on_delete=fields.CASCADE)
    name = fields.CharField(max_length=64)

# Every Member can have bank account with an amount of the Guild's currency
class BankAccount(models.Model):
    member = fields.MemberField(pk=True, on_delete=fields.CASCADE)
    balance = fields.IntegerField(db_index=True)discord-hero comes with a few built-in models: User, Guild, TextChannel,
VoiceChannel, Role, Emoji, Member and Message. Each of them have a
corresponding field, e.g. UserField, GuildField, etc., that works like
a ForeignKey and allows you to easily reference the model in your own models.SettingsSettings are a special type of Models, you can define one of these Model
classes by subclassinghero.models.Settings.GraphQL schemas# TODOThe GraphQL schemas generated automatically, you just need to configure
your models accordingly. If you want to overwrite the default
permissions, you can use the web interface. You can still add custom permissions.UsageWriting a discord-hero ExtensionStructure:__init__Required for the Extension to be recognized.cogsThis is where your Cogs live. Cogs are a part of a discord-hero Extension that
enhance the bot by adding commands, event listeners, and optional state and
methods that you want to make available inside the Cog. For more information
see below.cogs.__init__Your Cogs can be anywhere inside thecogspackage as long as you
import them here so discord-hero’s Extension loader can find them.modelsThis is where your Models live.Additional featuresNew in discord-hero are the following features available from inside a Cog:awaitself.db.load(discord_obj)Used to connect a given Discord object to the database and load data
related to it that is stored in the database.Returns: an instance of the hero Model that is associated to the class
thediscord_objis an instance of. This object wraps the Discord
object and exposes all of its attributes and methods, which means
it can be used like one as well.Example:@hero.command()
@hero.guild_only()
async def get_balance(self, ctx):
    member = await self.db.load(ctx.author)
    await ctx.send(f"You have {member.balance} currency.")Hero Models as parametersYou can define a discord-hero Model as a parameter type for a command.
This will automatically parse the user input and pass a (loaded) instance
of the Model to your command. Example:@hero.command()
@hero.guild_only()
async def get_balance(self, ctx, member: hero.Member):
    await ctx.send(f"{member.name} has {member.balance} currency.")Automatic grouping of commandsdiscord-hero automatically interprets a_in a command name as a
space. This means there is no need to manually group commands anymore,
and you can use groups introduced by other Extensions or discord-hero
itself to create commands that are closer to natural language and
thus more intuitive to use for the general audience.self.cacheThis is ahero.Cacheinstance that allows you to set or get
a given key into the database. There are more methods available
to you than just get or set; for now, check out the source code
for those.self.ctlYour Extension’s Controller.Noneif your Extension doesn’t have
ahero.Controllersubclass (you can only have one per Extension).self.settingsYour Extension’s Settings.Noneif your Extension doesn’t have
ahero.Settingssubclass (you can only have one per Extension).Note:You need at least one Cog for your extension to work.
Alternatively, you can define a (non-async) function calledsetupthat takes one argument, ahero.Coreinstance.
This function will be called when discord-hero loads the Extension.
It needs to be imported tocogs.__init__if it isn’t defined there,
it needs to instantiate all the Cog classes you have created, and
it needs to pass each Cog instance to the Core’sadd_cogmethod.New in discord-hero are the following features regarding (Django) Models:asyncDjango’s ORM has been made to work well with asyncio with the help of asgiref.
discord-hero introduces a decoratorhero.async_using_dbthat turns a
synchronous function or method into an async one (that needs to be awaited)
and also makes any database operations in it work, magically. What happens
behind the scenes is that these database operations are executed in order
in a single, separate thread.Furthermore, discord-hero adds async versions of QuerySet and Model instance
methods that are prefixed withasync_(only for those methods that
actually operate on the database to load, create, update or delete data).
This is a temporary solution until Django’s ORM officially supports async,
but for the time being it works extremely well!Legal stuffDiscord is a registered trademark of Discord Inc.Except as otherwise noted, discord-hero is licensed under the Apache
License, Version 2.0 (LICENSE.Apache-2.0orhttp://www.apache.org/licenses/LICENSE-2.0) or
the MIT license (LICENSE.MITorhttp://opensource.org/licenses/MIT), at your option.Unless you explicitly state otherwise, any contribution intentionally
submitted for inclusion in the work by you, as defined in the
Apache-2.0 license, shall be dual licensed under the Apache
License, Version 2.0, and the MIT license, without any
additional terms or conditions.SPDX-License-Identifier: Apache-2.0 OR MIT