gas
slackbot

Slack上でG Suiteドキュメントを管理するBOTをサーバーレス(GAS)で作った

More than 1 year has passed since last update.

この記事はITC Advent Calendar(2) 4日目の記事です

その一
https://adventar.org/calendars/2563

その二
https://adventar.org/calendars/2640

初めまして、がっちゃんです。
本年度のITCの部長やってます。

今回はとあるイベント( https://cybozu.connpass.com/event/70773/ )でとあるLT( https://www.slideshare.net/AyaSuzuki9/gasbot-83171149 )を聞いてGAS面白そうと思って触ってみたので記事にしました。

まず導入

GASについて〜SlackからGoogle Spread Sheetにデータを登録するまでは
素晴らしいスライド( https://www.slideshare.net/AyaSuzuki9/gasbot-83171149 )の方で書いてくださってるので是非そちらをどうぞ。

これやってみるときにびっくりしたこと

え、めっちゃ認証厳重やん。

ログイン認証しようと思ったらこれ出て来て…
ログイン認証しようと思ったらこれ.png

詳細を開いて…
詳細を開いて….png

「次へ」を手入力して…
次へを手入力して….png

やっと認証許可ができるw
やっと認証許可ができるw.png

初回にミスったせいで一生ハマってた

一発目の選択で「自分だけ」を設定してしまって、別のURLが発行されてて、それに登録しようとしまくっててそんなURL無い!って言われ続けてハマってた。

何回か設定を変えて公開し直したりしたら /u/0/ がないURLが発行されるので、それを使えば治りました。(いまだに治った原因が定かじゃない…w)

これを一通り作ってみてから、Slackでドキュメントを管理するBOTアプリを作った

完成イメージ

管理させてるドキュメントを一覧でみれたり
一覧開く.png

新しくドキュメントを管理させれたり
新しくドキュメントを管理させれたり.png

ラベル名でドキュメントを検索できたり
ラベル名で検索できたり.png

必要なくなったドキュメントを管理対象から外したり
必要なくなったドキュメントを管理対象から外したり.png

できるBOTアプリをサーバーレス(流行ってるから言いたい)で作りました。

構成

Slack Incoming/Outgoing Webhook

  • Slack入力を読み取ってもらう
  • レスポンスを出力してもらう

GAS

  • 受け口
  • ルーティング
  • フォーマット掛け
  • もろもろの管理など

Google Spreadsheet

  • データの保存

苦労したとことハマったとこ

Google Apps ScriptのGUIエディタだとファイル分割ができない(と言うよりもめんどくさい)

普段のJSの感覚で import とか require とか使えると思ったら使えないっぽかった
(と言うよりも、ググった時にびっくりするほどJSの書き方がヒットしてノイズだらけで読む気が失せた)
ので、1ファイルで書くことにしました。

その結果、300行ぐらいの1ファイルコードになりました()

次やる時か、気が向いたときにファイル分割とリファクタリングしよう…

Arrayを与えてもよしなに指定の行にデータをぶっ込んでくれなかった…

これは、Google Spreadsheet の特性上仕方ないことなんだとは思うんですが、
行を指定して、データを並べた Array を与えたのですが、うまいことデータ挿入をやってくれなくって、結構はまりました。
以下の記事のおかげで解決しましたが、なかなかにややこしかった。

https://qiita.com/ShishidoToru/items/0ab9de4ea281df9358f4

スタンドアロンで考えて設計しないとデバッグがめんどくさい。

SlackBotとしてGASアプリを作る時に気をつけておかないといけないのが、
この (https://www.slideshare.net/AyaSuzuki9/gasbot-83171149) スライドの37枚目でも書いているように、一度Webアプリケーションとして公開して、SlackBotで叩けるようにすると、更新のたびにGUIで更新ぽちぽちしないといけなくなります。

Webアプリをローカルで試さずにいちいちデプロイしてテストする感じですね。

自分は流石にめんどくさかったので、

// sample request
// var sample = 'docadmin add スプレッドシート soso xxxxxxxxxxx';
// var sample = 'docadmin list';
// var sample = 'docadmin find 自己紹介プレゼン';
// var sample = 'docadmin activate active piyo';

function router(rawRequest) {
  var request = adjustValues(rawRequest /* sample */);
  // ~~~
}

function adjustValues(request) {
  var parameter = request.parameter.text.split(' ');
  // var parameter = request.split(' ');
  // ~~~

みたいな感じで、いくつかの入力パターンを用意して、開発中はそっちのパターンを利用して、
できる限り少ないコストで Slack 連携に切り替えれるようにしてました。

これがまた結構大事。

遅くなるし、メソッドを探すのが大変だったりするので無理にSpreadsheet上で操作しようとしない。

この記事を読んでハッと気づかされたのですが、作り始めはSpreadsheet内の行そのものを操作してデータ書き換えをしたり、走査をしたりしようとしてました。

でも、それだとSpreadsheetで提供されているメソッドを探すのに苦労したり、Spreadsheet APIを叩く分遅くなります。 (GASは5分を超える処理はタイムアウトにされるので、実行時間にも注意)
なので、GASではほぼJSと同じ構文で書けることが多いので、できるだけその書き方をすることをお勧めします。

SpreadsheetApp.openById(SPREAD_SHEET_ID).getSheets()[0] ってしてあげた方がいい

度々出てきているのですが、このスライド ( https://www.slideshare.net/AyaSuzuki9/gasbot-83171149 ) でのスプレッドシートの取得のやり方をすると、
Spreadsheet オブジェクト(ファイル丸ごとみたいなイメージ)を sheet に代入することになり、
getRange(row, colmun) などのメソッドを使うことができなくなります。

原因は getRange(row, column) のメソッドが Sheet オブジェクト(ファイルの中にあるシートみたいなイメージ)に属しているためで、
これを解決するには、 SpreadsheetApp.openById(SPREAD_SHEET_ID).getSheets()[0] のような形で、
Spreadsheet オブジェクトの中の 0番目の Sheet オブジェクトを取得する必要があります。

自分はこれがいまいち理解できてなくって、 getRange(row, column) がno_methods errorを吐かれることにハマってましたw

まとめ

いかがだったでしょうか。
スライドをみて、GASを触ってみたいなって思い、そのあと詰まったりハマったりしながらも大体10時間ぐらいでこれぐらいのサーバーレスBOTを作ることができました。

思った以上にお手軽にBOTを作れて楽しかったのでまた別の機会にちょっとしたところを便利にするBOT作ってみようと思います。

これを読んだみなさんもGASに興味を持って色々遊んでもらえれば、幸いです!
ありがとうございました!

参考リンク

公開予定のリポジトリ(リファクタリング後にコピペしまする)