ローカルでLINEチャットbotテスト環境を構築する(python, ngrok)


## はじめに

こんにちは！アベンドカレンダー13日目担当です。

趣味でLINEチャットbotを開発していましたが、一番難しかったのがコードを変更せず、本番用botとテスト用bot両方を使える環境を構築することでした。手探りに時間はかかりましたが、構築自体はすごく簡単なものだったのでこの記事で共有します。

## 手順

1. ngrokインストール
2. LINEデベロッパーコンソールで本番用、テスト用bot作成, トークン発行
3. herokuなどのデプロイプラットフォームで 環境変数登録
4. コード修正
5. 実行

### 1. ngrokインストール

[ngrok - download](https://ngrok.com/download)

### 2. LINEデベロッパーコンソールで本番用、テスト用bot作成

![스크린샷 2021-12-13 00.26.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674486/d4a99036-a37e-a69f-c21e-c97be9ce638f.png)


こんな感じで二つ作ります。チャンネル作成方法と各プラットフォームデプロイ方法は割愛させていただきます。

各チャンネルの詳細から以下の情報をメモします。

- アクセストークン
- チャンネルシークレットキー

### 3. herokuなどのデプロイプラットフォームの用意

本番用のトークンはプラットフォームの方に登録します。

herokuの場合、アプリの設定から楽に登録ができます。

![스크린샷 2021-12-13 00.36.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674486/71b3f59f-843a-c8b4-5d42-ddcf3ec18a50.png)


### 4. コード修正

.envファイルを新しく作成し、gitignoreに追加します。

コード例 

```python
// .env

# LINE ACCOUNT INFO
LINE_CHANNEL_ACCESS_TOKEN = YOUR_CHANNEL_ACCESS_TOKEN
LINE_CHANNEL_SECRET = YOUR_CHANNEL_SECRET

# ngrok用PORT番号指定
PORT=9000

```

[https://github.com/line/line-bot-sdk-python](https://github.com/line/line-bot-sdk-python)

```python
# app.py

import os # ここを追加
from dotenv import load_dotenv # ここを追加
from flask import Flask, request, abort

from linebot import (
    LineBotApi, WebhookHandler
)
from linebot.exceptions import (
    InvalidSignatureError
)
from linebot.models import (
    MessageEvent, TextMessage, TextSendMessage,
)

# .envから読み込み
# herokuでは自動でherokuに登録されている環境変数を読み込み
load_dotenv()

channel_access_token = os.getenv("LINE_CHANNEL_ACCESS_TOKEN")
channel_secret = os.getenv("LINE_CHANNEL_SECRET")

app = Flask(__name__)

line_bot_api = LineBotApi(channel_access_token)
handler = WebhookHandler(channel_secret)

@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:
        print("Invalid signature. Please check your channel access token/channel secret.")
        abort(400)

    return 'OK'

@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__":
    port = int(os.getenv("PORT"))
    app.run(host="0.0.0.0", port=port)
```

### 5. 実行

app.pyを実行後、ngrokを実行します。

```python
$ ngrok http 9000
```

ngrokを実行すると、ローカルのアドレスが表示されます。

![스크린샷 2021-12-13 00.57.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674486/f47fe756-b0b5-293c-4a05-9a950b0ac9e4.png)


Forwardingと書いているURLをコピーし、LINEデベロッパーコンソールを開きます。

テスト用BotメニューにあるMessaging API からWebhook URLをコピーしたURLを貼ります。

Webhook URLなのでコピーしたURLの後ろに/callbackを付けます。

```python
https://nagaiURL.ngrok.io/callback
```

## 注意点

herokuはherokuの環境変数で動作するし、テストするbotはngrokを実行すれば動作します。

ただ、ngrokの無料版は以下のデメリットがあります。

- 時間制限（２時間/ログインすると制限なし）
- ngrokを実行するたびにURLも変わるので毎回テスト用BotのCallbackURLを変更する必要がある