LINEbotからの返信をボタンテンプレート（と、URIアクション）にする

# はじめに
色々なページを参考に、テキストをオウム返しするLINEbotを作成しました。
次のステップとして、[公式ドキュメント](https://developers.line.biz/ja/docs/messaging-api/message-types/)を参考にボタンテンプレートを返そうと思いましたがイメージが掴めなかったので、とりあえず作るかの精神で色々試した結果うまくいったので、参考になればと思い記事にしました。

# 完成イメージ
下の画像のような感じで、にゃーんと言うとボタンテンプレートが送られてくるようにします。
また、画像上の「URIアクションのLABEL」部分をタップすると、指定のURLを開くようにします。
<img width="375" alt="IMG_6195.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/181775/800c6b7c-5ed9-f522-3152-635e5f86a3d0.png">
ちなみにその前のにゃーんの連打は、失敗したやつです。悪しからず。

# 前提条件
すでにMessaging APIを利用して、オウム返しができる状態から解説を始めます。
0から始める場合は下記記事などを参考にしてください。

[LINE Messaging API を使ってLINEにメッセージ送信／メッセージ返信する](https://qiita.com/fkooo/items/d07a7b717e120e661093)
[PythonでLine botを作ってみた](https://qiita.com/krocks96/items/67f7510b36945eb9689b)
[Python初心者がたったの3日間でチャットボットを作った【0日目】](https://yukituna.com/1192/)
[FlaskでLINE botを実装し，herokuにdeployするまで](https://qiita.com/suigin/items/0deb9451f45e351acf92)
[line-bot-sdk-python（こちらのコードを元にオウム返し版を作成しました）](https://github.com/line/line-bot-sdk-python/tree/master/examples/flask-echo)

私はPython3+Flask+Herokuで作りました。

# 追加コード
準備として、`from linebot.models import()`の中に`TemplateSendMessage,ButtonsTemplate,URIAction`を追加してください。

```Python
from linebot.models import (
    MessageEvent, TextMessage, TextSendMessage, 
    TemplateSendMessage,ButtonsTemplate,URIAction #こ↑こ↓が追加分
)
```

今回は分かりやすくするため、関数として定義します。
下記コードを`@app.route("/")`の上あたりに記載します。
（[記事の最後にコード全文](https://qiita.com/drafts/c599a94dfa39c6466dfa/edit#%E3%82%B3%E3%83%BC%E3%83%89%E5%85%A8%E4%BD%93)がありますので、どこかよく分からない場合は参考にしてください）

```app.py
def make_button_template():
    message_template = TemplateSendMessage(
        alt_text="にゃーん",
        template=ButtonsTemplate(
            text="どこに表示されるかな？",
            title="タイトルですよ",
            image_size="cover",
            thumbnail_image_url="https://任意の画像URL.jpg",
            actions=[
                URIAction(
                    uri="https://任意のページURL",
                    label="URIアクションのLABEL"
                )
            ]
        )
    )
    return message_template
```

各パラメーターの詳しい解説は、下記を参照してください。
[ボタンテンプレート](https://developers.line.biz/ja/reference/messaging-api/#buttons)

次に、`@handler.add(MessageEvent, message=(TextMessage))`を下記のように変更します。

```app.py
@handler.add(MessageEvent, message=(TextMessage))
def handle_image_message(event):
    messages = make_button_template()
    line_bot_api.reply_message(
        event.reply_token,
        messages
    )
```

# 簡単な解説
`def make_button_template():`にて、テンプレートメッセージ（今回はボタンテンプレート）を作成します。
そして`action`のところでURIActionを使用して、表示したいURLとタップする箇所のラベル文字を指定します。

あとは`line_bot_api.reply_message`の部分で、作成したテンプレートメッセージを送信してもらいます。

# 完成！
にゃーんとメッセージを送信すると、下記のようにボタンテンプレートが返ってきます。
（今回はオウム返しの延長として作っているので、テキストならなんでも返ってきますが）
<img width="375" alt="IMG_6195.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/181775/fa3782d8-3534-12b2-e913-31d79150de80.png">
↓「URIアクションのLABEL」部分をタップすると
<img width="375" alt="IMG_6196.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/181775/44fff639-b6af-8fff-293d-c82ace6f16fb.png">

指定したURLに飛びます。
今回はテスト用に[私の写真ブログ](https://www.shimay.uno/nekoguruma/)の画像とURLを使用しました。

# 応用
例えばこのコードを基に、`title`や`thumbnail_image_url`なんかをベタ書きではなく、ブログやニュースサイトなんかをスクレイピングしてランダムに送信するとか、送信したメッセージによって取ってくる記事のジャンル（野球、サッカーみたいな感じ）を指定したりとかすると、発想次第では面白いLINEbotができそうですね。
LINEbotを作るのに参考にした中では、下記のbotが個人的に面白かったです。

[[筋トレ] LINE Notifyからマッチョの画像が送られてくる](https://qiita.com/marusho_summers/items/ad7c1da11b2bf2a05598)
[毎朝大相撲力士の画像を送ってくれるLINE BOTを作った](https://qiita.com/a0082273/items/59fac519b5695fdd4dea)


# 困ったところ(2020.04.22追記)
## チャネルアクセストークンがない
1年ぶりくらいに触ったらチャネルアクセストークンがなくて焦りましたが、
「Messaging API設定」タブの一番下にあります。

古い記事だと更新されていないので、チャネル基本設定を穴があくほど見がちですが、場所を移動しただけでした。

## メッセージが返ってこない
試してみて欲しいこととしては、
1. 「Webhook設定」-「検証」をクリックする
「成功」または「Webhookが無効なHTTPステータスコードを返しました（期待されるステータスコードは200です）」が出れば、ひとまずMessaging APIの設定は問題ないと思われます。

ダメな場合は、
1. チャネルアクセストークンを再発行する
2. Herokuの環境設定でアクセストークンを再設定する
3. Herokuを再起動する   `heroku restart`

これで解決したことがありました。

## 「メッセージありがとうございます！」+おうむ返しが返ってくる
1. 「Messaging API設定」タブ-「あいさつメッセージ」の編集をクリックする
2. 「応答設定」-「詳細設定」-「応答メッセージ」をオフにする

ところで「応答メッセージ」の編集と「あいさつメッセージ」の編集が結局同じページに行くのは何故なんだぜ？

#おわりに
近々これを応用したLINEbotを作成する予定です。お楽しみに。

分かりづらい所や誤りがあればコメントください。

#コード全体
<details><summary>サンプルコードを開く</summary><div>

```app.py
from flask import Flask, request, abort
from linebot import (
    LineBotApi, WebhookHandler
)
from linebot.exceptions import (
    InvalidSignatureError
)
from linebot.models import (
    MessageEvent, TextMessage, TextSendMessage, 
    TemplateSendMessage,ButtonsTemplate,URIAction
)
import os

app = Flask(__name__)

#環境変数取得
YOUR_CHANNEL_ACCESS_TOKEN = os.environ["YOUR_CHANNEL_ACCESS_TOKEN"]
YOUR_CHANNEL_SECRET = os.environ["YOUR_CHANNEL_SECRET"]

line_bot_api = LineBotApi(YOUR_CHANNEL_ACCESS_TOKEN)
handler = WebhookHandler(YOUR_CHANNEL_SECRET)

def make_button_template():
    message_template = TemplateSendMessage(
        alt_text="にゃーん",
        template=ButtonsTemplate(
            text="どこに表示されるかな？",
            title="タイトルですよ",
            image_size="cover",
            thumbnail_image_url="https://example.com/gazou.jpg",
            actions=[
                URIAction(
                    uri="https://example.com",
                    label="URIアクションのLABEL"
                )
            ]
        )
    )
    return message_template


@app.route("/")
def hello_world():
    return "hello world!"


@app.route("/callback", methods=['POST'])
def callback():
    # get X-Line-Signature header value
    signature = request.headers['X-Line-Signature']

    # get request body as text
    body = request.get_data(as_text=True)
    app.logger.info("Request body: " + body)

    # handle webhook body
    try:
        handler.handle(body, signature)
    except InvalidSignatureError:
        abort(400)

    return 'OK'


@handler.add(MessageEvent, message=(TextMessage))
def handle_image_message(event):
    messages = make_button_template()
    line_bot_api.reply_message(
        event.reply_token,
        messages
    )


if __name__ == "__main__":
#    app.run()
    port = int(os.getenv("PORT",5000))
    app.run(host="0.0.0.0", port=port)
```

</div></details>

[GitHubのリポジトリ](https://github.com/shimayu22/LINE-Chatbot-Flask-test)