Slack Bot作り最初の壁 ~APIの選び方~

Slackを導入していないIT企業の方が少ないでしょう。Slackの知識は身につけておいて損はありません。
そう思ってSlackのBotを作って会社のワークスペースで動かしていますが、最初はかなり戸惑ったのでSlack Bot制作の初学者向けに色々書き残しておきます。

## 作ったbot
Bot作りの経験者であることを明記しないと説得力が無いと思いましたのでデモ動画を載せておきます。
Gmail, Googleカレンダーと連携してメールチェックや予定の確認ができます。
![suebot_demo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601155/35718126-5106-8d6d-9229-115fe86eb244.gif)


## 最初の壁
事前知識無しにSlackのBot作りに挑むと案外戸惑います。
「SlackBot 作り方」とかでググるとSlackの日本語公式ページが見つかリますが初心者向けには書かれていません。イベントAPIを有効化しろとかいきなり出てきます。
そしてよくわからないままワークスペースの管理画面からEvents APIを有効化しようとするとリクエスト用のURLを入れろとか言われてもう訳がわかりません。
私がBot制作を始めたときに戸惑ったのは主に以下です。

* [Getting Started][1]の日本語ページはない。読むのに時間がかかる。
* Events APIを有効化するときにリクエストURLを要求される。何のことだろう。
* 他にもBotに使えそうなAPIがある。どれを使えばいいのかがわからない。

この記事ではコーディングには触れず、最初の壁であるAPI選びについて解説していきます。

## Slack Botの実現手段
大きく分けて4つあると思います。

* Incoming Webhook
* Outgoing Webhook
* Events API + Web APIの組み合わせ
* Real Time Message API

この記事ではそれぞれの向き不向きに着目して順番にざっくり解説します。


## Incoming Webhook
Incoming WebhookはSlackのAppディレクトリで公開されているアプリです。ワークスペースにインストールして使用します。
![スクリーンショット 2020-08-24 11.54.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601155/e5942ad6-ddaf-dad6-da5a-9f1927d52198.png)

### 特徴まとめ
- Slackから指定されるエンドポイントに対するHTTPリクエストを送信することでBotユーザーに発言させることができる
- 発言の内容はHTTPリクエストのbodyに含めることができる

最大の特徴は**プログラムを作成する必要がない**ことです。

### 概要
端的に書くと、**最も簡単なSlackへの情報出力手段です。Slackからの入力を受け付ける必要がないならこれを使いましょう。**
プログラミングを必要とせず、Slackから提供されるURLに対してPOSTリクエストを発行するだけで特定のチャンネルへの発言ができます。
公式からcurlのサンプルも提供されており、bodyの部分を変えるだけで自由なテキストをSlackに表示させることができます。

Bot経由の発言として扱われ、Botの名前やアイコン画像はワークスペース管理画面から自由に変えられるので、第三者から見ればBotと見分けがつきません。
エラーログ監視レポートや、CIジョブの異常終了などをSlackに通知したければIncoming Webhookで十分でしょう。


## Outgoing Webhook
こちらもSlackのAppディレクトリで公開されているアプリです。ワークスペースにインストールして使用します。
![スクリーンショット 2020-08-24 11.56.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601155/0b206166-5181-d11b-528a-119eda850f54.png)

Slackのチャンネル内でトリガーとなる言葉が発言されると、SlackからWebhookが送信されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601155/a664a910-5ceb-4977-6de7-9972390c51fb.png)

### 特徴まとめ
- Web APIを作成し、Slackサーバーからのリクエストに対してレスポンスを返すことでBotに発言をさせる
- Slackのワークスペース管理画面からAPIに対してリクエストを送るトリガーとなる言葉を登録できる

### 概要
Incoming Webhookは我々がSlackに対してリクエストを送信するのに対し、Outgoing WebhookはSlackが我々の用意するサーバーに対してリクエストを送信してきます。
ワークスペースの管理画面からトリガーとなるワードとトリガーを受け付けるチャンネルを登録し、リクエスト先のURLを登録すれば使用できます。
「最初の壁」で述べたEvents APIのリクエストURLとはこれと同じもので、Slackからのリクエストを受け付けるAPIサーバーのエンドポイントのことです。

つまり、**Slack Botを作る = WebAPIサーバーを作る**です。前情報無しの初心者はこれを知らないので躓きがちです。

Slackから送信されるリクエストの内容、こちらが返すべきレスポンスの内容はOutgoing WebhookのApp管理画面から確認できます。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601155/03fa53c9-d545-afd4-f077-df017a888fca.png)
引用: Slack Outgoing Webhook Appディレクトリ画面



## Events API + Web APIの組み合わせ
Outgoing Webhookと基本は同じですが、トリガーの幅はこちらの方が広く持たせられます。
Slack Botの最も一般的な実現方法だと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601155/6b6657d9-9beb-5437-ffe1-3bb08639c7d5.png)

### 特徴まとめ

- Slack上のメッセージだけでなく、チャンネル入退場、チャンネル作成などのイベントをトリガーとして動作することができる
- Appの管理画面からどのイベントをトリガーとするか設定できる
- Botに何か発言させたい時はSlack Web APIに対してリクエストを送信する

### 概要
Outgoing Webhookと同様に、Slackが特定のトリガーに反応してWeb APIに対してリクエストを送信してきます。
Bot制作当初はSlackイベントを取り扱う予定がなくても、運用していく過程でイベントへの反応が欲しくなることがあるでしょう。
実装の手間は多少膨らみますが、Outgoing WebhookよりもEvents APIで制作を始めることを個人的にはおすすめします。

Events APIはSlack Appを作成し、Events Subscriptionsを設定することで有効化できます。
![Events-API.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601155/585f408a-64cb-b201-c3b9-e1fed3c2f903.png)

引用: Slack AppのBasic Information画面

Events APIでの開発は公式でBoltというフレームワークが提供されています。
[日本語ドキュメント][2]が用意されており、非常に見やすいのでWeb APIの制作経験がない方でも取っ付きやすいかもしれません。

## Real Time Messaging API
いわゆるRTM APIです。SlackのサーバーとWebsocketで通信し、Slack上のイベント発生通知を受け取ります。
![RTM.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601155/f7047218-a4e2-46b7-e926-45d01393171e.gif)

### 特徴まとめ

- Web APIを用意する必要がない。公開サーバーを用意しなくてもローカルマシンでSlack Botを動かせる
- Websocket通信でSlackのサーバーと通信する。大きなワークスペースと接続するとリソースの消費が大きい。

最大の利点は**ローカルマシンでSlack Botを動かせる手軽さ**です。

### 概要
RTM APIでBotを作成する場合はOutgoing WebhookやEvents APIと違ってAPIサーバーを必要としません。
ワークスペースにBotを登録するとトークンが配布され、それを利用してSlackとWebsocketで接続します。
インターネットに繋がる環境であれば何処でも動かすことができ、開発PCでそのまま動かすことができるので、間違いなく手軽さはNo.1です。

一応、欠点としてはリソース消費の大きさが挙げられます。
Events APIと異なり、トリガーとなるイベントを絞り込むことができないので、大きいワークスペースでは大量のイベントが送信されてくることになります。
複数のワークスペースとコネクションを確立することもできますが、その分多くのリソースを消費することになります。

注意点として、new Slack appsではRTMは利用できないようです。
下記のページ最下部にあるCreate a classic Slack appのボタンからV1 OAuth認証のSlack Appを作成する必要があります。
[Real Time Messaging API][3]

## APIの選び方まとめ
私が考える目的別のAPIの選び方はこんな感じです。

|やりたいこと|API|
|---|---|
|エラーログ監視、ジョブの失敗などをSlackに通知させたい|Incoming Webhook|
|定期的にBotユーザーに発言させたい|Incoming Webhook|
|公開Webサーバーを用意せずにBotを作りたい|Realtime Message API|
|ユーザーからの特定の単語に反応するBotを少ない実装で作りたい|Outgoing Webhook|
|チャンネル参加 チャンネル作成などのイベントに合わせて発言させたい|Events API|
|拡張性も考慮してとりあえず無難にBotを作りたい|Events API|

以上、誤りや改善点などありましたらコメントください。

[1]:https://api.slack.com/bot-users
[2]:https://slack.dev/bolt-js/ja-jp/tutorial/getting-started
[3]:https://api.slack.com/rtm