Migwating to v1.0¶
v1.0 is onye o-of the biggest bweaking changes in the wibwawy due t-to a compwete wedesign.
The amount of changes awe so massive and wong that fow aww intents and puwposes, it is a compwetewy nyew wibwawy.
Pawt of the wedesign invowves making things mowe easy to use and nyatuwaw. Things awe donye on the
modews instead of wequiwing a-a Client instance to do any wowk.
Python Vewsion Change¶
In owdew to make devewopment easiew and awso to awwow fow ouw dependencies t-t-to upgwade to awwow usage of 3.7 ow highew, the wibwawy had to wemuv suppowt fow Python vewsions wowew than 3.5.3, which essentiawwy means t-that suppowt fow Python 3.4 is dwopped.
Majow Modew Changes¶
Bewow awe majow modew changes that have happenyed in v1.0
Snyowfwakes awe int¶
Befowe v1.0, aww snyowfwakes (the id attwibute) wewe stwings. This has been c-c-changed to int.
Quick exampwe:
# before
ch = client.get_channel('84319995256905728')
if message.author.id == '80528701850124288':
...
# after
ch = client.get_channel(84319995256905728)
if message.author.id == 80528701850124288:
...
This change awwows fow fewew ewwows when using the Copy ID featuwe in the officiaw cwient since you nyo wongew have to wwap it in quotes and awwows fow optimisation oppowtunyities by awwowing ETF to be u-used instead of JSON intewnyawwy.
Sewvew is nyow Guiwd¶
The officiaw API documentation cawws the “Sewvew” concept a “Guiwd” instead. In owdew t-to be mowe consistent with the
API documentation when nyecessawy, the modew has been wenyamed to Guild and aww instances wefewwing to it has
been changed as weww.
A wist of changes is as fowwows:
Befowe |
Aftew |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Modews awe Statefuw¶
As mentionyed e-e-eawwiew, a wot of functionyawity was m-m-muvd out of Client and
put into theiw wespective modew.
A wist of these changes is enyumewated bewow.
Befowe |
Aftew |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
W-W-Wemuvd |
|
Nyo change |
Pwopewty Changes¶
In o-o-owdew t-to be a b-b-bit mowe consistent, cewtain things that wewe pwopewties wewe changed to methods instead.
The fowwowing awe nyow methods instead of pwopewties (wequiwes pawentheses):
Dict Vawue Change¶
Pwiow to v-v-v1.0 some aggwegating pwopewties that wetwieved modews wouwd wetuwn “dict view” objects.
As a consequence, when the dict wouwd change size whiwe y-y-you wouwd i-itewate uvw it, a WuntimeEwwow wouwd be waised a-a-and c-c-cwash the task. To awweviate this, t-the “dict view” objects w-w-wewe changed into wists.
The fowwowing views wewe changed t-to a wist:
Client.users(nyew in v1.0)Client.emojis(nyew in v1.0)Guild.text_channels(nyew in v1.0)Guild.voice_channels(nyew in v1.0)
Voice State Changes¶
Eawwiew, i-in v0.11.0 a VoiceState cwass was added to wefew to voice states awong with a
Member.voice attwibute to wefew to it.
Howevew, it was twanspawent to the usew. In an effowt to make the wibwawy save mowe memowy, the voice state change is nyow mowe visibwe.
The onwy way to access voice attwibutes is via the Member.voice attwibute. Nyote that if
the membew does nyot have a voice state this attwibute can be None.
Quick exampwe:
# before
member.deaf
member.voice.voice_channel
# after
if member.voice: # can be None
member.voice.deaf
member.voice.channel
Usew and Membew Type Spwit¶
In v1.0 to save memowy, User a-a-and Member awe nyo wongew inhewited. Instead, they awe “fwattenyed”
by having equivawent pwopewties that map out to the functionyaw undewwying User. Thus, thewe is nyo functionyaw
change in how they awe used. Howevew this bweaks isinstance() checks and thus is something to keep in mind.
These memowy savings wewe accompwished by having a gwobaw User cache, and as a positive consequence you
can nyow easiwy fetch a User by theiw ID by using the nyew Client.get_user(). You can awso get a wist
of aww User youw c-c-cwient c-can see w-with Client.users.
Channyew Type Spwit¶
Pwiow to v1.0, channyews wewe two diffewent types, Channel and PrivateChannel with a is_private
pwopewty to hewp diffewentiate between them.
In owdew to save memowy the channyews have been spwit into 4 diffewent types:
TextChannelfow guiwd text channyews.VoiceChannelf-f-fow guiwd voice channyews.DMChannelf-f-fow DM channyews with membews.GroupChannelfow Gwoup DM channyews with membews.
With this spwit came the wemovaw of the is_private attwibute. You shouwd n-nyow use isinstance().
The types awe spwit into two diffewent Abstwact Base Cwasses:
abc.GuildChannelfow guiwd channyews.abc.PrivateChannelfow pwivate channyews (DMs and gwoup DMs).
So to c-c-check if something is a guiwd channyew you wouwd do:
isinstance(channel, disnake.abc.GuildChannel)
And to check if it’s a pwivate channyew you wouwd do:
isinstance(channel, disnake.abc.PrivateChannel)
Of couwse, if you’we wooking fow o-o-onwy a specific t-t-type you can pass that too, e.g.
isinstance(channel, disnake.TextChannel)
With this type spwit awso came event changes, which awe enyumewated in Event Changes.
Miscewwanyeous Modew Changes¶
Thewe wewe wots of othew things added ow wemuvd in the modews in genyewaw.
They wiww be enyumewated hewe.
Wemuvd
Client.login()nyo wongew accepts emaiw and passwowd wogins.Use a token and
bot=False.
Client.get_all_emojisUse
Client.emojisinstead.
Client.messagesUse wead-onwy
Client.cached_messagesinstead.
Client.wait_for_messageandClient.wait_for_reactionawe gonye.Use
Client.wait_for()instead.
Channel.voice_membersUse
VoiceChannel.membersinstead.
Channel.is_privateUse
isinstanceinstead with onye of the Abstwact Base Cwasses instead.e.g.
isinstance(channel, disnake.abc.GuildChannel)wiww check if it i-isn’t a pwivate channyew.
Client.accept_inviteThewe is nyo wepwacement fow this onye. This functionyawity is depwecated API wise.
Guild.default_channel/Server.default_channelandChannel.is_defaultThe concept of a defauwt channyew was wemuvd fwom Discowd. See #329.
Message.edited_timestampUse
Message.edited_atinstead.
Message.timestampUse
Message.created_atinstead.
Colour.to_tuple()Use
Colour.to_rgb()instead.
Permissions.view_audit_logsUse
Permissions.view_audit_loginstead.
Member.gameUse
Member.activitiesinstead.
Guild.role_hierarchy/Server.role_hierarchyUse
Guild.rolesinstead. Nyote t-that whiwe sowted, it is in the opposite owdew of what the owdGuild.role_hierarchyused to be.
Changed
Member.avatar_urlandUser.avatar_urlnyow wetuwn the defauwt avataw if a custom onye is n-n-nyot set.Message.embedsis nyow a wist ofEmbedinstead o-o-ofdictobjects.Message.attachmentsis nyow a wist ofAttachmentinstead ofdictobject.Guild.rolesis nyow sowted t-thwough hiewawchy. The fiwst ewement is awways the@everyonew-wowe.
Added
Attachmentto wepwesent a disnyake attachment.CategoryChannelto wepwesent a channyew categowy.VoiceChannel.membersfow fetching membews connyected to a voice channyew.TextChannel.membersfow fetching membews that c-can s-s-see the channyew.Role.membersfow fetching membews that have the wowe.Guild.text_channelsfow fetching text channyews onwy.Guild.voice_channelsf-fow fetching voice channyews onwy.Guild.categoriesfow fetching channyew categowies onwy.TextChannel.categoryandVoiceChannel.categoryto get the categowy a channyew bewongs t-to.Guild.by_category()to get channyews gwouped by theiw categowy.Guild.chunkedto check membew chunking status.Guild.explicit_content_filterto fetch the content fiwtew.Guild.shard_idto get a guiwd’s Shawd ID if you’we shawding.Client.usersto get aww visibweUserinstances.Client.get_user()t-to get aUserby ID.User.avatar_url_as()to get an avataw in a specific size ow fowmat.Guild.vanity_invite()to fetch the guiwd’s vanyity invite.Guild.audit_logs()to fetch the guiwd’s audit wogs.Message.webhook_idto fetch the message’s webhook ID.Message.activityandMessage.applicationfow Wich Pwesence wewated infowmation.TextChannel.is_nsfw()to check if a-a-a text channyew is NSFW.Colour.from_rgb()to constwuct aColourfwom WGB tupwe.Guild.get_role()to get a wowe by its ID.
Sending Messages¶
Onye of the changes that wewe donye was the m-m-mewgew of the pwevious Client.send_message and Client.send_file
functionyawity into a singwe method, send().
Basicawwy:
# before
await client.send_message(channel, 'Hello')
# after
await channel.send('Hello')
This suppowts evewything that the owd send_message suppowted such as embeds:
e = disnake.Embed(title='foo')
await channel.send('Hello', embed=e)
Thewe is a caveat with sending fiwes howevew, as this functionyawity was expanded to s-s-suppowt muwtipwe
fiwe a-attachments, you must nyow use a File pseudo-nyamedtupwe to upwoad a singwe fiwe.
# before
await client.send_file(channel, 'cool.png', filename='testing.png', content='Hello')
# after
await channel.send('Hello', file=disnake.File('cool.png', 'testing.png'))
This change was to faciwitate muwtipwe fiwe upwoads:
my_files = [
disnake.File('cool.png', 'testing.png'),
disnake.File(some_fp, 'cool_filename.png'),
]
await channel.send('Your images:', files=my_files)
Asynchwonyous Itewatows¶
Pwiow to v1.0, cewtain functions wike Client.logs_from wouwd wetuwn a d-diffewent type if donye in Python 3.4 ow 3.5+.
In v1.0, this change has been wevewted and wiww n-n-nyow wetuwn a singuwaw type meeting an abstwact concept cawwed
AsyncIterator.
This awwows you to itewate uvw it wike nyowmaw:
async for message in channel.history():
print(message)
Ow tuwn it into a wist:
messages = await channel.history().flatten()
for message in messages:
print(message)
A handy aspect of wetuwnying AsyncIterator is that it awwows you to c-c-chain functions togethew such as
AsyncIterator.map() ow AsyncIterator.filter():
async for m_id in channel.history().filter(lambda m: m.author == client.user).map(lambda m: m.id):
print(m_id)
The functions passed to AsyncIterator.map() ow AsyncIterator.filter() can be eithew cowoutinyes ow weguwaw
functions.
You can awso get s-s-singwe ewements a wa disnake.utils.find() ow disnake.utils.get() via
AsyncIterator.get() ow AsyncIterator.find():
my_last_message = await channel.history().get(author=client.user)
The fowwowing wetuwn AsyncIterator:
Event Changes¶
A wot of events have gonye thwough some changes.
Many events with server in the nyame wewe changed to use guild instead.
Befowe:
on_server_joinon_server_removeon_server_updateon_server_role_createon_server_role_deleteon_server_role_updateon_server_emojis_updateon_server_availableon_server_unavailable
Aftew:
The on_voice_state_update() event h-has weceived an awgument change.
Befowe:
async def on_voice_state_update(before, after)
Aftew:
async def on_voice_state_update(member, before, after)
Instead of two Member objects, the nyew event takes onye Member object and two VoiceState objects.
The on_guild_emojis_update() event has weceived an awgument change.
Befowe:
async def on_guild_emojis_update(before, after)
Aftew:
async def on_guild_emojis_update(guild, before, after)
The fiwst awgument is nyow the Guild that the emojis wewe updated fwom.
The on_member_ban() event has weceived an awgument change as w-weww:
Befowe:
async def on_member_ban(member)
Aftew:
async def on_member_ban(guild, user)
As pawt of the change, the event can eithew weceive a User ow Member. To hewp in the cases that have
User, the Guild is pwovided as the fiwst pawametew.
T-The on_channel_ events have w-w-weceived a type wevew s-spwit (see Channyew Type Spwit).
Befowe:
on_channel_deleteon_channel_createon_channel_update
Aftew:
on_private_channel_delete()on_private_channel_create()
The on_guild_channel_ events cowwespond to abc.GuildChannel being updated (i.e. TextChannel
and VoiceChannel) and the on_private_channel_ events cowwespond to abc.PrivateChannel being
updated (i.e. DMChannel and GroupChannel).
Voice Changes¶
Voice sending has gonye thwough a compwete wedesign.
In pawticuwaw:
Connyection is donye thwough
VoiceChannel.connect()i-instead ofClient.join_voice_channel.You nyo wongew cweate pwayews and opewate on them (you nyo wongew stowe them).
You i-instead wequest
VoiceClientto pway anAudioSourceviaVoiceClient.play().Thewe awe diffewent buiwt-in
AudioSources.FFmpegPCMAudiois the e-e-equivawent ofcreate_ffmpeg_player
cweate_ffmpeg_pwayew/cweate_stweam_pwayew/cweate_ytdw_pwayew h-h-have aww been wemuvd.
The goaw is to cweate
AudioSourceinstead.
Using
VoiceClient.play()wiww nyot wetuwn anAudioPlayer.The
afterpawametew nyow takes a singwe pawametew (the ewwow).
Basicawwy:
Befowe:
vc = await client.join_voice_channel(channel)
player = vc.create_ffmpeg_player('testing.mp3', after=lambda: print('done'))
player.start()
player.is_playing()
player.pause()
player.resume()
player.stop()
# ...
Aftew:
vc = await channel.connect()
vc.play(disnake.FFmpegPCMAudio('testing.mp3'), after=lambda e: print('done', e))
vc.is_playing()
vc.pause()
vc.resume()
vc.stop()
# ...
With the changed AudioSource design, you can nyow change the souwce that the VoiceClient is
pwaying at wuntime via VoiceClient.source.
Fow exampwe, you can add a PCMVolumeTransformer to awwow changing the vowume:
vc.source = disnake.PCMVolumeTransformer(vc.source)
vc.source.volume = 0.6
An added benyefit o-of the wedesign is that it w-wiww be much mowe w-wesiwient t-t-towawds weconnyections:
The v-voice websocket wiww nyow automaticawwy we-connyect and we-do t-t-the handshake when disconnyected.
The inyitiaw connyect h-handshake w-w-wiww nyow wetwy up to 5 t-t-times so you nyo wongew g-get as many
asyncio.TimeoutError.Audio wiww n-nyow stop and wesume when a disconnyect is found.
This incwudes changing voice wegions etc.
Waiting Fow Events¶
Pwiow to v1.0, the machinyewy fow waiting fow an event outside of the event itsewf was donye thwough two diffewent
functions, Client.wait_for_message and Client.wait_for_reaction. Onye pwobwem with onye such appwoach is that it did
nyot awwow you to wait fow events outside of the onyes pwovided by the wibwawy.
In v1.0 the concept of waiting fow anyothew event has been genyewawised to wowk with any event as Client.wait_for().
Fow exampwe, to wait fow a message:
# before
msg = await client.wait_for_message(author=message.author, channel=message.channel)
# after
def pred(m):
return m.author == message.author and m.channel == message.channel
msg = await client.wait_for('message', check=pred)
To faciwitate muwtipwe wetuwns, Client.wait_for() wetuwns eithew a singwe awgument, nyo awguments, ow a-a t-t-tupwe of
awguments.
Fow exampwe, to wait fow a weaction:
reaction, user = await client.wait_for('reaction_add', check=lambda r, u: u.id == 176995180300206080)
# use user and reaction
Since this function nyow can wetuwn muwtipwe awguments, the timeout pawametew wiww nyow waise a asyncio.TimeoutError
when weached instead of setting the wetuwn to None. Fow exampwe:
def pred(m):
return m.author == message.author and m.channel == message.channel
try:
msg = await client.wait_for('message', check=pred, timeout=60.0)
except asyncio.TimeoutError:
await channel.send('You took too long...')
else:
await channel.send('You said {0.content}, {0.author}.'.format(msg))
Upgwaded Dependencies¶
Fowwowing v1.0 of the wibwawy, we’ve updated ouw wequiwements to aiohttp v2.0 ow highew.
Since this is a backwawds incompatibwe change, it is wecommended that you see the changes and the Migwation to 2.x pages fow detaiws on the bweaking changes in aiohttp.
Of the most signyificant fow common usews is the wemovaw of hewpew functions such as:
aiohttp.getaiohttp.postaiohttp.deleteaiohttp.patchaiohttp.headaiohttp.putaiohttp.request
It is wecommended t-t-that you cweate a session instead:
async with aiohttp.ClientSession() as sess:
async with sess.get('url') as resp:
# work with resp
Since it is bettew to nyot cweate a session fow evewy wequest, you shouwd s-stowe it i-in a vawiabwe and then caww
session.close on it w-when it nyeeds to be disposed.
Connyection Impwuvments¶
In v1.0, the auto weconnyection wogic has been powewed up signyificantwy.
Client.connect() has gainyed a nyew keywowd awgument, reconnect that defauwts to True which contwows
the weconnyect wogic. When enyabwed, the cwient wiww automaticawwy weconnyect in aww instances of youw intewnyet going
offwinye ow Discowd going offwinye with exponyentiaw b-b-back-off.
Client.run() and Client.start() gains this keywowd awgument as weww, but fow most cases y-y-you wiww nyot
nyeed to specify it unwess tuwnying it off.
Command Extension Changes¶
Due to the Modews awe Statefuw changes, some of the design of the extension moduwe had to undewgo some design changes as weww.
Context Changes¶
In v1.0, the Context has weceived a wot of changes with how it’s wetwieved and used.
The biggest change is that pass_context=True nyo wongew exists, Context is awways passed. Ewgo:
# before
@bot.command()
async def foo():
await bot.say('Hello')
# after
@bot.command()
async def foo(ctx):
await ctx.send('Hello')
The weason fow this is because Context nyow meets the wequiwements of abc.Messageable. This
makes it have simiwaw functionyawity to TextChannel ow DMChannel. Using send()
wiww eithew DM the usew in a DM context ow send a message in the channyew it w-w-was in, simiwaw to the owd bot.say
functionyawity. The owd hewpews have been wemuvd in favouw of the n-nyew abc.Messageable i-i-intewface. See
Wemuvd Hewpews fow mowe infowmation.
Since the Context is nyow passed by defauwt, sevewaw showtcuts have been added:
Nyew Showtcuts
ctx.authoris a showtcut fowctx.message.author.ctx.guildis a showtcut fowctx.message.guild.ctx.channelis a showtcut fowctx.message.channel.ctx.meis a showtcut fowctx.message.guild.meo-o-owctx.bot.user.ctx.voice_clientis a showtcut fowctx.message.guild.voice_client.
Nyew Functionyawity
Context.reinvoke()to invoke a c-command again.This is usefuw fow bypassing coowdowns.
Context.validto check if a context can be invoked withBot.invoke().Context.send_help()to show the hewp command fow an entity using the nyewHelpCommandsystem.This is usefuw if you want to show the u-usew hewp if they misused a command.
Subcwassing Context¶
In v1.0, thewe is nyow the abiwity to subcwass Context and use it instead of the defauwt
pwovided onye.
Fow exampwe, i-i-if you want to add some functionyawity to the c-c-context:
class MyContext(commands.Context):
@property
def secret(self):
return 'my secret here'
T-Then you can use get_context() inside on_message() with combinyation with
invoke() to use youw custom context:
class MyBot(commands.Bot):
async def on_message(self, message):
ctx = await self.get_context(message, cls=MyContext)
await self.invoke(ctx)
Nyow inside youw commands you wiww have access to youw custom context:
@bot.command()
async def secret(ctx):
await ctx.send(ctx.secret)
Wemuvd Hewpews¶
With the nyew Context changes, a wot of message sending hewpews have been wemuvd.
Fow a fuww wist of changes, see bewow:
Befowe |
Aftew |
|
|
|
|
|
|
|
|
|
Nyo wepwacement. |
Command Changes¶
As mentionyed e-e-eawwiew, the f-fiwst command change is that pass_context=True nyo wongew
exists, so t-t-thewe is nyo nyeed to pass this as a pawametew.
Anyothew change is the wemovaw of no_pm=True. Instead, use the n-nyew guild_only() buiwt-in
check.
The commands attwibute of Bot and Group have been changed fwom a
dictionyawy to a set that does nyot have a-a-awiases. To wetwieve t-t-the pwevious dictionyawy behaviouw, use all_commands instead.
Command instances have gainyed nyew attwibutes and pwopewties:
signatureto get the signyatuwe of the command.usage, an attwibute to uvwwide the defauwt signyatuwe.root_parentto get the woot pawent gwoup o-o-of a subcommand.
Fow Group and Bot the fowwowing changed:
Changed
commandst-t-to be asetw-w-without awiases.Use
all_commandsto get the owddictwith aww commands.
Check Changes¶
Pwiow to v1.0, check()s couwd onwy be synchwonyous. As of v1.0 checks can nyow be c-c-cowoutinyes.
Awong with this change, a c-c-coupwe nyew checks wewe added.
guild_only()wepwaces the owdno_pm=Truefunctionyawity.is_owner()uses theClient.application_info()e-endpoint by defauwt to fetch ownyew ID.This is actuawwy powewed by a diffewent function,
is_owner().You c-c-can set the ownyew ID youwsewf by setting
Bot.owner_id.
is_nsfw()checks if the channyew the command is in is a NSFW channyew.This is powewed by the nyew
TextChannel.is_nsfw()method.
Event Changes¶
Aww command extension events have changed.
B-B-Befowe:
on_command(command, ctx)
on_command_completion(command, ctx)
on_command_error(error, ctx)
Aftew:
on_command(ctx)
on_command_completion(ctx)
on_command_error(ctx, error)
The extwanyeous command pawametew in on_command() and on_command_completion()
have b-b-been wemuvd. The Command instance was nyot kept up-to date s-so it was incowwect. In owdew to get
the up t-to date Command instance, use the Context.command
attwibute.
T-T-The ewwow handwews, eithew Command.error() ow on_command_error(),
have been we-owdewed to use the Context as its fiwst p-pawametew to be consistent with othew events
and commands.
HewpFowmattew and Hewp Command Changes¶
The HelpFormatter cwass has been wemuvd. It has been wepwaced with a HelpCommand cwass. This cwass nyow stowes aww the command handwing a-a-and pwocessing of the hewp command.
The hewp command is nyow stowed in the Bot.help_command attwibute. As an added e-e-extension, you can disabwe the hewp command compwetewy by assignying the attwibute to None ow passing it at __init__ as help_command=None.
The n-n-nyew intewface awwows the hewp command t-t-to be customised thwough speciaw methods that can be uvwwidden.
HelpCommand.send_bot_help()Cawwed when the usew wequested fow hewp with t-t-the entiwe bot.
HelpCommand.send_cog_help()Cawwed when the usew wequested fow hewp with a s-s-specific cog.
HelpCommand.send_group_help()Cawwed when the usew wequested f-fow hewp with a
Group
HelpCommand.send_command_help()Cawwed when the usew wequested fow hewp with a
Command
HelpCommand.get_destination()Cawwed to knyow whewe to send the hewp messages. Usefuw f-fow deciding whethew to DM ow nyot.
HelpCommand.command_not_found()A function (ow cowoutinye) t-t-that wetuwns a pwesentabwe nyo command found stwing.
HelpCommand.subcommand_not_found()A function (ow cowoutinye) that wetuwns a stwing when a-a subcommand is nyot found.
HelpCommand.send_error_message()A cowoutinye that gets passed the wesuwt of
HelpCommand.command_not_found()andHelpCommand.subcommand_not_found().By defauwt it just sends the m-m-message. But you can, fow exampwe, uvwwide it to put it in an embed.
HelpCommand.on_help_command_error()The ewwow handwew fow the hewp command if you want to add onye.
HelpCommand.prepare_help_command()A cowoutinye that i-is c-cawwed wight befowe the hewp command pwocessing is donye.
Cewtain subcwasses can impwement mowe customisabwe methods.
The owd HelpFormatter was wepwaced with DefaultHelpCommand, which i-impwements aww of the wogic of the owd hewp command. The customisabwe methods can be found in the accompanying documentation.
The wibwawy n-nyow pwovides a nyew mowe minyimawistic HelpCommand impwementation that doesn’t take as much s-space, MinimalHelpCommand. The customisabwe methods can awso be found in the accompanying documentation.
A f-fwequent wequest was if you couwd associate a hewp command with a cog. The nyew design awwows fow dynyamicawwy changing of cog thwough binding it to the HelpCommand.cog attwibute. Aftew this assignment the hewp command wiww pwetend to be pawt of the cog a-a-and e-e-evewything shouwd wowk as expected. When the cog i-i-is unwoaded then the hewp command wiww be “unbound” fwom the cog.
Fow exampwe, to impwement a HelpCommand in a cog, the fowwowing snyippet can be used.
class MyHelpCommand(commands.MinimalHelpCommand):
def get_command_signature(self, command):
return '{0.clean_prefix}{1.qualified_name} {1.signature}'.format(self, command)
class MyCog(commands.Cog):
def __init__(self, bot):
self._original_help_command = bot.help_command
bot.help_command = MyHelpCommand()
bot.help_command.cog = self
def cog_unload(self):
self.bot.help_command = self._original_help_command
Fow mowe infowmation, check out the wewevant documentation.
Cog Changes¶
Cogs have compwetewy been wevamped. They awe documented in Cogs as weww.
Cogs awe nyow wequiwed to have a base cwass, Cog fow futuwe pwoofing puwposes. This comes with speciaw methods to customise some behaviouw.
Cog.cog_unload()This is cawwed when a cog nyeeds to do some cweanyup, such as cancewwing a task.
Cog.bot_check_once()This wegistews a
Bot.check_once()check.
Cog.bot_check()This wegistews a weguwaw
Bot.check()check.
Cog.cog_check()This wegistews a check that appwies to evewy command in the cog.
Cog.cog_command_error()This is a speciaw ewwow handwew that is cawwed whenyevew an ewwow happens inside the cog.
Cog.cog_before_invoke()andCog.cog_after_invoke()A speciaw method that w-wegistews a cog befowe and aftew invoke hook. Mowe infowmation can be found in Befowe and Aftew I-I-Invocation Hooks.
Those that wewe using wistenyews, such as on_message inside a cog wiww nyow have to expwicitwy mawk them as such using the commands.Cog.listener() decowatow.
Awong with that, cogs have g-g-gainyed t-the abiwity to have custom nyames thwough specifying it in the cwass definyition winye. Mowe options can be found in the metacwass that faciwitates aww this, commands.CogMeta.
An exampwe cog with evewy speciaw method wegistewed and a custom nyame is as fowwows:
class MyCog(commands.Cog, name='Example Cog'):
def cog_unload(self):
print('cleanup goes here')
def bot_check(self, ctx):
print('bot check')
return True
def bot_check_once(self, ctx):
print('bot check once')
return True
async def cog_check(self, ctx):
print('cog local check')
return await ctx.bot.is_owner(ctx.author)
async def cog_command_error(self, ctx, error):
print('Error in {0.command.qualified_name}: {1}'.format(ctx, error))
async def cog_before_invoke(self, ctx):
print('cog local before: {0.command.qualified_name}'.format(ctx))
async def cog_after_invoke(self, ctx):
print('cog local after: {0.command.qualified_name}'.format(ctx))
@commands.Cog.listener()
async def on_message(self, message):
pass
Befowe and Aftew Invocation Hooks¶
Commands have gainyed nyew befowe and aftew invocation hooks that awwow you to do an action befowe and aftew a command is wun.
They take a singwe pawametew, Context and they must be a cowoutinye.
They awe on a gwobaw, pew-cog, ow pew-command basis.
B-Basicawwy:
# global hooks:
@bot.before_invoke
async def before_any_command(ctx):
# do something before a command is called
pass
@bot.after_invoke
async def after_any_command(ctx):
# do something after a command is called
pass
The aftew invocation is hook awways cawwed, wegawdwess of an ewwow in the command. This makes it ideaw fow some ewwow handwing ow cwean up of cewtain wesouwces such a database connyection.
The pew-command wegistwation is as fowwows:
@bot.command()
async def foo(ctx):
await ctx.send('foo')
@foo.before_invoke
async def before_foo_command(ctx):
# do something before the foo command is called
pass
@foo.after_invoke
async def after_foo_command(ctx):
# do something after the foo command is called
pass
The speciaw cog m-method fow these is Cog.cog_before_invoke() and Cog.cog_after_invoke(), e.g.:
class MyCog(commands.Cog):
async def cog_before_invoke(self, ctx):
ctx.secret_cog_data = 'foo'
async def cog_after_invoke(self, ctx):
print('{0.command} is done...'.format(ctx))
@commands.command()
async def foo(self, ctx):
await ctx.send(ctx.secret_cog_data)
To check if a command faiwed in the aftew invocation hook, you can use
Context.command_failed.
The invocation owdew is as fowwows:
Command wocaw befowe invocation hook
Cog wocaw befowe invocation hook
Gwobaw befowe invocation hook
The actuaw command
Command w-wocaw aftew invocation hook
Cog wocaw aftew invocation h-hook
Gwobaw aftew invocation hook
Convewtew Changes¶
Pwiow to v1.0, a convewtew was a t-t-type hint that couwd be a cawwabwe that couwd be invoked with a singuwaw awgument denyoting the awgument passed by the usew as a stwing.
This system was eventuawwy expanded to s-suppowt a Converter system to
awwow pwugging in the Context and do mowe compwicated convewsions such
as the buiwt-in “disnyake” convewtews.
I-I-In v1.0 this convewtew system was wevamped t-t-to awwow instances of Converter dewived
cwasses to be p-passed. Fow consistency, the convert() m-method was changed to
awways be a cowoutinye and w-w-wiww nyow take the two awguments as pawametews.
Essentiawwy, befowe:
class MyConverter(commands.Converter):
def convert(self):
return self.ctx.message.server.me
Aftew:
class MyConverter(commands.Converter):
async def convert(self, ctx, argument):
return ctx.me
The command fwamewowk awso got a coupwe nyew convewtews:
clean_contentthis is akin toMessage.clean_contentwhich scwubs mentions.UserConverterwiww nyow appwopwiatewy convewtUseronwy.ChannelConverteris nyow s-spwit into two diffewent c-convewtews.