LoginSignup
2
5

More than 3 years have passed since last update.

Google ChatでBotに送った添付ファイルをDriveAppを使って保存するよ

Last updated at Posted at 2020-08-11

こんにちは。:relaxed:だよ。
今日もChatの続きをやっていくよ。

前回までの振り返り

【問合せBotを作成するまでの道】
1.BOTにDMを送ったら、チャットルームへの転送がされる。 →完了
2.チャットルーム内でのユーザーごとのthread名を保持し、同じユーザーからのDMは同じスレッドに書き込まれる。
3.スレッドに:relaxed:から書き込みをしたら、対象のユーザーにDMが送られる。
4.(余力があれば)よくある質問集みたいな一覧を作ってBotが自動返答してくれる。

:relaxed: は説明下手だから画像キャプチャばかり送ってしまう悪癖があるんだけれど、
今の応答だと画像が転送されないことがわかったよ・・
こーまーるーよー・・・・

そこで、今回は、Botに送った画像をGoogleDriveに格納して、
転送されるようにするよ!

画像つきのメッセージが送られる時のEventの内容を確認しよう。

まずはBotに対して画像を送ってみるよ。
スクリーンショット 2020-08-08 19.43.49.png

onMessage()関数内で console.log(event)をした時の結果・・

スクリーンショット 2020-08-08 19.47.04.png

お・・:relaxed:
スクリーンショット 2020-08-08 19.47.44.png

attachmentという項目がMessageに載っているね!
そのダウンロードURIにアクセスしてみると、こんがらがっちゃって困っている男の人が見えたよ。
:relaxed:もよくなるから親近感!

いらすとやさんの可愛い画像をお借りしたよ。)

URIわかったのでこんな感じのButtonをMessageに含めて、クリックで表示できるようにしたんだけれど、問題発生!

スクリーンショット 2020-08-10 11.13.44.png

送った本人は、ボタンクリックで画像の表示ができるんだけれど、他の人に開いてもらうと、403エラーが出ちゃったんだ。
URI見て分かる通り謎APIを叩いているっぽいんだけれど、このAPIはもとより、attachmentの情報が公式に全くなくて、公式命!公式大好きな:relaxed:は絶望したよね・・

でも悔しいので、調べに調べた結果、ここに辿りついた!!

IssueTracker:get attachment with the api

すごくタイムリーに問題が解決されていて、サンプルまで載っているよ!
https://chat.googleapis.com/v1/media/" + resourceName + "?alt=media
のAPIを使うと、添付をバイナリデータとして取得できるみたい。

詳細は上記リンク先を見てもらいたいんだけれど、
画像付きのメッセージを送る→Google Driveに保管→そのLINKをメッセージにつけて転送というフローにすることで画像問題を解決するよ。
*2020.09.13現在、公式にも使い方が記載されていることを確認。記事の最後にURL付けています。

DriveAppを使って、GoogleDriveにファイルを保存するよ

IssueTrackerのサンプルのgetByteStream()をベースに、GoogleDrive上に保存する関数を作ったよ。

/**
 * Upload Attachment To GoogleDrive
 *
 * @param  {Object} attachement
 * @param  {Object} folderId
 * @param  {Object} fileName 
 * @return {string} GoogleDriveURL
 */

function uploadAttachmentToDrive(attachment, folderId, fileName){
  var resourceName = attachment[0].attachmentDataRef.resourceName;
  var blob     = "";
  var url      = "https://chat.googleapis.com/v1/media/" + resourceName + "?alt=media"
  var service  = getOAuth2Service(); 

 var response = UrlFetchApp.fetch(url, {
    headers: {
      'Authorization': 'Bearer ' + service.getAccessToken(),
    },
    'muteHttpExceptions': true,
  });

  if (response.getResponseCode() != 200) {
    return "Failed to get file content with error code: " + response.getResponseCode();
  }

  blob = response.getBlob();
  var folder = DriveApp.getFolderById(folderId);
  var uploadFile = folder.createFile(blob);

  uploadFile.setName(fileName);

  return uploadFile.getUrl();
}



// 以下、OAuth2の取得の仕方は参考まで。いろいろなやり方があるからね。

/**
 * Creates OAuth2 Service to use chat api
 *
 * @return {Object} contains OAuth2 token
 */

function getOAuth2Service() {

  var jsonKey                   = JSON.parse(PropertiesService.getScriptProperties().getProperty("jsonKey"));    
  var serviceAccountPriveKey    = jsonKey.private_key;
  var serviceAccountClientEmail = jsonKey.client_email; 
  var scope = 'https://www.googleapis.com/auth/chat.bot';
  var service = OAuth2.createService('chat')
      .setTokenUrl('https://accounts.google.com/o/oauth2/token')
      .setPrivateKey(serviceAccountPriveKey)
      .setClientId(serviceAccountClientEmail)
      .setPropertyStore(PropertiesService.getUserProperties())
      .setScope(scope);

  if (!service.hasAccess()) {
    console.log('Authentication error: %s', service.getLastError());
    return;
  }

  return service;
}

Google Driveの操作が必要になるので、このAPIも有効にしてあげようね。
スクリーンショット 2020-08-11 10.27.10.png

引数のattachment=event.message.attachmentで、存在するときだけこの関数を呼び出すよ。
戻り値のurlはwidgetsにボタン形式で持たせたよ。

"widgets": [
  { "buttons": [
    { "textButton": 
      {  "text": "添付を見る",
         "onClick": { "openLink": { "url": url}}
      }
    }
  }
]

で、いきなりこのサンプルにDriveAppが出てきてびっくりしたよね!
これについてちょっと説明するね。

GoogleAppsScript : DriveApp

DriveAppsはGoogleAppsScriptに用意されているGoogleDriveを簡単に扱うためのクラスだよ。
いろいろなメソッドがあるけれど、今回使ったのはこの四種類だよ。

createFile(blob)
Googleさんが作ってくれたサンプルではバイナリファイルを取ってこられるようになっていたね。
それを引数に与えると、このメソッドでファイルを作成することができるよ。

getFolderById(folederId)
特定の場所に添付ファイルを置きたかったので、このメソッドを使ってフィルダーの場所を指定したよ。
引数のfolderIdには、GoogleDriveでそのフォルダーを開いた時のおしりがつくよ。画像だとオレンジの部分だよ。
スクリーンショット 2020-08-11 11.48.11.png

setName(fileName)
ドライブにあげたファイルに管理がしやすいように名前をつけるのに使ったよ。

getUrl()
onClickでこのGoogleDriveの画像を開けるようにしたかったのでURLも取得するようにしたよ。

実際の動きを見てみよう

実行するとこんな感じ。
:relaxed: → systemBot】
スクリーンショット 2020-08-11 11.26.14.png

【systemBot → 特定のワークスペース】

スクリーンショット 2020-08-11 12.13.11.png

添付を見るをクリックすると画像が現れる&指定したフォルダに、画像ができているよ。
スクリーンショット 2020-08-11 11.29.33.png

わーい、これで画像問題は解決だよーー!
ちなみに画像以外にも、EXCELなどのドキュメントも問題なくアップロードできることを確認したよ!

今日はここまで!
次回はここまでできた応答システムのコードを公開したいなぁ・・

参考にさせていただいたもの

ふふふ、公式:relaxed:
公式:GoogleAppsScript

2020.09.13現在

今日確認したら、attachmentsについてのAPIが公式サイトに追記されていたね。
公式:ChatAPI Download

2
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
5