A modern, easy to use, feature-rich, and async ready API wrapper for Discord written in Python.
Development of discord.py has now been "revived", see further details here. As such, there really isn't much motivation for this fork anymore.
Practically everything that was implemented for this fork was also implemented for Danny's. Additionally, ext-commands compatibility (previously done using discord-ext-compat) is planned. Danny implemented application commands in a way that they are declared using functions. This fork implements it in a way that uses classes: they were much cleaner, readable, and reduced unnecessary repetition with names. Additionally, they just seemed more declarative than it's function-based counterpart. Although I'm not the biggest fan of a function-based implementation, see here as to why Danny went with it.
Note: The following was written before Danny announced the "resurrection" of discord.py
It was originally made to implement Danny's slash command DSL (The class based version), and it does it pretty well.
There have been many changes since this DSL was created however, for example slash commands turning into a category of "application commands". These "application commands" also contain "context menus", specifically referred to as "message commands" and "user commands". This fork does, in fact, support them.
As a result of this, naming schemes that go along "slash command" have been renamed to their counterparts that go along with "application_command". This unfortunately does make things a bit verbose, however shortening the names would leave name conflicts and confusion.
- Application commands
- Slash commands
- Context menus (Message commands & user commands)
-
channel_types
option field - Autocomplete options
- Attachment option type
- UI
- Modals @
discord.ui.Modal
-
ItemContainer
ABC
- Modals @
- Role icons
- Welcome screens
- Guild scheduled events
- Member chat timeout (
communication_disabled_until
)
- Modern Pythonic API using
async
andawait
. - Proper rate limit handling.
- Optimised in both speed and memory.
Python 3.8 or higher is required
To install the library without full voice support, you can just run the following command:
# Linux/macOS
python3 -m pip install -U discord.py
# Windows
py -3 -m pip install -U discord.py
Otherwise to get voice support you should run the following command:
# Linux/macOS
python3 -m pip install -U "discord.py[voice]"
# Windows
py -3 -m pip install -U discord.py[voice]
To install the development version, do the following:
$ git clone https://github.com/jay3332/discord.py
$ cd discord.py
$ python3 -m pip install -U .[voice]
- PyNaCl (for voice support)
Please note that on Linux installing voice you must install the following packages via your favourite package manager (e.g. apt
, dnf
, etc) before running the above commands:
- libffi-dev (or
libffi-devel
on some systems) - python-dev (e.g.
python3.6-dev
for Python 3.6)
import discord
class MyClient(discord.Client):
async def on_ready(self):
print('Logged on as', self.user)
async def on_message(self, message):
# don't respond to ourselves
if message.author == self.user:
return
if message.content == 'ping':
await message.channel.send('pong')
client = MyClient()
client.run('token')
import discord
from discord.application_commands import ApplicationCommand, ApplicationCommandTree, option
tree = ApplicationCommandTree(guild_id=123456)
class HelloWorld(ApplicationCommand, name='hello-world', tree=tree):
"""Hello"""
async def callback(self, interaction):
await interaction.response.send_message('Hello, world!')
client = discord.Client(update_application_commands_at_startup=True)
client.add_application_command_tree(tree)
client.run('token')
import discord
from discord.ext import commands
bot = commands.Bot(command_prefix='>')
@bot.command()
async def ping(ctx):
await ctx.send('pong')
bot.run('token')
You can find more examples in the examples directory.
This fork does implement a class-based application commands implementation. However, Danny chose to not implement it this way on discord.py itself:
"I think this is too hung up on syntactic features (i.e. this is mostly focused on "syntax looks" rather than functionality). There's actually a reason that classes aren't abused like this in most Python libraries and that's because their composability is too restricted. For example, classes can't compose very well if they override one functionality without an explicit call to super and making many mixins which infects the MRO chain. Every caller in the MRO chain then depends on calling super or else the chain ends, sometimes unexpectedly prematurely.
I've messed with class based commands, but it doesn't actually work very well. To give a concrete example, consider checks. Checks are nice and reusable, but if every command was a class where would you shove the check in? In traditional systems you'd have a check method you override with your logic but in this system you now have to maintain every function call. Alternatively you can stack decorators that do this.
I've also messed with returning a class sentinel value (e.g. TextResponse in your example) in many of my old bots before d.py existed. That system doesn't work either because of the concept of follow ups. Sometimes you want to send more than one message at a specific point and sometimes that message depends on user input from an asynchronous system. Things get complicated if you had to return a value to signal whether to return a response or not. It's just not good dev UX."