LineMessageAPI+ngrok+Lambdaで送られてきたメッセージをそのまま返すBotを作ってみました

[前回](https://qiita.com/uekichi3/items/bb9cb7d35653ee873982)は、AWSで公開されているgolangのLambdaコンテナイメージの事を書きましたが、
今回はこれを拡張してLineBotを作ってみました。

## 前提条件
[ngrok](https://ngrok.com/)に登録済みで且つ、インストール済み
[LINE Developers](https://developers.line.biz/ja/)に登録済みでチャネルも登録済み

## パッケージの構成
前回の構成で、コードを拡張しようと思ったのですが、
初回main.goをbuildしようとしたらgopkg.in/yaml.v３に関するエラーが出たので今回はPythonで試す事にしました。
```
├── docker
│   └── lambda-python-test
│       └── Dockerfile
├── docker-compose.yml
├── lambda
│   ├── app.py
│   └── .env
└── requirements.txt
```

## Dockerファイル作成
新たにPythonで動かすようにしたので
[こちら](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images-create.html#images-create-from-base)を参考にDockerfileを作成。
```Dockerfile
FROM public.ecr.aws/lambda/python:3.8

# Copy function code
COPY ../../lambda ${LAMBDA_TASK_ROOT}

# Install the function's dependencies using file requirements.txt
# from your project folder.

COPY requirements.txt ${LAMBDA_TASK_ROOT}
RUN pip3 install -r requirements.txt

# Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile)
CMD [ "app.handler" ]
```
* requirements.txtの中身はpython-dotenvだけ。
```Dockerfile
# 環境変数
python-dotenv
```

## Pythonのコード
```python
from dotenv import load_dotenv

import os
import sys
import json
import urllib.request

load_dotenv() # 環境変数ファイル読み込み
CHANNEL_ACCESS_TOKEN = os.environ['CHANNEL_ACCESS_TOKEN']
CHANNEL_SECRET = os.environ['CHANNEL_SECRET']
REPLY_URL = os.environ['REPLY_URL']

def handler(event, context):
    message = event['events']

    for message in event['events']:
        url = 'https://api.line.me/v2/bot/message/reply'
        headers = {
            'Content-Type': 'application/json',
            'Authorization': 'Bearer ' + CHANNEL_ACCESS_TOKEN
        }
        body = {
            'replyToken': message['replyToken'],
            'messages': [
                {
                    'type': 'text',
                    'text': message['message']['text'],
                }
            ]
        }
        request = urllib.request.Request(url, data=json.dumps(body).encode('utf-8'), method='POST', headers=headers)
        with urllib.request.urlopen(request) as response:
            body = response.read() # ログ出すようにする
#            logger.info(res.read().decode("utf-8"))

    return {
        "statusCode": 200,
        "body": json.dumps({"status": "ok"})
    }
```
**CHANNEL_SECRET** はLine Developersの「チャネル基本設定」の下の方にあるチャネルシークレットを指定。
![スクリーンショット 2022-08-14 18.31.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2662201/0cd45f48-e351-c27c-5d14-768b08bc157e.png)
**CHANNEL_ACCESS_TOKEN** はLine Developersの「Messaging API設定」の下にあるチャネルアクセストークンを指定。
チャネル作成時は無いので発行する必要があります。
![スクリーンショット 2022-08-14 18.36.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2662201/afa6ea3a-5fd6-4c11-38b3-3bd429707566.png)


## ngrok起動
```
$ ngrok http 9000
```
```
ngrok                                                                                                          

Session Status                online
Account                       xxxxxxxx (Plan: Free)
Version                       3.0.6
Region                        Japan (jp)
Latency                       -
Web Interface                 http://127.0.0.1:4040
Forwarding                    https://xxxxxxxxxxxxxxxxxx.ngrok.io -> http://localhost:9000
```
https://xxxxxxxxxxxxxxxxxx.ngrok.io のドメインとLambdaのパスの部分をLine DevelopersのWebhook URLに設定します。
「Webhookの利用」のチェックも確か初回は入っていなかったと思うので、こちらもチェックする。
![スクリーンショット 2022-08-14 19.15.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2662201/ccc87d87-09cd-347c-9bb2-9dc13b949225.png)

※ngrok起動時に出力される**web Interface**のhttp://127.0.0.1:4040 にアクセスすると、
　リクエストの中身を見る事ができます。（これは嬉しい！！）

## 動作確認
実際にリクエストをしてみます。
<img width="250" alt="" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2662201/1e6c26f5-c808-9d20-5511-74ff580dc4f8.png">

なんか受け付けてない言われたけど一先ず返ってきた。。。
調べてみたらLine Developers側の「応答メッセージ」なる設定をオフにしないといけなかったみたいです。
「Message API設定」→「応答メッセージ:編集」→応答メッセージをオフへ切替え。
<img width="550" alt="" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2662201/9d118ce6-880e-3348-49d6-6c108044bd81.png">

改めて送信したらちゃんと返ってきました！
<img width="250" alt="" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2662201/02005311-9483-0373-37d7-4c7907554ae8.png">

## 最後に
Lambdaのデバッグのやり方を調べなかったので若干ハマりました。
ngrokは非常に便利なサービスだなーと思いました！
次回はオウム返しするだけじゃなくて別の事を返すように改良しようと思います！

※訂正や補足等あればコメント等いただけますとありがたいです。
**最後まで読んでいただき、ありがとうございました**


## 参考
[AWS Lambda + Python + LINE Botで傘が必要か教えてもらう](https://qiita.com/taku-0728/items/c80bcf65aba318ac6db0)