Stimulator

機械学習とか好きな技術話とかエンジニア的な話とかを書く

Slack botをGASでつくる方法で一番楽そうなやつ

- はじめに -

正直今時AWS LambdaがSlackサポートしていてポチポチやってスクリプト数行でbotが出来るし、フレームワークも充実しているので、何故今更GASなのかと思ったらブラウザバックした方が良い。
hubotもAWSも実質サーバ代がかかるけど `GASは無料` で `Google Driveの中身を触れる` くらいしかメリットがない。

投稿するだけなら以下の記事のようにIncoming Webhooksだけ設定して適当な所からPOSTするので良い
vaaaaaanquish.hatenablog.com


 
それでもGoogle Apps Scriptで簡単に応答するbotが作りたいんじゃいという記事。

Slackにbotもどきを導入する方法はいくつかあるが、今回目指すのは以下のようにbotがリプライできて、リプライ内容に対してbotが返信してくれる状態。
f:id:vaaaaaanquish:20170927155852p:plain:h170:w300

結論からいうとSlackにAppでbot追加するのと、Outgoing WebHooksを組み合わせるのが現状最善手っぽい。


 

- Slack側の色々 -

Slackにbotらしきものを導入する方法はいくつかある。

Custom Integrations には Bots や Outgoing WebHooks、Incoming Webhooksが用意されているし、公開AppにはHubot連携等のbot作成フレームワークとの連携Appがいくつかある。

本記事では簡単に「独自App追加」と「Outgoing WebHooks」だけでSlack botを実現する。

 

Slackにbotを追加して投稿する設定

SlackのAppページから新しいAppを作成
https://api.slack.com/apps

f:id:vaaaaaanquish:20170927162923p:plain:h200:w400

アプリ名と登録したいチャンネルを選んでCreate App
f:id:vaaaaaanquish:20170927163027p:plain:h200:w200

画面が遷移しApp管理画面に移る
 
左タブからBot Userを選択、適当な名前でbotを追加し、Always Show My BotをOnにしてSave。
f:id:vaaaaaanquish:20170927163157p:plain


このBotから投稿できるよう、左タブからIncoming Webhooksを選択。
f:id:vaaaaaanquish:20170927163716p:plain:h300:w300

認証画面が出るのでここで投稿したいチャンネルを選んでAuthorize。
f:id:vaaaaaanquish:20170927163815p:plain:h200:w250

 
Botの投稿URLが生成されるのでコピーしておく。
f:id:vaaaaaanquish:20170927164040p:plain:h250:w300


ちなみにこの時点でコンソール等からURLに対してPOSTしてやれば試せる(まあ試さなくても大体できてる)。

curl -X POST -H 'Content-type: application/json' --data '{"text":"Hello, World!"}' https://hooks.slack.com/services/~~~

あとこの時点で、botデフォルトのicon等が設定でき、左タブのSettings>Basic Informationに飛んで下の方にスライドしていくと設定する箇所がある。

 

GASからSlackにPOST

GASが入ってない場合は新規でアプリの追加すれば、Google Drive上から右クリックメニュー>その他>Google Apps Scriptが選択出来るようになる。
f:id:vaaaaaanquish:20170927165029p:plain:w300:h300

GASでSlackする記事を見ると、大抵soundTrickerさんが作ったLibraryを使った方法が出て来るが、Slack APIのTokenが必要な事と拡張できないので使わない。

もしライブラリを使うなら以下が導入で分かりやすいかも。
Slack BotをGASでいい感じで書くためのライブラリを作った
GASとSlackではじめるチャットボット〜初心者プログラマ向け〜
初心者がGASでSlack Botをつくってみた - CAMPHOR- Tech Blog

 
先程取得したbotのURLを指定してGASのコードをコピペして、test関数をGASエディタの上部バーの再生ボタンっぽいやつで実行。

function postSlack(text){
  var url = "https://hooks.slack.com/services/T~~~~";
  var options = {
    "method" : "POST",
    "headers": {"Content-type": "application/json"},
    "payload" : '{"text":"' + text + '"}'
  };
  UrlFetchApp.fetch(url, options);
}

function test(){
  postSlack("これはテストです");
}


f:id:vaaaaaanquish:20170927165343p:plain
注意するとしたらpayloadは {"text": "hoge"} という内容のStringであるという事くらいか。

Slackの投稿フォームで@を押した際に出るサジェストにbotが追加されている事も確認する。

 

SlackからGASでリプライを受け取る

本来なら上記のAppでリプライを受け取れたり出来れば良いのだが、現状できなさそう。
一般的な Browse Apps > Custom Integrations > Outgoing WebHooks を使って受け取りを行う。

 

GAS側の設定


GASはdoPost()なるイベントハンドラがデフォルトで用意されているので、doPostを適当に書けばHTTPメソッドでPOSTされた内容を受け取る事ができる。GETされる場合はdoGETもある。
先程のコードに以下を追記する。

function doPost(e) {
  var message = "こんにちは " + e.parameter.user_name + "さん";
  postSlack(message)
}

Slackから受け取った内容からuser_nameを見て返すというシンプルなコード。
Slackの場合だとe.parameter.textで投稿内容を取得できますが今回はスルー。

 
上記を追記し保存したら、GASをWebアプリケーションとして公開する。

GASエディタ画面の上部から公開を選択、ウェブアプリケーションとして導入する。
f:id:vaaaaaanquish:20170927172638p:plain:h200:w200

プロジェクトバージョンを新規作成して、アプリケーションの実行者を自分に、全員が実行できるよう設定して公開する。
f:id:vaaaaaanquish:20170927173148p:plain:h200:w200

最初だけ許可の確認があるかもしれないので許可。

こんな感じで公開されたURLが出て来るので保存しておく。
f:id:vaaaaaanquish:20170927173413p:plain


GASの一番面倒くさいところは、この「プロジェクトとして公開する」ところにある。

ウェブアプリケーションとしてAPIのような形で公開していく場合、スクリプトの保存に加えて、上記の「ウェブアプリケーションとして導入」「プロジェクトバージョンを新しく作成」「公開」の手順を毎回踏む必要がある。
(スクリプトの保存だけして新バージョンとして公開してなかった〜という事が多々発生する)

僕は適当にバージョン1、バージョン2、…と命名しているけど、大体どっかで破綻してしまうので何かいい方法が欲しい…

 

Slack側の設定

自分のSlackチーム名を確認してappsに飛ぶ

https://自分のSlackチームドメイン.slack.com/apps

検索窓があるので Outgoing WebHooks を検索。
f:id:vaaaaaanquish:20170927171320p:plain

Add ConfigurationするとWebhock Integrationボタンがある画面に遷移するのでIntegration。

f:id:vaaaaaanquish:20170927174105p:plainf:id:vaaaaaanquish:20170927174139p:plain

 
それっぽい設定画面に遷移したら少し下にスクロールして、Integration Settingを行いSaveする。
f:id:vaaaaaanquish:20170927180319p:plain:h200:w350

URLは上部GAS側の設定時に取得したウェブアプリケーションのURL。

Trigger Wordは、Slack上の投稿の先頭を見て引っ掛ける単語で、カンマ区切りで設定できる。

test,bot,@,&

みたいに複数設定できるのだが、例えば@だと

@hoge こんにちは

が取得できない。
理由は@hogeとした場合、リプライやコマンド形式となり、リンクになるから。

リプライをcatchしたい時は、実際Botへリプライして右クリックでリンク取得し、URL末尾のIDを<@ >で挟む。
f:id:vaaaaaanquish:20170927181412p:plain

上記だとhttps://hogehoge.slack.com/team/U78NAL1QQ になるので <@U78NAL1QQ> をtrigger wordに設定しておけば良い。


詳しくは以下。
https://api.slack.com/docs/message-formatting


ちゃんとSaveする。


 
上記設定した上でBotに向けてリプライを飛ばせば返答が得られる。
f:id:vaaaaaanquish:20170927181858p:plain



 

- おわりに -

多分GAS使うならこれが一番楽です。

App上でOutgoing WebHooksも作れたら本当はもっと楽ですが…

一番ラクなのはGASを使わずにAWSに課金してLambdaでポチポチやる事だと思います(Python書けるし…)

あと少しだけGASで運用してたbotに関する記事を投稿すると思います。