📨

DiscordのBotメッセージをmicroCMS × GitHub Actionsで管理する

2022/04/26に公開

microCMSとGitHub Actionsを使って、面倒なボット発信のメッセージ管理を改善します。

使ってみたい方へ

  • 読者ターゲット
    • Discordボットを使ってメンバーへの告知メッセージなどを送信しているが、編集が面倒で管理に困っている。
    • GitHubを日常的に使用している。
      • Fork、またはTemplateからのリポジトリ作成に支障がない。
      • Actionsの作成に支障がない。
  • 流れ
    1. Gitリポジトリを作る
    • https://github.com/white-lucida/microcms-discord-message
    • 上記のリポジトリをPublic Templateに設定しています。これをご利用ください。
      • あまり考えないでコミットしてたらActionsで実験してるときにすごくログが汚くなってしまった
    1. microCMSアカウントを作る
    • 本記事の内容から逸れるので、省略させていただきます。
    1. microCMSでAPIの作成を開始する
    • 省略させていただきます。
    1. APIスキーマの定義画面で設定をインポートする
    1. APIキーの権限を設定する
    • defaultのAPIキーを利用するか、あるいはAPIキーを新規に作成します。
    • APIキー一覧の画面キャプチャ
    • 上記の画面で、権限を設定したいAPIキーをクリックします。
    • APIキー詳細の画面キャプチャ
    • 上記の画面で、新たに「PATCH」にチェックを入れます。
    1. Discordボットのトークンを取得する
    • 本記事の内容から逸れるので、省略させていただきます。
    1. Secretsを登録する
    • 1.で作ったリポジトリのSecretsに情報を登録します。
    • 以下の3つの情報を登録してください。
      • DISCORD_TOKEN - 6.で取得したDiscordのトークン
      • MICROCMS_SERVICE_ID - 2.3.で作成したサービスID(詳細は省略します)
      • MICROCMS_API_KEY - 5.のページでAPIキーをコピーしてきてください。
    • この情報はGitHub Actions内で使用します。
    1. Personal Access Token(以下、PAT)を作成する
    • GitHubのPersonal Access Token(PAT)を作成してください。
    • PATの作成方法は省略します。
    • PATは一度別のページに移動すると伏せられてしまうため、必ずここでコピーしてください。
    1. microCMSのWebhookを作成する
    • GitHub ActionsとmicroCMSを繋ぎこみます。
    • 作成方法
    • 要点
      • API/Webhookの画面キャプチャ
      • 私の場合の設定値です。
      • 「GitHubトークン」というのが、8.で作成したPATに該当します。
      • ユーザー名、リポジトリ名は、1.やユーザー設定に合わせてください。
    1. 完了
    • 上記の方法でもう一度環境を作成して再現したわけではないので、もし動かなければコメントで報告いただければ幸いです。
  • 以下の内容は、技術選定や、知見の記録です。

必要だったこと

Discordボットでメッセージを送信したい

  • Discordには埋め込みやMessage Componentなどのリッチな表現を可能にする機能があります。
  • しかし、これらの機能は通常のユーザーアカウントから送信することはできません。
    • 埋め込みを送信する方法
      • Discordボット
      • Webhook
    • Message Componentを送信する方法
      • Discordボット
  • だから、これらの機能を利用するためには、Discordボットを使ってメッセージを送信する必要があります。

送信したメッセージを管理したい

  • 送信したメッセージを管理するのが難しい
    • Discordボットでメッセージを送信した場合、そのメッセージを後から編集する際はDiscord APIにリクエストを送る必要があります。
  • フォーム上で管理したい
    • 上記の問題点を踏まえ、以下の機能が必要と考えました。
      • フォームに必要事項を入力してメッセージを送信する
      • メッセージ内容を保存する
      • 送信したメッセージのIDを保存する
      • あとから再度必要事項を入力して、メッセージの内容を編集できる

使ったもの

microCMS

  • microCMSは国産のヘッドレスCMSです。
  • フォームでコンテンツを編集し、APIから内容を取得するという、Webサイト開発のコアな部分の機能を提供しています。
  • 感想
    • 今までは、CMSとはホームページを作るためのもので、今回の問題にはまったく関係がないと思っていました。
    • しかし機能を調べてみると、かなり上手く作れそうに見えました。
      • シンプルな機能構成
      • フォームのスキーマの表現力が高い
      • GitHub Actionsと接続可能
    • そして、実際に今回この機能を作ってみて、様々なシーンに対応できるツールと感じました。
      • コンテンツを保存してあとから編集したい、という場合には必ず役に立つでしょう。

やったこと

  • スキーマを定義して、データをフォームから入力できるようにした。
  • GitHub Actionsに繋いで、データ入力以外の処理を投げられるようにした。

GitHub Actions

やったこと

  • microCMSでコンテンツが更新されたときにDiscordにメッセージが送信されるようにした。

結果

  • 以下のような流れでメッセージを投稿できるようになりました。
  • 投稿
    1. microCMSのメッセージ用APIでコンテンツを作成する。
    2. GitHub Actionsの動作が始まるので、しばらく待つ
    3. メッセージが投稿され、microCMS上のデータとDiscordのメッセージが紐付けられる
  • 更新
    1. microCMSで作成したコンテンツに更新を加える
    2. 同様に待つ
    3. microCMS上のメッセージIDを使って、Discordのメッセージが更新される
  • 削除については、microCMS上にメッセージのIDを保存した関係上、いい方法を思いつきませんでした。
    • microCMS上でコンテンツを削除したらメッセージも削除されるようにActionsを書きたかったです。
    • でもコンテンツを削除したらメッセージIDがわからないのでDiscord APIを叩けません。

知見

microCMSのスキーマ

Discord APIのスキーマを再現したい

できたこと

ボタン
  • うまくいきました。
  • 特に、通常の「ボタン」と「リンクボタン」をスキーマ上で分けたことで、より安全に入力できるようになりました。
    • コンテンツ作成時の画面キャプチャ
    • この2つがstyleだけで出し分けられているのが以前から悩みの種だったのですが、綺麗に解決できました!
セレクトメニュー
  • うまくいきました。

難しかったところ

定数のオプション
  • 例えば、Message Componentのtypeです。
    • 123という定数にそれぞれAction RowButtonSelect Menuという意味が与えられています。
    • 数字だったので、説明文に注釈を入れたうえで直接数字を打ってもらう形にしました。

できなかったこと

Footerなどの指定
  • 「Embed」というカスタムフィールドを作って、その中に「Footer」というカスタムフィールドを入れたかった
  • でも、方法が分かりませんでした。
  • カスタムフィールド/スキーマの画面キャプチャ
  • 「繰り返し」だけが表示されます。よくわかっていないところです。
colorの指定
  • 色型、というのはニッチですかね。
  • 世の中には16進数6桁で記述する場合もあれば、rgb()のタプルで記述する場合もあって、APIのレスポンスの設計が難しいのかもしれません。
  • Discordの場合は内部的には数値として取り扱われるのでそれに従いました。
  • (追記)iframeフィールドを試してみましたが難しいです。
    • iframeフィールドはGET APIとPATCH APIのスキーマが全く違います。
    • 詳細
      • 見た目はよくなりました
        • コンテンツ入稿画面のキャプチャ
      • 投稿そのものにはGET APIを使っているのでこれもうまくできました
      • でもメッセージIDを紐づける処理でPATCH APIを使ってるのでここで詰まりました
    • 結論
      • iframeフィールドを含むコンテンツの更新はAPIを叩く側での工夫が必要です。
      • カスタムフィールド(入出力の形式が同じ)
        • GETでfieldIdを返す
        • PATCHでもfieldIdが必要
      • iframeフィールド(入出力の形式が違う)
        • GETでidなどを返さない
        • PATCHではidなどを含めてコンテンツはdataに格納
          • このidのような情報はどこから取得することを想定しているのか気になります
          • GETでは受け取れないので、一度iframeフィールドを作ってしまうと、一部だけ更新する、というのが難しくなってしまうような
    • 蛇足
      • 個人的には、以下の設計がいいんじゃないかな、と思いました。
      • fieldIdと同じ感じで
{
  "meta": {
    "id": "string",
    "title": "string",
    "description": "string",
  },
  "実データ1": "huga"
  "実データ2": "..."
}
セレクトメニューのemojiの指定
  • parital emojiオブジェクトにはidというプロパティが含まれています。
  • でもmicroCMSではidというフィールド名は使用不可でした。
  • JavaScript側でごにょごにょやるのは避けたいのでとりあえず諦めました。
    • Discord APIのスキーマを可能な限り再現したかったのです。

やらなかったこと

timestamp
  • 実装の必要性を感じませんでした。
  • 日時を使えば上手くできるんでしょうか。

総評

  • カスタムフィールドの自由度が非常に高いです!
  • 表現しきれない部分はうまくこちら側でさばけるといいですね。

セレクトフィールドの値

  • 「セレクトフィールド」はAPI上では単一の値を返してくるものだと思っていました。
  • 実際には、["5"]のように配列として返してきます。
  • 「複数選択可」にするオプションがあるのがこの設計の理由かと思います。

その他

microCMSのスキーマをいじっていたときのアクシデント

  • 不要なカスタムフィールドを消そうと思ったら別のフィールドを消していました。
  • 削除しようとしているフィールド名を確認させるダイアログがあったらいいなと思いました。

以上です。
「microCMS」ぜひ使ってみてください!

Discussion