【2019年版】pythonでインタラクティブなボタン付きslackbot作成

# 大本
https://qiita.com/sh-tatsuno/items/55cd5f9e78b212fb57c2

# 目的
* 上の記事を元に作成slackbotを作成しようとしたが変更点が色々あったので記録


# 環境
* OS：Mac Mojave 10.14.5

# 前提
* herokuへの登録
* 適当なslackアカウント

# slack app の準備

botを入れたいワークスペースで
#### 1. 
<img width="210" alt="スクリーンショット 2019-08-13 22.23.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196857/57acdc02-a655-1158-f101-8f12ec3a78c9.png">
のAppを押します。

#### 2. 

<img width="870" alt="スクリーンショット 2019-08-13 22.23.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196857/56943670-1275-0bbc-487a-2b060baf1bb7.png">
Appディレクトリを表示　を押して

#### 3. 

<img width="1154" alt="スクリーンショット 2019-08-13 22.24.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196857/b73c46f0-7eac-cfcf-a571-3a361d9a7faf.png">
ビルド　を押して

#### 4. 

<img width="1443" alt="スクリーンショット 2019-08-13 22.24.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196857/4114891c-961d-a58e-c692-4a74c7dd0a46.png">
Your Apps（右上）　を押して
#### 5. 

<img width="752" alt="スクリーンショット 2019-08-13 22.24.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196857/bce9385c-3328-6027-331f-6e9f65391e44.png">
Create New App　を押して
#### 6. 

<img width="547" alt="スクリーンショット 2019-08-13 22.24.57.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196857/a7300fbd-3417-f7c8-fe22-4b591cb76521.png">
App name をつけて、ワークスペースを選択して

#### 7. 

<img width="767" alt="スクリーンショット 2019-08-13 22.25.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196857/7f571461-1203-4544-89d5-a7bbf23abbbb.png">
Interactice Componentを選んで

#### 8. 

<img width="774" alt="スクリーンショット 2019-08-13 22.27.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196857/104cfde7-8ad3-e864-d1f7-2d9f198eeeb0.png">
https://(herokuのアプリ名)/herokuapp.com/slack/json_html
というURLにして
（herokuのアプリ名？となる場合はvenvでの環境づくりを先にやると良いでしょう。）

#### 9. 

<img width="738" alt="スクリーンショット 2019-08-13 22.27.53.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196857/46324a57-4e31-1850-824b-1047b7297cb0.png">
Scopeをsend message as (app名）にして

#### 10. 

<img width="727" alt="スクリーンショット 2019-08-13 22.28.16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196857/d38cbc20-c17f-2351-ef7f-85c8b5c8d25b.png">

OAuth tokenをメモしてinstallします。

#### 11. 

<img width="742" alt="スクリーンショット 2019-08-13 22.28.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196857/4a77edaa-c5e2-3568-d968-76e2fdbfff7c.png">
そして verification token をメモして終了です。


# venvでの環境づくり[^1]
まずは

```shell
heroku apps
```
で作成されているアプリ名の一覧を取得しましょう。
ここで`myslackbot`というアプリがあったとしましょう。
もしなければ

```shell
heroku create <app-name>
```
で作成できます。

作業用のディレクトリも作っておきましょう

```shell
mkdir bot_test
cd bot_test
```

この中で、venvを使って仮想環境を作ってみましょう。

```bath
python3 -m venv slackbot
```
とすれば仮想環境が作成できます。（slackbotというフォルダが出来ているはずです）

```bash
. slackbot/bin/activate
```
とすれば、仮想環境に入ることが出来ます[^2]。
今回はこの中で使いたいライブラリをpipで入れます。

```bash
pip install flask
pip install gunicorn
pip install slackclient
```

# Heroku用の準備[^1]
（この章は[^1]のほぼ真似です。素晴らしい記事に大感謝です。）
Herokuでは

* requirements.txt
* runtime.txt
* Procfile

の3ファイルが必要になります。

## runtime.txt

```
python-3.6.8
```
と**過不足なく**書いてください。
ちなみにHerokuでは

* python-3.7.3
* python-3.6.8
* python-2.7.16

が使用可能です[^3]。（3.7.3でも動くはずです）

## requirements.txt

上で紹介したvenvで仮想環境に入った状態で、

```
pip freeze > requirements.txt
```
を実行してください。

## Procfile
今回はmain.pyを実行するので

```
slackbot: gunicorn main:app --log-file=-
```

とすれば問題ありません。

# main.pyの作成

大本の記事のほとんどコピペです。
変更点は後述しますが、slackclientがversion 2になったためです。
（ですので無理矢理version1.3とかにすれば、問題なく使えるのかな、と思ったりしますがオススメはしません）
またコメントで書いておりますが、herokuで変数設定が出来ない（なんで？）ため、tokenを直打ちしています。

``` python3
from flask import Flask, request, make_response, Response
import os
import json

# 変更点1
from slack import WebClient

# Your app's Slack bot user token

# herokuでうまく変数設定出来なかったので直接打ち込んでいます。
SLACK_BOT_TOKEN = "OAuth tokenを入力"
SLACK_VERIFICATION_TOKEN ="verify tokenを入力"

# Slack client for Web API requests
slack_client = WebClient(SLACK_BOT_TOKEN)


# Flask webserver for incoming traffic from Slack
app = Flask(__name__)

# your attachment
attachments_json = [
    {
        "fallback": "Upgrade your Slack client to use messages like these.",
        "color": "#258ab5",
        "attachment_type": "default",
        "callback_id": "the_greatest_war",
        "actions": [
            {
                "name": "choco1",
                "text": "きのこ",
                "value": "kinoko",
                "type": "button"
            },
            {
                "name": "choco2",
                "text": "たけのこ",
                "value": "takenoko",
                "type": "button"
            }
        ]
    }
]

#route
#when you access such as curl command, slackbot post interactive message
@app.route("/", methods=["GET"])
def index():
    # 変更点2
    slack_client.api_call('chat.postMessage', json={
        'channel': '#general',
        'text': 'あなたはどっち派？',
        'attachments':attachments_json
    })

    return make_response("", 200)

## 変更点4
#redirect from button
@app.route("/slack/json_html", methods=["POST"])
def json_html():

    # Parse the request payload
    form_json = json.loads(request.form["payload"])

    val = form_json["actions"][0]["value"]
    if val == "kinoko":
        response_text = "よろしい、ならば戦争だ"
    else:
        response_text = "よろしい、ならば盟友だ"
    # 変更点3
    response = slack_client.api_call(
        "chat.postMessage",
        json={
        "channel":"#general",
        "text":response_text,
        "attachments":[]
        }
    )

    return make_response("", 200)
```

## 変更点1
githubのissue[^4]を見ていただければわかりますが

```python3
# Before:
# import slackclient

# After:
from slack import WebClient
```

とのことです。

## 変更点2、3
これも変更点1と同様のURLを見ていただければわかりますが

```python3
# Before:
# from slackclient import SlackClient
#
# client = SlackClient(os.environ["SLACK_API_TOKEN"])
# client.api_call('chat.postMessage',
#     timeout=30,
#     channel='C0123456',
#     text="Hi!")

# After:
import slack

client = slack.WebClient(os.environ["SLACK_API_TOKEN"], timeout=30)
client.api_call('chat.postMessage', json={
    'channel': 'C0123456',
    'text': 'Hi!'})

# Note: The SlackAPIMixin allows you to write it like this.
client.chat_postMessage(
    channel='C0123456',
    text='Hi!')
```

とのことです。
1個目のように、json=の中に入れ込んでもいいですし
2個目のように、chat_postMessageメソッドを使ってもいいみたいですね。

channel, text, attachments 以外で使えるものは公式[^5]を参照してください。

## 変更点4
（slackのsettingの方を変更していますが）、slackのapp作成時に登録したURL（slackの準備：8のURL)とmain.pyでbutton redirectするURLを一致させています。



# gitの設定とデプロイ

## gitの設定

```bash
git init
git add .
git commit -m "first commit"
git push heroku master
```

このあと

```bash
heroku open
```
でslackに投稿されていれば成功です。

<img width="231" alt="スクリーンショット 2019-08-13 22.23.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196857/c5f2508e-54e3-a199-57a0-2c79f74d1786.png">



[^1]: https://www.lisz-works.com/entry/heroku-python-deploy
[^2]: mac以外のOSなど、venvの詳しい使い方は https://qiita.com/fiftystorm36/items/b2fd47cf32c7694adc2e
[^3]: https://devcenter.heroku.com/articles/python-support#supported-runtimes
[^4]: https://github.com/slackapi/python-slackclient/issues/384 
[^5]: https://api.slack.com/methods/chat.postMessage