Google Chat アプリで休暇を設定する

1. はじめに

Google Chat アプリを使えば、サービスやリソースを Chat に取り入れることができるため、ユーザーは会話から離れることなく情報を取得し、操作を行うことができます。

この Codelab では、「Attendance Bot」という Chat アプリを作成する方法を学習します。このアプリは、Gmail で不在通知を設定し、Google カレンダーでミーティングをスケジューリングするためのものです。Google Apps Script で Attendance Bot を作成すると、ドライブ、Gmail、カレンダー、ドキュメント、スプレッドシートなど、他の Google サービスに容易にアクセスできます。

学習内容

  • Chat で発生したイベントのハンドラを追加する方法
  • Chat から送信されたイベント オブジェクトを解析する方法
  • Chat でカード形式のレスポンスを返す方法
  • カード内でボタンがクリックされたときのカスタム アクションを定義し、応答する方法

必要なもの

  • インターネット アクセスとウェブブラウザ。
  • Google Chat へのアクセス権を持つ Google Workspace アカウント。
  • 基本的な JavaScript のスキル(Google Apps Script は JavaScript のみサポートしています)。

2. サンプルコードを取得する

このサンプルの各ステップのコードは、ZIP ファイルをダウンロードするか、GitHub リポジトリのクローンを作成することで確認できます。

この Codelab の各ステップにおける望ましい最終状態は、step-NN フォルダに格納されています。これらは参照用に用意されています。

コードをダウンロードする

この Codelab のコードをダウンロードするには、以下のボタンをクリックします。

ダウンロードした ZIP ファイルを解凍すると、ルートフォルダ(hangouts-chat-apps-script-codelab)が展開されます。このフォルダには、この Codelab のステップごとに 1 つのフォルダが含まれています。

GitHub リポジトリのクローンを作成する

この Codelab の GitHub リポジトリのクローンを作成するには、以下のコマンドを実行します。

git clone https://github.com/googleworkspace/hangouts-chat-apps-script-codelab

3. Google Chat イベント用のハンドラを作成する

Apps Script プロジェクトを作成する

Apps Script プロジェクトを作成するには、手順を実施します。

  1. script.new にアクセスします。
  2. [無題のプロジェクト] をクリックします。
  3. スクリプト名を Attendance Bot に変更して、[名前を変更] をクリックします。

Google Chat のイベント

Apps Script と Chat のやり取りは、その多くがイベント ドリブンです。ユーザー、Chat アプリ、Chat 間のやり取りは、通常、次のような流れになります。

  1. ユーザーが、スペースへの Chat アプリの追加、Chat アプリを使用したダイレクト メッセージ(DM)の開始、スペースからの Chat アプリの削除といったアクションを実行します。
  2. このアクションにより、Chat の Chat アプリに対してイベントが発生します。
  3. Chat は、Chat アプリのスクリプトで定義された、対応するイベント ハンドラを呼び出します。

Chat は、アプリがリッスンできる次の 4 つのイベントを発生させます。

  • ADDED_TO_SPACE: このイベントは、人間のユーザーがスペースまたはダイレクト メッセージ(DM)に Chat アプリを追加したときに発生します。このイベントを処理するために、Apps Script で onAddToSpace() 関数を定義します。
  • REMOVED_FROM_SPACE: このイベントは、ユーザーがスペースまたは DM から Chat アプリを削除したときに発生します。このイベントでは、Chat に対してレスポンスは返されません。このイベントを処理するために、Apps Script で onRemoveFromSpace() 関数を定義します。
  • MESSAGE: このイベントは、ユーザーがダイレクト メッセージ(DM)で直接、またはスペースの @mention で Chat アプリにメッセージを送信したときに発生します。このイベントに応答するために、Apps Script で onMessage() 関数を定義します。
  • CARD_CLICKED: このイベントは、カスタム アクションが割り当てられたボタンをユーザーがクリックしたときに発生します。このイベントに応答するために、Apps Script で onCardClick() 関数を定義します。

Code.gs ファイルの内容を次のコードで置き換えます。これにより、ADDED_TO_SPACE イベントおよび REMOVE_FROM_SPACE イベントのハンドラが定義されます(MESSAGE イベントおよび CARD_CLICKED イベントのハンドラは、この Codelab で後ほど追加します)。

コード.gs

/**
 * Responds to an ADDED_TO_SPACE event in Google Chat.
 * @param {object} event the event object from Google Chat
 * @return {object} JSON-formatted response
 * @see https://developers.google.com/chat/api/guides/message-formats/events
 */
function onAddToSpace(event) {
  console.info(event);
  var message = 'Thank you for adding me to ';
  if (event.space.type === 'DM') {
    message += 'a DM, ' + event.user.displayName + '!';
  } else {
    message += event.space.displayName;
  }
  return { text: message };
}

/**
 * Responds to a REMOVED_FROM_SPACE event in Google Chat.
 * @param {object} event the event object from Google Chat
 * @see https://developers.google.com/chat/api/guides/message-formats/events
 */
function onRemoveFromSpace(event) {
  console.info(event);
  console.log('Chat app removed from ', event.space.name);
}

4. Chat アプリをテストして公開する

スクリプトのマニフェスト ファイルを更新する

Chat にアプリを公開する前に、スクリプトのマニフェストを更新する必要があります。

  1. [プロジェクトの設定] outline_settings_black_24dp.png をクリックします。
  2. [「appsscript.json」マニフェスト ファイルをエディタで表示する] チェックボックスをオンにします。
  3. [エディタ] outline_code_black_24dp.png をクリックします。
  4. appsscript.json ファイルをクリックします。
  5. "chat": {} という行をマニフェスト ファイルに追加します。

マニフェスト ファイルは、次の例のようになります。

appsscript.json

{
  "timeZone": "America/Los_Angeles",
  "dependencies": {
  },
  "chat": {}
}

Google Cloud プロジェクトを作成する

Chat アプリを実行してテストする前に、Google Cloud プロジェクトを作成し、Chat API を有効にして構成し、Google Workspace の組織に Chat アプリを公開する必要があります。

  1. Google Cloud コンソールで、メニュー f5fbd278915eb7aa.png > [IAM と管理] > [プロジェクトを作成] に移動します。

  2. [プロジェクト名] に、わかりやすい名前を入力します。
  3. プロンプトが表示されたら、[組織] と [請求先アカウント] を選択します。
  4. [作成] をクリックします。
  5. プロジェクトの作成が完了すると、ページの右上に通知が表示されます。[プロジェクト「<プロジェクト名>」を作成] エントリをクリックして、プロジェクトを開きます。
  6. メニュー f5fbd278915eb7aa.png > [API とサービス] > [認証情報] をクリックします。
  7. [OAuth 同意画面] をクリックします。
  8. [アプリ名] に、「Attendance Bot」と入力します。
  9. プロンプトが表示されたら、ユーザー サポートのメールアドレスとデベロッパーの連絡先情報を入力します。
  10. [保存して次へ] をクリックします。
  11. 設定とユーティリティ 50fa7e30ed2d1b1c.png > [プロジェクトの設定] をクリックします。
  12. [プロジェクト番号] をコピーします。
  13. App Script エディタに戻り、[プロジェクトの設定] outline_settings_black_24dp.png をクリックします。
  14. [Google Cloud Platform(GCP)プロジェクト] で、[プロジェクトを変更] をクリックします。
  15. [GCP のプロジェクト番号] をクリックして、プロジェクト番号を入力します。
  16. [プロジェクトを設定] をクリックします。

アプリを Chat に公開する

Chat アプリを Google Chat に公開するには、手順を実施します。

  1. Apps Script エディタで、[デプロイ] > [新しいデプロイ] をクリックします。
  2. [種類の選択] の隣にある [デプロイタイプを有効にする] outline_settings_black_24dp.png をクリックします。
  3. [アドオン] を選択して、[デプロイ] をクリックします。
  4. [デプロイ ID] をコピーして、[完了] をクリックします。
  5. Google Cloud コンソールで、メニュー f5fbd278915eb7aa.png > [API とサービス] > [ライブラリ] に移動します。

  6. Google Chat API」を検索し、結果のリストから、この API を選択します。
  7. [Google Chat API] ページで、[有効にする] をクリックします。
  8. API を有効にしたら、[構成] をクリックします。認証情報の作成に関するメッセージは無視して構いません。
  9. [構成] ページで、手順を実施します。
  • [アプリ名] に、「Attendance Bot」と入力します。
  • [アバターの URL] に、「https://goo.gl/kv2ENA」と入力します。
  • [説明] に、「Apps Script codelab Chat app」と入力します。
  • [機能] で、[1:1 のメッセージを受信する] を選択します。
  • [接続設定] で、[Apps Script プロジェクト] を選択して、テキスト ボックスにスクリプトのデプロイ ID を貼り付けます。
  • [権限] の [ドメイン内の特定のユーザーとグループ] を選択します。プルダウン メニューの下のテキスト ボックスに、Google Workspace 組織に関連付けられているメールアドレスを入力します。
  • [保存] をクリックします。

変更内容を保存したら、Google Chat API ページの [アプリのステータス] で、[ライブ - ユーザーが利用可能] というステータスになっていることを確認します。

Chat アプリをテストする

Google Chat でアプリをテストするには、手順を実施します。

  1. Google Chat を開きます。
  2. [チャットを開始] round_add_black_24dp.png > [アプリを検索] をクリックして、Chat アプリに新しいダイレクト メッセージを送信します。
  3. [アプリを検索] ページで、「Attendance Bot」を検索します。
  4. [Attendance Bot] の隣にある、[追加] > [Chat] をクリックします。

ダイレクト メッセージのスレッドが開き、次の画像のように、DM への追加に対する Chat アプリからの感謝のメッセージが表示されます。

22ea6d660d72eeca.png

5. カード形式のレスポンスを定義する

前の手順では、作成したアプリは Google Chat のイベントに対してシンプルなテキストのレスポンスを返していました。この手順では、カードを使用したレスポンスを返すようにアプリを更新します。

カード形式のレスポンス

Google Chat では、カードを使用したレスポンスがサポートされています。カードは視覚的なコンテナであり、ユーザー インターフェース ウィジェットをまとめてグループ化できます。カードには、ヘッダー、段落テキスト、一連のボタン、画像、Key-Value のテキストを表示できます。アプリでは、Google Chat に対するレスポンスを JSON 形式の 1 つ以上のカードで定義でき、レスポンスは対応する UI 要素に変換されます。

次の画像は、3 つのセクションを含むカード形式のレスポンスです。この中には、ヘッダー、Key-Value のウィジェット、画像ウィジェット、テキストボタンがあります。

b5a194ed8d745ba9.png

ユーザーのメッセージに対してカード形式のレスポンスを返すには、次のコードを Chat アプリの Code.gs ファイルに追加します。

コード.gs

var DEFAULT_IMAGE_URL = 'https://goo.gl/bMqzYS';
var HEADER = {
  header: {
    title : 'Attendance Bot',
    subtitle : 'Log your vacation time',
    imageUrl : DEFAULT_IMAGE_URL
  }
};

/**
 * Creates a card-formatted response.
 * @param {object} widgets the UI components to send
 * @return {object} JSON-formatted response
 */
function createCardResponse(widgets) {
  return {
    cards: [HEADER, {
      sections: [{
        widgets: widgets
      }]
    }]
  };
}

/**
 * Responds to a MESSAGE event triggered
 * in Google Chat.
 *
 * @param event the event object from Google Chat
 * @return JSON-formatted response
 */
function onMessage(event) {
  var userMessage = event.message.text;

  var widgets = [{
    "textParagraph": {
      "text": "You said: " + userMessage
    }
  }];

  return createCardResponse(widgets);
}

この手順で追加した onMessage() 関数は、ユーザーの元のメッセージを読み取り、シンプルな TextParagragh ウィジェットとしてレスポンスを作成します。次に、onMessage() 関数は createCardResponse() を呼び出します。これにより、TextParagraph ウィジェットが 1 つのカードのセクション内に配置されます。bot は、カード形式のレスポンスで構成された JavaScript オブジェクトを Google Chat に返します。

Chat アプリをテストする

このアプリをテストするには、Google Chat のアプリとのダイレクト メッセージに戻り、メッセージを入力します(メッセージの内容は何でも構いません)。

e12417d9aa7e177c.png

onMessage() イベント ハンドラは、Google Chat によって渡されたイベント オブジェクトを解析し、ユーザーの元のメッセージを取り出します。また、イベントを生成したユーザーの名前、そのユーザーのメールアドレス、イベントが発生したスペースの名前など、イベントに関するその他の情報も取得できます。

Google Chat によって送信されるイベント オブジェクトの構造について詳しくは、イベント形式に関するページをご覧ください。

6. カード内のボタンクリックに応答する

前の手順では、作成した Chat アプリは、ユーザーからのメッセージ(MESSAGE イベント)に対して、TextParagragh ウィジェットを含むシンプルなカードで返信しました。この手順では、それぞれのボタンにカスタム アクションが定義された、複数のボタンを含むレスポンスを作成します。

インタラクティブなカード

カード形式のレスポンスには、2 種類のいずれかのボタンを含めることができます。1 つは TextButton ウィジェットで、テキストのみのボタンを表示します。もう 1 つは ImageButton ウィジェットで、テキストなしのシンプルなアイコンまたは画像のボタンを表示します。TextButton ウィジェットと ImageButton ウィジェットのどちらも、onClick の 2 つの動作(Google Chat に対する JSON 形式のレスポンスで定義されます)のいずれか、つまり openLink または action をサポートします。名前のとおり、openLink は指定されたリンクを新しいブラウザタブで開きます。

action オブジェクトでは、ボタンで実行するカスタム アクションを指定します。action オブジェクトでは、一意の actionMethodName や Key-Value 形式のパラメータなど、複数の任意の値を指定できます。

ボタンに対して action オブジェクトを指定すると、インタラクティブなカードが作成されます。ユーザーがメッセージのボタンをクリックすると、Google Chat は CARD_CLICKED イベントを生成し、元のメッセージを送信したアプリに対してリクエストを返送します。その後、このアプリは Google Chat が生成したイベントを処理し、そのスペースに対してレスポンスを返す必要があります。

Code.gs 内の onMessage() 関数を次のコードで置き換えます。このコードにより、Google Chat に送信されるカードに 2 つのボタンが作成されます。1 つは [Set vacation in Gmail] ボタンでもう 1 つは [Block out day in Calendar] ボタンです。

コード.gs

var REASON = {
  SICK: 'Out sick',
  OTHER: 'Out of office'
};
/**
 * Responds to a MESSAGE event triggered in Google Chat.
 * @param {object} event the event object from Google Chat
 * @return {object} JSON-formatted response
 */
function onMessage(event) {
  console.info(event);
  var reason = REASON.OTHER;
  var name = event.user.displayName;
  var userMessage = event.message.text;

  // If the user said that they were 'sick', adjust the image in the
  // header sent in response.
  if (userMessage.indexOf('sick') > -1) {
    // Hospital material icon
    HEADER.header.imageUrl = 'https://goo.gl/mnZ37b';
    reason = REASON.SICK;
  } else if (userMessage.indexOf('vacation') > -1) {
    // Spa material icon
    HEADER.header.imageUrl = 'https://goo.gl/EbgHuc';
  }

  var widgets = [{
    textParagraph: {
      text: 'Hello, ' + name + '.<br/>Are you taking time off today?'
    }
  }, {
    buttons: [{
      textButton: {
        text: 'Set vacation in Gmail',
        onClick: {
          action: {
            actionMethodName: 'turnOnAutoResponder',
            parameters: [{
              key: 'reason',
              value: reason
            }]
          }
        }
      }
    }, {
      textButton: {
        text: 'Block out day in Calendar',
        onClick: {
          action: {
            actionMethodName: 'blockOutCalendar',
            parameters: [{
              key: 'reason',
              value: reason
            }]
          }
        }
      }
    }]
  }];
  return createCardResponse(widgets);
}

CARD_CLICKED イベントを処理するには、Chat アプリのスクリプトに onCardClick() 関数を追加する必要があります。Code.gs に、onCardClick() 関数を定義する次のコードを追加します。

コード.gs

/**
 * Responds to a CARD_CLICKED event triggered in Google Chat.
 * @param {object} event the event object from Google Chat
 * @return {object} JSON-formatted response
 * @see https://developers.google.com/chat/api/guides/message-formats/events
 */
function onCardClick(event) {
  console.info(event);
  var message = '';
  var reason = event.action.parameters[0].value;
  if (event.action.actionMethodName == 'turnOnAutoResponder') {
    turnOnAutoResponder(reason);
    message = 'Turned on vacation settings.';
  } else if (event.action.actionMethodName == 'blockOutCalendar') {
    blockOutCalendar(reason);
    message = 'Blocked out your calendar for the day.';
  } else {
    message = "I'm sorry; I'm not sure which button you clicked.";
  }
  return { text: message };
}

ユーザーによるクリックへの応答として、Chat アプリは、Gmail でユーザーの不在通知に「out of office(休暇中)」のメッセージを設定するか、ユーザーのカレンダーに終日のミーティング予定を設定するか、この 2 つのうちいずれかを実行します。これらのタスクを実行するために、アプリは Gmail Advanced Service および Calendar Service を呼び出します。

次のコードをスクリプトに追加して、Chat アプリと Gmail および Google カレンダーを連携させます。

コード.gs

var ONE_DAY_MILLIS = 24 * 60 * 60 * 1000;
/**
 * Turns on the user's vacation response for today in Gmail.
 * @param {string} reason the reason for vacation, either REASON.SICK or REASON.OTHER
 */
function turnOnAutoResponder(reason) {
  var currentTime = (new Date()).getTime();
  Gmail.Users.Settings.updateVacation({
    enableAutoReply: true,
    responseSubject: reason,
    responseBodyHtml: "I'm out of the office today; will be back on the next business day.<br><br><i>Created by Attendance Bot!</i>",
    restrictToContacts: true,
    restrictToDomain: true,
    startTime: currentTime,
    endTime: currentTime + ONE_DAY_MILLIS
  }, 'me');
}

/**
 * Places an all-day meeting on the user's Calendar.
 * @param {string} reason the reason for vacation, either REASON.SICK or REASON.OTHER
 */
function blockOutCalendar(reason) {
  CalendarApp.createAllDayEvent(reason, new Date(), new Date(Date.now() + ONE_DAY_MILLIS));
}

最後に、プロジェクトで Gmail Advanced Service を有効にする必要があります。Gmail API を有効にするには、次の手順を実施します。

  1. Apps Script エディタで、[サービス] の隣にある [サービスを追加] round_add_black_24dp.png をクリックします。
  2. [Gmail API] を選択します。
  3. その下にある [Google Cloud Platform API ダッシュボード] をクリックして、Google Cloud コンソールを開きます。
  4. [API とサービスの有効化] をクリックします。
  5. Gmail API」を検索して、[Gmail API] をクリックします。
  6. [Gmail API] ページで、[有効にする] をクリックします。

Chat アプリをテストする

このバージョンの Chat アプリをテストするには、前の手順で始めた DM を Google Chat で開き、「I'm going on vacation」と入力します。アプリから、次の画像のようなカードが返されます。

注: アプリへのアクセス権を提供するよう求められた場合は、2 回目のメッセージ入力が必要になる場合があります。

c0e8d9d0b5d0cf8b.png

7. 完了

Chat アプリでユーザーのメッセージに応答できるようになりました。さらに、Gmail で不在通知を設定し、カレンダーに終日の予定を設定できるようになりました。

学習した内容

  • Apps Script を使用して Google Chat アプリを作成する
  • ユーザー メッセージに対してシンプルなレスポンスを返す
  • Chat アプリを通じて、ユーザーの代わりに他の Google Workspace サービスとやり取りする

詳細