Google Apps ScriptでGoogle Chatにメッセージを送る【GAS】

Google Apps Scriptには、Google Chatに送る為のメソッド類は装備されていません。Google ChatはREST APIとして提供されているので、Google Apps Scriptで利用する場合は、このAPIを叩いて送信する必要があります。

Webhookを利用して送りつける方法はあるのですが、自動化などで利用する場合には、そのWebhook URLを知っておく必要がある上に送信しか出来ないので、色々と不便です。そこでこのAPIを利用して色々出来ないか調べてみました。

※いわゆるチャットボットになります。

※OpenAIのGPT-3人工チャットAIのAPIを機能として追加。以下のエントリーを参考にしてみてください。

Google ChatのBotにOpenAIのchatGPTを繋げてみた【GAS】

今回利用するスプレッドシート等

今回のスクリプトは事前準備がかなり大変なので、一個作っておいて使いまわしするような形で運用すると良いでしょう。

事前準備

面倒なことに、Google Chat APIを叩く為にはサービスアカウントの準備等が必要のようで、Google Apps Scriptから叩くには手間が必要になっています。予め、Cloud Consoleにプロジェクトは用意しておいてください。このあたりの情報は以下のエントリーにまとめてあります。今回は、サービスアカウントの作成から開始します。

Google Cloud Consoleを弄ってみる

Google Apps Scriptで画像から文字起こしを実現する【GAS】

Cloud Consoleでの作業

APIの有効化

Cloud ConsoleのGoogle Chat APIを有効化しておきます

  1. サイドバーから「APIとサービス」⇒「有効なAPIとサービス」を開きます
  2. APIとサービスの有効化をクリック
  3. 検索窓でchatと入れて検索すると、Google Chat APIが出てくるのクリック
  4. もしGoogle Drive APIが有効化されていない場合は、Drive APIも追加しておきます
  5. 有効化をクリックする

今回は認証はOAuth2.0認証ではなくサービスアカウントでの認証となるのでこれでOK。OAuth同意画面のスコープにもいれておくとベストですが、今回特に追加してはいません。また、GAS側にもサービスとしてDriveやChat APIを追加していません。

※一部の環境で、実行時に「Permission denied to enable service [drive]」というようなエラーログが出るケースでは、GCP上でDrive APIを有効化してないであったり、OAuth同意画面のスコープでDrive APIを入れていない等の問題があるのかもしれません。

図:まずはAPIを有効化しておきましょう

Chat APIの構成を作る

有効化したChat APIを開いて、構成の中身を構築します。これがBotとなり、スクリプトからのメッセージを変わりに投稿してくれます。

  1. Google Chat APIを開く
  2. 構成タブを開く
  3. アプリ名を適当につける(今回はchatmanとしました)。これを控えておきます。
  4. アバターのURLは今回は、こちらのURLを利用しました。
  5. 機能の2つのチェックボックスをオンにします
  6. 接続設定はApps Script Projectをチェックします
  7. デプロイIDですが、後半にあるデプロイメントIDを取得するを参考に先にApps Scriptのデプロイを実行してDeployment IDを取得して入れます。
  8. 権限はドメイン内の全メンバーとしました。後述のアプリを検索で出てこない場合には、個別に公開設定にメアドをカンマ区切りで入れてみてください。今回は特定のグループアドレスと管理者のアカウントの2つを入れておきました。

Google Chat APIをGCPで設定するに辺り、1プロジェクト1設定しか出来ませんので、複数のGoogle Chat APIを利用するスプレッドシートがある場合は、別にGCPプロジェクトを作成して、上記の手順でデプロイメントIDを登録する必要があります。

図:これがChatbotの設定になります

サービスアカウントの作成

まずは、Google Chat用のサービスアカウントを用意します。

  1. サイドバーから「IAMと管理」⇒「サービスアカウント」を開きます
  2. 上部にあるサービスアカウントを作成をクリックする
  3. サービスアカウント名、IDを適当にセットし、作成して続行をクリック
  4. このサービス アカウントにプロジェクトへのアクセスを許可する」の項目は省略して進める。続行をクリック。
  5. ユーザーにこのサービス アカウントへのアクセスを許可」も同様に省略して進める。完了をクリック。
  6. これで、サービスアカウントの作成が完了。すると、アカウント名@プロジェクト名.iam.gserviceaccount.comでアカウントが出来ます。これを控えておきます。
  7. OAuth 2 クライアント IDを「一意のID」として控えておきます。

※ちなみにサービスアカウントでは、スペースのメッセージ取得などのメソッドがスコープを追加しても使えません。また、特に今回IAMに参加するユーザを登録したりロールを割り振ったりは行っていません。

図:サービスアカウント自体は作るのは簡単

秘密鍵の作成

このままだと、このサービスアカウントが誰でも利用可能な状態なので、秘密鍵を作成します。

  1. 作ったサービスアカウントをクリックして開く
  2. キータブをクリックする
  3. 鍵を追加をクリックして、新しい鍵を作成をクリック
  4. キーのタイプをJSONとして、作成をクリック
  5. 鍵が作成されて、JSONファイルがダウンロードされます。
  6. このファイルは大切に保管しておき漏洩しないように注意が必要です。

図:秘密鍵は必ず作成しておきます。

注意点

社内のGoogle WorkspaceとGCPで作成したChatbotですが、社内のユーザに公開して利用するために公開設定で設定をしています。社内で利用する分にはGoogle Workspaceの組織内アドオン同様にこれで社内で利用が可能と思います。

問題は外部ユーザを含めたスペースに於いて、作成したChatbotを加えている場合、社内メンバーはこの機能を利用できますが、外部メンバーは利用が出来ません。外部メンバーも利用可能とするとなると、メッセージにもあるようにアドオンの場合同様にMarketplaceに公開する作業が必要になってしまいます。GWSの全体の委任にgmail.comも追加が必要かもしれません(セキュリティ的におすすめしません)

もとより、この手のChatbotは社内向けで作成するものであるので、外部ユーザがホイホイ使えてしまうのは問題であるので、外部ユーザは使えない・使わせないという点に注意しましょう。

図:基本は内部で利用とします。

Google Spreadsheet用の組織内アドオンを作成する【GAS】

管理コンソールでの作業

Google Workspaceの管理コンソールでも作業が必要になります。

  1. 管理コンソールの「セキュリティ」⇒「アクセスとデータ管理」⇒「APIの制御」⇒「ドメイン全体の委任」を開きます
  2. APIクライアントの新規追加をクリック
  3. クライアントIDに控えておいた「一意のID」を追加する
  4. Scopeには、「https://www.googleapis.com/auth/chat.bot」を追加する

これで、Google Workspace内で利用が可能になります。

図:管理コンソールでAPI利用の許可をする

スプレッドシートの共有に追加

サービスアカウントに対して、スプレッドシートの読み書きなどの作業が伴う場合には、スプレッドシートの共有設定に予め控えておいた「サービスアカウント」のアドレスを追加し、許可してあげる必要性があります。ただし、外部ドメインを追加できる設定のテナントでなければサービスアカウントで読み書き設定は追加できません。また必須の作業ではないのでチャットを返すだけならばこの作業は省略可能です。

※本スプレッドシートには対象のChatスペースに参加してるユーザがアクセスできるように、アクセス権限のあるディレクトリに配置しておきましょう。

図:サービスアカウントからの読み書き許可

Google Apps Script側の準備

このままでは、Google Apps Scriptから操作が出来ないので、以下の作業をしてあげます。

プロジェクトの移動

Google Apps ScriptとCloud Consoleのプロジェクトを紐付けする作業が必要です。以下の手順でプロジェクトの変更を行います。

  1. Cloud Console側のプロジェクトのホームを開き、「プロジェクト番号」を控えておく
  2. Google Apps Scriptのスクリプトエディタを開く
  3. サイドバーからプロジェクト設定を開く
  4. GCPプロジェクトの「プロジェクトを変更」をクリック
  5. GCPのプロジェクト番号に、1.の番号を入力して、プロジェクトを設定をクリック
  6. これで紐付けが完了しました。

図:プロジェクトの移動も必須の作業です

秘密鍵の配置

サービスアカウント作成時にダウンロードされた秘密鍵ですが、これをGoogle Apps Scriptから利用する必要があるので、Google Driveにアップロードします。但しこのファイルは誰かと共有しないようにする必要があります。よって、アクセス権限は自分のみとし、流出しないようにします。

また、Google Apps Scriptから参照する為に、このアップロードしたファイルのIDを控えておきます。スクリプトから参照して値を取り出すのに必要です。自分の場合はこのファイルのIDをスクリプトプロパティに格納しておきます。今回はjsonmanという項目のスクリプトプロパティに手動でJSONファイルのファイルIDを追加しておきました。

※スクリプトプロパティにJSONの中身を全部コピペする方法もありますが、流出注意。

図:秘密鍵のIDをスクリプトプロパティに入れておく

認証用のライブラリを追加する

秘密鍵のJSONファイルを使ってサービスアカウントの認証をする為に、Google Apps Scriptにライブラリを追加します。以下の手順でOAuth2 for Apps Scriptライブラリを追加しましょう。

  1. スクリプトエディタを開きます。
  2. サイドバーより、ライブラリの+アイコンをクリックする
  3. ライブラリを追加欄に「1B7FSrk5Zi6L1rSxxTDgDEUsPzlukDsi4KGuTMorsTQHhGBzBkMun4iDF」を追加し、検索します。
  4. 現時点ではバージョンは41が最新ですので、それを選択しておきます。
  5. 追加ボタンを押して完了

これで、OAuth2.0認証にまつわる様々な関数を手軽に利用できるようになります。

図:OAuth2.0認証ライブラリを追加する

デプロイメントIDを取得する

GCP側の構成で利用するIDとなります。

  1. デプロイをクリックし、新しいデプロイをクリック
  2. アドオンのまま、デプロイをクリックすると、Deployment IDが出てくるのでこれをコピーする

このIDをセットしないと、API実行時に「No bot associated with this project.」として404エラーが返ってきます。また、コードを変更したら、再度バージョンを変更してデプロイしないと反映しないので、要注意です。

図:これがないと、404エラーとなってしまう

appsscript.jsonに追記

以下の手順で文字列を追記します

  1. スクリプトのプロジェクト設定を開き、「appsscript.json」マニフェスト ファイルをエディタで表示するにチェックを入れる
  2. appsscript.jsonが表示されるので開く
  3. runtimeVersionの行の下にでも、以下の1行を追記する
  4. 上書き保存する

このappsscript.jsonの記載ですが、公式ではV8ランタイムでは動かないということなのですが、自分のほうでは動作しています。気になるようならば、V8 Runtimeの記載は削除して旧式のランタイムで動かすと良いでしょう。

ちなみに、上記ではメッセージナシの文字列ですが、実際には

みたいな形で記載すると、スペース追加時に自動メッセージが出るらしいです。ただ、後述してるonAddToSpace関数があるので、特にここで記述する必要性はありません。

図:謎の文字列を追記しておきます

Google Chat側の準備

Chatのスペースを作成しIDを取得する

今回はGoogle Chatのスペースに対してチャットをぶん投げるので、「キノコを語る会」というスペースを作成。その後URLを取得します。

  1. Google Chatを開く
  2. スペースの横の+アイコンをクリックして、スペースを作成をクリック
  3. スペース名を適当につける(今回はキノコを語る会とした)
  4. スペースのアクセスは、ドメイン全体を選択しておく
  5. 作成をクリックするとスペースへのURLが出る。「https://mail.google.com/chat/u/0/#chat/space/」に続けて表示されてるのが、スペースのIDとなるので、これを控えておく
  6. GAS側のコード内にある「spaceid」の中に5.のスペースのIDを記述して再度デプロイを実行しておく。

図:スペースのIDをもってメッセージを送信する

チャットボットの追加

チャットの左上にある+アイコンをクリックして、チャットボットを追加します。GCP側で設定しておいた構成で出てきますので、これを追加します。追加しないと、APIのみではメッセージ投稿が出来ないので、注意が必要です。

  1. Chatスペース名をクリックしてアプリと統合をクリック
  2. アプリを追加をクリックする
  3. Chat APIの構成を作るで控えておいたアプリ名を元に検索(今回はchatmanです)
  4. 検索結果に出てくるので、選んで、追加をクリックすると準備完了

もし出てこない場合、1度Google Chatをリロードしてからもう一度作業しましょう。またそれでも出てこない場合、再度デプロイを実施して新しいバージョンでデプロイし、Google Chatをリロードすれば出てくるはずです。

図:これでチャット自動投稿の準備完了

ソースコード

認証用コード

サービスアカウントの認証用のコードです。startoauthを実行してAccess Tokenを取得できればOK。

  • スプレッドシートのメニューの「設定」⇒「OAuth認証」を実行すると実行されます。
  • この認証方式はサービスアカウントが認証を行うので、いつものユーザが認証するものとは異なり、Access Token取得は自動で行われます。
  • 取得したアクセストークン等の塊は、OAuth2ライブラリ最新版より、スクリプトプロパティではなくユーザプロパティに格納されているので、より安全になっています。

チャット投稿コード

  • 控えておいたスペースのIDをspaceidに記述しておきます。
  • OAuth2.0ライブラリによって、Access Tokenの取得が行われ、UrlfetchAppにてPOSTリクエストします。
  • 今回のコードは単純に新規スレッドに投稿してるだけなので、毎回新規スレッドになりますが、responseの中にスレッドIDがあったりするので、それを元にスレッドに対して返信も可能です。

図:botとしてchatmanが投稿してくれました

自動応答メッセージのコード

Google公式のGoogle Apps Scriptのテンプレートを見ると、onMessageといった特殊なシンプルトリガーみたいな関数が用意されています。これらは、メンションでchatbotに対してメッセージを投稿した場合や、スペースにボットを追加・削除した場合に発動する特別な関数です。

  • eventの中にメッセージのタイプやら内容やらが詰まってるので、これを元に判定して返したりします。
  • 日本語形態素解析APIのようなものを合わせて使う事で、チャットの内容を解析し、スプレッドシートの内容を検索して返すといったようなロボットを作る事が可能です。
  • 他にもインタラクティブカードというタイプの返答をしたりも可能のようです。
  • Slackのようなスラッシュコマンドもサポートしています。
  • 自動応答メッセージでダイアログを表示して返答を受け付けるといったような機能も装備しています。
  • 単純なボットというだけでなく、かなり色々とできそうな機能が装備されてるので、作り込み次第では、かなり業務軽減になる可能性を秘めていると思います。

図:オウム返しする自動ボット

独自のスラッシュコマンドを装備

Slackなどでよく見かける「スラッシュコマンド」。例えば、/member 社員番号と入れると部署名やらメアドやらの情報を返すといったようなコマンドをGoogle Apps Script側で構築することが可能になります。Chat APIの構成からセットアップが必要です。

  1. Google Chat APIの構成を開く
  2. スラッシュコマンドの項目で、ADD SLASH COMMANDをクリック
  3. /kinokoなどのスラッシュコマンドを記述
  4. コマンドIDはこのコマンドに対する明示的なIDで、GAS側でこの値を元にどんなスラッシュコマンドが来たのかを判定します(今回は1を指定しました)
  5. 完了をクリックで使えるようになる。
  6. GAS側のonMessage関数にて、以下のようなコードを追加する

    argumentTextでスラッシュコマンドに対する引数を取得出来ます。今回は/kinoko membernameといった形でスペースで区切って渡して、取得した際にスペースは削除しています。
  7. 引数とコマンドの判定を行ったら、あとはGASで色々処理をして、返してあげたりする

図:Cloud Console側設定

図:スラッシュコマンドを打ってみた

メッセージを装飾する

Google Chatへのメッセージ送信ではHTMLは利用する事が出来ません。代わりにMarkdown記号のような形で装飾記号を利用する事で簡単な装飾を行う事が可能になっています。例えば太字にする場合には、messageの前後をアスタリスクで括ることで太字になって投稿されます。

図:太字にしてみた

Cardを送信する

Google Apps ScriptにはCardServiceという特殊なクラスがあり、Cardと呼ばれるものを構築できるのですが、以前もGMailのアドオンでUIを構築する場合には利用しました。今回メッセージではなくこのカードで送りたいと思い色々チャレンジしていたのですが、どうもGoogle Chatのメッセージで送る場合はこのクラスではなく、自分でCardのJSONを構築して送信すると旨く送信できるようです。

※Teamsで言うところのAdaptive Cardの形式になります。

  • createMessageにてカードを構築します。
  • sendchatMessageでは、createMessageの中身を受け取って直接payloadにJSON.stringifyにて送信する
  • CardではHTMLをサポートしているのでノーマルのテキストと違い、書式設定が可能です。

旨くいくと以下のスクショのようにカード形式で送れるようになるので、様々な装飾を施したメッセージを送ることが可能です。この手法は、Webhookへ投げる場合でも有効です。

図:画像とテキストをカード形式で投稿してみた

Google Apps Scriptでちょっとした顧客管理台帳を作る - GMailアドオン編【GAS】

Advanced ServiceにChat API登場

いつの間にか、Google Apps Scriptの開発画面のサービスに「Google Chat API」が登場してるのですが、何故かこれを追加して以下のようなコードを記述し、認証を実行しようとすると400 invalid_scopeとして「https://www.googleapis.com/auth/chat.import」を求められてアクセスがブロックされます。

リファンレスページも用意されているのですが、どうしてなのか?調べてみたら、こちらに回答がありました。appsscript.jsonに以下のスコープを別途追加しないと認証出来ないようです。よって、これを使う場合は他のスコープ類もoauthScopesに追加することが必須になるので要注意です。

送信する場合ですが、spaceNameはspaces/にスペースのIDをつなげたものを利用します。また、メッセージはJSON形式でtextに対して送信したいメッセージを記述し、最後にChat.Spaces.Messages.createにて送信すると送ることが可能です。以下のコードの事例は自分自身が自分として投稿してることになるので、サービスアカウントとして投稿でない形でのノーマルな投稿になります。

サービスアカウントを使っての投稿をする場合には、前述までのサービスアカウントのTokenを利用して投稿するようにします。すると全ユーザからはChatbotからの自動投稿として見えるようになります。利用するトークンで自分が投稿になるのか?サービスアカウントが投稿することになるのか?が分かれますので要注意です。

図:サービスに登場して使えるようになってる

Webhookで投稿する方法

単純に機械的に投稿するだけ、ということであれば前述でも出てきた「Webhook」を設置して、そのURLに対してGoogle Apps Scriptで叩くだけでも投稿可能です。ただし投稿するだけなので、一方的な通知等といった用途に限られます。

しかし、前述のChatbotの設定やらサービスアカウントやらの設定が一切不要なのでお手軽にGASのみで叩けるメリットがあります。

Webhookの設置方法

まずはWebhookを設置してそのURLを取得します。

  1. Google Chatを開き、対象のスペースを開く
  2. 上のほうにある「スペース名▼」をクリックして、
  3. アプリと統合をクリックする
  4. ダイアログが出てきたら、「Webhookを管理」をクリックする
  5. 着信Webhookのダイアログが出るので、名前とアバターのアイコンURLを指定して、保存をクリック
  6. URLが出るので、コピーアイコンをクリックして、URLをコピーする。

図:ちょっとわかりにくい場所にある

図:このURLに対してGASで叩く

ソースコード

  • POSTで送信する必要があります。
  • メッセージはJSON.stringifyで括ってから送信する必要があります。

図:簡単に通知投稿が可能です。

関連リンク

Google Apps ScriptでGoogle Chatにメッセージを送る【GAS】” に対して3件のコメントがあります。

  1. AN より:

    こんにちは。GoogleChatでchatGPTのAPIを利用しチャットできるようにしたいと調べていたらこちらへたどり着きました。
    詳細に手順を記載いただきありがとうございます、とても参考になります。

    手順通り実施してみて一点躓いた点があり、もし原因がおわかりでしたらご教示いただけないでしょうか。

    認証用コードのcheckOAuth関数を実行すると、
    let content = DriveApp.getFileById(fileId).getAs(“application/json”).getDataAsString();
    の部分でエラーが出てしまいます。
    デバッグでcontent 変数がundefinedなのでjsonファイルをうまく取得できないようなのです。
    jsonファイルは同アカのドライブへアップし、URLの○部分(https://drive.google.com/file/d/○〇〇/)をjsonmanとしてスクリプトプロパティへ格納しました。

    GASからドライブへのアクセス権限がないことも原因かと思い、ドライブAPIを有効にしマニフェストでドライブのスコープを追加してみたのですがエラーは解消しませんでした。

    主様で他に実施された設定などはございませんでしょうか?

  2. officeの杜 より:

    AN様

    officeの杜管理人です。
    対象のJSONファイルのIDが間違っていないことを前提に考えた場合であれば、以下のようなコードでも取得できないでしょうか?

    var prop = PropertiesService.getScriptProperties();
    var fileid = prop.getProperty(“jsonman”)

    var file = DriveApp.getFileById(fileid);
    var jsondata = JSON.parse(file.getBlob().getDataAsString(“UTF-8”));

    fileidが○の部分が入ってくる。そして、それを元にDriveAppで取得し、中身をgetblobのgetdataasstringで取得する。

    ならどうでしょうか?単純にfileidを元に引っ張ってきてるだけなので、jsonmanにファイルIDが入っていないか、誤っているか?ではないかなと思います。前述のコードもこのコードもどちらでも、JSONファイルの中身を先程試してみたら取得出来ていたので、fileIdがきちんと取得できてるかを確認してみてください。

    1. AN より:

      管理人様

      返信いただきありがとうございます。
      いただきましたコードで試してみたところ、無事取得jsonを取得できました。
      全体を通して実行してみたいと思います。
      お忙しい中ご連絡いただきありがとうございます。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)