逆引き:discord.py の詰まりどころ
discord.pyのIntent、イベント、on_message、Cog、View、asyncioまわりの実装相談を整理します。
この記事で分かること
- Portal側とコード側のIntentを両方見る
- on_messageとcommands.Botの関係を確認する
- Message ContentとMember取得を分ける
- raw event/cache/fetchを使い分ける
- Cog/extensionの読み込み単位
- View/Button/Modalのcallbackとtimeout
コミュニティの相談ログを匿名化・一般化し、discord.pyでつまずきやすい実装点を整理した逆引きです。
discord.py Intent・イベント
Portal側とコード側Intent
IntentはDeveloper Portalとコード側指定の両方を確認します。
両側を見る
Privileged IntentはDeveloper Portal側で有効化し、コード側でもdiscord.Intentsに含める必要があります。片方だけでは、イベントや本文が期待どおり届かないことがあります。
再起動まで含める
IntentやBot設定を変更した後は、BotのGateway接続を張り直します。4014 close codeや起動時warningが出ていないか、起動ログで確認します。
確認ポイント
- PortalのBotページ
- コードのdiscord.Intents
- Bot再起動
- 起動時warning
参考(公式ドキュメント)
- https://discordpy.readthedocs.io/en/stable/intents.html
- https://docs.discord.com/developers/topics/gateway
Message ContentとMember
message.contentが空、Memberが取れない時の確認です。
Message Content
メッセージ本文、添付、Embed、componentsなどはMessage Content Intentの影響を受けます。prefix commandで本文を読む設計なら、必要性と代替案を確認します。
Member
Member join/update、ロール、ニックネーム、大量取得はGuild Members Intentやcache/fetchの前提に影響されます。UserとMemberを混同しないようにします。
確認ポイント
- message.contentだけ空か確認する
- Member objectが必要か確認する
- slash commandへ移せるか見る
参考(公式ドキュメント)
- https://docs.discord.com/developers/resources/message
- https://discordpy.readthedocs.io/en/stable/intents.html
on_messageとcommands.Bot
on_messageを追加した後にprefix commandが動かない時の確認です。
処理の流れを見る
commands.Botでon_messageを自前実装すると、コマンド処理へ渡しているかを確認します。handler先頭、bot自身の除外、prefix判定、例外ログを分けます。
握りつぶさない
try/exceptで例外を消すと、反応しないように見えます。利用者への短い返信と、管理ログの例外全文を分けます。
確認ポイント
- handler先頭ログ
- bot自身の除外
- process_commandsの要否
- 例外全文
参考(公式ドキュメント)
- https://discordpy.readthedocs.io/en/stable/ext/commands/commands.html
- https://discordpy.readthedocs.io/en/stable/faq.html
raw eventとcache/fetch
過去メッセージやリアクション、Member情報をcache前提で扱わない確認です。
cache前提を見る
起動前のメッセージ、古いリアクション、未cacheのMemberは、通常イベントだけでは十分な情報がない場合があります。raw eventやfetchで補う対象を限定します。
取得できないものを分ける
削除済みメッセージやBotが見えないチャンネルの情報は取得できません。取得失敗時は、存在しない対象、権限不足、cache不足を分けてログに残します。
確認ポイント
- 対象message/channelを限定する
- raw eventを使う理由を書く
- fetch失敗を記録する
参考(公式ドキュメント)
- https://discordpy.readthedocs.io/en/stable/api.html
- https://docs.discord.com/developers/events/gateway
discord.py Cog・View・asyncio
Cogとextension読み込み
Cog、extension、setup、load_extensionで詰まる時の確認です。
読み込み単位を見る
ファイル名、extension名、setup関数、Cog class、bot.add_cogの流れを分けます。discord.py v2系では非同期setupなど、古い記事と違う点があるため対象バージョンを確認します。
起動ログに出す
読み込み失敗を握りつぶさず、どのextensionが失敗したかを起動ログに出します。reload時は未完了taskやViewの状態も確認します。
確認ポイント
- Python/discord.py版
- extension名
- setup関数
- load/reload例外
参考(公式ドキュメント)
Python環境とrequirements
ローカル、Docker、ホスティング環境でだけ起きる差を確認します。
環境を固定する
Pythonのバージョン、discord.pyのバージョン、requirements.txt、venv、Docker base imageを確認します。古い記事のpip install例や別ライブラリ名をそのまま使わないようにします。
本番ログで見る
build log、runtime log、起動コマンド、環境変数の有無を分けます。Tokenや秘密情報はログに出さず、変数名と未設定だけを確認します。
確認ポイント
- Python版
- discord.py版
- requirements.txt
- build/runtime log
参考(公式ドキュメント)
View・Button・Modal callback
UI部品のcallback、応答期限、timeoutを確認します。
callback到達を見る
Button、Select、Modalが動かない時は、callback先頭、interaction type、custom_id、押したuser、対象messageを分けます。
応答と状態
Interactionは初回応答、defer、follow-up、ephemeralを意識します。誰が押せるか、何回押せるか、timeout後にどう表示するかを決めます。
確認ポイント
- callback先頭ログ
- deferの要否
- 押せるuser
- timeout後の表示
参考(公式ドキュメント)
- https://discordpy.readthedocs.io/en/stable/interactions/api.html
- https://docs.discord.com/developers/interactions/receiving-and-responding
asyncioと通常起動
Notebookや既存loop、create_taskの誤用を切り分けます。
通常起動で確認する
Jupyter Notebookや対話環境では既にイベントループが動いていることがあります。Botはまずターミナルや本番環境で、通常の起動方法で最小構成を確認します。
taskの中身を見る
asyncio.create_taskにはコルーチンを渡します。Token文字列、通常関数、戻り値を渡すエラーは、BotのToken問題ではなく非同期処理の呼び方として切り分けます。
確認ポイント
- 最小Botで起動
- await漏れ
- create_taskの引数
- 長時間処理のdefer
参考(公式ドキュメント)
一次情報(公式ドキュメント)
- discord.py intents documentation
- Discord Developer Documentation: Gateway Intents
- Discord Developer Documentation: Message Resource
- discord.py commands extension documentation
- discord.py interactions API
- Python asyncio documentation