バージョン 1.5 で追加.

ゲートウェイインテント入門

バージョン1.5では Intents が導入されました。これにより、Botの書き方が根本的に変わります。基本的にインテントは、特定のイベント群をBotにサブスクライブさせるためのものです。各インテントに対応するイベントは、 Intents のドキュメントに個別の属性として記載されています。

インテントは intents 引数を介して Client またはそのサブクラス(AutoShardedClient, AutoShardedBot, Bot)のコンストラクタに渡されます。

どのインテントが必要でしょうか?

あなたのBotに必要なインテントは、あなたにしかわかりません。 Intents クラスのドキュメントの各属性欄には、どの events に対応し、どのようなキャッシュを有効化するのか記述されています。

たとえば、プレゼンスやタイピングといったわずらわしいイベント抜きに動作するbotを書きたい場合、次のようにします。

 import discord
 intents = discord.Intents.default()
 intents.typing = False
 intents.presences = False

 # Somewhere else:
 # client = discord.Client(intents=intents)
 # or
 # from discord.ext import commands
 # bot = commands.Bot(command_prefix='!', intents=intents)

なお、特権インテントであるため、 Intents.members は有効になりません。

別の例: メッセージとギルド情報だけを扱うボット:

 import discord
 intents = discord.Intents(messages=True, guilds=True)
 # If you also want reaction events enable the following:
 # intents.reactions = True

 # Somewhere else:
 # client = discord.Client(intents=intents)
 # or
 # from discord.ext import commands
 # bot = commands.Bot(command_prefix='!', intents=intents)

特権インテント

API変更に伴い、Bot製作者がインテントを指定する必要が生じました。いくつかのインテントはより制約され、手動での設定を必要とするようになりました。これらのインテントを 特権インテント と呼びます。

特権インテントは、開発者ポータルで手動で有効にしなければならないインテントです。有効化の手順は以下のとおりです。

  1. まずは Discordのウェブサイト にログインしてください。

  2. アプリケーションページ に移動します。

  3. 特権インテントを有効にしたいBotをクリックします。

  4. 画面の左側にあるBotタブに移動します。

    アプリケーションページの「bot」タブ
  5. 「特権ゲートウェイインテント」セクションまでスクロールし、必要なものを有効にします。

    特権ゲートウェイのセレクタ

警告

もしあなたのBotが100以上のギルドで利用されているなら、特権インテントを有効化するために bot verification が必要です。すでに認証済みのBotで特権インテントを有効化したい場合、 Discord support で報告してください。

注釈

開発者ポータルでインテントを有効化した後は、コード内でインテントを有効化しましょう。

特権インテントは必要ですか?

それぞれの特権インテントが必要かどうかを確認する簡単なチェックリストを用意しました。

プレゼンスインテント

メンバーインテント

  • メンバーの参加や退出を追跡するかどうか。それぞれ on_member_join()on_member_remove() イベントが対応します。

  • ニックネームやロールの変更など、メンバーの更新を追跡するかどうか。

  • ユーザー名、アバター、識別子などのユーザーの更新を追跡するかどうか。

  • Guild.chunk()Guild.fetch_members() でギルドメンバーリストをリクエストするかどうか。

  • Guild.members で高精度メンバーキャッシュを使用するかどうか。

メッセージ内容のインテント

  • メッセージの内容を確認するために Message.content を使用するかどうか。

  • メッセージの添付ファイルを確認するために Message.attachments を使用するかどうか。

  • メッセージの埋め込みを確認するために Message.embeds を使用するかどうか。

  • メッセージコンポーネントをチェックするために Message.components を使用するかどうか。

  • コマンド拡張機能をメンションなしプレフィックスで使用するかどうか。

メンバーキャッシュ

Discordは、インテントとともにメンバーをキャッシュする機能をさらに制限し、必要に応じてボット作成者がキャッシュできるようになりました。 しかし、退出したメンバーを追跡・退出させるには、適切にキャッシュを維持する Intents.members インテントが必要です。

キャッシュされる必要のないメンバーキャッシュを手伝うために、ライブラリにメンバーキャッシュを制御するための MemberCacheFlags フラグが追加されました。クラスのドキュメントページではできる限り明確なポリシーを調べることができます。

可能な限りDiscordがメンバー情報を提供するため、メンバーキャッシュを必要としないことがあります。例えば:

  • キャッシュが無効になっていても、on_message()Message.author がメンバーになります。

  • キャッシュが無効の場合でも、on_voice_state_update()member パラメータをメンバーにします。

  • on_reaction_add() は、キャッシュが無効になっている場合でもサーバー内であれば user パラメータをメンバーにします。

  • on_raw_reaction_add() は、キャッシュが無効になっていてもサーバー内にいれば RawReactionActionEvent.member がメンバーになります。

  • ダイレクトメッセージで追加されたリアクションは追加情報を含んでいません。これはDiscordの制限です。

  • リアクション削除イベントにメンバー情報はありません。これはDiscordの制限です。

Member を取るその他のイベントでは、メンバーキャッシュの使用が必要になります。メンバーキャッシュの絶対的な精度が必要な場合は、 Intents.members インテントを有効にすることをお勧めします。

メンバーの取得

キャッシュが無効になっている場合、または起動時にサーバーのチャンキングを無効にしている場合でも、membersをロードする方法が必要になる場合があります。 ライブラリには、以下の方法が用意されています。

  • Guild.query_members()
    • ニックネームまたはユーザー名の一致でメンバーを照会するために使用されます。

    • これは、ユーザーIDによってメンバーを照会するためにも使用できます。

    • これはHTTPではなくゲートウェイを使用します。

  • Guild.chunk()
    • これはゲートウェイからメンバーリスト全体を取得するために使用できます。

  • Guild.fetch_member()
    • HTTP APIを介してIDからメンバーを取得するために使用されます。

  • Guild.fetch_members()
    • HTTP APIを介して多数のメンバーを取得するために使用されます。

ゲートウェイには、60秒あたり120リクエストという厳格なレート制限があることに注意してください。

トラブルシューティング

強制的なインテントの変更に関連するいくつかの一般的な問題。

私のメンバーはどこに行ったのか?

APIの変更 に伴い、Discordはメンバーキャッシュを必要とする開発者に明示的なオプトインを求めるようになりました。これはDiscordが強制的に行っている変更で、これを回避する方法はありません。これを取り戻すためには、明示的に メンバー特権インテント を有効にして、 Intents.members 属性をtrueに変更する必要があります。

例:

 import discord
 intents = discord.Intents.default()
 intents.members = True

 # Somewhere else:
 # client = discord.Client(intents=intents)
 # or
 # from discord.ext import commands
 # bot = commands.Bot(command_prefix='!', intents=intents)

on_ready が発火するまでに時間がかかるのはなぜか?

インテントに関するAPIの変更の一環として、Discordは起動時のメンバーの読み込み方法も変更しました。 もともとライブラリは 75 個のギルドを一度にリクエストでき、 Guild.large 属性が True になるサーバーのみのメンバーをリクエストしました。Intentが新しく変更された場合、Discordはリクエストごとに1つのサーバーしか送信できません。 これは75倍の減速を引き起こし、大規模なサーバーだけでなく*すべての*サーバーが要求されているという事実によってさらに複雑になります。

これを修正するためにいくつかの解決策があります。

最初の解決策は、presence intentとmember intentの両方を有効にすることです。 これにより、初期メンバーリストに以前のゲートウェイと同様にオンラインメンバーを含めることができます。 我々はまだリクエストごとに1つのギルドに制限されていることに注意してください。しかし、我々がリクエストするギルドの数は大幅に減少します。

二つ目の解決方法は、クライアントを構築する際に chunk_guilds_at_startupFalse に設定することでメンバーのチャンクを無効にすることです。 サーバーのチャンキングが必要な場合は、 メンバーの取得 の様々なテクニックを使うことができます。

APIの変更によって引き起こされる減速を説明するために、840サーバーに参加していて、そのうち95サーバーは「大きい」(250人以上のメンバーがいる) というボットを使います。

元のシステムでは、メンバーリスト(75サーバーと、20サーバー)を取得するために2回のリクエストを行うと、およそ60秒かかります。 Intents.presences は使用せず Intents.members を使用した場合、840回のリクエストが必要となり、60秒あたり120回のリクエストというレート制限があるため、すべてのメンバーを取得するためにレート制限を待つ時間は合計で約7分となります。 Intents.membersIntents.presences の両方がある状況では、ほとんどが以前の動作になるので、大規模な95のギルドに対してのみリクエストする必要があることになります。これはレートリミットよりわずかに少ないので、元のシステムでメンバーリストを取得する時間と近くなります。

申し訳ありませんが、この変更はDiscordから要求されているため、ライブラリがこれを軽減するためにできることはありません。

DiscordのAPIに関する方向性が本当に嫌いなら、サポート で連絡できます。