メディア掲載: レバテックフリーランス様のサイトで当ブログが紹介されました

Google Chatにシートの内容やフォームの回答を自動投稿する

Google Chatは、Webhookを利用すればChatの画面以外からでもメッセージを送ることができます。

もちろん、Google Apps Scriptからもメッセージを送ることができるので、1. スプレッドシートのデータを元にしたメッセージをチャットに自動投稿したり、2. Googleフォームに回答が届いたらチャットに自動投稿する・・・ということも可能です。

この記事では、Google Apps ScriptWebhookを使ったGoogle Chatへの投稿方法の基本と、上記1. 2. のサンプルを紹介します。

なお、記事執筆時点では、無料版のGoogleアカウントではWebhookは利用できませんでしたので、ご注意ください。

WebhookのURLを取得

Webhookを使ってチャットにメッセージを送信するには、WebhookのURLが必要です。
URLはGoogle Chatの画面で取得することができます。

Google Chatに作成した「テストチャット」スペース。スペースの名称をクリックして表示されるメニューから「アプリと統合」をクリックしている。
スペースのタイトルをクリックし、「アプリと統合」をクリック
Google ChatのスペースのWebhookやアプリを管理するウィンドウ。
「Webhookを管理」ボタンをクリックしている。
「Webhookを管理」をクリック
Google ChatのスペースのWebhookの設定画面。名称に「サンプルWebhook」を設定し、オプションとして、WebhookのアバターのURLを入力している。
Webhookに好きな名前をつけて「保存」をクリック。なお、必要に応じてアイコンを設定することもできるので、犬の画像を設定してみた。
Google ChatのスペースのWebhookの管理ウィンドウ。作成したWebhookが表示されているので、URLをコピーする。
WebhookのURLが表示されるのでコピーしておく。

以上で、WebhookのURLが取得できました。

GASからチャットに投稿する

続いて、Google Apps Scriptからメッセージを投稿してみます。

拡張機能メニューより、Apps Scriptを起動します。

[ 拡張機能 ] > [ Apps Script ] をクリック

あらかじめ入力されているコード(myFunction)を削除し、当記事のコードを貼り付けます。
貼り付け後、保存してください。

スクリプトを貼り付けて保存する
不要なコードを削除し、当記事のコードを貼り付けて保存ボタンを押す

Google Workspaceのガイドのコードを(ほぼ)そのまま使ってみます。
2行目のURLは、先ほど取得したWebhookのURLに、9行目の”Hello from…”は、ご希望の文言に書き換えてください。

function sendToChat() {
  const url = "https://chat.googleapis.com/v1/spaces/XXXXXXXXXXX/messages?key=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX&token=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  const options = {
    "method": "post",
    "headers": {
      "Content-Type": "application/json; charset=UTF-8"
    },
    "payload": JSON.stringify({
      "text": "Hello from Apps Script!"
    })
  };
  const response = UrlFetchApp.fetch(url, options);
}

▷実行で実行すればチャットにメッセージが投稿されます。
初回の実行時は、権限の承認が必要です。

「承認が必要です」というダイアログが表示されますので、権限を確認 をクリックします。
* この部分の解説画像は、他の記事から流用しているため、実際のものと若干異なる場合があります。

このスクリプトを使うGoogleアカウントを選択します。

(この画面が表示された場合のみ)左下の 詳細 をクリックします。

(この画面が表示された場合のみ)左下の プロジェクト名(安全ではないページ)に移動 をクリックします。

右下の 許可 をクリックします。

Google Chatのスペースに、サンプルWebhookから「Hello from Apps Script!」というメッセージが投稿されている。
“text”に設定したメッセージがチャットに投稿された。

GASからスレッドを指定してチャットに投稿する

GASからGoogle Chatにメッセージを投稿する際、任意のthreadKeyを設定しておくと、あとからそのスレッドにwebhookを使って返信することができるようになります。

先ほどのコードを修正して、threadKeyを設定して投稿されるようにします。

たとえば、毎朝1つスレッドを立てて、同日中はそのスレッドにしか投稿しないというスクリプトの場合は、threadKeyに日付を指定すると簡単です。
サンプルとして、threadKey20230526のようなyyyyMMdd形式の日付を設定してみました。

function sendToChat() {
  const url = "https://chat.googleapis.com/v1/spaces/XXXXXXXXXXX/messages?key=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX&token=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  const threadKey = Utilities.formatDate(new Date(), "JST", "yyyyMMdd");
  const options = {
    "method": "post",
    "headers": {
      "Content-Type": "application/json; charset=UTF-8"
    },
    "payload": JSON.stringify({
      "text": "Hello from Apps Script! with threadKey!"
    })
  };
  const response = UrlFetchApp.fetch(
    `${url}&threadKey=${threadKey}&messageReplyOption=REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD`,
    options
  );
}

▷実行ボタンでチャットにメッセージを送信しました。
新しく送信したメッセージは、見た目は先ほどと変わりませんが、threadKeyを保持しているはずです。

Google Chatのスペースに、サンプルWebhookから「Hello from Apps Script! with threadKey!」というメッセージが投稿されている。
新しく送信したメッセージ。threadKeyを設定して送信しても見た目は変わらない。しかし、内部的にはthreadKeyが記録されているはず。

そして、再度メッセージを送信してみます。
判別するために、メッセージを少し変えてから▷実行ボタンを押しました。

    "payload": JSON.stringify({
      "text": "Reply from Apps Script! with threadKey!"
    })

前回のメッセージと同じthreadKeyを指定しているので、新たなスレッドが立つのではなく、既存のスレッドに返信する形でメッセージが投稿されます。

Google Chatの画面を見てみると、スレッドに返信する形で投稿されたことがわかります。

Google Chatのスペースに、サンプルWebhookから「Reply from Apps Script! with threadKey!」というメッセージが投稿されている。
このメッセージは、先ほどのメッセージに返信する形で投稿されている。
先ほど立てたスレッドに返信する形でメッセージが投稿されていた

カード型のメッセージを投稿する

先ほどまでの、シンプルなテキストメッセージだけでなく、カード型のメッセージを投稿することもできます。

Google Chatのスペースに、カード型デザインのメッセージが投稿されている。
アイコンがあったり、タイトル、サブタイトルの書式が少し違ったりする。また、「却下」「承認」などのボタンも設置されている。
このように見栄えのするカード型メッセージも投稿可能。

上図のカードを投稿したスクリプトは下記のとおりです。

function sendToChat() {
  const url = "https://chat.googleapis.com/v1/spaces/XXXXXXXXXXX/messages?key=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX&token=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  const options = {
    "method": "post",
    "headers": {
      "Content-Type": "application/json; charset=UTF-8"
    },
    "payload": JSON.stringify({
      "cardsV2": [
        {
          "cardId": "unique-card-id2",
          "card": {
            "header": {
              "title": "ユーザー新規登録依頼",
              "subtitle": "2023年5月28日 川田 新一(営業部)",
              "imageUrl": "https://web-breeze.net/wp-content/uploads/2019/12/cropped-favicon-1.jpg"
            },
            "sections": [
              {
                "header": "申請内容",
                "widgets": [
                  {
                    "textParagraph": {
                      "text": "5月末までに、以下のユーザーの新規登録をお願いいたします。"
                    }
                  },
                  {
                    "divider": {}
                  },
                  {
                    "decoratedText": {
                      "startIcon": { "knownIcon": "PERSON" },
                      "text": "山 智子",
                    },
                  },
                  {
                    "decoratedText": {
                      "startIcon": { "knownIcon": "EMAIL" },
                      "text": "yama@web-breeze.net",
                    }
                  },
                  {
                    "buttonList": {
                      "buttons": [
                        {
                          "text": "却下",
                          "onClick": {
                            "openLink": { "url": "https://example.com/reject" }
                          }
                        },
                        {
                          "text": "承認",
                          "onClick": {
                            "openLink": { "url": "https://example.com/approve" }
                          }
                        },
                      ],
                    }
                  },
                ],
              },  
            ]
          },
        },
      ]
    })
  };

  const response = UrlFetchApp.fetch(url, options);
}

結構細かく設定できるようになっているため、各パーツの詳細については割愛させていただきます。
詳細はGoogleの公式Docに記載されていますが、基本的な使い方は下記のとおりです。

  • options > payloadには、cardsV2オブジェクトを格納します。
  • cardsV2 > cardオブジェクトには、下記を含めることができます。
    • header(オブジェクト)
      カードのタイトルやサブタイトル、アイコンを設定します。詳細
    • sections(配列)
      カード内にセクションを複数設けることができます。
      各セクションには、ヘッダーを設けることができ、折りたたみの設定も可能です。詳細
      • widgets(配列)
        テキスト、画像、ボタン、区切り線などを設置できます。詳細

活用例: チームメンバーの勤務予定をチャットに毎朝自動投稿する

GASWebhookを使っての自動投稿の活用例として、毎朝、チームメンバーの勤務予定を自動投稿する方法を紹介します。

勤務予定表をスプレッドシートで作成する

前提として、下図のようなスプレッドシートの勤務表が使われているものとします。

Googleスプレッドシート製の勤務表。1行目は日付、2行目は曜日、3行目以降は各チームメンバーの勤務予定(有休、在宅・・・など)が記載されている。出勤の場合は何も記入しない。なお、1列目はメンバーの氏名になっている。
よくあるスプレッドシート製の勤務表。

スプレッドシートにスクリプトを追加する

Google Apps Scriptでこのシートを参照し、本日の勤務予定を取得してチャットに送信します。

勤務予定シートをもとにチャット投稿メッセージを作る関数createMessageを作成しました。

メッセージを送信するsendToChat関数は先ほどまでとほぼ同じですが、“text”へはcreateMessage関数の実行結果をセットするよう修正します。

function sendToChat() {
  const url = "https://chat.googleapis.com/v1/spaces/XXXXXXXXXXX/messages?key=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX&token=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  const options = {
    "method": "post",
    "headers": {
      "Content-Type": "application/json; charset=UTF-8"
    },
    "payload": JSON.stringify({
      "text": createMessage()
    })
  };
  const response = UrlFetchApp.fetch(url, options);
}

function createMessage() {
  // 「勤務予定」シートを取得
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('勤務予定');

  // 本日の 0時 0分 0秒 0ミリ秒 のDateオブジェクトを作成
  const today = new Date(new Date().setHours(0, 0, 0, 0));

  // チャットに送信するメッセージ(1行目は <MM/dd 勤務予定> とする)。 **で囲うと太字になる
  let message = `*<${today.getMonth() + 1}/${today.getDate()} 勤務予定>*`;

  for (let col = 2; col <= sheet.getLastColumn(); col++) {
    // 1行目が本日日付の列を探す
    if (sheet.getRange(1, col).getValue().getTime() === today.getTime()) {
      // 3行目から最終行まで、氏名と勤務予定を取得し、メッセージに追加する
      for (let row = 3; row <= sheet.getLastRow(); row++) {
        const name = sheet.getRange(row, 1).getValue();
        const cellValue = sheet.getRange(row, col).getValue();
        const plan = cellValue ? cellValue : '出勤';
        message += '\n' + `${name}:\t${plan}`;
      }
    }
  }

  return message;
}

webhook関数を選択して▷実行します。(初回は権限の確認が必要です)
すると、期待どおりのメッセージがチャットに送信されました。

Google Chatに、サンプルWebhookから以下のメッセージが投稿されている。
---
<5/26 勤務予定>
佐藤 衛:	在宅
山 智子:	出勤
堀 裕佑:	有休
チームメンバーの本日の勤務予定がチャットに投稿された。

トリガーを設定する

毎日8時〜9時ごろ(土日を除く)にチャットに自動投稿されるよう、トリガーを作成します。

スクリプトエディタの左側メニューから「トリガー」を選択し、右下の「トリガーを追加」ボタンをクリックする。
トリガーメニューを選択し、+トリガーを追加をクリック
トリガーの設定ウィンドウ。sendToChat関数を選択し、時間主導型、週ベースのタイマーで、毎週月曜日、午前8時〜9時を設定している。
この画像のように設定する

これで、月曜日の8時〜9時ごろにチャットに自動投稿するトリガーが作成できました。
同様の手順で、火曜日〜金曜日のトリガーも作成すればOKです。
(このスクリプトですと、祝日にも投稿されてしまいますが、そのあたりの処理は当記事の本旨とは離れてしまいますので割愛させていただきます。)

活用例: Googleフォームに回答が送信されたらチャットに自動投稿する

GASWebhookを使っての自動投稿の活用例として、お問合せフォーム(Googleフォーム)に問合せが届いたら、問合せ内容をチャットに投稿する例を紹介します。

Googleフォームでお問合せフォームを作成する

前提として、下図のようなお問合せフォーム(Googleフォーム)が使われているものとします。

完成したGoogleフォーム。メールアドレスが収集される設定になっており、所属部署、氏名、問合せ内容の入力欄がある。
メールアドレスを収集し、その他に、所属部署・氏名・問合せ内容を記入するフォーム。

フォームにスクリプトを追加する

フォームが作成できたら、スクリプトエディタを起動します。

右上の三点メニューから、スクリプトエディタを起動します。

三点メニュー > スクリプトエディタ

あらかじめ入力されているコード(myFunction)を削除し、当記事のコードを貼り付けます。
貼り付け後、保存してください。

スクリプトを貼り付けて保存する
不要なコードを削除し、当記事のコードを貼り付けて保存ボタンを押す

下記のスクリプトを貼り付け、▷実行ボタンを押し、権限の承認を行なってください。

function webhook(e) {
  const url = "https://chat.googleapis.com/v1/spaces/XXXXXXXXXXX/messages?key=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX&token=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  const options = {
    "method": "post",
    "headers": {
      "Content-Type": "application/json; charset=UTF-8"
    },
    "payload": JSON.stringify({
      "text": createMessage(e.response)
    })
  };
  const response = UrlFetchApp.fetch(url, options);
  Logger.log(response);
}

function createMessage(response) {
  // 質問・回答およびメールアドレスを取得
  const itemResponses = response.getItemResponses();
  const respondentEmail = response.getRespondentEmail();

  // チャットに送信するメッセージ。 **で囲うと太字になる
  let message = '*フォームに問合せが届きました*';

  // 回答した質問すべてのタイトル・回答を取得し、メッセージにセット
  for (const itemResponse of itemResponses) {
    const title = itemResponse.getItem().getTitle();
    const response = itemResponse.getResponse();
    message += '\n\n' + `${title}:\n${response}`;
  }

  // メッセージ末尾に返信先のメールアドレスを記載
  message += '\n\n' + `返信先:\n${respondentEmail}`;
  
  return message;
}

このスクリプトは、フォームから回答が送信された時に動作する前提のスクリプトになっているので、▷実行ボタンで実行するとエラーが発生します
しかし、今回は権限の承認を行うことが目的なので問題ありません。

トリガーを設定する

フォームから問合せが送信された時にスクリプトが実行されるよう、トリガーを作成します。

スクリプトエディタの左側メニューから「トリガー」を選択し、右下の「トリガーを追加」ボタンをクリックする。
トリガーメニューを選択し、+トリガーを追加をクリック
トリガーの設定ウィンドウ。sendToChat関数を選択し、イベントソースはフォームから、イベントの種類はフォーム送信時を選択している。
この画像のように設定する

これでトリガーの準備は完了です。
実際にフォームから問合せを送信してみると、チャットにメッセージが投稿されました。

Google ChatにサンプルWebhookから、以下のメッセージが投稿されている。
---
フォームに問合せが届きました

所属部署:
営業部

氏名:
佐藤 衛

問合せ内容:
GMAILの使い方がわからないのでレクチャーしてほしい。

返信先:
sato@web-breeze.net

コメント

タイトルとURLをコピーしました