Line Botは簡単に作れるいう人は多いです。。。でも、簡単に作れるまでには、プログラミング言語を覚えて、コマンドプロントの扱い方を覚えてなど、出来るようにならないといけない。そんな、四苦八苦をしながら勉強している僕が、ハマったLine Botのデプロイ方法について備忘録がてらまとめてみます。もし、おかしい内容があったら優しくご指摘いただけると嬉しいです。
使うのは、python,Flask,herokuです。
最初にLine APIの登録
まず、LineBotを使うためにはLine Developersに登録が必要です。
ただ、登録は簡単でいろんな方々がまとめてくださっているので、参考URLまでに・・・
僕は、以下のURLを参考させていただきました。
https://qiita.com/nkjm/items/38808bbc97d6927837cd
次にローカール環境での開発を目指す
herokuにデプロイする際に、ローカル環境で動かないBotを作成すると、エラーを起こして怒られてしまうので、ローカルで動くLineBot作成を目指します。
ここまでで、必要なのは
-LineAPI登録
- LineDevelopers登録
- Channel Secret
- アクセストークン
- ngrokのインストール
コレに関しては以下のURLがすごくわかりやすかったので参考にさせていただきました。
https://qiita.com/sekikazu/items/f079e5290ad2a3402dd7
ここまでを参考に以下のような、おうむ返しに少しアレンジを加えたような物を作成しました。
from flask import Flask, request, abort
import json, requests
from linebot import LineBotApi, WebhookHandler
from linebot.models import (
MessageEvent,TextMessage, TextSendMessage, StickerSendMessage, ImageSendMessage,TemplateSendMessage
)
from linebot.exceptions import (
LineBotApiError, InvalidSignatureError
)
import os
app = Flask(__name__)
# linebotのaccesstokenとchannel_secret
LINE_CHANNEL_ACCESS_TOKEN = YOUR_ACCESS_TOKEN
LINE_CHANNEL_SECRET = YOUR_CHANNEL_SECRET
line_bot_api = LineBotApi(LINE_CHANNEL_ACCESS_TOKEN)
handler = WebhookHandler(LINE_CHANNEL_SECRET)
@app.route('/')
def index():
return "hello world"
@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)
try:
handler.handle(body, signature)
except InvalidSignatureError:
abort(400)
except LineBotApiError as e:
app.logger.exception(f'LineBotApiError: {e.status_code} {e.message}', e)
raise e
return 'OK'
@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
# lineでテキスト送信した際のイベント設定
try:
print(event.message.text)
# qr or QRと送信とPASSと送信された場合のreply_messageを設定
if event.message.text == "qr" or event.message.text == "QR":
message="QR要求を受け取りました"
elif event.message.text == "PASS":
message = "PASS要求を受け取りました"
else:
# 上記以外のメッセージ要求の場合、要求した同じメッセージ内容をmessage変数に代入する
message = event.message.text
# linebotでの返答内容をreply_messageで設定
line_bot_api.reply_message(event.reply_token,TextSendMessage(text=message))
# 例外でエラー内容を取得
except Exception as e:
print(e)
line_bot_api.reply_message(event.reply_token,TextSendMessage(text="取得に失敗しました。\n再度取得をお願いします。"))
if __name__ == '__main__':
debug=True
app.run()
取りあえず、ngrokを使ったローカル環境で動くことがわかったので、次にherokuにデプロイを目指してしみます
Herokuの登録する
ここからは、こちらの内容に大変お世話になりました。
https://miyabi-lab.space/blog/21
ここまでを、上の内容をあげてくださった方々を参考に進め、Herokuにアプリを作成し、いざ、デプロイとしたら、エラー起こり、そのエラーを消せない時間に悩まされました。
つまり、ここからが一番忘れたくない、エラー内容と解決した手段でした。
ホントに挫折して自分は一生ローカルで頑張ろうとする思いそうでした。。。
#ハマった内容
Procfileの作成
LineBotをherokuにデプロイするためには、
- pythonファイル
- runtime.txt
- requirements.txt
- Procfile
という4つのファイルが必要らしく、自分なりに作成してみました。
が、実際には、自分が作成した時、
Procfileではなく、procfileであったり、”procfile”であったり、procfile.txtで出会ったりだったのです。
Procfileは、**拡張子ない、Pは大文字出ないとダメ!!**だと調べず、知らずのままpを小文字で作成してしまったりしてしまっていました。
そしたら、デプロイしても、LineBotで既読スルーされ続けられてしまった。
なので、ログを確かめようと
$ heroku logs --tail
をbashで打ち込んでみると、H14だとか503のエラーが発生しているのがわかったのでやっと調べるとProcfileがprocfileになっていることに気づき修正。
ちなみに中身は・・・
web: python main.py
万事解決!!
と、思いきや、またもや既読スルーされてしまいました。。。。。。
今度はrequirements.txtがおかしい
今度は、H10と503のエラーが発生していました。
僕は、この時また知らなかったのです。requirements.txtファイルは直打ちで作成するものではないということを・・・。
どうやら、
$ cd アプリを起動しているローカルディレクリ名
$ pip install pipreqs
$ pipreqs . # 最後の . が忘れやすい
pip freezeというコマンドもあるらしいのだが、現在のプロジェクトで使用しないパッケージを含め、環境内のすべてのパッケージを保存するから注意(仮想環境外ではやらないほうが・・・)する必要があるらしい。
上記コマンドが無難だと思いました。
僕の場合、上記コマンドを打った時に、requirements.txtファイルが上書きされなかったので、一度まっさらな状態で作成するのが良いのでは・・・。
作られたrequirements.txtファイルの中身
Flask==1.1.1
requests==2.22.0
line_bot_sdk==1.14.0
gunicorn==19.9.0
*注意
Flaskでの作製の場合、gunicornが必要らしいのだが、僕の場合、gunicornがインストールされていなかったので、下記コマンドでインストールしました。
$ pip install gunicorn
とりあえず、残りのruntime.txt
python-3.7.4
を作成し、デプロイで、解決と思いきや、まだエラーは直りませんでした。
同じく H10と503のエラーが続くのである。
LineBotプログラム内の問題
最初のpythonの内容では、ダメな点が2つあったのだ。
-
環境変数の適応をローカル起動時のままにしていたこと。
herokuでsetを行っている必要あり -
以下の部分にポート指定などを忘れていたこと
なので、一つずつ直していきました。
# linebotのaccesstokenとchannel_secret
LINE_CHANNEL_ACCESS_TOKEN = YOUR_ACCESS_TOKEN
LINE_CHANNEL_SECRET = YOUR_CHANNEL_SECRET
line_bot_api = LineBotApi(LINE_CHANNEL_ACCESS_TOKEN)
handler = WebhookHandler(LINE_CHANNEL_SECRET)
の部分を以下のように
line_bot_api = LineBotApi(os.environ.get('LINE_CHANNEL_ACCESS_TOKEN'))
handler = WebhookHandler(os.environ.get('LINE_CHANNEL_SECRET'))
あと、
if __name__ == '__main__':
debug=True
app.run()
の部分を以下のように・・・
if __name__ == '__main__':
port = int(os.getenv("PORT", 8080))
app.run(host="0.0.0.0", port=port, debug=True)
と、ここまできたら、
Herokuにデプロイしました。
# gitの初期ファイルを作成
$ git init
# ローカルリポジトリに結びつくリモートリポジトリの設定
$ heroku git:remote -a (アプリ名)
# 変更したファイルをインデックスに登録
$ git add .
# 登録したファイルをリポジトリに書き込む
$ git commit -m "コメント"
# herokuにローカルで作成したpush
$ git push heroku master
そして、最後に
$ heroku ps:scale web=1
をやったら、無事デプロイできました。