v1.0への移行¶
v1.0 では完全な書き直しが行われたため,このライブラリにおけるもっとも大きな更新のひとつといえます。
すべての意図と目的を達成するために変更点が長大になった結果,ライブラリは完全に新しいものになりました。
一部の書き換えは,より使いやすく自然に物事を表現するために行われています。あらゆる仕事をするのに Client
インスタンスを要求するのではなく,代わりに models を用いることができるようになりました。
Pythonのバージョンの変更¶
discord.py の開発をより簡単にし,またその依存関係にあるライブラリをアップグレードして Python 3.7 以上を使えるようにするために,discord.py は Python 3.5.3 より古いバージョンに対するサポートを諦めざるを得ませんでした。これはつまり Python 3.4 に対するサポートは打ち切られた ということです。
主要モデルの変更¶
以下は v1.0 で発生した主要なモデルの変更点です。
Snowflakeのint型への変更¶
v1.0以前は、全てのsnowflake (id
属性) が文字列として扱われていましたが、これは int
型に変更されました。
簡単な例:
# before
ch = client.get_channel('84319995256905728')
if message.author.id == '80528701850124288':
...
# after
ch = client.get_channel(84319995256905728)
if message.author.id == 80528701850124288:
...
この変更により,公式クライアントの「 ID をコピー」機能を使用した際に間違いがより起こりにくくなりました。もはや取得した ID をクォーテーションマークで囲う必要はありませんし,内部で JSON の代わりに ETF を用いることで最適化の機会を得ることにもなります。
Server は Guild になりました¶
公式のAPIドキュメントでは、「Server」は「Guild」と呼ばれています。APIドキュメントとの一貫性を保つため、モデルの名称が Guild
へ変更されました。同時にこのモデルを参照するすべてのインスタンスも変更されています。
変更点の一覧
変更前 |
変更後 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
モデルのステートフル化¶
前述したように、多くの機能が Client
から各々の model へと移されました。
以下が、これによる変更点の一覧です。
変更前 |
変更後 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
削除されました |
|
削除されました |
|
変更なし |
辞書の値の変更¶
v1.0以前では、複数のモデルを集約して取得するプロパティは「辞書ビュー」オブジェクトで結果を返していました。
これは、オブジェクトを用いて繰り返し処理を行っている間に、辞書サイズが変更されたとき、RuntimeErrorを発生させてタスクをクラッシュさせていました。これを軽減させるため「辞書ビュー」オブジェクトはリストに変更されました。
以下のビューがリストへ変更されています。
Client.users
(v1.0にて追加)Client.emojis
(v1.0にて追加)Guild.text_channels
(v1.0にて追加)Guild.voice_channels
(v1.0にて追加)
ボイスステートの変更¶
v0.11.0では、ボイスステートを参照するために VoiceState
が追加され、このクラスを参照するために Member.voice
が使われていました。
これはユーザーにとって透過的なものでしたが、ライブラリがメモリを節約できるようボイスステートの変化が可視的になりました。
ボイスの属性にアクセスするには Member.voice
を用いる方法しか存在しません。メンバーがボイスステートを持たない場合は None
が返ることに注意してください。
簡単な例:
# before
member.deaf
member.voice.voice_channel
# after
if member.voice: # can be None
member.voice.deaf
member.voice.channel
ユーザーとメンバーの分離¶
v1.0では、メモリの節約のため、 Member
は User
のサブクラスではなくなりました。代わりに、 User
に記述されたものと同等のプロパティを実装することで、この二つのクラスは平坦化されています。そのため、使用方法に機能的変更はありません。ただし、 isinstance
が使えなくなってしまったことは留意しておくべきです。
メモリの節約は、グローバルな User
のキャッシュを持つことで実現しました。これによって Client.get_user()
を使ってIDから簡単に User
を取得できます。また、あなたのクライアントが見ることができるユーザーを Client.users
ですべて取得できるようにもなりました。
チャンネルタイプの分割¶
v1.0以前のバージョンでは、チャンネルは is_private
で判別する Channel
と PrivateChannel
の二通りしかありませんでした。
メモリ使用量を削減するため、チャンネルを4つのタイプへ分割しました。
ギルドのテキストチャンネル用である
TextChannel
。ギルドのボイスチャンネル用である
VoiceChannel
。メンバーのDMチャンネル用である
DMChannel
。メンバーが参加するグループDMチャンネル用である
GroupChannel
。
これらに分割されたことにより、 is_private
は削除されました。v1.0では isinstance
を使うべきでしょう。
型は二通りの 抽象基底クラス に分けられます。
ギルドのチャンネルを表す
abc.GuildChannel
。プライベートチャンネル(DMやグループDM)を表す
abc.PrivateChannel
。
チャンネルがギルドチャンネルであるかをチェックしたい場合:
isinstance(channel, discord.abc.GuildChannel)
チャンネルがプライベートチャンネルであるかをチェックしたい場合:
isinstance(channel, discord.abc.PrivateChannel)
もちろん、特定のチャンネルタイプを探したい場合、そのチャンネルタイプを渡すことも可能です。
isinstance(channel, discord.TextChannel)
この分割により、イベントにも変更がありました。これについては イベントの変更 に詳細があります。
その他のモデルの変更¶
一般的なモデルには追加、あるいは削除されたものが多くあります。
以下がその一覧です。
削除
Client.login()
はEメールとパスワードによるログインを受け付けなくなりました。トークンと
bot=False
を使用してください。
Client.get_all_emojis
代わりに
Client.emojis
を使用してください。
Client.wait_for_message
およびClient.wait_for_reaction
は削除されました。代わりに
Client.wait_for()
を使用してください。
Channel.voice_members
代わりに
VoiceChannel.members
を使用してください。
Channel.is_private
代わりに
isinstance
と 抽象基底クラス を使用してください。例を挙げると
isinstance(channel, discord.abc.GuildChannel)
でプライベートチャンネルであるかを確認できます。
Client.accept_invite
これに代わるものはありません。これは非推奨のAPIです。
Guild.default_channel
/Server.default_channel
およびChannel.is_default
デフォルトチャンネルの概念は、Discordから削除されました。 #329 を参照してください。
Message.edited_timestamp
代わりに
Message.edited_at
を使用してください。
Message.timestamp
代わりに
Message.created_at
を使用してください。
Colour.to_tuple()
代わりに
Colour.to_rgb()
を使用してください。
Permissions.view_audit_logs
代わりに
Permissions.view_audit_log
を使用してください。
Member.game
代わりに
Member.activities
使用してください。
Guild.role_hierarchy
/Server.role_hierarchy
代わりに
Guild.roles
を使用してください。ソート順が以前のGuild.role_hierarchy
とは逆になっていることに注意してください。
変更
Member.avatar_url
とUser.avatar_url
はアバターが設定されていなければ、デフォルトアバターが返るようになりました。Message.embeds
はdict
オブジェクトからEmbed
のリストに変更されました。Message.attachments
はdict
オブジェクトからAttachment
のリストに変更されました。Guild.roles
はヒエラルキー順にソートされるようになりました。先頭には必ず@everyone
が格納されます。
追加
Discordのアタッチメントを表す
Attachment
。チャンネルのカテゴリを表す
CategoryChannel
。ボイスチャンネルに接続しているメンバーを取得する
VoiceChannel.members
。テキストチャンネルを閲覧可能なメンバーを取得する
TextChannel.members
。役割を持っているメンバーを取得する
Role.members
。テキストチャンネルのみを取得する
Guild.text_channels
。ボイスチャンネルのみを取得する
Guild.voice_channels
。チャンネルのカテゴリのみを取得する
Guild.categories
。チャンネルが属するカテゴリを取得する
TextChannel.category
とVoiceChannel.category
。カテゴリによってグループ化されたチャンネルを取得する
Guild.by_category()
。メンバーのチャンク状態を確認する
Guild.chunked
。不適切な表現のフィルターを取得する
Guild.explicit_content_filter
。Shardingを使用している場合のみ、ギルドのShard IDを取得する
Guild.shard_id
。Botによってみることができる
User
インスタンスをすべて返すClient.users
。IDから
User
を取得するClient.get_user()
。特定のサイズ、あるいはフォーマットのアバターを取得する
User.avatar_url_as()
。ギルドのカスタム招待URLを取得する
Guild.vanity_invite()
。ギルドのサーバーログを取得する
Guild.audit_logs()
。メッセージのWebhook IDを取得する
Message.webhook_id
。リッチプレゼンスに関する情報を取得する
Message.activity
およびMessage.application
。テキストチャンネルがNSFWであるかを確認する
TextChannel.is_nsfw()
。RGBのタプルから
Colour
を作成するColour.from_rgb()
。IDから役職を取得する
Guild.get_role()
。
メッセージの送信¶
変更点の一つは、以前の Client.send_message
と Client.send_file
の機能を単一のメソッド send()
に統合したことです。
基本形
# before
await client.send_message(channel, 'Hello')
# after
await channel.send('Hello')
これは埋め込みメッセージなどといった、従来の send_message
が持っていた機能を全てサポートしています。
e = discord.Embed(title='foo')
await channel.send('Hello', embed=e)
これはファイルの送信に対応できるように拡張されましたが、複数のファイルを送信する際には、 File
の擬似的な名前付きタプルでファイルを渡す必要があります。
# before
await client.send_file(channel, 'cool.png', filename='testing.png', content='Hello')
# after
await channel.send('Hello', file=discord.File('cool.png', 'testing.png'))
この変更は、複数の添付ファイルの送信を容易にするために行われました。
my_files = [
discord.File('cool.png', 'testing.png'),
discord.File(some_fp, 'cool_filename.png'),
]
await channel.send('Your images:', files=my_files)
非同期のイテレータ¶
v1.0以前のバージョンは、Python 3.4 または 3.5以上の環境において Client.logs_from
のような特定の関数で、処理終了時に異なった型を返していました。
これはv1.0で元に戻り、 AsyncIterator
という抽象概念を満たす特異な型を返します。
これは通常のイテレータと同様の処理が行なえます。
async for message in channel.history():
print(message)
またはリストにできます。
messages = await channel.history().flatten()
for message in messages:
print(message)
AsyncIterator
を返すことで便利な点は AsyncIterator.map()
や AsyncIterator.filter()
といった関数をチェーンできることです:
async for m_id in channel.history().filter(lambda m: m.author == client.user).map(lambda m: m.id):
print(m_id)
AsyncIterator.map()
または AsyncIterator.filter()
に渡される関数はコルーチンか通常の関数です。
You can also get single elements a la discord.utils.find()
or discord.utils.get()
via
AsyncIterator.get()
or AsyncIterator.find()
:
my_last_message = await channel.history().get(author=client.user)
AsyncIterator
を返すのは以下のとおりです:
イベントの変更¶
多くのイベントに変更がありました。
名前に server
が含まれていたイベントのほとんどが、 guild
を使った名前に変更されました。
変更前
on_server_join
on_server_remove
on_server_update
on_server_role_create
on_server_role_delete
on_server_role_update
on_server_emojis_update
on_server_available
on_server_unavailable
変更後
on_voice_state_update()
イベントの引数が変更されました。
更新前
async def on_voice_state_update(before, after)
更新後
async def on_voice_state_update(member, before, after)
新しくなったイベントは、二つの Member
の代わりに、 一つの Member
と二つの VoiceState
を受け取るようになりました。
on_guild_emojis_update()
イベントの引数が変更されました。
更新前
async def on_guild_emojis_update(before, after)
更新後
async def on_guild_emojis_update(guild, before, after)
最初の引数は絵文字の更新が行われた Guild
です。
on_member_ban()
も引数が変更されました。
更新前
async def on_member_ban(member)
更新後
async def on_member_ban(guild, user)
変更の一つは、イベントが Member
または User
のどちらかを受け取れるようになったことです。 User
で受け取る場合には第一引数として Guild
が渡されます。
on_channel_
のようなイベントは、チャンネルタイプにより分割されました ( チャンネルタイプの分割 を参照)。
変更前
on_channel_delete
on_channel_create
on_channel_update
変更後
on_guild_channel_
イベントは更新される abc.GuildChannel
(TextChannel
および VoiceChannel
)に対応しており、 on_private_channel_
イベントは更新される abc.PrivateChannel
(DMChannel
および GroupChannel
)に対応しています。
ボイスの変更¶
ボイスの送信が完全に再構成されました。
主な変更点は以下のとおりです。
ボイスチャンネルへの接続は
Client.join_voice_channel
に代わってVoiceChannel.connect()
になりました。プレイヤーを作成せずに操作が可能になりました。(プレイヤーの保存の必要もありません)
代わりに
VoiceClient
のVoiceClient.play()
を介してAudioSource
の再生を要求します。There are different built-in
AudioSource
s.FFmpegPCMAudio
is the equivalent ofcreate_ffmpeg_player
create_ffmpeg_player/create_stream_player/create_ytdl_player have all been removed.
The goal is to create
AudioSource
instead.
Using
VoiceClient.play()
will not return anAudioPlayer
.The
after
parameter now takes a single parameter (the error).
基本的には以下のとおりです:
更新前
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()
# ...
更新後
vc = await channel.connect()
vc.play(discord.FFmpegPCMAudio('testing.mp3'), after=lambda e: print('done', e))
vc.is_playing()
vc.pause()
vc.resume()
vc.stop()
# ...
AudioSource
の再設計により、 VoiceClient.source
を介して実行中の VoiceClient
のソースを変更できるようになりました。
例えば、 PCMVolumeTransformer
を追加すると、ボリュームの変更ができるようになります。
vc.source = discord.PCMVolumeTransformer(vc.source)
vc.source.volume = 0.6
再設計によるさらなる利点は、再接続において遥かに柔軟性を持ったことです。
音声ウェブソケットは、切断された際に自動的に再接続し、ハンドシェイクを再実行します。
初期接続のハンドシェイクは、最大5回までの再試行となったので、大量の
asyncio.TimeoutError
に悩まされることはなくなりました。VCの切断を検知すると、オーディオは停止し、再開しようとします。
これはサーバーリージョンの変更も含まれます。
イベントの待機¶
v1.0以前のバージョンでは、イベントの発生を待つ方法として Client.wait_for_message
と Client.wait_for_reaction
の二つの関数が用意されていました。このアプローチの欠点はライブラリが提供するイベント以外の発生を待つことが出来ない点です。
v1.0では別のイベント待機の概念が Client.wait_for()
イベントのように一般化されました。
例えば、メッセージを待つ処理は以下のようになります。
# 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)
複数の返り値に対応するため、 Client.wait_for()
は単一の引数、引数なし、あるいは引数のタプルを返すようになっています。
例えば、リアクションを待つ処理は以下のようになります。
reaction, user = await client.wait_for('reaction_add', check=lambda r, u: u.id == 176995180300206080)
# use user and reaction
この関数は複数の引数を返すため、 timeout
に設定した時間経過すると、 None
を返すのではなく、 asyncio.TimeoutError
を発生させるようになりました。以下はその例になります。
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))
依存関係のアップグレード¶
ライブラリのv1.0への更新に伴い、要件が aiohttp
v2.0以上へと変更されました。
これは後方互換性のない変更となるため、 aiohttp
の変更点の詳細については changes と migrating ページを参照してください。
ユーザーにとって最も重要な変更点は、以下のヘルパー関数の削除です。
aiohttp.get
aiohttp.post
aiohttp.delete
aiohttp.patch
aiohttp.head
aiohttp.put
aiohttp.request
代わりにセッションを作成することをお勧めします。
async with aiohttp.ClientSession() as sess:
async with sess.get('url') as resp:
# work with resp
リクエストごとにセッションを作成するのは良いとは言えないため、変数に格納しておき、破棄しなければならない時に session.close
を呼び出すのが良いでしょう。
シャーディング¶
シャーディングの扱いに対して大きな変更があり、現在、シャーディングは第一級オブジェクトとして扱われています。
Botアカウントを使用していて、かつ一つのプロセスでBotをシャーディングしたい場合は、 AutoShardedClient
を使用してください。
このクラスは複数のプロセスを起動したり、IPCを処理することなくシャーディングが行えます。
シャーディングしたクライアントはユーザーアカウントをサポートしないことを覚えておきましょう。これは、接続の形態と状態処理の変更によるものです。
使い方は簡単です。
client = discord.AutoShardedClient()
Client
の代わりに上記のようにしてください。
これは /gateway/bot
エンドポイントを使って、あなたのBotに必要な数のシャードを起動します。このエンドポイントはシャードごとに1000ギルドを割り当てます。
シャードをより詳細に制御したい場合は、 shard_count
と shard_ids
を利用してください。
# launch 10 shards regardless
client = discord.AutoShardedClient(shard_count=10)
# launch specific shard IDs in this process
client = discord.AutoShardedClient(shard_count=10, shard_ids=(1, 2, 5, 6))
コマンド拡張を利用しているユーザーのために、同様に動作する AutoShardedBot
が用意されています。
接続の改善¶
v1.0では、自動再接続機能が大幅に強化されました。
Client.connect()
には新しいキーワード引数が追加されました。再接続機能の設定を行う reconnect
はデフォルトで True
に設定されています。有効にすると、クライアントは全インターネットのインスタンスがオフラインになった際や、Discordが指数関数的後退によってオフラインになった際に自動で再接続を試みます。
Client.run()
や Client.start()
にも同様のキーワード引数が追加されていますが、このさい接続機能をオフにする場合以外は指定する必要はありません。
コマンド拡張の変更¶
モデルのステートフル化 により、拡張モジュールの設計にもいくつかの変更があります。
コンテキストの変更¶
v1.0において、 Context
は取得と利用の面において、多くの変更があります。
最も大きな変更点は pass_context=True
が廃止され、常に Context
が渡されるようになったことです。そのため以下のようになります。
# before
@bot.command()
async def foo():
await bot.say('Hello')
# after
@bot.command()
async def foo(ctx):
await ctx.send('Hello')
その理由として、 Context
が abc.Messageable
の要件を満たしていることが挙げられます。 これは TextChannel
や DMChannel
と同等の機能を持っており、 send()
を用いることで、従来の bot.say
のようにDMまたはテキストチャンネルにメッセージを送信することが出来ます。古いヘルパー関数は新しい abc.Messageable
インタフェースの実装に伴い削除されました。詳細は ヘルパー関数の削除 を参照してください。
Context
が常に渡されるようになったため、いくつかのショートカットが追加されています。
新しいショートカット
author
はctx.message.author
のショートカットです。guild
はctx.message.guild
のショートカットです。channel
はctx.message.channel
のショートカットです。me
はctx.message.guild.me
あるいはctx.bot.user
のショートカットです。voice_client
はctx.message.guild.voice_client
のショートカットです。
新しい機能
reinvoke()
はコマンドを再度呼び出します。クールダウンの回避に利用できます。
コンテキストのサブクラス¶
v1.0では、 Context
を継承したサブクラスを作成し、デフォルトで実装されているものの代わりに使うことが出来ます。
例えば、コンテキストに機能の追加を行いたい場合は以下のように実装が出来ます。
class MyContext(commands.Context):
@property
def secret(self):
return 'my secret here'
また、 on_message()
内で get_context()
と invoke()
を組み合わせることであなたのカスタムコンテキストを使用できます。
class MyBot(commands.Bot):
async def on_message(self, message):
ctx = await self.get_context(message, cls=MyContext)
await self.invoke(ctx)
これにより、コマンドからあなたのカスタムコンテキストにアクセスすることが可能です。
@bot.command()
async def secret(ctx):
await ctx.send(ctx.secret)
コマンドの変更¶
前述の通り、 pass_context=True
は削除されたため、これをパラメータとして渡す必要はありません。
他に no_pm=True
も削除されました。代わりに新しい組み込みチェックである guild_only()
を使用してください。
Bot
と Group
の commands
属性は辞書からエイリアスを持たないsetに変更されました。以前のような辞書を取得するには all_commands
を使用してください。
コマンドインスタンスには新たな属性とプロパティが追加されました。
コマンドのシグネチャを取得する
signature
。デフォルトのシグネチャをオーバーライドする属性
usage
。サブコマンドのルートである親グループを取得する
root_parent
。
commands
は エイリアスなしのset
に変更されました。すべてのコマンドを従来の
dict
で取得するにはall_commands
を使用してください。
チェックの変更¶
v1.0以前のバージョンでは check()
は同期関数でしたが、 v1.0のチェックはコルーチンになりました。
この変更に加え、新たなチェックが二つ追加されました。
no_pm=True
の代わりとなるguild_only()
。is_owner()
はClient.application_info()
のエンドポイントを使用してオーナーIDを取得します。実際には
is_owner()
という別の関数を使用して実行されます。Bot.owner_id
に値を指定することで自分でオーナーIDの設定ができます。
is_nsfw()
はコマンドが実行されたチャンネルがNSFWチャンネルかどうかをチェックします。これは新しく追加された
TextChannel.is_nsfw()
メソッドにより実行されています。
イベントの変更¶
すべてのコマンド拡張のイベントが変更されました。
更新前
on_command(command, ctx)
on_command_completion(command, ctx)
on_command_error(error, ctx)
更新後
on_command(ctx)
on_command_completion(ctx)
on_command_error(ctx, error)
on_command()
と on_command_completion()
の command
パラメータが削除されました。 Command
インスタンスは更新されておらず、正しいものではありませんでした。最新の Command
インスタンスを取得するには Context.command
属性を使用してください。
Command.error()
や on_command_error()
のようなエラーハンドラは他のイベント及びコマンドとの一貫性を保つため、最初のパラメータとして Context
を使用するよう変更されました。
HelpFormatter and Help Command Changes¶
The HelpFormatter
class has been removed. It has been replaced with a HelpCommand
class. This class now stores all the command handling and processing of the help command.
The help command is now stored in the Bot.help_command
attribute. As an added extension, you can disable the help command completely by assigning the attribute to None
or passing it at __init__
as help_command=None
.
The new interface allows the help command to be customised through special methods that can be overridden.
HelpCommand.send_bot_help()
Called when the user requested for help with the entire bot.
HelpCommand.send_cog_help()
Called when the user requested for help with a specific cog.
HelpCommand.send_group_help()
Called when the user requested for help with a
Group
HelpCommand.send_command_help()
Called when the user requested for help with a
Command
HelpCommand.get_destination()
Called to know where to send the help messages. Useful for deciding whether to DM or not.
HelpCommand.command_not_found()
A function (or coroutine) that returns a presentable no command found string.
HelpCommand.subcommand_not_found()
A function (or coroutine) that returns a string when a subcommand is not found.
HelpCommand.send_error_message()
A coroutine that gets passed the result of
HelpCommand.command_not_found()
andHelpCommand.subcommand_not_found()
.By default it just sends the message. But you can, for example, override it to put it in an embed.
HelpCommand.on_help_command_error()
The error handler for the help command if you want to add one.
HelpCommand.prepare_help_command()
A coroutine that is called right before the help command processing is done.
Certain subclasses can implement more customisable methods.
The old HelpFormatter
was replaced with DefaultHelpCommand
, which implements all of the logic of the old help command. The customisable methods can be found in the accompanying documentation.
The library now provides a new more minimalistic HelpCommand
implementation that doesn't take as much space, MinimalHelpCommand
. The customisable methods can also be found in the accompanying documentation.
A frequent request was if you could associate a help command with a cog. The new design allows for dynamically changing of cog through binding it to the HelpCommand.cog
attribute. After this assignment the help command will pretend to be part of the cog and everything should work as expected. When the cog is unloaded then the help command will be "unbound" from the cog.
For example, to implement a HelpCommand
in a cog, the following snippet 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
For more information, check out the relevant documentation.
コグの変更¶
コグは完全に刷新されました。これは コグ としてドキュメント化されています。
コグは将来的な校正のためのクラスである Cog
を基底クラスとして持つ必要があります。このクラスには動作のカスタマイズのために、特別なメソッドが用意されています。
Cog.cog_unload()
これはタスクのキャンセルのような、コグに何らかのクリーンアップが必要なときに呼び出されます。
Cog.bot_check_once()
これは
Bot.check_once()
チェックを登録します。
Cog.bot_check()
これは普通の
Bot.check()
チェックを登録します。
Cog.cog_check()
これはコグのすべてのコマンドに適用されるチェックを登録します。
Cog.cog_command_error()
これは特別なエラーハンドラで、コグ内でエラーが発生するたびに呼び出されます。
Cog.cog_before_invoke()
とCog.cog_after_invoke()
コグの前後に呼び出されるフックを登録する特別なメソッド。詳細は 前後処理のフック に記載されています。
コグ内で on_message
のようなリスナーを使用していた人は、 commands.Cog.listener()
デコレータを用いて、リスナーを明示する必要があります。
Along with that, cogs have gained the ability to have custom names through specifying it in the class definition line. More options can be found in the metaclass that facilitates all this, commands.CogMeta
.
すべての特別なメソッドを使用し、そして名前を指定したコグの例が以下のようになります:
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
前後処理のフック¶
コマンドに、コマンドの実行前および実行後に処理が行えるようにするフックが新たに追加されました。
これは単一のパラメータとして Context
を受け取り、かつコルーチンである必要があります。
また、このフックは全体、コグごと、あるいはコマンドごとに設定することが可能です。
基本形
# 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
後処理のフックは コマンドのエラー発生に関わらず 必ず呼び出されます。そのため、データベース接続のようなリソースのクリーンアップやエラー処理に最適です。
コマンドごとに設定する方法は以下のとおりです。
@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 special cog method for 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)
Context.command_failed
を使うことで、後処理でコマンドがエラーになったかを確認する事ができます。
呼び出される順序は以下のとおりです。
コマンドごとの前処理。
コグごとの前処理。
全体での前処理。
実行されたコマンド。
コマンドごとの後処理。
コグごとの後処理。
全体での後処理。
コンバーターの変更¶
Prior to v1.0, a converter was a type hint that could be a callable that could be invoked with a singular argument denoting the argument passed by the user as a string.
This system was eventually expanded to support a Converter
system to
allow plugging in the Context
and do more complicated conversions such
as the built-in "discord" converters.
In v1.0 this converter system was revamped to allow instances of Converter
derived
classes to be passed. For consistency, the convert()
method was changed to
always be a coroutine and will now take the two arguments as parameters.
Essentially, before:
class MyConverter(commands.Converter):
def convert(self):
return self.ctx.message.server.me
更新後
class MyConverter(commands.Converter):
async def convert(self, ctx, argument):
return ctx.me
コマンドフレームワークにも二つのコンバーターが追加されました。
clean_content
this is akin toMessage.clean_content
which scrubs mentions.UserConverter
will now appropriately convertUser
only.ChannelConverter
は二つのコンバーターに分離されました。