Slack APIを使ってみよう！【Slack + Rails】

# はじめに
この記事では、Slackへメッセージを送るRailsアプリを作成してみます。
動作としてはこんな感じです。

1. http://localhost:3000/hello にアクセスする
2. Slackに「こんにちは」とメッセージが送られる

# Slack APIとは何か？
Slack用のアプリケーション開発のためにSlackから公開されているAPIです。

# 事前準備
1. Slackのワークスペースを作成する  
下記ページを参考に、Slackのワークスペースを作成しておきましょう。
  - [Slack ワークスペースを作成する | Slack](https://slack.com/intl/ja-jp/help/articles/206845317-Slack-%E3%83%AF%E3%83%BC%E3%82%AF%E3%82%B9%E3%83%9A%E3%83%BC%E3%82%B9%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B)

**※注意**
アプリケーション開発用のワークスペースをすでに作成済みであれば、
新たに作成する必要はありません。
実際の業務などで使用しているワークスペースを流用しないようにしてください。

# Slackアプリを作ってみよう

まずは、Slack側でアプリを作ってみます。

## アプリの新規作成 
  1. 下記ページにアクセス
      - [Slack API: Applications | Slack](https://api.slack.com/apps)
  2. 「Create New App」ボタンを押してモーダルを開きます。  
  3. `App Name` は 「テストBot」(名前はなんでも良い)、  
`Develoment Slack Workspace` には作成した開発用のワークスペースを指定します。  
  4. 右下の「Create App」ボタンを押すと、アプリが作成されます。
![Slackアプリ新規作成Modal.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261148/226ecefa-5eb7-945a-7318-0ca9ba004569.png)

## アプリのPermission(権限)の設定

1. 権限設定画面を開く  
アプリ新規作成後、下記のようなアプリの基本情報画面に遷移します。  
`Install your app to your workspace` というメニューを開くと、  
「最低1つ以上の`feature`か、`permission scope`を設定する必要がある」と書いてあります。  
![アプリの基本情報画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261148/cdec155e-2dac-10d6-954c-1de3176f8536.png)
この`permission scope`というリンクを押すと、権限設定画面に移動します。
![権限設定画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261148/4303c3d3-fa4b-e5a1-6b43-db5216ac1239.png)
2. 必要なスコープの設定
権限設定画面で、必要な権限を設定します。  
今回は、 **メッセージの送信をできるようにしたい** ので、   
`chat:write` というスコープを設定します。  
これで、Botとして参加しているチャンネル内でメッセージの送信を行えるようになります。
![スクリーンショット 2020-08-16 21.45.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261148/cbea493c-067d-ea77-7242-611ba502f298.png)  
[スコープ](https://api.slack.com/scopes)にはいろいろな種類があり、  
それぞれのアプリに最低限必要なもののみを設定することで、  
セキュリティを保つことができます。

これで権限設定は完了です。

## Botを設定する
1. Botの名前を設定  
左サイドメニューから`App Home`を選択して、アプリケーションのホーム画面を開きます。  
赤枠で囲んだ部分の「Edit」ボタンを押して、アプリの名前を設定します。
![Botの設定画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261148/4dff4413-879a-f6a7-a436-624bdc3932e8.png)
今回は下記のように設定しましたが、好きな名前で設定して問題ないです。
![Botの名前設定モーダル.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261148/4ca389e3-656f-3d06-e050-30ca50c8f84c.png)

これでワークスペースにアプリをインストールできるようになりました。

## ワークスペースにアプリをインストールする

1. インストール画面を開く  
左サイドメニューから`Install  App`を選択して、  
ワークスペースへのアプリインストール画面を開きます。
![アプリインストール画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261148/b01f588a-7bfe-b92f-9c74-a1ca060b7389.png)
2. インストールの確認画面  
「Install App To Workspace」ボタンを押すと、下記のような画面が開きます。  
(画像では、ワークスペース名などを隠しています。)  
「実行出来る内容」の部分が期待通りであることを確認して、「許可する」ボタンを押しましょう。
![インストールの確認画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261148/f9832a50-c5eb-f023-06d8-f54bb2406b37.png)
3. トークンが発行される
「許可する」ボタン押下後、下記の画面に遷移します。  
この時に表示されるトークンが、  
Slack APIを利用したメッセージの送信時に必要なので、メモしておいてください。  
**(このトークンを公開してはいけません。**  
**トークンを知った人であれば誰でも、先ほど作成したBotとしてワークスペースへメッセージを送ることができるようになってしまいます。)**
![スクリーンショット 2020-08-16 22.12.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261148/904598d8-fff7-275b-0a8b-e85a0e67ce94.png)

## ワークスペースのチャンネルにアプリを招待する

任意のチャンネルに、作成したアプリを招待します。
アプリを招待したいチャンネルを開いて、 
`/invite @アプリのワークスペースでの表示名` を送信します。
(今回は `#テスト用チャンネル` という名前のチャンネルです。
任意のチャンネルで問題ないです。)

これで、 `#テスト用チャンネル` 内で作成したアプリがメッセージを送信できるようになりました。
![Slack招待.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261148/311ee972-d40a-bfdf-efb9-c03a74152dd5.png)

以上で、Slack側の準備は完了です。

# RailsアプリからSlackへメッセージを送ってみよう

## Railsアプリの準備
下記リポジトリに、今回使うRailsアプリを用意しているのでcloneしてください。

- [slack-rails-example](https://github.com/KanaeMurakami/slack-rails-example)

`README.md` の手順にしたがって、環境構築を行ってください。

## 今回使うgemの説明

下記2つのgemを `Gemfile` に追加しています。

### 1. [dotenv-rails](https://github.com/bkeepers/dotenv#rails)

開発環境で、
アプリケーションのルートディレクトリに配置した `.env` ファイル内から
[ENV](https://docs.ruby-lang.org/ja/latest/class/ENV.html) に変数を読み込むためのgemです。

今回は、ワークスペースにアクセスするためのトークンの管理に使用します。

### 2. [slack-ruby-client](https://github.com/slack-ruby/slack-ruby-client)

RubyでSlackのAPIを利用するためのgemです。

今回は、Slackへメッセージを送信するために使います。

## トークンを設定する
Railsアプリケーションに、作成したSlackアプリのトークンを設定します。
(ここで説明するのはレガシーな方法なですが、
今回はいったん手っ取り早くできるこちらの方法を利用します。)

### `.env` ファイルを作成する
アプリケーションのルートディレクトリに、 `.env` というファイルを作成しましょう。
ファイルの中身は下記です。

```:.env
BOT_USER_ACCESS_TOKEN=Botのアクセストークン
```

`Botのアクセストークン`の部分は、
 [こちら](#ワークスペースにアプリをインストールする)で作成したトークンに置き換えてください。

### トークンの設定
次に、下記のファイルを作成してください。
これで、gem `slack-ruby-client` を利用したAPIの実行時、
認証用のトークンがパラメータとして送信されるようになります。

```ruby:config/initializers/slack_ruby_client.rb
Slack.configure do |config|
  config.token = ENV['BOT_USER_ACCESS_TOKEN']
end
```

## `hello` アクションを作成してみよう

では、`slack-ruby-client`を利用してSlackAPIを実行するように、
コントローラーのアクションを作ってみます。

### ルーティングの追加

`config/routes.rb` にルーティングを追加します。
「 `/hello` というパスには`applicationコントローラー` の `hello` アクション が対応する」
というルーティングです。

```diff:config/routes.rb
Rails.application.routes.draw do
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
+ get "hello", to: 'application#hello'
end
```

### アクションを作成する
`hello` アクションを作成します。

```ruby:app/controllers/application_controller.rb
class ApplicationController < ActionController::API
  def hello
    client = Slack::Web::Client.new
    client.chat_postMessage(
      channel: '#テスト用チャンネル',
      text: 'こんにちは'
    )
  end
end
```

上記のソースについて簡単に説明します。

- `client = Slack::Web::Client.new`
`slack-ruby-client` では、基本的にこのオブジェクトをレシーバとして、
様々なSlackAPIに対応したメソッドを呼び出します。

- `client.chat_postMessage` 
これは、 [chat.postMessage method](https://api.slack.com/methods/chat.postMessage)というAPIに対応する `slack-ruby-client` のメソッドです。  
見ただけでわかると思うのですが、
メソッドの引数で「メッセージを送信するチャンネル」と「テキスト」を指定しています。

## メッセージを送る
では、実際にメッセージを送信してみましょう。

`bin/rails`でサーバーを起動し、
ブラウザで http://localhost:3000/hello にアクセスします。
Slackを確認すると、下記のようにメッセージが送信されていると思います。

![スクリーンショット 2020-08-16 23.18.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261148/24056576-fe2b-3ade-4df1-5becbe6a0129.png)

今回作りたかったアプリケーションはこれで完成です。
今回は一つのAPIしか利用していませんが、
いろいろなAPIを複合的に利用することで目的のアプリを作成できるようになると思います。

- 用意されているAPIの一覧
  - [Using the Slack Web API | Slack](https://api.slack.com/web#methods)


# Block Kit Builderを使ってメッセージのフォーマットを整えてみよう
実際にアプリを作成した場合、もう少しいい感じにテキストを表示したいと思います。
(箇条書き、文字サイズ、文字色の指定など)

そんな場合は、下記のBlock Kit Builderを使ってみましょう。

- [Block Kit Builder | Slack](https://app.slack.com/block-kit-builder/)

これを使うと、簡単にボタンやテキストを配置のプロトタイプを作成することができます。

![BlockKitBuilder使用例.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261148/941e9545-71c4-ea36-d378-ed70dbcb9265.png)

画面の右側に作成したリッチテキストから生成されたコードが表示されるので、
これをコピーすればすぐにアプリケーションに組み込むことができます。

<details><summary>作成したコード</summary><div>

```json
{
	"blocks": [
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": "今日も暑いね:watermelon: 無理せずがんばろう:smile:"
			}
		},
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": "何をチェックする？",
				"emoji": true
			}
		},
		{
			"type": "actions",
			"elements": [
				{
					"type": "button",
					"text": {
						"type": "plain_text",
						"emoji": true,
						"text": "天気"
					},
					"style": "primary",
					"url": "https://www.jma.go.jp/jp/yoho/"
				},
				{
					"type": "button",
					"text": {
						"type": "plain_text",
						"emoji": true,
						"text": "カレンダー"
					},
					"style": "danger",
					"url": "https://calendar.google.com/"
				},
				{
					"type": "button",
					"text": {
						"type": "plain_text",
						"emoji": true,
						"text": "ニュース"
					},
					"url": "https://news.google.co.jp/"
				}
			]
		}
	]
}
```
</div></details>

## `hello` アクションを更新してみよう

試しに、先ほど作成した `hello` アクションを更新して、
作成したブロックをメッセージとして送信できるようにしてみましょう。

`chat_postMessage`の引数に、 `blocks` を追加しています。
(ソースコードが長いので折りたたんでいます。)

<details><summary>`hello` アクションを更新</summary><div>

```ruby:app/controllers/application_controller.rb
  def hello
    client = Slack::Web::Client.new
    client.chat_postMessage(
      channel: '#テスト用チャンネル',
      text: 'こんにちは',
      blocks: [
        {
          "type": "section",
          "text": {
            "type": "mrkdwn",
            "text": "今日も暑いね:watermelon: 無理せずがんばろう:smile:"
          }
        },
        {
          "type": "header",
          "text": {
            "type": "plain_text",
            "text": "何をチェックする？",
            "emoji": true
          }
        },
        {
          "type": "actions",
          "elements": [
            {
              "type": "button",
              "text": {
                "type": "plain_text",
                "emoji": true,
                "text": "天気"
              },
              "style": "primary",
              "url": "https://www.jma.go.jp/jp/yoho/" # 気象庁HP
            },
            {
              "type": "button",
              "text": {
                "type": "plain_text",
                "emoji": true,
                "text": "カレンダー"
              },
              "style": "danger",
              "url": "https://calendar.google.com/" # Googleカレンダー
            },
            {
              "type": "button",
              "text": {
                "type": "plain_text",
                "emoji": true,
                "text": "ニュース"
              },
              "url": "https://news.google.co.jp/" # Googleニュース
            }
          ]
        }
      ]
    )
  end
```

</div></details>

Railsアプリを起動し、 再度 http://localhost:3000/hello にアクセスします。
すると、Slackには下記のような通知がくると思います。

![Blockを含んだメッセージ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261148/44d24551-3cf3-10ce-33c8-ed28f94debb9.png)

Block Kit Builderの紹介は以上です。
Block Kit のチュートリアルについては、こちらも参照してください。

- [Block Kit を使ってより情報的なレストラン検索コマンドを作ろう | Slack](https://api.slack.com/lang/ja-jp/slash-block-kit)

# あとがき

実際にRailsアプリをHerokuなどにデプロイすることで、
Slack上でコマンドを実行するとそれに応じてメッセージを返すBotを作成することもできます。

記事ボリュームの都合上入れられなかったので、それについてはまた次回書きます。

Slack APIについてはいくつか日本語翻訳されているページもあるので、
[こちら](https://api.slack.com/lang/ja-jp) をベースにいろいろ学習できると思います。

# 参考URL
- [bkeepers/dotenv](https://github.com/bkeepers/dotenv)
- [object ENV (Ruby 2.7.0 リファレンスマニュアル)](https://docs.ruby-lang.org/ja/latest/class/ENV.html)
- [slack-ruby/slack-ruby-client](https://github.com/slack-ruby/slack-ruby-client)
- [Block Kit Builder | Slack](https://app.slack.com/block-kit-builder/)