GIGAZINEは公式Discordサーバーを運用しており、新着記事を即時配信したり記事に関連するフォーラムを設置したりしています。公式Discordサーバーでの新着記事配信にはGIGAZINE技術部による独自開発BOT「GIGAZINE BOT」を用いており、「自分のサーバーでもGIGAZINEの記事を配信したい!」という読者のためにGIGAZINE BOTの無料公開も実施中。詳しい導入手順や使い方は以下の記事で解説しています。

DiscordでGIGAZINEの新着記事を速攻チェックできるボット「GIGAZINE BOT」の入れ方と使い方まとめ - GIGAZINE



実は、GIGAZINE BOTの開発当初は特権インテントを使用していることから登録可能サーバー数が100件までに制限されていたため、2023年9月頃から新規登録が不可能な状態が続いていました。その後、プログラムの修正やDiscord公式サポートとのやり取りを通じて2023年10月頃に制限が解除されて誰でもGIGAZINE BOTを使用可能な状態になったので、今後BOTを自作したいという人のためにGIGAZINE BOTの開発経緯や制限解除までの公式サポートとのやり取りをまとめておきます。

・目次

◆1:BOT作成

◆2:1回目の認証申請と差し戻し

◆3:特権インテント調査

◆4:認証申請再び

◆5:最後に残った特権インテント問題

◆6:解決

◆7:振り返り

◆8:GIGAZINE BOTの不具合報告について

◆1:BOT作成

「GIGAZINE BOT」は、読者の運営するサーバー上でGIGAZINEの新着記事を通知することを第一の目的としたBOTです。開発に用いた具体的な要素技術は以下の通り。

・Discordの「DEVELOPER PORTAL」上でBOTの定義・設定を行う

・Node.js + TypeScript環境でDiscord.jsを用いて作成したアプリを動作させる

・sqlite3で通知対象サーバー・チャンネルと最新記事を管理する

・それらをDockerイメージに収める

・余力のあるLinuxサーバー上でDockerコンテナを常駐させる

この段階で苦労した点といえば、ネット上のサンプルが「誰かがpingと発言するとpongと応答する」という機能しか持たないものばかりで、欲しい情報がなかなか見つからなかったことと、Discord.jsが度々破壊的変更をおこなってきたためにせっかく見つけた情報の多くが陳腐化していて役に立たなかったことぐらいです。



2022年12月にはBOTが期待通りに動作するようになったので、記事化して公開することにしました。

DiscordでGIGAZINEの新着記事を速攻チェックできるボット「GIGAZINE BOT」の入れ方と使い方まとめ - GIGAZINE

https://gigazine.net/news/20221222-discord-gigazine-bot/



◆2:1回目の認証申請と差し戻し

Discordでは「未認証BOTはサーバー登録数が最大100件に制限され、認証処理はサーバー登録数が75件を突破しないと実行できない」というBOT認証方式が採用されています。この時点で、何となくではありますが、認証を受けられるまでの敷居の高さと、そこから上限までの余裕の無さを認識し、前途に不安を覚えることになります。

2023年2月末になって、認証申請が可能になったことを告げるDiscord公式からのダイレクトメッセージが届きました。



「DEVELOPER PORTAL」を確認してみると確かに、認証処理が必要であることを告げる黄枠付きメッセージと、認証を開始するボタンが追加されています。



「Get Started」ボタンを押すと認証処理を開始するための情報入力画面が表示されました。ここでは例えば以下のように根掘り葉掘りな質問が用意されています。

・あなたのアプリケーションは何をするものなのか?

・Discordのどのデータを保存するのか?

・BOTをどのようにしてホスティングするのか?

・BOTの作成にどんな言語/ライブラリを使用しているのか?

そして、その中にこんな一行がありました。

・どの特権インテントの使用を申請するのか?

特権インテントというのはDiscordの中でも特別かつ重大な意味合いを持つ権限を指し、記事作成時点では以下の3つが定義されています。

・PRESENCE INTENT:メンバーの状態や行動を追跡可能にする

・SERVER MEMBERS INTENT:メンバーの入退室や更新を追跡可能にする

・MESSAGE CONTENT INTENT:メッセージの内容を追跡可能にする

特権インテントの導入時点では2つでしたが、将来的には更に増加する可能性があります。



これら3つの特権インテントについては、BOT作成時にウェブで調査したところ、ほぼ「とりあえず3つ全部オンにして使うようにすればいいよ」といった情報しか見当たらなかったので、それらに従ってオンにしていました。ただ、

・1つでもインテントの使用を申請すると、鬼のように質問項目が増える(3つ申請すると漏れなく3倍に)

・説明を見た限りでは、新着記事を通知するだけのBOTに必要な権限とは思えない

ということから、これらの使用申請をするととても面倒臭いことになりそうな予感があったため、可能であれば使用申請なしで認証を受けたいところです。そこで試しに、BOTの動作中にDEVELOPER PORTALですべての特権インテントをオフにし、しばらく様子を観察してみたところ、これで問題なく動作しているのを確認できたので、これらの使用申請は行わずに認証を申請しました。

結論から言うと、動作確認時に「BOTの動作中にすべての特権インテントをオフにした」のが誤りで、面倒でも一旦BOTを停止して確認すべきでした。

BOTはユーザーと同様にDiscordに対してログインする必要があります。ただたまにBOTの動作中に勝手にログアウトすることがあり、その場合に備えて自動的にログインするようにしていたのですが、特権インテントをオフにした状態ではログイン直後にブロッキング状態から復帰しなくなり、BOTとしての動作に行き着くことができなくなっていました。慌てて特権インテントをオンに戻そうとしましたが、当然といえば当然ながら、認証処理中につきBOTに関するあらゆる設定が変更できなくなっていたのでした。



大いに慌てましたが、こんな時のためにサポートが存在するということを思い出し、早速サポートに認証処理を一旦キャンセルしてくれるよう連絡しました。



しかしながら、「そんなに大層なリクエストではないから、すぐにキャンセルは通るだろう」という期待を裏切り、認証処理のキャンセルまでに5日程度を要しました。これは技術的に困難だったからではなく、サポーターとのコミュニケーションがなかなか成立しなかったからです。どうして認証処理のキャンセルを要求しているかを理路整然と説明しても、「大丈夫!認証処理はちゃんと進めてるよ!」「インテントの使用申請をしてくれたらいいよ!」といったゴキゲンかつ頓珍漢な回答が返ってくるのを見るにつけ、サポーターが最初に目についた単語に機械的に反応して定型的な応答を返しているっぽいことに気付かされるのでした。

それでも他に手段がないので諦めずに幾度か送信し直していると、どうやらついにマトモなサポーターの目に留まったらしく、ようやく会話が成立。そして一瞬で認証処理を差し戻してもらえたのでした。どうやらDiscordにはサポーターガチャが存在することを知り得た5日間となりました。

◆3:特権インテント調査

申請の差し戻しによりBOTの設定が変更可能となったので、まずは3つの特権インテントのうちどれがBOTの動作に必要なのかを調査することに。結果、どの特権インテントをオフにしても、ブロッキング状態から回復しなくなることがわかりました。

また、ブロッキングが発生している箇所ですが、状況的にどうやら「スラッシュコマンド」を設定している箇所で発生しているらしいことがわかりました。それにしても、スラッシュコマンドを登録するのに特権インテントが必要な理由について、ドキュメントを幾度も読み直しましたが皆目見当がつきません。

改めてネット上の情報を検索してみたものの、そもそも多数のサーバーに登録する前提でインテントの設定を具体的に検討した情報がとんと見当たりませんでした。

ともかく、この時点での調査では状況的に「BOTを動作させるためにはすべての特権インテントが必要」と判断せざるを得ないという結論となり、それを前提として改めて認証申請を行うこととなりました。

◆4:認証申請再び

2回目の認証申請では、前回の申請内容に加えて、「なぜ特権インテントを使用するのか」という点について回答することにします。状況的にスラッシュコマンドをBOTに登録する際に必要とされているっぽい挙動を示していることから、「スラッシュコマンドを使用するために必要」と説明することにします。

申請を行った翌日に、Discordから以下の追加資料を送るよう連絡がありました。

・Discordサーバー内で動作しているBOTのスクリーンショットとビデオ

・BOTのヘルプおよびコマンドリスト

・最もよく使用するコマンドのコードスニペット

これらを送付し、DEVELOPER PORTALを確認したところ「Verification Request Processing」と表示されていたので、認証処理が滞りなく進んでいるであろうと認識しました。



そうして半月が経過。

「これは流石にちょっと放置されすぎなのではないか」とDiscordサポートに進捗状況の確認をリクエストしてみると、「何かそっちからの返事待ちになってるよ!BOT認証に必要な情報を送ってね!」という珍回答がありました。どうやら互いに「待ち」の状況に陥っていたようだということまでは読み取れたのですが、それにしてもサポーターの回答があまりにも要領を得ないものばかりだったので何度か問い合わせを繰り返し、サポーターガチャに勝利して得られた進捗状況は以下の通りでした。

・今初めて追加資料が送付されているのに気付いた

・つまり、送付した追加資料を見てもいなかった

・そして追加資料を開けない

「資料を開けない」と言っている意味がさっぱり理解できませんでしたが、どうやらGoogle Driveで共有ファイルのリンクを送ったものの、サポーター側の視点ではURLだけ見ても何のファイルかわからないので怖くて開けなかった可能性があることに思い至ります。改めて画像はImgur、動画はYouTubeと、何のデータなのか一目で確認できるサービスを利用して送り直しました。そうしてまたもやサポーターガチャを繰り返してアタリの人から得られた進捗状況は、「うちのチームメイトの1人からの返事待ちだよ!もうちょっと待つことをオススメするよ!」というのんきなものでした。思わず「内輪の事情はどうでもいいからとにかく処理を進めてくれ」と返答したくなるのでした。

かくして認証処理をやり直してから2か月強、グダグダなやり取りの末にようやく認証が通りました。DiscordでBOTを確認してみると、確かにBOTであることを示すマーク中に、認証済みであることを示すチェックマークが付加されています。



◆5:最後に残った特権インテント問題

認証処理をクリアした喜びも冷めやらぬ中、Discordサポートから怪メールが届きました。

その内容は、「BOTで特権インテントを使用していることに気付いたよ!使いたいなら承認を受ける必要があるよ!」というものでした。BOT認証申請でも特権インテントの使用有無とその理由を尋ねていましたが、あれは何だったのでしょうか。

……などとぼやいていても始まらないので、BOT認証申請と同様の説明・資料を用いて「スラッシュコマンドを使用するために必要である」との方針で特権インテントの使用承認を受けることにしました。DEVELOPER PORTALを確認したところ、自己主張強めの青枠表示で「Apply for privileged intents」という項目が追加されており、そこにある「Apply」ボタンから処理を開始します。



すると、早々と却下の回答が届きました。しかしながら回答の内容を読み進めると、「あなたのやりたいことはスラッシュコマンドを使えば実現できるよ!」と書いてあり、「そのスラッシュコマンドを登録するところで権限がないと動かなくて困っているんだが!?」と内心で叫ばざるを得ない内容でした。

その後も、切り口を変えながら幾度もサポートに質問してみましたが、一向に要領を得た回答をもらえませんでした。何よりも閉口したのは、Discordのドキュメントに絶大な自信があるのか、「このドキュメントに目を通せばきっと解決するよ!」と、とっくに目を通して役に立たないと切り捨てたドキュメントのURLをあたかもAIチャットの回答みたいに送り付けてくることでした。その中で、まだアタリの方のサポーターが「Discord Developer Server」というDiscord関連の開発者が集まるサーバーを教えてくれたのが一番有益な情報でした。

結局、Discordのサポートはまるで役に立たないと判断せざるを得ず、またDiscord Developer Serverでもなかなか有益な情報に巡り会えなかったため、基本に立ち返って「特権インテントを使用せずに済む方法はないものか」と自力でコードの見直しをすることにしました。

これまでのコードはネット上のサンプルを参考にした箇所が多かったため、多少不必要なものがあっても動作するならそれでヨシとしていましたが、余計な設定のせいで特権インテントが必要になっている可能性が考えられるため、そのあたりから要不要の精査が必要と判断しました。そうして権限に関係していそうなGatewayIntentBitsのあたりを見直すべく、絶対に必要であろう以下のビットだけを有効にしてそれ以外を落とし、特権インテントの有無による挙動への影響を確認することにしました。

・GatewayIntentBits.Guilds(サーバー関連)

・GatewayIntentBits.GuildMessages(サーバーのメッセージ関連)

しかしながら結果は以前の調査と同様に、3つの特権インテントをすべて与えると正常に起動し、1つでもオフにすると起動に失敗する、というものでした。

これ以外にも思いつく限りの様々な実験を行いましたが、いずれも有益な結果を得られるものはありませんでした。そうして時間だけが経過していくなかで、GatewayIntentBitsに関する挙動について、些細な違和感を覚えました。そこで、Docker外部から確認できるログファイルではなく標準出力を確認してみたところ、WebSocketが切断され、その理由である「許可されていないインテントを使用した」という以下のメッセージを伴う例外を発生させていたのが確認できました。

Error: Used disallowed intents
at WebSocketShard.onClose (/home/container/node_modules/@discordjs/ws/dist/index.js:1066:15)
at WebSocket.emit (node:events:513:28)
at WebSocket.emitClose (/home/container/node_modules/ws/lib/websocket.js:258:10)
at TLSSocket.socketOnClose (/home/container/node_modules/ws/lib/websocket.js:1264:15)
at TLSSocket.emit (node:events:525:35)
at node:net:332:12
at TCP.done (node:_tls_wrap:588:7)

これは1回目の認証申請の際に発生した「ログイン直後のブロッキングから回復しない」現象とは明らかに異なっており、状況からみて特権インテントに起因するものではなくGatewayIntentBitsを制限したことによるものと推測できました。そこで、GatewayIntentBitsの一覧をじっとよく見て、この中では一番WebSocketに関係ありそうな気がしないでもない

・GatewayIntentBits.GuildWebhooks

だけを追加してみました。そうするとなぜか特権インテントなしで無事に正常起動するようになったのでした。

そもそもWebSocketとWebHookはまったく別のものだよねなど、突っ込みたいことは多々ありつつも、実際動いてるという厳然たる事実は揺るぎ難く、さらに言うならばその後試しにGatewayIntentBits.GuildWebhooksを外してみても正常に動作したように見えたのですが、また突然動作しなくなったら困るので、お守り代わりにこのビットは立てたままにしてあります。

◆6:解決

こうして、ついに特権インテントの問題にけりを付けることができました。言い換えれば、サーバー登録件数の制限がかかる要因をすべて排除でき、ようやく公開しても恥ずかしくないBOTになったのでした。

これまでサーバーにGIGAZINE BOTを登録しようとして、以下のエラーが出て登録に失敗していた人は、現在この問題は解消されているはずですので、今一度登録を試してみてください。

このBotは未承認のため、または未承認のゲートウェイ・インテントをリクエスト中のため、これ以上サーバーに追加できない状態です。


これとは別に、「登録はできているのに、新着記事の通知が行われない」という読者もいるようです。これについてはBOTの実行ログにて、以下ののいずれかであることが判明しています。

・DiscordAPIError[50001]: Missing Access(サーバー・チャンネルにアクセスできない)

・DiscordAPIError[50013]: Missing Permissions(BOTに適切な権限が与えられていない)

ですので、特に権限についてはBOT導入記事の通りにBOTを登録できているかどうか、今一度見直してください。Missing AccessのエラーについてはBOTに通知を行わせているチャンネル、あるいはサーバー自体が削除されているのが原因です。

◆7:振り返り

DiscordのBOTを開発してみて痛感したのは、こと開発関連に限って言えば、Discordのサポートはちょっと頼りにできない、ということです。

まずサポーターの質のばらつきが酷く、「ガチャ運」が悪いと「ChatGPTの方がはるかにマトモなのでは?」と疑わざるを得ない珍回答で切って捨てられ、 一方的にチケットをクローズされることすらあります。また、ステータスが「審査しています」となっているにもかかわらず実際には放置されていたりと、審査の進捗が不透明でかつこちらから問い合わせないと放置が解消されなかったのも好印象を持てない一因です。そもそも、「ガチャで激運を発揮しないと状況を教えてすらもらえない」などというのはサポートのあり様としていかがなものだろうかと考えてしまいます。

また、サポートへのリクエスト送信手段としてフォームが用意されていますが、これがお世辞にも使い勝手のよいものとは言えないものであり、これを用いてサポートとチケットに対するディスカッションを行うのはただただ苦行でしかありません。

そしてどちらかといえばDiscord.jsというよりはDiscordそのものの構成上の問題かとは思いますが、どの権限が何に関与しているかや、権限の依存関係がどうなっているかが、資料を見ても分からずエラーや例外を見てもさっぱり分からないというのは、ちょっといただけません。サポートがまったく何の役にも立たないのも、ひいてはこれが一因なのではないでしょうか。破壊的変更が発生すること自体はセキュリティ対策の上からも致し方ない側面がありますが、その対応の際に開発者にかかる負担は間違いなく大きいものになるであろうと推測できます。

もし読者の中に「DiscordのBOTを作ってみたい」という人がいたら、自分のサーバーかあるいはごく親しい仲間うちのサーバーでのみ動かすものを作り、それで満足することを強くお勧めします。絶対に認証を受けるなとまでは言いませんが、サポーターと虚しい対話もどきを延々と試みてまで認証を通す価値があるのか、一歩を踏み出す前に一度自問自答すべきです。

Discordというサービス自体についてGIGAZINEサーバーの観点に絞って考えてみると、GIGAZINEと読者との双方向的コミュニケーションを提供する場として非常に有益に機能していると言えます。ただ、BOTに関しては今後ともサービスを提供できるのか、特にまた破壊的変更が行われた際に適切な対処ができるのか、その際にサポーターガチャで激運を発揮できるのかを考えると一抹の不安があります。とはいえ、こうして何とか形になった以上は、できるだけのことはやっていく所存です。

◆8:GIGAZINE BOTの不具合報告について

もし、「GIGAZINE BOTを自分のサーバーに導入しようとしたけどできなかった」「新着記事の通知をさせようとしたけどできなかった」といったような不具合と思しき現象が発生したら、こちらのフォームから、不具合の発生状況などの情報に加えて、以下を書き添えて報告をお願いします。

・導入対象サーバーの「サーバーID」

・新着記事の通知対象となるチャンネルの「チャンネルID」

これらの情報がないと、現象の発生原因を特定できない可能性が高く、こちらでは何もできない場合があります。

Windows版Discordアプリで「サーバーID」と「チャンネルID」を取得するためには、あらかじめ「ユーザー設定」で「開発者モード」を有効化しておく必要があります。「ユーザー設定」の画面を表示させるには、画面下部のログインユーザー表示部に並んでいる歯車のアイコンをクリックします。



次に、「ユーザー設定」画面左部のメニュー一覧から「詳細設定」を選択し、一番上の「開発者モード」のスイッチをONにすれば、「開発者モード」が有効化されます。



「開発者モード」を有効化した状態で「サーバーID」を取得するには、画面左部に並んでいるサーバーのアイコンを選択し、右クリックで表示されるコンテキストメニューから「サーバーIDをコピー」の項目を選択することでクリップボードにコピーできます。



同様に「チャンネルID」を取得するには、サーバーを選択して表示されるチャンネルの一覧から目的のチャンネル名を右クリックし、表示されるコンテキストメニューから「チャンネルIDをコピー」の項目を選択することでクリップボードにコピーできます。



ウェブやスマートフォン版アプリの場合は、チャンネルのURLをコピー(アプリではチャンネル名を長押しして表示されるコンテキストメニューから「リンクをコピー」をタップ)すると「https://discord.com/shannels/【サーバーID】/【チャンネルID】」という形式のURLを取得できるので、これをそのまま伝えていただいても構いません。



そんな訳で、少々グダグダな顛末となりましたが、今後ともDiscordのGIGAZINEサーバーとGIGAZINE BOTをよろしくお願いします。