Migrating to Novus¶
Changing to Novus represents different breaking changes we needed to make. We did not only needed to fork the original discord.py repository but adapt changes in the Discord API in order of supporting its latest features, to work with threads, buttons and commands.
Overview¶
Methods and attributes that returned
TextChannel(such asClient.get_channel()) can now returnThread.Python 3.8 or newer is required.
Attributes that returned
Assetare renamed, eg attributes ending with_url(egavatar_url) are changed toavatar.url.User.avatarreturnsNonein case the default avatar is used.on_presence_update()replaceson_member_update()for updates toMember.statusandMember.activities.All datetimes are now timezone-aware.
Sticker changes:
StickerTypehas been renamed toStickerFormatType, and the type ofMessage.stickersis changed.Sticker.preview_image,Sticker.imageandSticker.tagsare removed.Webhooks are changed significantly:
WebhookAdapteris removed, and synchronous requests using requests is now insideSyncWebhook.Edit methods no longer update the cache and instead return modified instances.
Selfbots are no longer supported.
Client.logoutis removed; useClient.close()instead.on_private_channel_createandon_private_channel_deleteevents are removed.User.permissions_inis removed; useabc.GuildChannel.permissions_in()instead.Message.typefor replies are nowMessageType.reply.Reaction.custom_emojiproperty is changed toReaction.is_custom_emojimethod.missing_permsattributes and arguments are renamed tomissing_permissions.Many method arguments now reject
None.Many arguments are now specified as positional-only or keyword-only; eg
oauth_url()now takes keyword-only arguments, and methods starting withget_orfetch_take positional-only arguments.
Changes¶
Webhook changes¶
Webhook was overhauled.
Webhook and WebhookMessage are now always asynchronous. For synchronous use (requests), use SyncWebhook and SyncWebhookMessage.
WebhookAdapter, AsyncWebhookAdapter, and RequestsWebhookAdapter are removed, since they are unnecessary.
adapter arguments of Webhook.partial() and Webhook.from_url() are removed. Sessions are now passed directly to partial/from_url.
# Non-async webhooks
webhook = discord.SyncWebhook.from_url(
f"https://discord.com/api/webhooks/{id}/{token}"
)
webhook.send("Hello from discord.py 2.0")
# Async webhooks
async with aiohttp.ClientSession() as session:
webhook = discord.Webhook.partial(id, token, session=session)
await webhook.send("Hello from discord.py 2.0")
Asset changes¶
:class:`Asset`s have been changed.
Asset-related attributes that previously returned hash strings (eg
User.avatar) now returnsAsset.Asset.keyreturns the hash from now on.Class.x_urlandClass.x_url_asare removed.Asset.replace(),Asset.with_size(),Asset.with_format(), andAsset.with_static_format()methods can be used to get specific asset sizes or types.Emoji.urlandPartialEmoji.urlare nowstr.Emoji.save()andEmoji.read()are added to save or read emojis.Emoji.url_asandPartialEmoji.url_asare removed.Some
AuditLogDiffattributes now returnAssetinstead ofstr:splash,icon,avatar`User.avatarreturnsNoneif the avatar is not set and is instead the default avatar; useUser.display_avatarfor pre-2.0 behavior.
avatar_url = user.display_avatar.url # previously str(avatar_url)
avatar_128x128_url = user.display_avatar.with_size(128).url # previously str(avatar_url_as(size=128))
avatar_128x128_png_url = user.display_avatar.replace(size=128, static_format="png").url
# previously str(avatar_url_as(size=128, static_format="png"))
# The code above can also be written as:
avatar_128x128_png_url = user.display_avatar.with_size(128).with_static_format("png").url
avatar_bytes = await user.display_avatar.read() # previously avatar_url.read
# Emoji and Sticker are special case:
emoji_url = emoji.url # previously str(emoji.url)
emoji_32x32_url = emoji.with_size(32).url # previously str(emoji.url_as(size=32))
emoji_32x32_png_url = emoji.replace(size=32, static_format="png").url
# previously str(url_as(size=128, static_format="png"))
emoji_bytes = await emoji.read() # previously emoji.url.read
# Same applies to Sticker and PartialEmoji.
Minimum Python version bumped¶
Python 3.8 is now required.
Use of timezone-aware time¶
TL;DR: utils.utcnow() becomes now(datetime.timezone.utc). If you are constructing datetime yourself, pass tzinfo=datetime.timezone.utc:
embed = discord.Embed(
title = "Pi Day 2021 in UTC",
timestamp = datetime(2021, 3, 14, 15, 9, 2, tzinfo=timezone.utc)
)
Note that newly-added discord.utils.utcnow() can be used as an alias of datetime.datetime.now(datetime.timezone.utc).
Embed.__bool__ change¶
Embed is now always considered truthy if any of the content is set.
Duplicate registration of cogs¶
commands.Bot.add_cog() now raises when a cog with the same name is already registered. The override argument can be used to bring back the 1.x behavior.
Message.type for replies¶
Message.type now returns MessageType.reply for replies, instead of default.
Command.clean_params¶
commands.Command.clean_params is now a dict, not collections.OrderedDict. The behaviour is the same however - dictionaries are ordered as of 3.7.
DMChannel.recipient¶
DMChannel.recipient is now optional, and will return None in many cases.
permissions_for positional only argument¶
abc.GuildChannel.permissions_for() method’s first argument is now positional only.
Colour.blurple¶
Colour.blurple() is renamed to Colour.og_blurple(), and Colour.blurple() now returns the different color.
oauth_url taking keyword only arguments¶
utils.oauth_url()’s permissions, guild, redirect_uri, and scopes arguments are now keyword only.
StageChannel changes¶
Due to the introduction of StageInstance representing the current session of a StageChannel,
StageChannel.edit() can no longer edit topic. Use StageInstance.edit() instead.
StageChannel.clone() no longer clones its topic.
Message.channel¶
Message.channel can now return Thread.
Guild methods taking positional only arguments¶
Guild.get_channel(), Guild.get_role(), Guild.get_member_named(), Guild.fetch_member(), and Guild.fetch_emoji() methods’ first arguments are now positional only.
Guild.create_text_channel topic argument¶
Guild.create_text_channel()’s topic argument no longer accepts None.
Reaction.custom_emoji¶
Reaction.custom_emoji is now a method called Reaction.is_custom_emoji for consistency.
Reaction.users arguments keyword only¶
Arguments of Reaction.users are now keyword only.
IntegrationAccount.id¶
IntegrationAccount.id is now str, instead of int, due to Discord changes.
BadInviteArgument new required argument¶
commands.BadInviteArgument now requires one argument, argument.
missing_perms¶
missing_perms arguments and attributes of commands.MissingPermissions and commands.BotMissingPermissions are renamed to missing_permissions.
Guild.vanity_invite¶
Guild.vanity_invite can now return None.
abc.Messageable.fetch_message positional only¶
Its first argument is now positional only.
get_partial_message positional only¶
Its first argument is now positional only.
Template.edit name argument¶
Template.edit()’s name argument no longer accepts None.
Member.edit roles argument¶
Member.edit()’s roles argument no longer accepts None.
CommandOnCooldown new required argument¶
commands.CommandOnCooldown now requires an additional argument, type.
fetch_channel¶
Client.fetch_channel() and Guild.fetch_channel() can now return Thread.
on_member_update and on_presence_update separation¶
on_member_update() event is no longer dispatched for status/activity changes. Use on_presence_update() instead.
Message.stickers¶
Message.stickers is now List[StickerItem] instead of List[Sticker]. While StickerItem supports some operations of previous Sticker, description and pack_id attributes do not exist. Sticker can be fetched via StickerItem.fetch() method.
AuditLogDiff.type¶
AuditLogDiff.type is now Union[ChannelType, StickerType], instead of ChannelType.
ChannelNotReadable.argument¶
commands.ChannelNotReadable.argument can now return Thread.
NSFWChannelRequired.channel¶
commands.NSFWChannelRequired.channel can now return Thread.
Bot.add_listener and Bot.remove_listener¶
commands.Bot.add_listener and commands.Bot.remove_listener’s name arguments no longer accept None.
Context attributes¶
The following Context attributes can now be None: prefix, command, invoked_with, invoked_subcommand. Note that while the documentation change suggests potentially breaking change, the code indicates that this was always the case.
Command.help¶
commands.Command.help can now be None.
Client.get_channel¶
Client.get_channel() can now return Thread.
Client methods taking positional only arguments¶
Client.get_guild(), Client.get_user(), and Client.get_emoji() methods’ first arguments are now positional only.
edit method behavior¶
edit methods of most classes no longer update the cache in-place, and instead returns the modified object.
on_socket_raw_receive behavior¶
on_socket_raw_receive() is no longer dispatched for incomplete data, and the value passed is always decompressed and decoded to str. Previously, when received a multi-part zlib-compressed binary message, on_socket_raw_receive() was dispatched on all messages with the compressed, encoded bytes.
Guild.get_member taking positional only argument¶
Guild.get_member() method’s first argument is now positional only.
Removals¶
Selfbot support¶
Selfbots is no longer supported. Thus, these features that were only applicable to them are removed:
botargument ofClient.start/runafkargument ofClient.change_presence()Classes:
Profile,Relationship,CallMessage,GroupCallRelationshipType,HypeSquadHouse,PremiumType,UserContentFilter,FriendFlags,ThemeGroupChannel.add_recipients,remove_recipients, edit (NOTE:GroupChannelitself still remains)Guild.ackClient.fetch_user_profileMessage.callandackClientUser.email,premium,premium_type,get_relationship,relationships,friends,blocked,create_group,edit_settingsClientUser.edit()’spassword,new_password,email,house argumentsUser.relationship,mutual_friends,is_friend,is_blocked,block,unblock,remove_friend,send_friend_request,profileEvents:
on_relationship_addandon_relationship_update
This means that detection of Nitro is no longer possible.
Client.logout¶
This method was an alias of Client.close(), which remains.
ExtensionNotFound.original¶
This always returned None for compatibility.
MemberCacheFlags.online¶
Due to Discord changes, this cache flag is no longer available. MemberCacheFlags’s online argument is removed for similar reasons.
Client.request_offline_members¶
Deprecated since 1.5.
on_private_channel_create and on_private_channel_delete¶
These events will no longer be dispatched due to Discord changes.
User.permissions_in and Member.permissions_in¶
Use abc.GuildChannel.permissions_for() instead.
guild_subscriptions argument¶
guild_subscriptions argument of Client is replaced with intents system.
fetch_offline_members argument¶
This argument of Client was an alias of chunk_guilds_at_startup since 1.5.
HelpCommand.clean_prefix¶
This was moved to commands.Context.clean_prefix.
Sticker.preview_image¶
This was removed as Discord no longer provides the data.
self_bot argument¶
Bot’s self_bot argument was removed, since userbots are no longer supported.
VerificationLevel attributes¶
VerificationLevel.table_flip (alias of high) was removed. extreme, very_high, and double_table_flip attributes were removed and replaced with highest.
StickerType¶
StickerType, an enum of sticker formats, is renamed to StickerFormatType. Old name is used for a new enum with different purpose (checking if the sticker is guild sticker or Nitro sticker).
Sticker.image¶
Sticker.image is removed. Its URL can be accessed via Sticker.url, just like new Emoji.
Python Version Change¶
In order to make development easier, the library had to remove support for Python versions lower than 3.8, which means that support for Python 3.7, 3.6 and 3.5 is dropped.
Meta Change¶
Performance of the library has improved significantly (all times with 1 process and 1 AutoShardedBot):
Test setup |
Boot up previusly |
Boot up now |
|---|---|---|
735 guilds (with chunking) |
57s/1.7 GiB RAM |
42s/1.4 GiB RAM |
27k guilds (with chunking) |
477s/8 GiB RAM |
303s/7.2 GiB |
48k guilds (without chunking) |
109s |
67s |
106k guilds (without chunking) |
3300s |
3090s |
The public API should be completely type-hinted
Almost all
editmethods now return their updated counterpart rather than doing an in-place edit