Google Chat で連絡先を収集、管理する

このチュートリアルでは、Google Chat ユーザーが個人用とビジネス用の連絡先を管理できるようにする Google Chat アプリを作成する方法について説明します。情報を収集するため、Chat アプリはカード メッセージとダイアログで連絡先フォームの入力を促します。

Chat アプリの使用例:

  • スラッシュ コマンドからのお問い合わせフォーム。
    図 1: Chat アプリは、スラッシュ コマンド /about にテキスト メッセージと、連絡先フォームを開くボタンで応答します。
  • ダイアログのお問い合わせフォーム。
    図 2. Chat 用アプリで、ユーザーが連絡先に関する情報を入力できるダイアログが開きます。
  • ダイアログを確認して確認します。
    図 3.Chat アプリは確認ダイアログを返します。これにより、ユーザーは送信する前に情報を確認して確認できます。
  • 新しい連絡先を確認するテキスト メッセージ。
    図 4.ユーザーがフォームを送信すると、Chat アプリから送信を確認する非公開のテキスト メッセージが送信されます。
  • カードのメッセージからお問い合わせフォームにアクセスする。
    図 5. Chat アプリでは、メッセージ内のカードから連絡先を追加するようユーザーに求めるメッセージも表示されます。

前提条件

目標

アーキテクチャ

Chat アプリは Google Apps Script で作成され、インタラクション イベントを使用して Chat ユーザーを処理し、応答します。

以下に、ユーザーが Chat アプリを通常どのように操作するかを示します。

  1. ユーザーが Chat アプリでダイレクト メッセージを開くか、Chat アプリを既存のスペースに追加します。

  2. チャットアプリは、連絡先フォームを作成して card オブジェクトとして表示し、連絡先を追加するようユーザーに求めます。連絡先フォームを表示するため、Chat アプリはユーザーに次のように応答します。

    • 名前リンク付きメッセージとダイレクト メッセージに、お問い合わせフォームを含むカード メッセージで返信する。
    • スラッシュ コマンド /addContact に応答して、問い合わせフォームを含むダイアログを開きます。
    • スラッシュ コマンド /about に、ユーザーがクリックして連絡先フォームを含むダイアログを開くことができる [連絡先を追加] ボタンを含むテキスト メッセージで応答します。
  3. お問い合わせフォームが表示されると、ユーザーは次のフィールドとウィジェットに連絡先情報を入力します。

    • 姓と名: 文字列を受け入れる textInput ウィジェット。
    • 生年月日: 日付のみを受け入れることができる dateTimePicker ウィジェット。
    • 連絡先の種類: ラジオボタンの selectionInput ウィジェット。ユーザーが 1 つの文字列値(Personal または Work)を選択して送信できます。
    • [確認して送信] ボタン: button ウィジェットを備えた buttonList 配列。ユーザーがクリックして入力した値を送信します。
  4. Google Chat アプリは CARD_CLICKED インタラクション イベントを処理して、ユーザーが入力した値を処理し、確認カードに値を表示します。

  5. ユーザーは確認カードを確認し、[送信] ボタンをクリックして連絡先情報を確定します。

  6. Google Chat アプリから、送信を確認する非公開のテキスト メッセージが送信されます。

環境を準備する

このセクションでは、Chat アプリ用の Google Cloud プロジェクトを作成して構成する方法について説明します。

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

Google Cloud コンソール

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

    [プロジェクトの作成] に移動

  2. [プロジェクト名] フィールドに、プロジェクトのわかりやすい名前を入力します。

    省略可: プロジェクト ID を編集するには、[編集] をクリックします。プロジェクトの作成後にプロジェクト ID を変更することはできないため、プロジェクトのライフタイムを考慮してニーズに合った ID を選択してください。

  3. [ロケーション] フィールドで [参照] をクリックして、プロジェクトの候補となるロケーションを表示します。[選択] をクリックします。
  4. [作成] をクリックします。Google Cloud コンソールで [ダッシュボード] ページが開き、数分以内にプロジェクトが作成されます。

gcloud CLI

次のいずれかの開発環境で、Google Cloud CLI(gcloud)にアクセスします。

  • Cloud Shell: gcloud CLI がすでに設定されているオンライン ターミナルを使用するには、Cloud Shell をアクティブにします。
    Cloud Shell をアクティブにする
  • ローカルシェル: ローカル開発環境を使用するには、gcloud CLI をインストールして初期化します。
    Cloud プロジェクトを作成するには、gcloud projects create コマンドを使用します。
    gcloud projects create PROJECT_ID
    作成するプロジェクトの ID を設定して、PROJECT_ID を置き換えます。

認証と権限付与の設定

Google Chat アプリでは、ユーザーが Google Chat などの Google Workspace アプリケーションでアプリを承認できるように、OAuth 同意画面を構成する必要があります。

このチュートリアルでは、テストと内部使用のみを目的とした Chat アプリをデプロイするため、同意画面にプレースホルダ情報を使用できます。Chat アプリを公開する前に、プレースホルダ情報を実際の情報に置き換えます。

  1. Google Cloud コンソールで、メニュー > [API とサービス] > [OAuth 同意画面] に移動します。

    [OAuth 同意画面] に移動

  2. [ユーザーの種類] で [内部] を選択し、[作成] をクリックします。

  3. [アプリ名] に「Contact Manager」と入力します。

  4. [ユーザー サポートメール] で、自分のメールアドレスまたは適切な Google グループを選択します。

  5. [デベロッパーの連絡先情報] にメールアドレスを入力します。

  6. [保存して次へ] をクリックします。

  7. [スコープ] ページで、[保存して次へ] をクリックします。(Chat アプリでは OAuth スコープは必要ありません)。

  8. 概要を確認し、[ダッシュボードに戻る] をクリックします。

Chat アプリを作成してデプロイする

次のセクションでは、Chat アプリに必要なすべてのアプリケーション コードを含む Apps Script プロジェクト全体をコピーして更新します。そのため、各ファイルをコピーして貼り付ける必要はありません。

必要に応じて、GitHub でプロジェクト全体を確認できます。

GitHub で表示

各ファイルの概要は次のとおりです。

main.gs

ユーザーがアプリにメッセージを送信したときの操作イベント、Chat アプリ メッセージのボタンのクリック、ダイアログの開閉イベントなど、すべてのアプリロジックを処理します。

main.gs コードを表示

apps-script/contact-form-app/main.gs
/**
 * Copyright 2024 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Responds to a MESSAGE interaction event in Google Chat.
 *
 * @param {Object} event the MESSAGE interaction event from Chat API.
 * @return {Object} message response that opens a dialog or sends private
 *                          message with text and card.
 */
function onMessage(event) {
  if (event.message.slashCommand) {
    switch (event.message.slashCommand.commandId) {
      case 1:
        // If the slash command is "/about", responds with a text message and button
        // that opens a dialog.
        return {
          text: "Manage your personal and business contacts 📇. To add a " +
                  "contact, use the slash command `/addContact`.",
          accessoryWidgets: [{
            buttonList: { buttons: [{
              text: "Add Contact",
              onClick: { action: {
                function: "openInitialDialog",
                interaction: "OPEN_DIALOG"
              }}
            }]}
          }]
        }
      case 2:
        // If the slash command is "/addContact", opens a dialog.
        return openInitialDialog();
    }
  }

  // If user sends the Chat app a message without a slash command, the app responds
  // privately with a text and card to add a contact.
  return {
    privateMessageViewer: event.user,
    text: "To add a contact, try `/addContact` or complete the form below:",
    cardsV2: [{
      cardId: "addContactForm",
      card: {
        header: { title: "Add a contact" },
        sections:[{ widgets: CONTACT_FORM_WIDGETS.concat([{
          buttonList: { buttons: [{
            text: "Review and submit",
            onClick: { action: { function : "openConfirmation" }}
          }]}
        }])}]
      }
    }]
  };
}

/**
 * Responds to CARD_CLICKED interaction events in Google Chat.
 *
 * @param {Object} event the CARD_CLICKED interaction event from Google Chat.
 * @return {Object} message responses specific to the dialog handling.
 */
function onCardClick(event) {
  // Initial dialog form page
  if (event.common.invokedFunction === "openInitialDialog") {
    return openInitialDialog();
  // Confirmation dialog form page
  } else if (event.common.invokedFunction === "openConfirmation") {
    return openConfirmation(event);
  // Submission dialog form page
  } else if (event.common.invokedFunction === "submitForm") {
    return submitForm(event);
  }
}

/**
 * Opens the initial step of the dialog that lets users add contact details.
 *
 * @return {Object} a message with an action response to open a dialog.
 */
function openInitialDialog() {
  return { actionResponse: {
    type: "DIALOG",
    dialogAction: { dialog: { body: { sections: [{
      header: "Add new contact",
      widgets: CONTACT_FORM_WIDGETS.concat([{
        buttonList: { buttons: [{
          text: "Review and submit",
          onClick: { action: { function: "openConfirmation" }}
        }]}
      }])
    }]}}}
  }};
}

/**
 * Returns the second step as a dialog or card message that lets users confirm details.
 *
 * @param {Object} event the interactive event with form inputs.
 * @return {Object} returns a dialog or private card message.
 */
function openConfirmation(event) {
  const name = fetchFormValue(event, "contactName") ?? "";
  const birthdate = fetchFormValue(event, "contactBirthdate") ?? "";
  const type = fetchFormValue(event, "contactType") ?? "";
  const cardConfirmation = {
    header: "Your contact",
    widgets: [{
      textParagraph: { text: "Confirm contact information and submit:" }}, {
      textParagraph: { text: "<b>Name:</b> " + name }}, {
      textParagraph: {
        text: "<b>Birthday:</b> " + convertMillisToDateString(birthdate)
      }}, {
      textParagraph: { text: "<b>Type:</b> " + type }}, {
      buttonList: { buttons: [{
        text: "Submit",
        onClick: { action: {
          function: "submitForm",
          parameters: [{
            key: "contactName", value: name }, {
            key: "contactBirthdate", value: birthdate }, {
            key: "contactType", value: type
          }]
        }}
      }]}
    }]
  };

  // Returns a dialog with contact information that the user input.
  if (event.isDialogEvent) {
    return { action_response: {
      type: "DIALOG",
      dialogAction: { dialog: { body: { sections: [ cardConfirmation ]}}}
    }};
  }

  // Updates existing card message with contact information that the user input.
  return {
    actionResponse: { type: "UPDATE_MESSAGE" },
    privateMessageViewer: event.user,
    cardsV2: [{
      card: { sections: [cardConfirmation]}
    }]
  }
}

/**
  * Validates and submits information from a dialog or card message
  * and notifies status.
  *
  * @param {Object} event the interactive event with parameters.
  * @return {Object} a message response that opens a dialog or posts a private
  *                  message.
  */
function submitForm(event) {
  const contactName = event.common.parameters["contactName"];
  // Checks to make sure the user entered a contact name.
  // If no name value detected, returns an error message.
  if (!contactName) {
    const errorMessage = "Don't forget to name your new contact!";
    if (event.dialogEventType === "SUBMIT_DIALOG") {
      return { actionResponse: {
        type: "DIALOG",
        dialogAction: { actionStatus: {
          statusCode: "INVALID_ARGUMENT",
          userFacingMessage: errorMessage
        }}
      }};
    } else {
      return {
        privateMessageViewer: event.user,
        text: errorMessage
      };
    }
  }

  // The Chat app indicates that it received form data from the dialog or card.
  // Sends private text message that confirms submission.
  const confirmationMessage = "✅ " + contactName + " has been added to your contacts.";
  if (event.dialogEventType === "SUBMIT_DIALOG") {
    return {
      actionResponse: {
        type: "DIALOG",
        dialogAction: { actionStatus: {
          statusCode: "OK",
          userFacingMessage: "Success " + contactName
        }}
      }
    }
  } else {
    return {
      actionResponse: { type: "NEW_MESSAGE" },
      privateMessageViewer: event.user,
      text: confirmationMessage
    };
  }
}

/**
 * Extracts form input value for a given widget.
 *
 * @param {Object} event the CARD_CLICKED interaction event from Google Chat.
 * @param {String} widgetName a unique ID for the widget, specified in the widget's name field.
 * @returns the value inputted by the user, null if no value can be found.
 */
function fetchFormValue(event, widgetName) {
  const formItem = event.common.formInputs[widgetName][""];
  // For widgets that receive StringInputs data, the value input by the user.
  if (formItem.hasOwnProperty("stringInputs")) {
    const stringInput = event.common.formInputs[widgetName][""].stringInputs.value[0];
    if (stringInput != null) {
      return stringInput;
    }
  // For widgets that receive dateInput data, the value input by the user.
  } else if (formItem.hasOwnProperty("dateInput")) {
    const dateInput = event.common.formInputs[widgetName][""].dateInput.msSinceEpoch;
     if (dateInput != null) {
       return dateInput;
     }
  }

  return null;
}

/**
 * Converts date in milliseconds since epoch to user-friendly string.
 *
 * @param {Object} millis the milliseconds since epoch time.
 * @return {string} Display-friend date (English US).
 */
function convertMillisToDateString(millis) {
  const date = new Date(millis);
  const options = { year: 'numeric', month: 'long', day: 'numeric' };
  return date.toLocaleDateString('en-US', options);
}
contactForm.gs

ユーザーからフォームデータを受け取るウィジェットが含まれます。これらのフォーム入力ウィジェットは、メッセージとダイアログに表示されるカードに表示されます。

contactForm.gs コードを表示

apps-script/contact-form-app/contactForm.gs
/**
 * Copyright 2024 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * The section of the contact card that contains the form input widgets. Used in a dialog and card message.
 * To add and preview widgets, use the Card Builder: https://addons.gsuite.google.com/uikit/builder
 */
const CONTACT_FORM_WIDGETS = [
  {
    "textInput": {
      "name": "contactName",
      "label": "First and last name",
      "type": "SINGLE_LINE"
    }
  },
  {
    "dateTimePicker": {
      "name": "contactBirthdate",
      "label": "Birthdate",
      "type": "DATE_ONLY"
    }
  },
  {
    "selectionInput": {
      "name": "contactType",
      "label": "Contact type",
      "type": "RADIO_BUTTON",
      "items": [
        {
          "text": "Work",
          "value": "Work",
          "selected": false
        },
        {
          "text": "Personal",
          "value": "Personal",
          "selected": false
        }
      ]
    }
  }
];
appsscript.json

Chat アプリの Apps Script プロジェクトを定義して構成する Apps Script マニフェスト

appsscript.json コードを表示

apps-script/contact-form-app/appsscript.json
{
  "timeZone": "America/Los_Angeles",
  "dependencies": {},
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8",
  "chat": {}
}

Cloud プロジェクトの番号と ID を確認する

  1. Google Cloud コンソールで、Cloud プロジェクトに移動します。

    Google Cloud コンソールに移動

  2. 設定とユーティリティ > [プロジェクトの設定] をクリックします。

  3. [プロジェクト番号] フィールドと [プロジェクト ID] フィールドの値をメモします。これらは、次のセクションで使用します。

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

Apps Script プロジェクトを作成して Cloud プロジェクトに接続するには:

  1. 次のボタンをクリックして、Apps Script プロジェクト「Manage contacts in Google Chat」を開きます。
    プロジェクトを開く
  2. [概要] をクリックします。
  3. 概要ページで、コピーを作成するアイコン [コピーを作成] をクリックします。
  4. Apps Script プロジェクトのコピーに名前を付けます。

    1. [Google Chat で連絡先を管理する] のコピーをクリックします。

    2. [プロジェクト タイトル] に「Contact Manager - Google Chat app」と入力します。

    3. [名前を変更] をクリックします。

Apps Script プロジェクトの Cloud プロジェクトを設定する

  1. Apps Script プロジェクトで、プロジェクト設定のアイコン [プロジェクトの設定] をクリックします。
  2. [Google Cloud Platform(GCP)プロジェクト] で、[プロジェクトを変更] をクリックします。
  3. [GCP プロジェクト番号] に、Cloud プロジェクトのプロジェクト番号を貼り付けます。
  4. [プロジェクトを設定] をクリックします。Cloud プロジェクトと Apps Script プロジェクトが接続されました。

Apps Script のデプロイを作成する

すべてのコードが配置されたので、Apps Script プロジェクトをデプロイします。デプロイ ID は、Google Cloud で Chat アプリを構成するときに使用します。

  1. Apps Script で Chat アプリのプロジェクトを開きます。

    [Apps Script] に移動

  2. [Deploy] > [New deployment] をクリックします。

  3. [アドオン] がまだ選択されていない場合は、[種類の選択] の横にあるデプロイタイプ プロジェクト設定のアイコン をクリックし、[アドオン] を選択します。

  4. [説明] に、このバージョンの説明を入力します(例: Test of Contact Manager)。

  5. [デプロイ] をクリックします。Apps Script は、デプロイが成功したことを報告し、デプロイ ID を提供します。

  6. [コピー] をクリックしてデプロイ ID をコピーし、[完了] をクリックします。

Google Cloud コンソールで Chat アプリを構成する

このセクションでは、Google Cloud コンソールで Google Chat API を構成し、Chat アプリに関する情報(Apps Script プロジェクトから作成したデプロイメントの ID など)を設定します。

  1. Google Cloud コンソールで、メニュー > [その他のプロダクト] > [Google Workspace] > [プロダクト ライブラリ] > [Google Chat API] > [管理] > [構成] をクリックします。

    Chat API の構成に移動

  2. [アプリ名] に「Contact Manager」と入力します。

  3. [アバターの URL] に「https://developers.google.com/chat/images/contact-icon.png」と入力します。

  4. [説明] に「Manage your personal and business contacts」と入力します。

  5. [インタラクティブ機能を有効にする] をクリックしてオンにします。

  6. [機能] で、[1:1 のメッセージを受信する] と [スペースとグループの会話に参加する] のチェックボックスをオンにします。

  7. [Connection settings] で [Apps Script] を選択します。

  8. [Deployment ID] に、前のセクションで Apps Script デプロイメントを作成するときにコピーした Apps Script デプロイ ID を貼り付けます。

  9. [スラッシュ コマンド] で、スラッシュ コマンド /about/addContact を設定します。

    1. [スラッシュ コマンドを追加] をクリックして、最初のスラッシュ コマンドを設定します。
    2. [名前] に「/about」と入力します。
    3. [コマンド ID] に「1」と入力します。
    4. [説明] に「Learn how to use this Chat app to manage your contacts」と入力します。
    5. [ダイアログを開く] を選択します。
    6. [完了] をクリックします。
    7. [スラッシュ コマンドを追加] をクリックして、別のスラッシュ コマンドを設定します。
    8. [名前] に「/addContact」と入力します。
    9. [コマンド ID] に「2」と入力します。
    10. [説明] に「Submit information about a contact」と入力します。
    11. [ダイアログを開く] を選択します。
    12. [完了] をクリックします。
  10. [公開設定] で [YOUR DOMAIN の特定のユーザーとグループにこの Chat アプリの利用を許可する] チェックボックスをオンにして、メールアドレスを入力します。

  11. [ログ] で [エラーを Logging にロギング] を選択します。

  12. [保存] をクリックします。構成が保存されたことを示すメッセージが表示されます。

Chat アプリをインストールして、Chat でテストする準備が整いました。

Chat アプリをテストする

Chat アプリをテストするには、Chat アプリでダイレクト メッセージ スペースを開き、メッセージを送信します。

  1. 自分自身を Trusted Tester として追加したときに指定した Google Workspace アカウントを使用して Google Chat を開きます。

    Google Chat に移動

  2. [ 新しいチャット] をクリックします。
  3. [1 人以上のユーザーを追加] フィールドに、Chat アプリの名前を入力します。
  4. 検索結果から Chat アプリを選択します。ダイレクト メッセージが開きます。

  1. Chat アプリの新しいダイレクト メッセージに「/addContact」と入力し、Enter キーを押します。

  2. 表示されたダイアログで、連絡先情報を入力します。

    1. [名前] テキスト フィールドに名前を入力します。
    2. [生年月日] 日付選択ツールで、日付を選択します。
    3. [連絡先の種類] で、[仕事] または [個人] ラジオボタンを選択します。
  3. [確認して送信] をクリックします。

  4. 確認ダイアログで、送信した情報を確認して [送信] をクリックします。Chat アプリは、CONTACT NAME has been added to your contacts. というテキスト メッセージを返します。

  5. 必要に応じて、次の方法でお問い合わせフォームをテストして送信することもできます。

    • /about スラッシュ コマンドを使用します。チャットアプリがテキスト メッセージと、Add a contact と表示されたアクセサリ ウィジェット ボタンで返信します。ボタンをクリックすると、お問い合わせフォームのダイアログが開きます。
    • Chat アプリにスラッシュ コマンドを使用せずにダイレクト メッセージを送信します(例: Hello)。Chat アプリは、お問い合わせフォームを含むテキストとカードで返信します。

クリーンアップ

このチュートリアルで使用したリソースについて、Google Cloud アカウントに課金されないようにするには、Cloud プロジェクトを削除することをおすすめします。

  1. Google Cloud コンソールで、[リソースの管理] ページに移動します。メニュー > [IAM と管理] > [リソースを管理] をクリックします。

    Resource Manager に移動

  2. プロジェクト リストで、削除するプロジェクトを選択し、[削除] をクリックします。
  3. ダイアログでプロジェクト ID を入力し、[シャットダウン] をクリックしてプロジェクトを削除します。