SlackBOT+AppsScript入門

# はじめに

Slack導入したのでせっかくだからBOT作ってみた。
辞書が簡単に編集できるといいなーということでスプレッドシートに。
そんなわけでGoogle Apps Scriptからスプレッドシート開いてその内容と発言のテキスト照合して以下云々する感じ。
初めてのGASながらかなりお手軽に作成できたので、引っ張ってきた情報や若干引っかかった点などをまとめ。

# 初めてといえばHelloWorld

Googleドライブ→マイドライブから新規作成。
選ぶと新しいプロジェクトができるので適当に名前をつけよう。

既にいい感じのライブラリがあるのでいい感じに感謝しつついい感じに使う。

[Slack BotをGASでいい感じで書くためのライブラリを作った - Qiita](http://qiita.com/soundTricker/items/43267609a870fc9c7453)
あたりを参考に、リソース→ライブラリ→ライブラリの検索に以下を入力。

```
M3W5Ut3Q39AaIwLquryEPMwV62A3znfOO
```

バージョンに最新を選んで保存するとこのライブラリが使えるようになる。

SlackのAPIキーを取得する必要があるので、[Slack Web API | Slack](https://api.slack.com/web)から取得。
対象のTeamとUserの右にあるCreate tokenボタンを押すだけ。とりあえずコピー。

トークンなどの定数はスクリプトプロパティに入れておくとよい。環境によってコード変える必要なくなるし。
ファイル→プロジェクトのプロパティ→スクリプトのプロパティにキーと値を入れておけるので、
キー：SLACK_TOKEN 値：さっきのをペースト
で登録する。

チャンネルにポストするにはチャンネルIDも取得する必要があるので、[channels.list method | Slack](https://api.slack.com/methods/channels.list/test)から取得。
対象のTeamを選んでTest Methodボタンを押すと、そのTeam内のチャンネル一覧が出るので、ポストしたいチャンネルのnameに対応するIDをコピー。
これも例によってスクリプトプロパティへ。
キー：CHANNEL_ID 値：さっきのをペースト

あとはポストするユーザー名を適当に決める。
キー：USER_ID 値：適当に決める

これで準備は完了。
ぱぱっとコードを書いてみる。

```
function doPost(e) {
  // 先ほどスクリプトプロパティに入れた値はこんな感じで取得できる
  var prop =  PropertiesService.getScriptProperties().getProperties();
  var slack = SlackApp.create(prop.SLACK_TOKEN);
  var slackpost = slack.postMessage(prop.CHANNEL_ID, "HelloWorld", {username : prop.USER_NAME});
  return null;
}
```

GASの特徴として、実行時はエディタで関数を選んで実行するというものがある。
だからこのコードの中には関数を呼び出す部分は特に記載していない。
なお、関数名のdoPost(e)については後ほどBOT化させるのに必要なのでこのようにしている。

これで実行すると指定したチャンネルにポストされる。

# ポストに反応させてみる

そんなわけで次はポストに反応させてみよう。
まずは先ほどのスクリプトを外から叩けるように公開する。
公開→Webアプリケーションとして導入するを選び、
プロジェクト バージョン：新規
コメント：編集内容を適当にメモ
アプリケーションにアクセスできるユーザー：全員(匿名ユーザーを含む)
これらを指定して登録すると、外部アクセス用のURLが出てくる。このURLを叩くとこのスクリプトが実行されるというわけだ。
ただし先ほどの関数はdoPostになっていて、GETメソッドのURL直打ちでは実行されない。

[App Directory | Slack](https://slack.com/apps)から「Outgoing WebHooks」というAppを探して導入する。
これを導入すると、特定の語で始まるポストが送られたときに指定したURLを叩かせることができる。
なお、いくつかの参考資料ではこのAppがGETで叩いているらしく先ほどのスクリプトの関数名がdoGet(e)となっていたが、筆者の環境ではdoPost(e)でしか動かなかったので、バージョン差などがあるかもしれない。

設定方法についてはこんな感じ。
Channel：監視したいチャンネルを選択。Allもできる。
Trigger Word(s)：反応する文字列。ポストがこの語で始まったらURLを叩く。チャンネルにAllを指定している場合は必須。,区切りで複数指定可能。(誤記があったので修正)
URL(s)：先ほどのURL。
Token：POSTの検証用。コピーしておく。

これで設定完了。
うまくいけば、この設定を終えたあとにチャンネル内で指定した語で始まるポストをすると、HelloWorldが帰ってくるはずだ。

ついでにトークンの検証も入れておこう。
今コピーしたTokenをスクリプトプロパティに追加。
キー：VERIFY_TOKEN 値：ペースト

で、トークンの検証を追加。

```
function doPost(e) {
  var prop =  PropertiesService.getScriptProperties().getProperties();
  // エディタ上から手動で実行するときはトークンがないので、テスト時のために追加しておく
  if (!e) {
    e = {
      parameter : {
        token : prop.VERIFY_TOKEN
      }
    };
  }
  if (prop.VERIFY_TOKEN != e.parameter.token) {
    throw new Error("invalid token.");
  }
  var slack = SlackApp.create(prop.SLACK_TOKEN);
  var slackpost = slack.postMessage(prop.CHANNEL_ID, "HelloWorld", {username : prop.USER_NAME});
  return null;
}
```

# スプレッドシートを開いたりする

[Google Apps Script 実践メモ（スプレッドシート） - Qiita](http://qiita.com/nurburg/items/744ec53477f4ae328555)あたりを見ながらさくっと。

```
function loadFromSpreadSheet(url) {
  var sheets = SpreadsheetApp.openByUrl(url).getSheets();
  var sheetdata = {};
  var startrow = 2;
  var startcol = 1;
  for (var i in sheets) {
    sheet = sheets[i];
    var lastrow = sheet.getLastRow();
    var lastcol = sheet.getLastColumn();
    var sheetname = sheet.getSheetName();
    sheetdata[sheetname] = sheet.getSheetValues(startrow, startcol, lastrow, lastcol);
  }
  return sheetdata;
}
```

たとえばこんな感じ。実にお手軽。
あとはdoPost()内に

```
  var sheetdata = loadFromSpreadSheet(prop.SPREADSHEET_URL);
  var sheetname = "シート1"
  var sheet = sheetdata[sheetname];
```

のように書いて、SPREADSHEET_URLをスクリプトプロパティに設定すればOK。
その後は煮るなり焼くなりするといいと思います。

発言は doPost() 内から e.parameter.text で取得できる。
ここから先頭の固定文字列などを切り捨てたものをスプレッドシートから検索などすることになるかと。
テスト用に e= って設定しているところに text: prop.TEST_TEXT のように設定しておいてプロパティ突っ込んでおくといいかもしれません。