【2019年版】インタラクティブなボタン付きslackbotをスラッシュコマンドで起動させる

#前回

https://qiita.com/okd46/items/201061f1950a990417ad

# 目的
前回作成したbotではURLを打ち込まないとbotが呼び出せない、という問題点があった。
これをslackのスラッシュコマンドで呼び出せるようにする。


# slack上での準備
##1. 
<img width="199" alt="スクリーンショット 2019-08-18 17.21.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196857/cc9a2e51-cfb3-dc7e-d875-96917f77f65f.png">
任意のワークスペースで画像のAppを押して
##2.
<img width="957" alt="スクリーンショット 2019-08-18 17.21.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196857/07216846-baf4-3fc3-6ae7-5f8cd49fd72f.png">
Appディレクトリを表示を押して
##3.
<img width="1143" alt="スクリーンショット 2019-08-18 17.21.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196857/96b04180-4c30-4f5e-746f-e2df3e12ed7e.png">

ビルドを押して
##4.
<img width="1390" alt="スクリーンショット 2019-08-18 17.23.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196857/aa8a2af2-6b09-23b4-9aec-4965b3f78fce.png">
Your Appsを押して
##5.
<img width="757" alt="スクリーンショット 2019-08-18 17.23.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196857/b38fe904-c401-70b5-98e1-6cc91802e5eb.png">
対象のAppを選んで
##6.
<img width="738" alt="スクリーンショット 2019-08-18 17.23.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196857/13f0195e-06c5-fd5d-128e-73e9a001763d.png">
Interactive Componentsを押して
##7.
<img width="732" alt="スクリーンショット 2019-08-18 17.26.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196857/b78609e0-82e5-2b8e-771e-2800fd37cc3f.png">
Scopesの Add slach commands and ...を選んで、save Changesを選択
##8.
<img width="1610" alt="スクリーンショット 2019-08-18 17.27.11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196857/f9a435f8-6452-9033-343d-a79d0b9f5d6f.png">
すると画面上部に、appを再インストールするように促されるので従って
##9.
<img width="304" alt="スクリーンショット 2019-08-18 17.27.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196857/466a9076-f4c1-8475-5c5e-c14732dd0ff3.png">
画面左側のFeaturesのところにSlash Commandsが追加されるので、これを選択して
##10.
<img width="587" alt="スクリーンショット 2019-08-18 17.29.03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196857/90355096-32a8-d661-9b49-ef42f0bc658d.png">
任意のコマンド名と、リクエストURL、その説明を打ち込む。
リクエストURLは "Herokuの自分が使っているAppのURL"/"コマンド名"
（例えばｈttps://Herokuのappの名前.herokuapp.com/testcommand)


これでslack上の設定は完了です。

# pythonコード
```python

# jsonifyを新たにimport
from flask import Flask, request, make_response, Response, jsonify
#　以下は前回のコードと一緒
# ---------ここから---------
import os
import json

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():
    slack_client.api_call('chat.postMessage', json={
    'channel': '#general',
    'text': 'あなたはどっち派？',
    'attachments':attachments_json
    }
)

    return make_response("", 200)

#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 = "よろしい、ならば盟友だ"
    response = slack_client.api_call(
        "chat.postMessage",
        json={
        "channel":"#general",
        "text":response_text,
        "attachments":[]
        }
    )

    return make_response("", 200)
# ---------ここまで---------
# 以下が今回追加するコード
# URLはslack上で設定したURLの.com以降
@app.route('/testcommand', methods=['POST'])
def bottest():
    return jsonify(
        response_type='in_channel',
        text='あなたはどっち派？',
        attachments = attachments_json
    )

```

`response_type='in_channel'`とすれば、そのまま同じチャンネルで返してくれるので嬉しい。

これを前回と同様にデプロイして、slack上で`/testcommand`と打てば前回と同じものが出てくるはず。
たまに

```
/testcommand はエラー「operation_timeout」により失敗しました
```
これが出てくることもあるが、これは多分herokuのapp立ち上げに時間がかかってtimeoutしてしまうだけで、もう一度実行すれば（もう立ち上がっているので）エラーは出ないはず


# 参考
大体全て
https://renzo.lucioni.xyz/serverless-slash-commands-with-python/
response_type, text, attachmentsについては
https://api.slack.com/slash-commands#responding_to_commands