V2.0への移行¶
v1.0と比較して、v2.0は主に開発のしやすさとAPIの対応に関連する破壊的変更があります。変更はコードすべての書き換えを必要とするほどの大規模なものではありませんが、少し書き換えが必要になる変更は多くあります。
Pythonのバージョンの変更¶
開発を容易にするために、セキュリティ関連の更新を維持するために、また新しい機能を使用するために v2.0はPython 3.7以前をサポートしなくなりました 。
ユーザーアカウント(セルフボット)のサポートの削除¶
ユーザートークンを用いてのログインはDiscordの 利用規約 に反しているため、ユーザーのみのエンドポイントに対するサポートはすべて削除されました。
以下の機能は削除されました。
Client.login()とClient.start()のbotパラメータClient.change_presence()のafkパラメータClientUser.edit()のpassword,new_password,email,houseパラメータCallMessageモデルGroupCallモデルProfileモデルRelationshipモデル列挙型
RelationshipType列挙型
HypeSquadHouse列挙型
PremiumType列挙型
UserContentFilter列挙型
FriendFlags列挙型
Themeon_relationship_addイベントon_relationship_removeイベントon_relationship_updateイベントClient.fetch_user_profileメソッドClientUser.create_groupメソッドClientUser.edit_settingsメソッドClientUser.get_relationshipメソッドGroupChannel.add_recipientsメソッドGroupChannel.remove_recipientsメソッドGroupChannel.editメソッドGuild.ackメソッドMessage.ackメソッドUser.blockメソッドUser.is_blockedメソッドUser.is_friendメソッドUser.profileメソッドUser.remove_friendメソッドUser.send_friend_requestメソッドUser.unblockメソッドClientUser.blocked属性ClientUser.email属性ClientUser.friends属性ClientUser.premium属性ClientUser.premium_type属性ClientUser.relationships属性Message.call属性User.mutual_friends属性User.relationship属性
asyncio イベントループの変更¶
Python 3.7で、自動的に非同期のイベントループを作成し破壊する asyncio.run() ヘルパー関数が導入されました。
これをサポートするために、discord.pyの asyncio のイベントループの扱い方が変更されました。
このため、 Client.run() を使用せずに、自分で非同期ループを作成して他の非同期のコードを準備できるようになります。
簡単な例:
client = discord.Client()
async def main():
# do other async things
await my_async_function()
# start the client
async with client:
await client.start(TOKEN)
asyncio.run(main())
Client クラスに setup_hook() メソッドが追加されました。このメソッドはログイン後、Discordゲートウェイに接続前に呼び出されます。
これは、非同期コンテキストで様々なボットの機能を準備するために使用することを意図しています。
setup_hook() は Client をサブクラス化して定義できます。
簡単な例:
class MyClient(discord.Client):
async def setup_hook(self):
print('This is asynchronous!')
client = MyClient()
client.run(TOKEN)
この変更により、 Client のコンストラクタは connector と loop パラメータを受け付けなくなりました。
これらとともに、コマンド拡張機能のエクステンションやコグの読み込みと読み込み解除にも変更がありました。 エクステンションとコグの読み込み・解除の非同期化 を参照してください。
インテントの必須化¶
以前のバージョンでは、intents キーワード引数は省略可能で、デフォルトで Intents.default() に指定されていました。 ユーザーにインテントを教え、より明示的にするために、このパラメータを必須にしました。
例:
# before
client = discord.Client()
# after
intents = discord.Intents.default()
client = discord.Client(intents=intents)
この変更は、 Client の すべての サブクラスに適用されます。
抽象基底クラスの変更¶
抽象基底クラス は abc.ABCMeta を継承していましたが、 typing.Protocol を継承するようになりました。
これにより、これらのクラスが使用する基幹メタクラスが変更されますが、一般的にこの変更はユーザーに対して完全に透過的であるべきです。
すべてのクラスは runtime-checkable プロトコルであるか明示的に継承されているので、 isinstance() や issubclass() の使用には影響を与えません。
以下のクラスは runtime-checkable な Protocol に変更されました:
以下のクラスは Protocol のサブクラスに変更されました:
以下のクラスは abc.ABCMeta の代わりにデフォルトのメタクラスを使用するよう変更されました:
datetime オブジェクトはUTC-Awareに¶
ライブラリ内でのnaiveな datetime.datetime オブジェクトはUTCタイムゾーンを使用したawareなものへ置き換えられました。naiveな datetime オブジェクトを受け取るメソッドは、 timezone-awareなオブジェクトも受け取るようになりました。 datetime のメソッドと同じように動作するよう、このライブラリのメソッドは naiveな datetime オブジェクトがローカルタイムを表すものと仮定するようになりました。(いくつかのメソッドは naiveな datetime を受け入れないことに注意してください。そのような例外は下に記載してあります。)
naiveな datetime が多くのメソッドからローカルタイムを表すものとして扱われるため、従来の動作では使用時にプログラムのエラーを引き起こす可能性が高かったのです。
移行を用意にするため、 utils.utcnow() ヘルパー関数が追加されました。
警告
datetime.datetime.utcnow() を使用するとnaiveな UTC datetime オブジェクトが返されるため、問題が発生します。
簡単な例:
# before
week_ago = datetime.datetime.utcnow() - datetime.timedelta(days=7)
if member.created_at > week_ago:
print(f'Member account {member} was created less than a week ago!')
# after
# The new helper function can be used here:
week_ago = discord.utils.utcnow() - datetime.timedelta(days=7)
# ...or the equivalent result can be achieved with datetime.datetime.now():
week_ago = datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(days=7)
if member.created_at > week_ago:
print(f'Member account {member} was created less than a week ago!')
以下はnaiveな datetime から UTC-awareなものへ変更されました:
Activity.end属性Game.end属性Spotify.end属性Game.start属性on_typing()イベントのtimestamp引数on_private_channel_pins_update()イベントのlast_pin引数on_guild_channel_pins_update()イベントのlast_pin引数
以下はawareな datetime を受け入れ、渡された datetime がnaiveであればそれをローカルタイムを表すものと仮定するようになりました:
Guild.audit_logs()メソッドTextChannel.purge()メソッドEmbedのコンストラクタEmbed.timestampプロパティのセッター
今のところ、このライブラリにはnaiveな datetime.datetime オブジェクトを受け入れない場所は1つしかありません:
Member.edit()のtimed_out_until引数これはユーザーがギルドメンバーに誤ったタイムアウトを適用することを防ぐために行われました。
主なWebhookの変更¶
Webhookのサポートは、タイピングとレート制限でより良い動作をするように書き換えられています。
その結果、同期的な機能は個別のクラスへと分割されました。
非同期的なWebhookの簡単な例:
# before
async with aiohttp.ClientSession() as session:
webhook = discord.Webhook.from_url('url-here', adapter=discord.AsyncWebhookAdapter(session))
await webhook.send('Hello World', username='Foo')
# after
async with aiohttp.ClientSession() as session:
webhook = discord.Webhook.from_url('url-here', session=session)
await webhook.send('Hello World', username='Foo')
同期的なWebhookの簡単な例:
# before
webhook = discord.Webhook.partial(123456, 'token-here', adapter=discord.RequestsWebhookAdapter())
webhook.send('Hello World', username='Foo')
# after
webhook = discord.SyncWebhook.partial(123456, 'token-here')
webhook.send('Hello World', username='Foo')
以下の破壊的変更が行われました。
WebhookとWebhookMessageの同期的な機能がWebhookとWebhookMessageに分離されました。WebhookAdapterクラスが削除され、それに基づくインターフェイス(WebhookAdapterとRequestsWebhookAdapter)は実装の詳細とみなされるようになりました。これらに依存してはいけません。Webhook.send()/SyncWebhook.send()のexecuteエイリアスが削除されました。
Assetのリデザインと変更¶
Asset オブジェクトにCDNアセットに関連する全てのメソッドと属性が含まれるようになりました。
これはアセット関連の属性とメソッドを持つ全てのモデルがこの新しいデザインを使用するように変えられたことを意味します。例として、( Asset 型の) Guild.icon がどのように変更されたかを以下に示します:
Guild.icon(str型)はGuild.icon.keyに置き換えられました。Guild.is_icon_animatedはGuild.icon.is_animatedに置き換えられました。Guild.icon_urlはGuild.iconに置き換えられました。Guild.icon_url_asはGuild.icon.replaceに置き換えられました。Asset.with_size()、Asset.with_format()、Asset.with_static_format()ヘルパーメソッドも追加されました。
これに加えて、 Emoji と PartialEmoji も Asset のようなインターフェイスを共有するようになりました。
Emoji.url_asは削除されました。Emoji.url.readはEmoji.read()に置き換えられました。Emoji.url.saveはEmoji.save()に置き換えられました。
Asset は実際に存在するCDNアセットを常に表すようになりました。 つまり:
Assetのstr(x)は空の文字列を返せなくなりました。Assetのbool(x)はFalseを返せなくなりました。Optionalな
Assetを含む属性はNoneになることがあります。
以下がこの影響を受けました:
-
AppInfo.cover_image(AppInfo.cover_image.keyに置き換えられました)AppInfo.cover_image_url(AppInfo.cover_imageに置き換えられました)新しい属性は
Noneになることがあります。
AppInfo.cover_image_url_as(AppInfo.cover_image.replaceへ置き換えられました)
-
AppInfo.icon(AppInfo.icon.keyに置き換えられました)AppInfo.icon_url(AppInfo.iconに置き換えられました)新しい属性は
Noneになることがあります。
AppInfo.icon_url_as(AppInfo.icon.replaceに置き換えられました)
-
AuditLogDiff.avatarはAsset型になりました。AuditLogDiff.iconはAsset型になりました。AuditLogDiff.splashはAsset型になりました。
-
Emoji.url_asは削除されました。Emoji.url.read(Emoji.read()に置き換えられました)Emoji.url.save(Emoji.save()に置き換えられました)
-
GroupChannel.icon(GroupChannel.icon.keyに置き換えられました)GroupChannel.icon_url(GroupChannel.iconに置き換えられました)新しい属性は
Noneになることがあります。
GroupChannel.icon_url_as(GroupChannel.icon.replaceに置き換えられました)
-
Guild.banner(Guild.banner.keyに置き換えられました)Guild.banner_url(Guild.bannerに置き換えられました)新しい属性は
Noneになることがあります。
Guild.banner_url_as(Guild.banner.replaceに置き換えられました)
-
Guild.discovery_splash(Guild.discovery_splash.keyに置き換えられました)Guild.discovery_splash_url(Guild.discovery_splashに置き換えられました)新しい属性は
Noneになることがあります。
Guild.discovery_splash_url_as(Guild.discovery_splash.replaceに置き換えられました)
-
Guild.icon(Guild.icon.keyに置き換えられました)Guild.is_icon_animated(Guild.icon.is_animatedに置き換えられました)Guild.icon_url(Guild.iconに置き換えられました)新しい属性は
Noneになることがあります。
Guild.icon_url_as(Guild.icon.replaceに置き換えられました)
-
Guild.splash(Guild.splash.keyに置き換えられました)Guild.splash_url(Guild.splashに置き換えられました)新しい属性は
Noneになることがあります。
Guild.splash_url_as(Guild.splash.replaceに置き換えられました)
-
Member.avatar(Member.avatar.keyに置き換えられました)Member.is_avatar_animated(Member.avatar.is_animatedに置き換えられました)Member.avatar_url(Member.avatarに置き換えられました)新しい属性は
Noneになることがあります。
Member.avatar_url_as(Member.avatar.replaceに置き換えられました)
-
Member.default_avatar(Member.default_avatar.keyに置き換えられました)Member.default_avatar_url(Member.default_avatarに置き換えられました)Member.default_avatar_url_as(Member.default_avatar.replaceに置き換えられました)
-
PartialEmoji.urlはstr型になりました。PartialEmoji.url_asは削除されました。PartialEmoji.url.read(PartialEmoji.read()に置き換えられました)PartialEmoji.url.save(PartialEmoji.save()に置き換えられました)
-
PartialInviteGuild.banner(PartialInviteGuild.banner.keyに置き換えられました)PartialInviteGuild.banner_url(PartialInviteGuild.bannerに置き換えられました)新しい属性は
Noneになることがあります。
PartialInviteGuild.banner_url_as(PartialInviteGuild.banner.replaceに置き換えられました)
-
PartialInviteGuild.icon(PartialInviteGuild.icon.keyに置き換えられました)PartialInviteGuild.is_icon_animated(PartialInviteGuild.icon.is_animatedに置き換えられました)PartialInviteGuild.icon_url(PartialInviteGuild.iconに置き換えられました)新しい属性は
Noneになることがあります。
PartialInviteGuild.icon_url_as(PartialInviteGuild.icon.replaceに置き換えられました)
-
PartialInviteGuild.splash(PartialInviteGuild.splash.keyに置き換えられました)PartialInviteGuild.splash_url(PartialInviteGuild.splashに置き換えられました)新しい属性は
Noneになることがあります。
PartialInviteGuild.splash_url_as(PartialInviteGuild.splash.replaceに置き換えられました)
-
Team.icon(Team.icon.keyに置き換えられました)Team.icon_url(Team.iconに置き換えられました)新しい属性は
Noneになることがあります。
Team.icon_url_as(Team.icon.replaceに置き換えられました)
-
User.avatar(User.avatar.keyに置き換えられました)User.is_avatar_animated(User.avatar.is_animatedに置き換えられました)User.avatar_url(User.avatarに置き換えられました)新しい属性は
Noneになることがあります。
User.avatar_url_as(User.avatar.replaceに置き換えられました)
-
User.default_avatar(User.default_avatar.keyに置き換えられました)User.default_avatar_url(User.default_avatarに置き換えられました)User.default_avatar_url_as(User.default_avatar.replaceに置き換えられました)
-
Webhook.avatar(Webhook.avatar.keyに置き換えられました)Webhook.avatar_url(Webhook.avatarに置き換えられました)新しい属性は
Noneになることがあります。
Webhook.avatar_url_as(Webhook.avatar.replaceに置き換えられました)
スレッドのサポート¶
スレッドをサポートする新しいAPIゲートウェイバージョンを使用するためにv2.0が更新され、その結果いくつかの破壊的変更が必要になりました。最も注目すべきは、 ギルド内で送信されるメッセージは TextChannel に加えて Thread でも送信できる点です。
テキストチャンネルとスレッドの主な違いは以下の通りです:
スレッドには固有の権限はありません。親チャンネルの権限を継承します。
これはスレッドにこれらの属性がないことを意味します:
changed_rolesoverwritespermissions_synced
注釈
テキストチャンネルにはスレッド専用の権限がいくつかあります:
スレッドは固有の年齢制限ステータスを持っていません。親チャンネルを継承します。
これは
Threadにnsfw属性がないことを意味します。
スレッドには固有のトピックがありません。
これは
Threadにtopic属性がないことを意味します。
スレッドはチャンネルリストに固有の位置を持っていません。
これは
Threadにposition属性がないことを意味します。
2022年1月10日より前に作成されたスレッドの
Thread.created_atはNoneです。Thread.membersは List[Member] ではなく、 List[ThreadMember] 型です。ほとんどの場合このデータは提供されず、
Thread.fetch_members()の呼び出しが必要になります。
便宜上、 Thread には親チャンネルに関する情報を返す一連のプロパティとメソッドがあります。
-
これは親チャンネルの権限を出力し、メンバーがなにかできるかどうかを判断するときに異なる権限をチェックする必要があるかもしれないことに注意してください。
次にいくつかの注目すべき例を示します:
ギルドメンバーは
send_messages権限を持っている場合にテキストチャンネルでメッセージを送信できます。- ギルドメンバーは以下の場合に公開スレッドでメッセージを送信できます:
親チャンネルで
send_messages_in_threads権限がある場合。スレッドが
lockedでない場合。
- ギルドメンバーは以下の場合にプライベートスレッドでメッセージを送信できます:
親チャンネルで
send_messages_in_threads権限がある場合。すでにスレッドのメンバーであるか、 親チャンネルで
manage_threads権限を持っている場合。スレッドが
lockedでない場合。
ギルドメンバーは
manage_channels権限を持っている場合テキストチャンネルを編集できます。ギルドメンバーは、親チャンネルで
manage_threads権限がある場合スレッドを編集できます。注釈
スレッドの
ownerは(ロックされていない)スレッドをアーカイブし、nameとauto_archive_durationをmanage_threads権限なしで編集できます。- ギルドメンバーは、以下の場合にテキストチャンネル内のメッセージに絵文字でリアクションすることができます:
read_message_history権限を持っているとき。add_reactions権限を持っているか、またはメッセージにすでにその絵文字のリアクションがついているとき。
- ギルドメンバーは以下の場合に公開スレッドのメッセージに絵文字でリアクションすることができます:
read_message_history権限を親チャンネルで持っているとき。親チャンネルで
add_reactions権限を持っているか、メッセージにすでにその絵文字のリアクションがついているとき。スレッドが
archivedでないとき。ギルドメンバーはメッセージにリアクションするためにスレッドを(lockedでない場合) アーカイブ解除することができます。
- ギルドメンバーは以下の場合にプライベートスレッドのメッセージにリアクションをつけることができます:
read_message_history権限を親チャンネルで持っているとき。親チャンネルで
add_reactions権限を持っているか、メッセージにすでにその絵文字のリアクションがついているとき。すでにスレッドのメンバーであるか、 親チャンネルで
manage_threads権限を持っている場合。スレッドが
archivedでないとき。ギルドメンバーはメッセージにリアクションするためにスレッドを(lockedでない場合) アーカイブ解除することができます。
以下のように変更されました:
Message.channelはThreadになるかもしれません。Message.channel_mentionsにThreadが含まれるかもしれません。AuditLogEntry.targetがThreadになりうるようになりました。PartialMessage.channelがThreadになるようになりました。Guild.get_channelはThreadを返しません。チャンネルやスレッドを取得したい場合は、代わりに
Guild.get_channel_or_threadを使用してください。スレッドを取得したい場合は、
Guild.get_threadまたはTextChannel.get_threadを代わりに使用してください。
on_guild_channel_pins_update()のパラメータchannelはThreadになるかもしれません。on_typing()のパラメータchannelはThreadになるかもしれません。Client.fetch_channel()がThreadも返すようになりました。Client.get_channel()がThreadも返すようになりました。Guild.fetch_channel()がThreadも返すようになりました。
編集時の置換を廃止¶
モデル内のデータを直接置き換えて編集していたメソッドのほとんどが、そうしないよう更新されました。代わりに、こうしたメソッドは更新された新しいモデルを返すように変更されました。これは、置換編集とモデル更新のゲートウェイイベントの競合を解消するために行われました。詳細については、 GH-4098 を確認してください。
簡単な例:
# before
await member.edit(nick='new nick')
await member.send(f'Your new nick is {member.nick}')
# after
updated_member = await member.edit(nick='new nick')
await member.send(f'Your new nick is {updated_member.nick}')
以下のように変更されました。
-
編集が位置のみの場合、
CategoryChannelの代わりにNoneを返すことに注意してください。
-
特定の属性が更新された場合にのみ、更新された
Memberを返すことに注意してください。
-
編集が位置のみの場合、
StageChannelの代わりにNoneを返すことに注意してください。
-
編集が位置のみの場合、
TextChannelの代わりにNoneを返すことに注意してください。
-
編集が位置のみの場合、
VoiceChannelの代わりにNoneを返すことに注意してください。
スタンプの変更¶
Discordがスタンプの動作を変更したため、スタンプのサポートが見直されました。
以下の破壊的変更が行われました。
Message.stickersの型は List[StickerItem]に変更されました。StickerItemからStickerを取得するには、StickerItem.fetch()または (ボットが参加しているギルドのスタンプのみ)Client.get_sticker()を使用します。
Sticker.formatはStickerFormatType型になりました。Sticker.tagsは削除されました。スタンプの種類に応じて、
StandardSticker.tagsまたはGuildSticker.emojiを使用できます。
Sticker.imageと関連するメソッドは削除されました。Sticker.preview_imageと関連するメソッドは削除されました。AuditLogDiff.typeは Union[ChannelType,StickerType] 型になりました。旧
StickerType列挙型はStickerFormatTypeに改名されました。StickerTypeは、今後はフォーマットではなく、スタンプのタイプ (公式のスタンプか、ギルドごとにアップロードされたスタンプか) を示します。
連携サービスの変更¶
新しいインテグレーションの種類をサポートするため、インテグレーションのサポートがやり直されました。
以下の破壊的変更が行われました。
以前の
IntegrationクラスはStreamIntegrationに改名されました。Guild.integrations()は、新しいIntegrationクラスのサブクラスを返すようになりました。
プレゼンスのアップデートが個別のイベントに変更¶
プレゼンスのアップデート (メンバーのステータスとアクティビティの変化) は、 on_presence_update() という別のイベントで扱われるようになりました。 on_member_update() イベントは、今後はメンバーのアップデート (ニックネーム、ロール、ペンディング状態の変化) の場合のみ呼び出されます。
APIからすると、これらは個別のイベントなので、この変更はAPIとライブラリーとの一致度を改善します。プレゼンスのアップデートは多くの場合扱われるイベントの90%を占めているので、分割は、メンバーアップデートのみ必要なリスナーに利益をもたらすはずです。
簡単な例:
# before
@client.event
async def on_member_update(self, before, after):
if before.nick != after.nick:
await nick_changed(before, after)
if before.status != after.status:
await status_changed(before, after)
# after
@client.event
async def on_member_update(self, before, after):
if before.nick != after.nick:
await nick_changed(before, after)
@client.event
async def on_presence_update(self, before, after):
if before.status != after.status:
await status_changed(before, after)
カスタム AsyncIterator からの移行¶
v1.0の非同期イテレータは、AsyncIterator というクラスを使用して実装されました。
v2.0は代わりに、ユーティリティメソッドを追加しない通常の非同期イテレータを提供します
つまり、以下のユーティリティメソッドを使用することはできなくなります。
AsyncIterator.next()明示的な
async forループの使用が一般的に推奨されます。# before it = channel.history() while True: try: message = await self.next() except discord.NoMoreItems: break print(f'Found message with ID {message.id}') # after async for message in channel.history(): print(f'Found message with ID {message.id}')
ループなしにイテレータから次のアイテムを取得する必要がある場合には、
anext()(Python 3.10で追加) か__anext__()を代わりに使用できます。# before it = channel.history() first = await it.next() if first.content == 'do not iterate': return async for message in it: ... # after it = channel.history() first = await anext(it) # await it.__anext__() on Python<3.10 if first.content == 'do not iterate': return async for message in it: ...
AsyncIterator.get()# before msg = await channel.history().get(author__name='Dave') # after msg = await discord.utils.get(channel.history(), author__name='Dave')
AsyncIterator.find()def predicate(event): return event.reason is not None # before event = await guild.audit_logs().find(predicate) # after event = await discord.utils.find(predicate, guild.audit_logs())
AsyncIterator.flatten()# before users = await reaction.users().flatten() # after users = [user async for user in reaction.users()]
AsyncIterator.chunk()# before async for leader, *users in reaction.users().chunk(3): ... # after async for leader, *users in discord.utils.as_chunks(reaction.users(), 3): ...
AsyncIterator.map()# before content_of_messages = [] async for content in channel.history().map(lambda m: m.content): content_of_messages.append(content) # after content_of_messages = [message.content async for message in channel.history()]
AsyncIterator.filter()def predicate(message): return not message.author.bot # before user_messages = [] async for message in channel.history().filter(lambda m: not m.author.bot): user_messages.append(message) # after user_messages = [message async for message in channel.history() if not m.author.bot]
この移行を容易にするために、次の変更が行われました:
AsyncIter.chunkの代わりとしてutils.as_chunks()が追加されました。utils.find()に asynchronous iterator がサポートされました。utils.get()に asynchronous iterator がサポートされました。
以下のメソッドの戻り値の型が asynchronous iterator に変更されました。
変更によって asynchronous iterator に対して anext() や __anext__() を呼び出すと StopAsyncIteration が発生するようになったため、 NoMoreItems 例外は削除されました。
特定のリストを遅延評価シーケンスに変更¶
リストの長さを計算するときのパフォーマンスを向上させるために、特定の属性が list ではなくシーケンスを返すように変更されました。
シーケンスは list と似ていますが読み込み専用です。これをリストに戻すには返されたシーケンスに対し list を呼び出せばよいです。
以下のプロパティは、リストの代わりにシーケンスを返すように変更されました:
list.append のようにシーケンスを変更しない限り、この変更は影響を与えないでしょう。
埋め込みの変更¶
以前は、埋め込みは属性が空であったり、属性の表示を除去することを示すのに、特別なセンチネルを使用していました。この Embed.Empty センチネルはDiscordの埋め込みの設計が漠然とし変化していた状態にあったときにできました。その後、埋め込みの設計は安定化したため、このセンチネルは過去のものとされてきました。
このため、 Embed.Empty は、 None に置き換えられ削除されました。
さらに、 Embed.__eq__ が実装されたため、埋め込みがハッシュ化できなくなりました。 (例えば、集合型や辞書型キーで使用できなくなりました)
# before
embed = discord.Embed(title='foo')
embed.title = discord.Embed.Empty
embed == embed.copy() # False
# after
embed = discord.Embed(title='foo')
embed.title = None
embed == embed.copy() # True
{embed, embed} # Raises TypeError
InvalidArgument 例外の削除¶
カスタム例外 InvalidArgument は削除され、これを発生させていた関数やメソッドは、代わりに TypeError や ValueError を発生させるようになりました。
以下のメソッドが変更されました:
ログの変更¶
ライブラリは Client.run() を使用した場合にデフォルトの logging 構成を提供するようになりました。無効化するには、 log_handler キーワード引数に None を渡してください。ライブラリがデフォルトでログ設定を提供するようになったため、次のメソッドは sys.stderr に出力せず、ロガーを使用するように変更されました。
詳しくは、 ログの設定 を確認してください。
ボイスチャンネル チャット¶
ボイスチャンネル チャット機能に対応するために、いくつかの変更が行われました:
VoiceChannelがabc.Messageableになり、メッセージの送受信ができるようになりました。Message.channelはVoiceChannelになるかもしれません。
将来的には、Discordが実装する際に、 StageChannel でも同様の変更が行われるかもしれません。
StoreChannel の削除¶
DiscordのAPIは、 2022年3月10日 をもって、ストアチャンネルを削除しました。そのため、ライブラリもそれに対するサポートを削除しました。
これにより、以下が削除されます。
StoreChannelcommands.StoreChannelConverterChannelType.store
Guild.bans エンドポイントの変更¶
Discord APIの破壊的変更のため、 Guild.bans() はギルドのすべてのBANのリストを返さなくなり、代わりに非同期イテレータを用いてページ化されるようになりました。
# before
bans = await guild.bans()
# after
async for ban in guild.bans(limit=1000):
...
フラグのクラスにカスタムの bool() 実装を追加¶
ライブラリユーザーがフラグクラスのインスタンスに何らかのフラグが立っているかどうかを確認しやすくするために、 bool を使用するとフラグが最低一個有効の場合に True を返すようにしました。
つまり、 真偽値の文脈 (例えば if obj:) で次のクラスのインスタンスを評価するとき、 True が返されない可能性があります:
関数シグネチャの変更¶
以下のメソッドの引数は全て位置限定になりました:
以下の引数が位置限定になりました:
utils.get()のiterableClient.on_error()のevent_methodClient.wait_for()のevent
以下はキーワード限定になりました:
Reaction.users()の引数utils.oauth_url()のpermissions,guild,redirect_uri,scopes引数utils.snowflake_time()のhigh引数
ライブラリは関数/メソッドの引数のデフォルト値として None を使用することが少なくなりました。
その結果、 これらの引数は None にはならなくなりました:
Asset.replace()のsize,format,static_formatTextChannel.purge()のcheckClient.create_guild()のiconとcodeEmoji.edit()のrolesGuild.create_text_channel()のtopic,position,overwritesGuild.create_voice_channel()のpositionとoverwritesGuild.create_voice_channel()のtopic,position,overwritesGuild.create_category()のpositionとoverwritesGuild.prune_members()のrolesGuild.estimate_pruned_members()のrolesGuild.create_template()のdescriptionGuild.create_custom_emoji()のrolesGuild.audit_logs()のbefore,after,oldest_first,user,actionStreamIntegration.edit()のenable_emoticonsMember.edit()のmute,deafen,suppress,rolesRole.edit()のpositionTemplate.create_guild()のiconTemplate.edit()のnameutils.oauth_url()のpermissions,guild,redirect_uri,scopesWebhook.send()のcontent,username,avatar_url,tts,file,files,embed,embeds,allowed_mentions
以下の引数で受け取られる型が変更されました:
Guild.create_voice_channel()のrtc_regionは Optional[str] 型になりました。StageChannel.edit()のrtc_regionは Optional[str] 型になりました。VoiceChannel.edit()のrtc_regionは Optional[str] 型になりました。Guild.edit()のpreferred_localeはLocale型になりました。
属性の型の変更¶
以下のように変更されました:
DMChannel.recipientがNoneになりうるようになりました。Guild.vanity_invite()がNoneを返しうるようになりました。これはこのメソッドが壊れたInviteオブジェクトを返す問題を解決するために行われました。Widget.fetch_invite()がNoneを返しうるようになりました。AutoShardedClientが使われていない場合、Guild.shard_idはNoneの代わりに0になるようになりました。Guild.mfa_levelはMFALevel型に変更されました。Guild.member_countの型が Optional[int] に変更されました。AuditLogDiff.mfa_levelはMFALevel型に変更されました。AuditLogDiff.rtc_regionはstr型に変更されました。StageChannel.rtc_regionはstr型に変更されました。VoiceChannel.rtc_regionはstr型になりました。ClientUser.avatarは、デフォルトのアバターが利用されている場合はNoneに変更されました。ユーザーの表示されているアバターを取得したい場合は、
ClientUser.display_avatarを検討してください。
Member.avatarは、デフォルトのアバターが使用されている場合はNoneに変更されました。メンバーやユーザーが表示しているアバターを取得したい場合は、
Member.display_avatarまたはUser.display_avatarを検討してください。
User.avatarは、デフォルトのアバターが利用されている場合はNoneに変更されました。ユーザーが表示しているアバターを取得したい場合は、
User.display_avatarを検討してください。
Webhook.avatarは、デフォルトのアバターが利用されている場合はNoneに変更されました。Webhookに表示されるアバターを取得したい場合は、
Webhook.display_avatarを検討してください。
AuditLogEntry.targetがPartialMessageableになりうるようになりました。PartialMessage.channelがPartialMessageableになりうるようになりました。Guild.preferred_localeの型がLocaleになりました。abc.GuildChannel.overwritesのキーがObjectになりうるようになりました。
削除¶
以下の非推奨の機能は削除されました。
Client.request_offline_members代わりに
Guild.chunk()を使用してください。
AutoShardedClient.request_offline_members代わりに
Guild.chunk()を使用してください。
Client.logout代わりに
Client.close()を使用してください。
Clientコンストラクタのfetch_offline_membersパラメータ代わりに
chunk_guild_at_startupを使用してください。
Permissions.use_slash_commandsとPermissionOverwrite.use_slash_commands代わりに
Permissions.use_application_commandsとPermissionOverwrite.use_application_commandsを使用してください。
以下の機能は削除されました。
MemberCacheFlags.online置換先はありません。現在のAPIバージョンは、このために必要な十分なデータを提供しません。
AppInfo.summaryこの項目を置き換えることはできません。現在の API バージョンではこの項目は提供されません。
User.permissions_inとMember.permissions_in代わりに
abc.GuildChannel.permissions_for()を使用してください。
Clientコンストラクタのguild_subscriptionsパラメータ現在の API バージョンはこの機能を提供していません。代わりに
intentsパラメーターを使用してください。
VerificationLevelのエイリアスVerificationLevel.table_flip- 代わりにVerificationLevel.highを使用してください。VerificationLevel.extreme- 代わりにVerificationLevel.highestを使用してください。VerificationLevel.double_table_flip- 代わりにVerificationLevel.highestを使用してください。VerificationLevel.very_high- 代わりにVerificationLevel.highestを利用してください。
StageChannel.edit()のtopicパラメータtopicパラメーターはStageChannel.create_instance()で設定する必要があります。
Reaction.custom_emoji代わりに
Reaction.is_custom_emoji()を使用してください。
AuditLogDiff.regionGuild.regionVoiceRegionこれはDiscordより非推奨とされていて、また追加されたペースが速いため多くの場合で反映するのが遅れていました。
Client.create_guild()のregionパラメータTemplate.create_guild()のregionパラメータGuild.edit()のregionパラメータon_private_channel_createイベントDiscord APIは、DMにはチャンネル作成イベントを送信しないようになりました。
on_private_channel_deleteイベントDiscord APIは、DMにはチャンネル作成イベントを送信しないようになりました。
文書化されていないプライベートな
on_socket_responseイベント代わりに、より新しくドキュメント化された
on_socket_event_type()イベントを使用することを検討してください。
abc.Messageable.trigger_typing代わりに
abc.Messageable.typing()をawaitしてください。
その他の変更点¶
以下のように変更されました:
Clientにenable_debug_eventsが設定されている場合にのみon_socket_raw_receive()が呼び出されるようになりました。on_socket_raw_receive()は 完全な メッセージを受信して解凍した後にのみ呼び出されるようになりました。渡されたmsgパラメータは 常にstrになりました。Clientにenable_debug_eventsが設定されている場合にのみon_socket_raw_send()が呼び出されるようになりました。文書化された
Guild.fetch_channels()の戻り値の型は Sequence[abc.GuildChannel] に変更されました。utils.resolve_invite()がResolvedInviteクラスを返すようになりました。utils.oauth_url()のスコープが与えられていない場合の初期値がbotからbotとapplications.commandsに変更されました。abc.Messageable.typing()は、通常の(非同期でない)コンテキストマネージャーとしては使用できなくなりました。Intents.emojisがIntents.emojis_and_stickersのエイリアスになりました。これは、このクラスのインスタンス内の
(name, value)ペアをイテレートするコードに影響を与える可能性があります。# before friendly_names = { ..., 'emojis': 'Emojis Intent', ..., } for name, value in discord.Intents.all(): print(f'{friendly_names[name]}: {value}') # after friendly_names = { ..., 'emojis_and_stickers': 'Emojis Intent', ..., } for name, value in discord.Intents.all(): print(f'{friendly_names[name]}: {value}')
created_atはabc.Snowflakeの一部ではなくなりました。既存のすべてのクラスは、この属性を保持します。ただ、このプロトコルの一部ではなくなりました。これは、DiscordがいくつかのモデルのID(snowflake)を他のモデルで再利用するために行われました。例えば、あるメッセージから
Threadが作成された場合、そのThread.idはそのメッセージの ID と同じで、スレッドの作成時刻に関する情報は含まれず、Thread.created_atに基づいて作成することはできません。Embedの bool 実装では、埋め込みに何らかのデータが設定されていればTrueが返されるようになりました。Emoji.edit()をroles引数なしで呼び出したときに、絵文字が全員に利用できるようにならなくなりました。絵文字を誰でも利用できるようにするには、空のリストを
rolesに渡してください。
古い
Colour.blurpleはColour.og_blurpleに改名されました。Colour.blurpleは別の色を参照するようになりました。
メッセージが返信である場合、
Message.typeがMessageType.replyに設定されるようになりました。これは、現在のDiscordAPIバージョンでの動作の違いによって引き起こされます。
Message.edit()はallowed_mentionsパラメータで渡されたオブジェクトをClient.allowed_mentionsと合わせるようになりました。このパラメータが指定されていない場合は、代わりにClient.allowed_mentionsで指定されたデフォルト値が使用されます。Permissions.stage_moderator()にPermissions.manage_channels権限が含まれるようになり、Permissions.request_to_speak権限が含まれなくなりました。File.filenameがNoneになることはなくなりました。以前そうなった場合ではファイル名は'untitled'になります。Message.applicationが生のAPIペイロードのdictではなくなり、MessageApplicationインスタンスを返すようになりました。
VoiceProtocol.connect() のシグネチャ変更¶
VoiceProtocol.connect() に、 self_deaf と self_mute キーワード引数が渡されるようになりました。これはクライアントがボイスチャットに参加する際にスピーカーミュートし、またはミュートすべきかを示します。
コマンド拡張の変更¶
エクステンションとコグの読み込み・解除の非同期化¶
asyncio の変更 に伴い、エクステンションとコグの読み込みや読み込み解除が非同期処理となりました。
これに対応するために、以下のように変更が行われました:
エクステンションの
setupとteardown関数はコルーチンでないといけません。ext.commands.Bot.load_extension()を呼び出すときには await が必要です。ext.commands.Bot.unload_extension()を呼び出すときには await が必要です。ext.commands.Bot.reload_extension()を呼び出すときには await が必要です。ext.commands.Bot.add_cog()を呼び出すときには await が必要です。ext.commands.Bot.remove_cog()を呼び出すときには await が必要です。
エクステンションのセットアップの簡単な例:
# before
def setup(bot):
bot.add_cog(MyCog(bot))
# after
async def setup(bot):
await bot.add_cog(MyCog(bot))
エクステンションの読み込みの簡単な例:
# before
bot.load_extension('my_extension')
# after using setup_hook
class MyBot(commands.Bot):
async def setup_hook(self):
await self.load_extension('my_extension')
# after using async_with
async def main():
async with bot:
await bot.load_extension('my_extension')
await bot.start(TOKEN)
asyncio.run(main())
コンバータの汎用ランタイムプロトコル化¶
Converter が runtime-checkable な typing.Protocol になりました。
その結果、これらのクラスで使用されるベースメタクラスが変更され、 Converter を継承するユーザーが作成したクラスに影響を与える可能性があります。
簡単な例:
# before
class SomeConverterMeta(type):
...
class SomeConverter(commands.Converter, metaclass=SomeConverterMeta):
...
# after
class SomeConverterMeta(type(commands.Converter)):
...
class SomeConverter(commands.Converter, metaclass=SomeConverterMeta):
...
さらに、 Converter は typing.Generic になり、ユーザーは(自己判断で)型ヒントをより正確に定義することができます。
関数シグネチャの変更¶
以下のメソッドの引数は全て位置限定になりました:
以下の引数が位置限定になりました:
ext.commands.Bot.check()のfuncext.commands.Bot.add_check()のfuncext.commands.Bot.get_context()のmessageext.commands.Command.__call__()のcontextext.commands.HelpCommand.filter_commands()のcommandsext.commands.DefaultHelpCommand.add_indented_commands()のcommandsext.commands.Bot.get_cog()のnameext.commands.Context.invoke()のcommandext.commands.GroupMixin.add_command()のcommand
以下のパラメータは削除されました。
Botのself_botこれは ユーザーアカウント(セルフボット)のサポートの削除 の変更によって行われました。
ライブラリは関数/メソッドの引数のデフォルト値として None を使用することが少なくなりました。
その結果、 これらの引数は None にはならなくなりました:
ext.commands.Bot.listen()のnameext.commands.Cog.listener()のnameext.commands.Command()のnameext.commands.command()のnameとclsext.commands.group()のnameとcls
削除¶
以下の属性が削除されました:
ExtensionNotFoundのoriginalext.commands.CommandOnCooldown.cooldownから提供されていたCooldownクラスのtype代わりに
ext.commands.CommandOnCooldown.typeを使用してください。
HelpCommandのclean_prefix代わりに
ext.commands.Context.clean_prefixを使用してください。
その他の変更点¶
ext.commands.Bot.add_cog()は、同名のコグがすでに読み込まれている場合にはClientExceptionを送出するようになりました。コグを上書きするには、新しい
overrideパラメータが使用できます。
cooldown()のtype引数に呼び出し可能な引数を渡す場合、Messageではなく、Contextを引数として受け付けないといけないようになりました。Contextのメタクラスがabc.ABCMetaからtypeへと変更されました。ext.commands.Command.clean_paramsの型をcollections.OrderedDictからPython 3.7以降で追加順が必ず保持されるdictに変更しました。スレッドのサポート の変更により、
ext.commands.ChannelNotReadable.argumentはThreadになる可能性があります。スレッドのサポート の変更により、
ext.commands.NSFWChannelRequired.channelはThreadになる可能性があります。スレッドのサポート の変更により、
ext.commands.Context.channelはThreadになる可能性があります。ext.commands.Context.channelがPartialMessageableになりうるようになりました。MissingPermissions.missing_permsはext.commands.MissingPermissions.missing_permissionsへと名前が変更されました。BotMissingPermissions.missing_permsはext.commands.BotMissingPermissions.missing_permissionsへと名前が変更されました。ext.commands.Cog.cog_load()が、 エクステンションとコグの読み込み・解除の非同期化 の変更に伴って追加されました。ext.commands.Cog.cog_unload()は、 エクステンションとコグの読み込み・解除の非同期化 のため coroutine になることができるようになりました。ext.commands.Command.clean_params型は既定値を扱うためカスタムinspect.Parameterを使用するようになりました。
タスク拡張機能の変更¶
stop()をbefore_loop()で呼び出すと、最初のイテレーションが実行されなくなりました。ext.tasks.Loop.change_interval()を呼び出すと、次のループの繰り返しの時ではなく、直ちにスリープ時間の間隔が変更されるようになりました。ext.tasks.loop()のパラメーターloopにNoneを渡せなくなりました。
v1.0への移行¶
この移行に関する内容は v1.0への移行 に移動されました。