HTTP Google Chat アプリを作成する

このページでは、Google Cloud サービスを使用して HTTP Google Chat アプリをビルドする方法について説明します。Chat 用アプリを作成するには、Chat 用アプリがユーザーのメッセージに応答するために使用する Cloud Run 関数を作成してデプロイします。

HTTP アーキテクチャでは、次の図に示すように、HTTP を使用して Google Cloud またはオンプレミス サーバーと統合するように Chat を構成します。

オンプレミス サーバーでウェブサービスを使用する Chat 用アプリのアーキテクチャ。

上の図では、HTTP Chat 用アプリを操作するユーザーは、次のような情報の流れになります。

  1. ユーザーが、ダイレクト メッセージまたは Chat スペースで Chat アプリにメッセージを送信します。
  2. HTTP リクエストは、Chat 用アプリのロジックを含むクラウドまたはオンプレミス システムのいずれかのウェブサーバーに送信されます。
  3. 必要に応じて、Chat 用アプリのロジックを Google Workspace サービス(カレンダーやスプレッドシートなど)、他の Google サービス(マップ、YouTube、Vertex AI など)、他のウェブ サービス(プロジェクト管理システムやチケット発行ツールなど)と統合できます。
  4. ウェブサーバーは、HTTP レスポンスを Chat の Chat 用アプリ サービスに返します。
  5. 回答がユーザーに返されます。
  6. 必要に応じて、Chat 用アプリは Chat API を呼び出して、メッセージを非同期的に投稿したり、他のオペレーションを実行したりできます。

このアーキテクチャでは、さまざまなプログラミング言語を使用して Chat 用アプリを設計できるため、システムにすでに存在するライブラリやコンポーネントを柔軟に使用できます。

目標

  • 環境をセットアップする。
  • Cloud Run 関数を作成してデプロイする。
  • Chat 用アプリを構成します。
  • アプリをテストします。

前提条件

環境を設定する

Google API を使用する前に、Google Cloud プロジェクトで API を有効にする必要があります。1 つの Google Cloud プロジェクトで 1 つ以上の API を有効にできます。
  • Google API コンソールで、Google Chat API、Cloud Build API、Cloud Functions API、Cloud Pub/Sub API、Cloud Logging API、Artifact Registry API、Cloud Run API を有効にします。

    API を有効にする

Cloud Run functions の関数を作成してデプロイする

送信者の表示名とアバター画像を含む Chat カードを生成する Cloud Run functions の関数を作成してデプロイします。Chat 用アプリがメッセージを受信すると、関数が実行され、カードで応答します。

Chat 用アプリの関数を作成してデプロイする手順は次のとおりです。

Node.js

  1. Google API コンソールで、Cloud Run ページに移動します。

    Cloud Run に移動

    Chat 用アプリのプロジェクトが選択されていることを確認します。

  2. [関数を作成] をクリックします。

  3. [サービスの作成] ページで、関数を設定します。

    1. [サービス名] フィールドに「addonchatapp」と入力します。
    2. [リージョン] リストでリージョンを選択します。
    3. [ランタイム] リストで、最新バージョンの Node.js を選択します。
    4. [認証] セクションで、[認証が必要] を選択します。
    5. [作成] をクリックし、Cloud Run がサービスを作成するのを待ちます。コンソールによって [ソース] タブにリダイレクトされます。
  4. [ソース] タブで次の操作を行います。

    1. [エントリ ポイント] で、デフォルトのテキストを削除して avatarApp と入力します。
    2. index.js の内容を次のコードに置き換えます。
    node/chat/avatar-app/index.js
    import { http } from '@google-cloud/functions-framework';
    
    // The ID of the slash command "/about".
    // You must use the same ID in the Google Chat API configuration.
    const ABOUT_COMMAND_ID = 1;
    
    /**
     * Handle requests from Google Workspace add on
     *
     * @param {Object} req Request sent by Google Chat
     * @param {Object} res Response to be sent back to Google Chat
     */
    http('avatarApp', (req, res) => {
      const chatEvent = req.body.chat;
      let message;
      if (chatEvent.appCommandPayload) {
        message = handleAppCommand(chatEvent);
      } else {
        message = handleMessage(chatEvent);
      }
      res.send({ hostAppDataAction: { chatDataAction: { createMessageAction: {
        message: message
      }}}});
    });
    
    /**
     * Responds to an APP_COMMAND event in Google Chat.
     *
     * @param {Object} event the event object from Google Chat
     * @return the response message object.
     */
    function handleAppCommand(event) {
      switch (event.appCommandPayload.appCommandMetadata.appCommandId) {
        case ABOUT_COMMAND_ID:
          return {
            text: 'The Avatar app replies to Google Chat messages.'
          };
      }
    }
    
    /**
     * Responds to a MESSAGE event in Google Chat.
     *
     * @param {Object} event the event object from Google Chat
     * @return the response message object.
     */
    function handleMessage(event) {
      // Stores the Google Chat user as a variable.
      const chatUser = event.messagePayload.message.sender;
      const displayName = chatUser.displayName;
      const avatarUrl = chatUser.avatarUrl;
      return {
        text: 'Here\'s your avatar',
        cardsV2: [{
          cardId: 'avatarCard',
          card: {
            name: 'Avatar Card',
            header: {
              title: `Hello ${displayName}!`,
            },
            sections: [{ widgets: [{
              textParagraph: { text: 'Your avatar picture: ' }
            }, {
              image: { imageUrl: avatarUrl }
            }]}]
          }
        }]
      };
    }
    1. [保存して再デプロイ] をクリックします。

Python

  1. Google API コンソールで、Cloud Run ページに移動します。

    Cloud Run に移動

    Chat 用アプリのプロジェクトが選択されていることを確認します。

  2. [関数を作成] をクリックします。

  3. [サービスの作成] ページで、関数を設定します。

    1. [サービス名] フィールドに「addonchatapp」と入力します。
    2. [リージョン] リストでリージョンを選択します。
    3. [ランタイム] リストで、最新バージョンの Python を選択します。
    4. [認証] セクションで、[認証が必要] を選択します。
    5. [作成] をクリックし、Cloud Run がサービスを作成するのを待ちます。コンソールによって [ソース] タブにリダイレクトされます。
  4. [ソース] タブで次の操作を行います。

    1. [エントリ ポイント] で、デフォルトのテキストを削除して avatar_app と入力します。
    2. main.py の内容を次のコードに置き換えます。
    python/chat/avatar-app/main.py
    from typing import Any, Mapping
    
    import flask
    import functions_framework
    
    # The ID of the slash command "/about".
    # You must use the same ID in the Google Chat API configuration.
    ABOUT_COMMAND_ID = 1
    
    @functions_framework.http
    def avatar_app(req: flask.Request) -> Mapping[str, Any]:
      """Handle requests from Google Workspace add on
    
      Args:
        flask.Request req: the request sent by Google Chat
    
      Returns:
        Mapping[str, Any]: the response to be sent back to Google Chat
      """
      chat_event = req.get_json(silent=True)["chat"]
      if chat_event and "appCommandPayload" in chat_event:
        message = handle_app_command(chat_event)
      else:
        message = handle_message(chat_event)
      return { "hostAppDataAction": { "chatDataAction": { "createMessageAction": {
          "message": message
      }}}}
    
    def handle_app_command(event: Mapping[str, Any]) -> Mapping[str, Any]:
      """Responds to an APP_COMMAND event in Google Chat.
    
      Args:
        Mapping[str, Any] event: the event object from Google Chat
    
      Returns:
        Mapping[str, Any]: the response message object.
      """
      if event["appCommandPayload"]["appCommandMetadata"]["appCommandId"] == ABOUT_COMMAND_ID:
        return {
          "text": "The Avatar app replies to Google Chat messages.",
        }
      return {}
    
    def handle_message(event: Mapping[str, Any]) -> Mapping[str, Any]:
      """Responds to a MESSAGE event in Google Chat.
    
      Args:
        Mapping[str, Any] event: the event object from Google Chat
    
      Returns:
        Mapping[str, Any]: the response message object.
      """
      # Stores the Google Chat user as a variable.
      chat_user = event["messagePayload"]["message"]["sender"]
      display_name = chat_user.get("displayName", "")
      avatar_url = chat_user.get("avatarUrl", "")
      return {
        "text": "Here's your avatar",
        "cardsV2": [{
          "cardId": "avatarCard",
          "card": {
            "name": "Avatar Card",
            "header": {
              "title": f"Hello {display_name}!"
            },
            "sections": [{ "widgets": [
              { "textParagraph": { "text": "Your avatar picture:" }},
              { "image": { "imageUrl": avatar_url }},
            ]}]
          }
        }]
      }
    1. [保存して再デプロイ] をクリックします。

Java

  1. Google API コンソールで、Cloud Run ページに移動します。

    Cloud Run に移動

    Chat 用アプリのプロジェクトが選択されていることを確認します。

  2. [関数を作成] をクリックします。

  3. [サービスの作成] ページで、関数を設定します。

    1. [サービス名] フィールドに「addonchatapp」と入力します。
    2. [リージョン] リストでリージョンを選択します。
    3. [ランタイム] リストで、最新バージョンの Java を選択します。
    4. [認証] セクションで、[認証が必要] を選択します。
    5. [作成] をクリックし、Cloud Run がサービスを作成するのを待ちます。コンソールによって [ソース] タブにリダイレクトされます。
  4. [ソース] タブで次の操作を行います。

    1. [エントリ ポイント] で、デフォルトのテキストを削除して App と入力します。
    2. デフォルトの Java ファイルの名前を src/main/java/com/google/chat/avatar/App.java に変更します。
    3. App.java の内容を次のコードに置き換えます。
    java/chat/avatar-app/src/main/java/com/google/chat/avatar/App.java
    package com.google.chat.avatar;
    
    import com.google.api.services.chat.v1.model.CardWithId;
    import com.google.api.services.chat.v1.model.GoogleAppsCardV1Card;
    import com.google.api.services.chat.v1.model.GoogleAppsCardV1CardHeader;
    import com.google.api.services.chat.v1.model.GoogleAppsCardV1Image;
    import com.google.api.services.chat.v1.model.GoogleAppsCardV1Section;
    import com.google.api.services.chat.v1.model.GoogleAppsCardV1TextParagraph;
    import com.google.api.services.chat.v1.model.GoogleAppsCardV1Widget;
    import com.google.api.services.chat.v1.model.Message;
    import com.google.cloud.functions.HttpFunction;
    import com.google.cloud.functions.HttpRequest;
    import com.google.cloud.functions.HttpResponse;
    import com.google.gson.Gson;
    import com.google.gson.JsonObject;
    import java.util.List;
    
    public class App implements HttpFunction {
      // The ID of the slash command "/about".
      // You must use the same ID in the Google Chat API configuration.
      private static final int ABOUT_COMMAND_ID = 1;
    
      private static final Gson gson = new Gson();
    
      /**
       * Handle requests from Google Workspace add on
       * 
       * @param request the request sent by Google Chat
       * @param response the response to be sent back to Google Chat
       */
      @Override
      public void service(HttpRequest request, HttpResponse response) throws Exception {
        JsonObject event = gson.fromJson(request.getReader(), JsonObject.class);
        JsonObject chatEvent = event.getAsJsonObject("chat");
        Message message;
        if (chatEvent.has("appCommandPayload")) {
          message = handleAppCommand(chatEvent);
        } else {
          message = handleMessage(chatEvent);
        }
        JsonObject createMessageAction = new JsonObject();
        createMessageAction.add("message", gson.fromJson(gson.toJson(message), JsonObject.class));
        JsonObject chatDataAction = new JsonObject();
        chatDataAction.add("createMessageAction", createMessageAction);
        JsonObject hostAppDataAction = new JsonObject();
        hostAppDataAction.add("chatDataAction", chatDataAction);
        JsonObject dataActions = new JsonObject();
        dataActions.add("hostAppDataAction", hostAppDataAction);
        response.getWriter().write(gson.toJson(dataActions));
      }
    
      /**
       * Handles an APP_COMMAND event in Google Chat.
       *
       * @param event the event object from Google Chat
       * @return the response message object.
       */
      private Message handleAppCommand(JsonObject event) throws Exception {
        switch (event.getAsJsonObject("appCommandPayload")
          .getAsJsonObject("appCommandMetadata").get("appCommandId").getAsInt()) {
          case ABOUT_COMMAND_ID:
            return new Message()
              .setText("The Avatar app replies to Google Chat messages.");
          default:
            return null;
        }
      }
    
      /**
       * Handles a MESSAGE event in Google Chat.
       *
       * @param event the event object from Google Chat
       * @return the response message object.
       */
      private Message handleMessage(JsonObject event) throws Exception {
        // Stores the Google Chat user as a variable.
        JsonObject chatUser = event.getAsJsonObject("messagePayload").getAsJsonObject("message").getAsJsonObject("sender");
        String displayName = chatUser.has("displayName") ? chatUser.get("displayName").getAsString() : "";
        String avatarUrl = chatUser.has("avatarUrl") ? chatUser.get("avatarUrl").getAsString() : "";
        return new Message()
          .setText("Here's your avatar")
          .setCardsV2(List.of(new CardWithId()
            .setCardId("avatarCard")
            .setCard(new GoogleAppsCardV1Card()
              .setName("Avatar Card")
              .setHeader(new GoogleAppsCardV1CardHeader()
                .setTitle(String.format("Hello %s!", displayName)))
              .setSections(List.of(new GoogleAppsCardV1Section().setWidgets(List.of(
                new GoogleAppsCardV1Widget().setTextParagraph(new GoogleAppsCardV1TextParagraph()
                  .setText("Your avatar picture:")),
                new GoogleAppsCardV1Widget()
                  .setImage(new GoogleAppsCardV1Image().setImageUrl(avatarUrl)))))))));
      }
    }
  5. pom.xml の内容を次のコードに置き換えます。

    java/chat/avatar-app/pom.xml
    <project xmlns="http://maven.apache.org/POM/4.0.0"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
    
      <groupId>com.google.chat</groupId>
      <artifactId>avatar-app</artifactId>
      <version>1.0-SNAPSHOT</version>
    
      <properties>
        <maven.compiler.target>17</maven.compiler.target>
        <maven.compiler.source>17</maven.compiler.source>
      </properties>
    
      <dependencies>
        <dependency>
          <groupId>com.google.cloud.functions</groupId>
          <artifactId>functions-framework-api</artifactId>
          <version>1.1.4</version>
        </dependency>
        <dependency>
          <groupId>com.google.code.gson</groupId>
          <artifactId>gson</artifactId>
          <version>2.9.1</version>
        </dependency>
        <dependency>
          <groupId>com.google.apis</groupId>
          <artifactId>google-api-services-chat</artifactId>
          <version>v1-rev20230115-2.0.0</version>
        </dependency>
      </dependencies>
    
      <build>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
            <excludes>
              <exclude>.google/</exclude>
            </excludes>
            </configuration>
          </plugin>
        </plugins>
      </build>
    </project>
    1. [保存して再デプロイ] をクリックします。

Cloud Run サービスの詳細ページが開きます。関数がデプロイされるまで待ちます。

Chat 用アプリを構成する

Cloud Run functions の関数をデプロイしたら、次の手順に沿って Google Chat 用アプリを構成してデプロイします。

  1. Google API コンソールで、Cloud Run ページに移動します。

    Cloud Run に移動

    Cloud Run を有効にしたプロジェクトが選択されていることを確認します。

  2. 関数のリストで、[addonchatapp] をクリックします。

  3. [サービスの詳細] ページで、関数の URL をコピーします。URL の末尾が run.app である。

  4. Google Cloud の検索フィールドで「Google Chat API」を検索し、[Google Chat API]、[管理] の順にクリックします。

    Chat API に移動

  5. [構成] をクリックして、Google Chat アプリを設定します。

    1. [アプリ名] に「Quickstart App」と入力します。
    2. [アバターの URL] に「https://developers.google.com/workspace/chat/images/quickstart-app-avatar.png」と入力します。
    3. [説明] に「Quickstart app」と入力します。
    4. [機能] で、[スペースとグループの会話に参加する] を選択します。
    5. [接続設定] で、[HTTP エンドポイント URL] を選択します。
    6. [トリガー] で、[すべてのトリガーに共通の HTTP エンドポイント URL を使用する] を選択し、Cloud Run functions の関数トリガーの URL をボックスに貼り付けます。
    7. [公開設定] で、[ドメイン内の特定のユーザーおよびグループにこの Google Chat 用アプリの利用を許可する] を選択し、メールアドレスを入力します。
    8. [ログ] で、[エラーを Logging にロギング] を選択します。
  6. [保存] をクリックします。

  7. [接続設定] で、[サービス アカウントのメールアドレス] をコピーします。このメールアドレスは、Chat 用アプリが関数を呼び出すことを承認するときに必要になります。

次に、Cloud Run functions を呼び出す権限を Chat 用アプリに付与します。

関数を呼び出すための権限を Google Chat に付与する

Google Chat が関数を呼び出すことを承認するには、Cloud Run 起動元ロールを持つ Chat 用アプリのサービス アカウントを追加します。

  1. Google API コンソールで、Cloud Run ページに移動します。

    Cloud Run に移動

  2. Cloud Run サービスリストで、受信側関数の横にあるチェックボックスをオンにします。(関数自体はクリックしないでください)。

  3. [権限] をクリックします。[権限] パネルが開きます。

  4. [プリンシパルを追加] をクリックします。

  5. [新しいプリンシパル] に、Chat 用アプリに関連付けられているサービス アカウントのメールアドレスを入力します。

    サービス アカウントのメールアドレスは、Chat API の構成ページの [接続設定] > [HTTP エンドポイント URL] > [サービス アカウントのメールアドレス] にあります。

    Chat API の構成に移動

  6. [ロールを選択] で、[Cloud Run] > [Cloud Run 起動元] を選択します。

  7. [保存] をクリックします。

Chat アプリは、Chat でメッセージを受信して返信できる状態です。

Chat 用アプリをテストする

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

  1. 信頼できるテスターとして登録したときに指定した Google Workspace アカウントを使用して、Google Chat を開きます。

    Google Chat に移動

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

  5. そのアプリの新しいダイレクト メッセージに、「Hello」と入力して enter を押します。

Chat 用アプリのメッセージには、次の画像に示すように、送信者の名前とアバター画像を表示するカードが含まれています。

送信者の表示名とアバター画像を含むカードで応答する Chat 用アプリ

Trusted Tester を追加してインタラクティブ機能のテストについて詳しくは、Google Chat 用アプリのインタラクティブ機能をテストするをご覧ください。

トラブルシューティング

Google Chat 用アプリまたはカードがエラーを返すと、Chat インターフェースに「エラーが発生しました」というメッセージが表示されます。または「リクエストを処理できませんでした。」と表示されることがあります。Chat UI にエラー メッセージが表示されない場合でも、Chat 用アプリやカードで予期しない結果が生じることがあります。たとえば、カード メッセージが表示されないことがあります。

Chat UI にエラー メッセージが表示されない場合でも、Chat 用アプリのエラー ロギングが有効になっている場合は、エラーの修正に役立つ説明的なエラー メッセージとログデータを利用できます。エラーの表示、デバッグ、修正については、Google Chat のエラーのトラブルシューティングと修正をご覧ください。

クリーンアップ

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

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

    Resource Manager に移動します。

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

アドオンではない Chat 用アプリ: HTTP Google Chat 用アプリを作成する

Google Workspace アドオンではない Chat 用アプリをビルドするには、次の手順に沿って Cloud Run 関数をデプロイし、呼び出し権限を付与して、アドオンではない Chat 用アプリを構成します。

アドオンではない Chat 用アプリの Cloud Run 関数を作成してデプロイする

Node.js

  1. Google API コンソールで、Cloud Run ページに移動します。

    Cloud Run に移動

    Chat 用アプリのプロジェクトが選択されていることを確認します。

  2. [関数を作成] をクリックします。

  3. [サービスの作成] ページで、関数を設定します。

    1. [サービス名] フィールドに「quickstartchatapp」と入力します。
    2. [リージョン] リストでリージョンを選択します。
    3. [ランタイム] リストで、最新バージョンの Node.js を選択します。
    4. [認証] セクションで、[認証が必要] を選択します。
    5. [作成] をクリックし、Cloud Run がサービスを作成するのを待ちます。コンソールによって [ソース] タブにリダイレクトされます。
  4. [ソース] タブで次の操作を行います。

    1. [エントリ ポイント] で、デフォルトのテキストを削除して avatarApp と入力します。
    2. index.js の内容を次のコードに置き換えます。

      node/avatar-app/index.js
      const functions = require('@google-cloud/functions-framework');
      
      // Command IDs (configure these in Google Chat API)
      const ABOUT_COMMAND_ID = 1; // ID for the "/about" slash command
      const HELP_COMMAND_ID = 2; // ID for the "Help" quick command
      
      /**
       * Google Cloud Function that handles HTTP requests from Google Chat.
       *
       * @param {Object} req - The HTTP request object sent from Google Chat.
       * @param {Object} res - The HTTP response object.
       */
      functions.http('avatarApp', (req, res) => {
        const event = req.body;
      
        if (event.appCommandMetadata) {
          handleAppCommands(event, res);
        } else {
          handleRegularMessage(event, res);
        }
      });
      
      /**
       * Handles slash and quick commands.
       *
       * @param {Object} event - The Google Chat event.
       * @param {Object} res - The HTTP response object.
       */
      function handleAppCommands(event, res) {
        const {appCommandId, appCommandType} = event.appCommandMetadata;
      
        switch (appCommandId) {
          case ABOUT_COMMAND_ID:
            return res.send({
              privateMessageViewer: event.user,
              text: 'The Avatar app replies to Google Chat messages.'
            });
          case HELP_COMMAND_ID:
            return res.send({
              privateMessageViewer: event.user,
              text: 'The Avatar app replies to Google Chat messages.'
            });
        }
      }
      
      /**
       * Handles regular messages (not commands).
       *
       * @param {Object} event - The Google Chat event.
       * @param {Object} res - The HTTP response object.
       */
      function handleRegularMessage(event, res) {
        const messageData = createMessage(event.user);
        res.send(messageData);
      }
      
      /**
       * Creates a card message with the user's avatar.
       *
       * @param {Object} user - The user who sent the message.
       * @param {string} user.displayName - The user's display name.
       * @param {string} user.avatarUrl - The URL of the user's avatar.
       * @return {Object} - The card message object.
       */
      function createMessage({displayName, avatarUrl}) {
        return {
          text: 'Here\'s your avatar',
          cardsV2: [{
            cardId: 'avatarCard',
            card: {
              name: 'Avatar Card',
              header: {
                title: `Hello ${displayName}!`,
              },
              sections: [{
                widgets: [
                  {textParagraph: {text: 'Your avatar picture:'}},
                  {image: {imageUrl: avatarUrl}},
                ],
              }],
            },
          }],
        };
      }

    3. [保存して再デプロイ] をクリックします。

Python

  1. Google API コンソールで、Cloud Run ページに移動します。

    Cloud Run に移動

    Chat 用アプリのプロジェクトが選択されていることを確認します。

  2. [関数を作成] をクリックします。

  3. [サービスの作成] ページで、関数を設定します。

    1. [サービス名] フィールドに「quickstartchatapp」と入力します。
    2. [リージョン] リストでリージョンを選択します。
    3. [ランタイム] リストで、最新バージョンの Python を選択します。
    4. [認証] セクションで、[認証が必要] を選択します。
    5. [作成] をクリックし、Cloud Run がサービスを作成するのを待ちます。コンソールによって [ソース] タブにリダイレクトされます。
  4. [ソース] タブで次の操作を行います。

    1. [エントリ ポイント] で、デフォルトのテキストを削除して avatar_app と入力します。
    2. main.py の内容を次のコードに置き換えます。

      python/avatar-app/main.py
      from typing import Any, Mapping
      
      import flask
      import functions_framework
      
      # Command IDs (configure these in Google Chat API)
      ABOUT_COMMAND_ID = 1  # ID for the "/about" slash command
      HELP_COMMAND_ID = 2  # ID for the "Help" quick command
      
      
      @functions_framework.http
      def avatar_app(req: flask.Request) -> Mapping[str, Any]:
          """Google Cloud Function that handles HTTP requests from Google Chat.
      
          Args:
              flask.Request: the request
      
          Returns:
              Mapping[str, Any]: the response
          """
          event = req.get_json(silent=True)
      
          if event and "appCommandMetadata" in event:
              return handle_app_commands(event)
          else:
              return handle_regular_message(event)
      
      
      def handle_app_commands(event: Mapping[str, Any]) -> Mapping[str, Any]:
          """Handles slash and quick commands.
      
          Args:
              Mapping[str, Any] event: The Google Chat event.
      
          Returns:
              Mapping[str, Any]: the response
          """
          app_command_id = event["appCommandMetadata"]["appCommandId"]
      
          if app_command_id == ABOUT_COMMAND_ID:
              return {
                  "privateMessageViewer": event["user"],
                  "text": "The Avatar app replies to Google Chat messages.",
              }
          elif app_command_id == HELP_COMMAND_ID:
              return {
                  "privateMessageViewer": event["user"],
                  "text": "The Avatar app replies to Google Chat messages.",
              }
          return {}
      
      
      
      
      def handle_regular_message(event: Mapping[str, Any]) -> Mapping[str, Any]:
          """Handles regular messages (not commands).
      
          Args:
              Mapping[str, Any] event: The Google Chat event.
      
          Returns:
              Mapping[str, Any]: the response
          """
      
          if not event or "user" not in event:
              return "Invalid request."
      
          message_data = create_message(event["user"])
          return message_data
      
      
      def create_message(user: Mapping[str, Any]) -> Mapping[str, Any]:
          """Creates a card message with the user's avatar.
      
          Args:
              Mapping[str, Any] user: The user who sent the message.
      
          Returns:
              Mapping[str, Any]: a card with the user's avatar.
          """
          display_name = user.get("displayName", "")
          avatar_url = user.get("avatarUrl", "")
      
          return {
              "text": "Here's your avatar",
              "cardsV2": [
                  {
                      "cardId": "avatarCard",
                      "card": {
                          "name": "Avatar Card",
                          "header": {"title": f"Hello {display_name}!"},
                          "sections": [
                              {
                                  "widgets": [
                                      {"textParagraph": {"text": "Your avatar picture:"}},
                                      {"image": {"imageUrl": avatar_url}},
                                  ]
                              }
                          ],
                      },
                  }
              ],
          }

    3. [保存して再デプロイ] をクリックします。

Java

  1. Google API コンソールで、Cloud Run ページに移動します。

    Cloud Run に移動

    Chat 用アプリのプロジェクトが選択されていることを確認します。

  2. [関数を作成] をクリックします。

  3. [サービスの作成] ページで、関数を設定します。

    1. [サービス名] フィールドに「quickstartchatapp」と入力します。
    2. [リージョン] リストでリージョンを選択します。
    3. [ランタイム] リストで、最新バージョンの Java を選択します。
    4. [認証] セクションで、[認証が必要] を選択します。
    5. [作成] をクリックし、Cloud Run がサービスを作成するのを待ちます。コンソールによって [ソース] タブにリダイレクトされます。
  4. [ソース] タブで次の操作を行います。

    1. [エントリ ポイント] で、デフォルトのテキストを削除して App と入力します。
    2. src/main/java/com/example/Example.java を src/main/java/AvatarApp.java に名前変更します。
    3. AvatarApp.java の内容を次のコードに置き換えます。

      java/avatar-app/src/main/java/AvatarApp.java
      import com.google.api.services.chat.v1.model.CardWithId;
      import com.google.api.services.chat.v1.model.GoogleAppsCardV1Card;
      import com.google.api.services.chat.v1.model.GoogleAppsCardV1CardHeader;
      import com.google.api.services.chat.v1.model.GoogleAppsCardV1Image;
      import com.google.api.services.chat.v1.model.GoogleAppsCardV1Section;
      import com.google.api.services.chat.v1.model.GoogleAppsCardV1TextParagraph;
      import com.google.api.services.chat.v1.model.GoogleAppsCardV1Widget;
      import com.google.api.services.chat.v1.model.Message;
      import com.google.api.services.chat.v1.model.User;
      import com.google.cloud.functions.HttpFunction;
      import com.google.cloud.functions.HttpRequest;
      import com.google.cloud.functions.HttpResponse;
      import com.google.gson.Gson;
      import com.google.gson.JsonObject;
      import java.util.List;
      
      public class AvatarApp implements HttpFunction {
        private static final Gson gson = new Gson();
      
        // Command IDs (configure these in Google Chat API)
        private static final int ABOUT_COMMAND_ID = 1; // ID for the "/about" slash command
        private static final int HELP_COMMAND_ID = 2; // ID for the "Help" quick command
      
        @Override
        public void service(HttpRequest request, HttpResponse response) throws Exception {
          JsonObject event = gson.fromJson(request.getReader(), JsonObject.class);
      
          if (event.has("appCommandMetadata")) {
            handleAppCommands(event, response);
          } else {
            handleRegularMessage(event, response);
          }
        }
      
        /**
         * Handles slash and quick commands.
         *
         * @param event    The Google Chat event.
         * @param response The HTTP response object.
         */
        private void handleAppCommands(JsonObject event, HttpResponse response) throws Exception {
          int appCommandId = event.getAsJsonObject("appCommandMetadata").get("appCommandId").getAsInt();
      
          switch (appCommandId) {
            case ABOUT_COMMAND_ID:
              Message aboutMessage = new Message();
              aboutMessage.setText("The Avatar app replies to Google Chat messages.");
              aboutMessage.setPrivateMessageViewer(new User()
                  .setName(event.getAsJsonObject("user").get("name").getAsString()));
              response.getWriter().write(gson.toJson(aboutMessage));
              return;
            case HELP_COMMAND_ID:
              Message helpMessage = new Message();
              helpMessage.setText("The Avatar app replies to Google Chat messages.");
              helpMessage.setPrivateMessageViewer(new User()
                  .setName(event.getAsJsonObject("user").get("name").getAsString()));
              response.getWriter().write(gson.toJson(helpMessage));
              return;
          }
        }
      
        /**
         * Handles regular messages (not commands).
         *
         * @param event    The Google Chat event.
         * @param response The HTTP response object.
         */
        private void handleRegularMessage(JsonObject event, HttpResponse response) throws Exception {
      
          if (!event.has("user")) {
            response.getWriter().write("Invalid request.");
            return;
          }
      
          JsonObject user = event.getAsJsonObject("user");
          String displayName = user.has("displayName") ? user.get("displayName").getAsString() : "";
          String avatarUrl = user.has("avatarUrl") ? user.get("avatarUrl").getAsString() : "";
          Message message = createMessage(displayName, avatarUrl);
          response.getWriter().write(gson.toJson(message));
        }
      
        /**
         * Creates a card message with the user's avatar.
         *
         * @param displayName The user's display name.
         * @param avatarUrl   The URL of the user's avatar.
         * @return The card message object.
         */
        private Message createMessage(String displayName, String avatarUrl) {
          return new Message()
              .setText("Here's your avatar")
              .setCardsV2(List.of(new CardWithId()
                  .setCardId("avatarCard")
                  .setCard(new GoogleAppsCardV1Card()
                      .setName("Avatar Card")
                      .setHeader(new GoogleAppsCardV1CardHeader()
                          .setTitle(String.format("Hello %s!", displayName)))
                      .setSections(List.of(new GoogleAppsCardV1Section().setWidgets(List.of(
                          new GoogleAppsCardV1Widget()
                              .setTextParagraph(new GoogleAppsCardV1TextParagraph()
                                  .setText("Your avatar picture:")),
                          new GoogleAppsCardV1Widget()
                              .setImage(new GoogleAppsCardV1Image().setImageUrl(avatarUrl)))))))));
        }
      }

    4. pom.xml の内容を次のコードに置き換えます。

      java/avatar-app/pom.xml
      <project xmlns="http://maven.apache.org/POM/4.0.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
        <modelVersion>4.0.0</modelVersion>
      
        <groupId>gcfv2</groupId>
        <artifactId>avatar-app</artifactId>
        <version>0.0.1</version>
        <name>Avatar App</name>
      
        <properties>
          <maven.compiler.release>21</maven.compiler.release>
        </properties>
      
        <dependencies>
          <dependency>
            <groupId>com.google.cloud.functions</groupId>
            <artifactId>functions-framework-api</artifactId>
            <version>1.1.4</version>
          </dependency>
      
          <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
          <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.12.1</version>
          </dependency>
      
          <!-- https://mvnrepository.com/artifact/com.google.apis/google-api-services-chat -->
          <dependency>
            <groupId>com.google.apis</groupId>
            <artifactId>google-api-services-chat</artifactId>
            <version>v1-rev20250116-2.0.0</version>
          </dependency>
      
        </dependencies>
      
      </project>

    5. [保存して再デプロイ] をクリックします。

関数を呼び出すための権限を Google Chat に付与する

Google Chat が関数を呼び出すことを承認するには、Cloud Run 起動元ロールを持つ Google Chat サービス アカウントを追加します。

  1. Google API コンソールで、Cloud Run ページに移動します。

    Cloud Run に移動

  2. Cloud Run サービスリストで、受信側関数の横にあるチェックボックスをオンにします。(関数自体はクリックしないでください)。

  3. [権限] をクリックします。[権限] パネルが開きます。

  4. [プリンシパルを追加] をクリックします。

  5. [新しいプリンシパル] に「chat@system.gserviceaccount.com」と入力します。

  6. [ロールを選択] で、[Cloud Run] > [Cloud Run 起動元] を選択します。

  7. [保存] をクリックします。

アドオンではない Chat 用アプリを構成する

Cloud Run 関数をデプロイしたら、次の手順でアドオンではない Chat 用アプリに変換します。

  1. Google API コンソールで、Cloud Run ページに移動します。

    Cloud Run に移動

    Cloud Run を有効にしたプロジェクトが選択されていることを確認します。

  2. サービスのリストで、[quickstartchatapp] をクリックします。

  3. [サービスの詳細] ページで、関数の URL をコピーします。

  4. 「Google Chat API」を検索し、[Google Chat API]、[管理] の順にクリックします。

    Chat API に移動

  5. [構成] をクリックして、アドオンではない Chat 用アプリを設定します。

    1. [この Chat 用アプリを Google Workspace アドオンとしてビルドする] をオフにします。確認を求めるダイアログが開きます。ダイアログで [無効にする] をクリックします。
    2. [アプリ名] に「Quickstart App」と入力します。
    3. [アバターの URL] に「https://developers.google.com/workspace/chat/images/quickstart-app-avatar.png」と入力します。
    4. [説明] に「Quickstart app」と入力します。
    5. [機能] で、[スペースとグループの会話に参加する] を選択します。
    6. [接続設定] で、[HTTP エンドポイント URL] を選択します。
    7. [トリガー] で、[すべてのトリガーに共通の HTTP エンドポイント URL を使用する] を選択し、Cloud Run functions の関数トリガーの URL をボックスに貼り付けます。
    8. [公開設定] で、[ドメイン内の特定のユーザーとグループにこの Chat 用アプリの利用を許可する] を選択し、メールアドレスを入力します。
    9. [ログ] で、[エラーを Logging にロギング] を選択します。
  6. [保存] をクリックします。