Recently, discord.py went through a major update, with quite a lot of changes to how certain things are done. Pretty much any discord bot that hasn't been updated will stop working, so I made this tutorial so you can easily update your code.
This is only a brief description of the changes. For a full guide to migrating, visit this page.
IDs are now integers rather than strings. If before you did
myChannel=client.get_channel("437048931827056644"), now you have to do
This also applies if you are storing IDs for channels, servers or users in
.env - you will have to do
In rewrite, many methods have been moved out of client. The most important example is now instead of
await client.send_message(myChannel,"Hello World!"), you now need
await myChannel.send("Hello World!"). To send private messages, you do the same but replace the channel with the user -
myUser.send("Hello World!"). The other arguments you can pass (
embed= etc) remain the same.
Some other examples of this are:
Servers are now
Pretty much every single instance of the word
server in the library is now a
guild instead. The class is now
discord.Guild, the server a message came from is
message.guild, and the list of the bot's servers is now
client.guilds. If in doubt about whether something should be
Checking if a channel is a DM
discord.Channel has been split up into a few different classes. The important ones we need to know about are
discord.abc.PrivateChannel. To check if a channel is a DM, you now have to use
- To edit a message, you now do
await myMessage.edit(content="New content!")instead of
await client.edit_message(myMessage,new_content="New content!"). Note the change from
send_filehas been removed. To send a file, you use the same method,
send, as for text and embeds:
with open("myPicture.png","rb") as myPicture: await myChannel.send(file=discord.File(myPicture))
- If your command takes a long time to process and output a result, it is now easier to send "typing" whilst your code runs:
async with myChannel.typing(): do_stuff_which_takes_a_while()
- To get all the users the bot can see, you can now use
- To get a channel's history, you can use
async for message in myChannel.history():which will iterate through each
discord.Message, or you can use
channelHistory=await channel.history().flatten(), which returns a list of
This is one of the biggest changes, and the main reason why I personally migrated to rewrite before the library updated.
In async, you had to do
client=discord.Client(shard_count=3,shard_id=1) (if this was the second shard of a 3-shard bot) and run the same code separately for each shard - I achieved this using threading and running the entire bot as a function, where the
shard_id was passed as an argument and each instance of the function was run in a separate thread. I then had to use a database that every shard could access and post their own individual server and user counts, in order to get the totals. This often made me want to cry myself to sleep.
In rewrite, you can simply do
client=discord.AutoShardedClient(). That's it.
client.users will now give the entire lists, including the parts that belong to other shards, and you only need to run one instance of the bot. Your bot is sharded with approximately 1000 servers to a shard, although you can control this by doing
client=discord.AutoShardedClient(shard_count=3) if you want a specific number of shards (bear in mind that the maximum number of servers a single shard can connect to is 2500).
That's all I'm going to cover. This tutorial is not by any means a definitive guide to migrating, you can find one of those here, and also make sure to check out the docs here.
Post your newly-migrated bots in the comments section!
I hope you found this post helpful. If you did (or even if you didn't) please leave an upvote!
@timmy_i_chen consider featuring this in newsletter? 😉