LinebotをHelokuにデプロイする際のH14とH10エラーの対処した履歴

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
 

ここまでを参考に以下のような、おうむ返しに少しアレンジを加えたような物を作成しました。

```bash
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で既読スルーされ続けられてしまった。

なので、ログを確かめようと

```bash
$ heroku logs --tail
```

をbashで打ち込んでみると、H14だとか５０３のエラーが発生しているのがわかったのでやっと調べると**Procfileがprocfileになっていることに気づき**修正。

ちなみに中身は・・・

```bash
web: python main.py
```

万事解決！！

と、思いきや、またもや既読スルーされてしまいました。。。。。。

## 今度はrequirements.txtがおかしい
 
今度は、H10と５０３のエラーが発生していました。

僕は、この時また知らなかったのです。**requirements.txtファイルは直打ちで作成するものではない**ということを・・・。

どうやら、

```bash
$ cd アプリを起動しているローカルディレクリ名
$ pip install pipreqs
$ pipreqs .　#　最後の . が忘れやすい
```
pip freezeというコマンドもあるらしいのだが、現在のプロジェクトで使用しないパッケージを含め、環境内のすべてのパッケージを保存するから注意（仮想環境外ではやらないほうが・・・）する必要があるらしい。
上記コマンドが無難だと思いました。

僕の場合、上記コマンドを打った時に、requirements.txtファイルが上書きされなかったので、一度まっさらな状態で作成するのが良いのでは・・・。

作られたrequirements.txtファイルの中身

 ```bash
Flask==1.1.1
requests==2.22.0
line_bot_sdk==1.14.0
gunicorn==19.9.0

```

＊注意
Flaskでの作製の場合、gunicornが必要らしいのだが、僕の場合、gunicornがインストールされていなかったので、下記コマンドでインストールしました。

```bash
$ pip install gunicorn
```

とりあえず、残りのruntime.txt

```bash
python-3.7.4
```

を作成し、デプロイで、解決と思いきや、まだエラーは直りませんでした。

同じく　H10と５０３のエラーが続くのである。

# LineBotプログラム内の問題

最初のpythonの内容では、ダメな点が2つあったのだ。

- 環境変数の適応をローカル起動時のままにしていたこと。
　herokuでsetを行っている必要あり

- 以下の部分にポート指定などを忘れていたこと

なので、一つずつ直していきました。

```bash
# 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)
```

の部分を以下のように

```bash
line_bot_api = LineBotApi(os.environ.get('LINE_CHANNEL_ACCESS_TOKEN'))
handler = WebhookHandler(os.environ.get('LINE_CHANNEL_SECRET'))
```

あと、

```bash
if __name__ == '__main__':
    debug=True
    app.run()
```

の部分を以下のように・・・

```bash
if __name__ == '__main__':
    port = int(os.getenv("PORT", 8080))
    app.run(host="0.0.0.0", port=port, debug=True)
```

と、ここまできたら、

### Herokuにデプロイしました。
```bash
# gitの初期ファイルを作成
$ git init

# ローカルリポジトリに結びつくリモートリポジトリの設定
$ heroku git:remote -a (アプリ名)

# 変更したファイルをインデックスに登録
$ git add .

# 登録したファイルをリポジトリに書き込む
$ git commit -m "コメント"

# herokuにローカルで作成したpush
$ git push heroku master

```

そして、最後に

```bash
$ heroku ps:scale web=1
```

をやったら、無事デプロイできました。