PythonとHerokuでLINEBOTを作ってみた

Python学習の一環でオウム返しするLINEBOTを作ってみました。
#完成イメージ
![スクリーンショット 2020-11-23 210818.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603568/99228e67-a413-d364-f741-a7c8473f9c95.png)
![Image from iOS.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603568/debd46d5-d1f5-ee9f-168a-25b60eb01761.png)
#環境構成
・Python
・Heroku
・LINE Developers
・Flask
#開発手順
1.LINE Developers 登録&設定
2.Heroku 登録&設定
3.Pythonで実装
4.再度LINE Developers 設定
5.Herokuへデプロイ
#LINE Developers 登録&設定
![スクリーンショット 2020-11-23 230638.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603568/f707d838-0468-2f97-aa99-caf6594096bb.png)
下記のリンク先でLINE Developersのアカウントとプロバイダー、チャンネルを作成する。
https://developers.line.biz/ja/services/messaging-api/
###アカウント作成
アカウントは名前とメールアドレスで作成可能です。
###プロバイダー作成
プロバイダー名（ご自分の名前や企業名）で作成
###チャンネル作成
・チャンネルタイプ　→　Messaging API
・プロバイダー
・チャンネル名
・チャンネル説明
・カテゴリー
・サブカテゴリ
・電子メールアドレス
利用規約に同意して作成する。
###友達登録
チャネル基本設定→メッセージAPIのQRコードで友達登録しておく。
###必要情報の確認
基本設定→チャネルシークレット確認
メッセージAPI設定→チャネルアクセストークン発行、確認
#Heroku 登録&設定
![スクリーンショット 2020-11-23 230824.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603568/0747d79c-fb0c-0c1b-a09b-7b2b34a9c2bc.png)
Herokuは簡単に言えばアプリケーションを公開するまでの準備を代行してくれるサービスです。
[Herokuとは](https://www.sejuku.net/blog/7858)
###Herokuインストール
インストール設定等は下記の記事を参考にさせていただきました。
https://uepon.hatenadiary.com/entry/2018/07/27/002843
###Herokuの設定
GitCMDにてログイン

```:GitCMD
heroku login

heroku: Press any key to open up the browser to login or q to exit:
Opening browser to https://cli-auth.heroku.com/auth/browser/XXXX
Logging in... done
Logged in as XXXX@XXXX
```
アプリケーションの登録

```:GitCMD
heroku create 自分のアプリケーション名(以下アプリ名)

Creating ● アプリ名... done
https://アプリ名.herokuapp.com/ | https://git.heroku.com/アプリ名.git
```
環境変数の設定→参照:[環境変数とは](https://qiita.com/jeyei/items/2c385e4e0488a5fa2591)
先ほどLINE Developersで確認したチャネルシークレットとチャネルアクセストークンを設定する。

```:GitCMD
heroku config:set YOUR_CHANNEL_SECRET="Channel Secretの文字列" --app アプリ名
heroku config:set YOUR_CHANNEL_ACCESS_TOKEN="アクセストークンの文字列" --app アプリ名
```
この設定により
「YOUR_CHANNEL_SECRET」はチャネルシークレット
「YOUR_CHANNEL_ACCESS_TOKEN」はチャネルアクセストークン
としてHeroku内で使用できるようになる。

設定の確認

```:GitCMD
heroku config --app アプリ名
```
#Pythonで実装
![スクリーンショット 2020-11-23 233037.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603568/f1554ee3-f9ab-f304-e94e-44a6abfdb08c.png)
###ライブラリのインストール
GitCMDにて以下の内容を入力する。

```:GitCMD
pip3 install flask
pip3 install line-bot-sdk
```
・Flask（フラスコ/フラスク）はPythonのWebアプリケーションフレームワークで、小規模向けの簡単なWebアプリケーションを作るのに適したものです。→参考:[Flaskとは](https://aiacademy.jp/media/?p=57)

・line-bot-sdkはLINEBOTを作るために必要な機能が入っています。
→参考:[line-bot-sdkとは](https://codezine.jp/article/detail/9905)

実際のコードは以下のサイトのmain.pyを参考にさせていただきました。
https://uepon.hatenadiary.com/entry/2018/07/27/002843
また、書かれている内容の把握の為下記のサイトを参考にさせていただきました。
https://www.wantedly.com/companies/casley/post_articles/139107

```python:main.py
# 必要モジュールの読み込み
from flask import Flask, request, abort
import os
from linebot import (
    LineBotApi, WebhookHandler
)
from linebot.exceptions import (
    InvalidSignatureError
)
from linebot.models import (
    MessageEvent, TextMessage, TextSendMessage,
)

# 変数appにFlaskを代入。インスタンス化
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)

# Herokuログイン接続確認のためのメソッド
# Herokuにログインすると「hello world」とブラウザに表示される
@app.route("/")
def hello_world():
    return "hello world!"

# ユーザーからメッセージが送信された際、LINE Message APIからこちらのメソッドが呼び出される。
@app.route("/callback", methods=['POST'])
def callback():
    # リクエストヘッダーから署名検証のための値を取得
    signature = request.headers['X-Line-Signature']

    # リクエストボディを取得
    body = request.get_data(as_text=True)
    app.logger.info("Request body: " + body)

    # 署名を検証し、問題なければhandleに定義されている関数を呼び出す。
    try:
        handler.handle(body, signature)
    # 署名検証で失敗した場合、例外を出す。
    except InvalidSignatureError:
        abort(400)
    # handleの処理を終えればOK
    return 'OK'

# LINEでMessageEvent（普通のメッセージを送信された場合）が起こった場合に、
# def以下の関数を実行します。
# reply_messageの第一引数のevent.reply_tokenは、イベントの応答に用いるトークンです。 
# 第二引数には、linebot.modelsに定義されている返信用のTextSendMessageオブジェクトを渡しています。
@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
    line_bot_api.reply_message(
        event.reply_token,
        TextSendMessage(text=event.message.text))

# ポート番号の設定
if __name__ == "__main__":
#    app.run()
    port = int(os.getenv("PORT"))
    app.run(host="0.0.0.0", port=port)
```
#Webhookの設定
再度LINE Message APIへ戻り、WebhookのWebhook URLにHerokuの接続先を設定する
Webhook URL:https://アプリ名.herokuapp.com/callback
<font color="Red">※最後にcallbackメソッドの記入を忘れない事</font>
#設定ファイルの作成とデプロイ
参照:[デプロイとは](https://wa3.i-3-i.info/word16767.html)
Herokuに設置するファイル(先ほどのPythonソースコード「main.py」も)などを作成する。
ファイル作成の為Python等のバージョンを確認

```:GitCMD
python --version
```
```:GitCMD
pip freeze
```
デプロイするディレクトリの作成(今回はフォルダー名をlinebotにしました)
ディレクトリ内のファイル
main.py　→ソースコード
runtime.txt　→Pythonのバージョンを記載
requirements.txt　→インストールするライブラリの記載
Procfile　→プログラムの実行方法を定義

```:runtime.txt
Python 3.9.0
```

```:requirements.txt
Flask==1.1.2
line-bot-sdk==1.17.0
```
Procfile
`web: python main.py`
※Procfileはコマンドプロンプト等で「echo web: python main.py > Procfile」と入力し作成。
#Gitを用いてHerokuへ設置
![スクリーンショット 2020-11-24 152809.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603568/2d9e230a-98a9-ae34-64fe-d86d53733f8c.png)

```:GitCMD

cd linebot  
git init
git add .
git commit -am "make it better"
git push heroku master
```
「cd」で作成したディレクトリに移動、それ以降の4行でHerokuに設置しています。
参照:[Gitとは](https://backlog.com/ja/git-tutorial/)
###デプロイできたか確認

```
heroku open
```
hello Worldが表示されたら正常にデプロイされています。
###ログ確認

```
heroku logs --tail
```
上記のコマンドでログが確認できます。
#詰まったところ
LINE Message APIのチャネルアクセストークンのコピーの際、翻訳した状態でコピペをしてしまい署名検証で引っ掛かりオウム返しされなかったが翻訳を解除してコピペしたところ期待値が返ってきた。
#参考文献
https://qiita.com/shimajiri/items/cf7ccf69d184fdb2fb26
https://www.sejuku.net/blog/7858
https://uepon.hatenadiary.com/entry/2018/07/27/002843
https://www.wantedly.com/companies/casley/post_articles/139107