[GAS/Chat]【ハンズオン】「カスタムアプリ」でオウム返しBotを作ろう!

GoogleChat未分類

どうも。ケニー(tsujikenzo)です。このシリーズでは 「GASでGoogleChat APIを使いこなそう」 をお送りしています。今日は最終回です。

前回のおさらい

前回は、GoogleChatAPIで高度なメッセージを送信しようということで、GCPとGASの連携にチャレンジしました。

最終回は、【ハンズオン】「カスタムアプリ」でオウム返しBotを作ろう!をお届けします。

はじめに

これまでお届けしたのは、GASから一方的にメッセージを送信するアプリでした。

ここまできたら、双方向のやりとりを行うアプリも実現したいですよね。

「双方向のやりとり」とは、具体的に言うと 「スペースでBotにメンションを送ると、GASが自動的に返答を呼び出してくれる」という機能です。

ハンズオンでお送りしますので、手を動かしながらやってみましょう。

おおまかな流れ

  1. Step 1:onMessage(e)関数を実装する
  2. Step 2:ウェブアプリとしてデプロイする
  3. Step 3:GCPプロジェクトにデプロイIDを紐づけする

Step 1:onMessage(e)関数を実装する

双方向アプリの心臓部、それがonMessage(e)関数です。

これは、ユーザーが手動で実行する関数ではありません。ユーザーがBotにメンションを送ったときに、Googleのサーバーが自動的に呼び出してくれる、特別な「イベントハンドラ」です。

GASに慣れている方なら、スプレッドシートを開いたときに自動で実行されるonOpen()のような仕組み、と言えば分かりやすいでしょう。

オウム返しBotの基本コード

この「イベントハンドラ」として、onMessage(e)という、決まった名前の関数を用意します。

function onMessage(e) {
  // ここに、応答のロジックを書いていく
}

この関数の引数であるe(イベントオブジェクト)の中に、誰が、どこで、どんなメッセージを送ったか、すべての情報が詰まっています。このeの中身を正しく読み解くことこそが、双方向アプリ開発の鍵です。

イベントオブジェクトeの公式リファレンス

Google Chat APIの、公式リファレンスはこちらです。

Google Chat API の概要  |  Google for Developers

しかし、今回作っているような、GCPの「構成」タブで設定を行うインタラクティブ(双方向)なアプリは、Googleのシステム上、より高機能な「Google Workspace アドオン」として扱われます。

そのため、われわれが受け取るイベントオブジェクトeは、「アドオン専用」の、特別な、そしてより複雑な構造をしています。(ドハマりポイント💦)

公式リファレンス:Google Workspaceアドオン – Chatイベントオブジェクト

イベント オブジェクト  |  Google Workspace Add-ons  |  Google for Developers

ユーザー名を取得する方法

「アドオン イベント オブジェクト」の公式リファレンスを見ると、メッセージを送信したユーザーの情報は、イベントオブジェクトeの直下ではなく、e.chat.userという階層に格納されていることが分かります。

以下のコードで、ユーザーの表示名を取得できます。

const userName = e.chat.user.displayName;

Botへのメンションを除いた純粋な本文を取得する方法

同様に、ユーザーが入力したメッセージ本文も、e.chat.messagePayload.messageという、深い階層の中にあります。

ここで便利なのが、argumentTextというプロパティです。これは、「@Bot名 こんにちは」という、元のメッセージから、Botへのメンション部分を取り除いた、純粋な本文(こんにちは)だけを返してくれます。

@Bot名 こんにちは

↓

こんにちわ

コードはこちらです。

const userMessage = e.chat.messagePayload.message.argumentText;

応答を返す

応答を返すには、前回お届けした、API経由で新しいメッセージを投稿する方法(Chat.Spaces.Messages.create())がいいでしょう。

これは、非同期応答という手法で、時間がかかる処理(スプレッドシートの読み書きなど)を挟む場合にも有効です。

onMessage(e)関数のreturn処理を使う、「同期応答」という手法があるようですが、ケニーは実装できませんでした。(ドハマりポイント💦)

onMessage(e) 関数の全体像はこちらです。

/**
 * Google Chatからのメッセージイベントに応答し、非同期でオウム返しする関数
 * @param {Object} e - Chatから送られてくるアドオン形式のイベントオブジェクト
 */
function onMessage(e) {
  try {
    // -----------------------------------------------------------------
    // Step 1: 必要な情報をイベントオブジェクトeから取得する
    // -----------------------------------------------------------------
    
    // 応答先のスペース名とスレッド名(会話の場所)を、正確に取得する
    const spaceName = e.chat.messagePayload.message.space.name;
    const threadName = e.chat.messagePayload.message.thread.name;
    
    // 送信者の名前と、メンションを除いたメッセージ本文を取得
    const userName = e.chat.user.displayName;
    const userMessage = e.chat.messagePayload.message.argumentText.trim();

    // -----------------------------------------------------------------
    // Step 2: 応答メッセージを作成し、非同期で投稿する
    // -----------------------------------------------------------------

    const replyText = `【オウム返し】${userName}さん、こんにちは!「${userMessage}」って言いましたね!`;
    
    // 送信するメッセージの本体(メッセージリソースオブジェクト)を作成
    const message = {
      text: replyText
    };
    
    // Chat APIを直接呼び出し、新しいメッセージとして投稿する
    // { threadKey: threadName } を指定することで、必ず同じスレッドに返信される
    Chat.Spaces.Messages.create(message, spaceName, { threadKey: threadName });

  } catch (err) {
    // もし、この処理の途中でエラーが起きたら、その内容をログに記録する
    // これにより、GCPのログエクスプローラでエラーの原因を追跡できる
    console.error(`onMessageでエラーが発生: ${err.stack}`);
  }
}

Step 2:ウェブアプリとしてデプロイする

onMessage(e)関数は、外部のGoogleサーバーから呼び出されるため、われわれのGASスクリプトには、外部からアクセス可能な「住所」が必要です。

そのために、GASを「ウェブアプリ」としてデプロイ(誰でも使える状態にすること)します。

GASエディタ右上の「デプロイ」から「新しいデプロイ」をクリックします。※スクショは割愛します

種類を「ウェブアプリ」に設定します。

【超重要】 「アクセスできるユーザー」を「全員」に設定します。(Googleのサーバーからのアクセスを許可するため) 

最後に「デプロイ」をクリックします。

デプロイが完了すると、「デプロイID」が表示されるので、メモしておきましょう。 

Step 3:GCPプロジェクトにデプロイIDを紐づけする

前回(メッセージ送信のみ)の記事で、Google Chat APIの構成から作成したアプリの「接続設定」の「トリガー」で、ダミーのURLを入れたことを覚えていますでしょうか。 

今回は、送信のみならず「受信」にチャレンジしますので、ここの設定をしていきます。

GCPプロジェクトは、新規で1つ作成しましょう。(トラブルを防ぐためです。前回に引き続きでもOKです)

GCPプロジェクトの「APIとサービス」から「Google Chat API」をクリックして、「構成」タブを開きます。※省略します

「接続設定」の項目で、「Apps Script」にチェックを入れて、デプロイIDを入力します。 

最下部の「Save」をクリックします。※省略します

サーバー上に設定が反映されるまで、少し時間をあけた方がよさそうです(ドハマりポイント💦)。小休憩して、いよいよ最後のGASを送信しましょう。

小休憩中なのでちなみに、トリガーに、イベントハンドラ(Chatアプリとやり取りを処理する方法)としての関数がデフォルトで入力されています。 

イベントハンドラ名は自由に変えられるようですが、オススメはしないです。

ちなみに、Step 3で作成したアプリのことを「(Google Chatの)カスタムアプリ」と呼んだりします。

Step 4:スペースからメンション付きでメッセージを送信する

まず、スペースで事前準備があります。

スペースにアプリを追加する

スペースのタイトル横の▼をクリックして、「アプリと統合」をクリックします。 

「+アプリを追加」をクリックします。

カスタムアプリを選択して、「追加」をクリックします。

スペースに、カスタムアプリが追加できました。

Botにメンション付きでメッセージを送信する

さぁ、すべての準備が整いました。スペースで、Botにメンション付きでメッセージを送信します。

Botが「【オウム返し】〇〇さん、こんにちは!「○○!」って言いましたね!」と返信してくれば、成功です! 

GASの更新作業

GASに更新があるときは、「デプロイを管理」から、ペンのアイコン(編集)をクリックしてから、「新バージョン」を選択すると、デプロイIDに変更なく、更新できます。 

補足

GCPを管理するアカウントでGCPプロジェクトを作ったけど、GASは1ユーザーとして作成する、というときは、ひと手間が必要です。

ナビゲーションメニューの「IAMと管理」から「IAM」をクリックします。

「アクセスを許可」をクリックします。

新しいプリンシパルとして、ユーザーのメールアドレスを入力して、ロール(オーナーや編集者など)を設定したら、最後に「保存」をクリックします。

まとめ

以上で、「カスタムアプリ」でオウム返しBotを作ろう!をお届けしました。

今回つくったのは、シンプルな「オウム返しBot」ですが、onMessage(e)関数の中に、スプレッドシート連携、外部API連携、そしてインタラクティブなカードメッセージといった、あなたのアイデアという名の「魂」を吹き込んでいくことで、その可能性は、無限に広がります。

写経してみて、動くことを確認したら、このブログ記事と公式リファレンスを、どうぞAIに食わせてください。生産性爆上がり間違いなしです。

あー疲れました。

参考資料

このシリーズの目次

  1. [GAS/Chat]GoogleChatでLINE Notifyから移行しよう
  2. [GAS/Chat]GoogleChatAPIで高度なメッセージを送信しよう
  3. [GAS/Chat]【ハンズオン】「カスタムアプリ」でオウム返しBotを作ろう!
タイトルとURLをコピーしました