はじめに
掲題通りです。
多くの記事では LINE Bot の応答を返すサーバーは Heroku の上に構築されていますが、API Gateway + AWS Lambda を利用してサンプルを構築してみたのでそのメモになります。
コンテンツ
以下の方法で作成した Chalice の line-bot プロジェクト内で動作を確認。
LINEの設定などで分からない点は、末尾の参考URLなどを参照ください。
$ pipenv install --python 3.7
$ pipenv install chalice line-bot-api
$ pipenv run chalice new-project line-api
ここで作成された app.py
, requirements.txt
, .chalice/config.json
を以下の通り修正します。
なお、ソースコードは line-bot-apiのGithub から持ってきた「ユーザーの発言と全く同じものを応答するbotの実装」になります。
#!/usr/bin/python
# -*- coding: utf-8 -*-
import os
import re
import logging
from chalice import Chalice
from chalice import BadRequestError
from linebot import LineBotApi, WebhookHandler
from linebot.exceptions import InvalidSignatureError
from linebot.models import MessageEvent, TextMessage, TextSendMessage
logger = logging.getLogger()
app = Chalice(app_name='line-api')
handler = WebhookHandler(os.environ.get('LINE_CHANNEL_SECRET'))
linebot = LineBotApi(os.environ.get('LINE_CHANNEL_ACCESS_TOKEN'))
@app.route('/callback', methods=['POST'])
def callback():
try:
request = app.current_request
# get X-Line-Signature header value
signature = request.headers['x-Line-Signature']
# get request body as text
body = request.raw_body.decode('utf8')
# handle webhook body
handler.handle(body, signature)
except Exception as err:
logger.exception(err)
raise BadRequestError('Invalid signature. Please check your channel access token/channel secret.')
return 'OK'
def _valid_reply_token(event):
'''
Webhook のテスト時には reply token が 0 のみで構成されているので、
その時に False を返します
'''
return not re.match('^0+$', event.reply_token)
@handler.add(MessageEvent, message=TextMessage)
def reply_for_text_message(event):
''' テキストメッセージを受け取った場合の応答 '''
if not _valid_reply_token(event):
return
linebot.reply_message(
event.reply_token,
TextSendMessage(text=event.message.text))
line-bot-sdk==1.16.0
{
"version": "2.0",
"app_name": "line-api",
"stages": {
"dev": {
"api_gateway_stage": "api",
"environment_variables": {
"LINE_CHANNEL_SECRET": "チャネルシークレットを入力",
"LINE_CHANNEL_ACCESS_TOKEN": "チャネルアクセストークン(ロングターム)を入力"
}
}
}
}
上記の内容を書き込んだ後、pipenv run chalice deploy
にて自分のAWSアカウント上にデプロイを行う。
$ pipenv run chalice deploy
Creating deployment package.
Updating policy for IAM role: line-api-dev
Updating lambda function: line-api-dev
Updating rest API
Resources deployed:
- Lambda ARN: arn:aws:lambda:ap-northeast-1:************:function:line-api-dev
- Rest API URL: https://********.execute-api.ap-northeast-1.amazonaws.com/api/
この後、ここでデプロイした API URL の /callback
を、この場合は https://********.execute-api.ap-northeast-1.amazonaws.com/api/callback
をLINE Messaging API の Webhook URL に設定・検証します。
検証の結果「成功」が返ってくれば正常に設定できていますので、LINE で自分のチャネルと会話をして、自分の発言をオウム返ししてくれるか否かを確認してください。
実装していて引っかかった点
- request コンテンツの取り方が Flask と Chalice で異なる
- Flask:
from flask import request
してからrequest.headers
やrequest.get_data()
で利用する - Chalice:
app.current_request
に入っている。app.current_request.headers
やapp.current_request.raw_body
でコンテンツを参照する
- Flask:
- Webhook の検証結果が正常に終了せず、"ボットサーバーから200以外のHTTPステータスコードが返されました" と出てしまう
- LINE Bot の Webhook URL を書き換えてすぐ検証した場合、新しいURLが反映されていないことがあった
- 検証時に利用されるリプライトークンは 0 埋めのものが返されてしまうので、Githubのサンプルの通りにやると検証はOKにならない
- 詳しくは Qiita - LINE DevelopesのWebhook URLの接続確認でエラーが出る件について で説明されている通り、検証時の場合は何もせずに処理を打ち切ればよい
- このプログラムでは
_valid_reply_token
関数で判定
- このプログラムでは
参考
LINE Developers内でチャネルを作成・設定したり、トークンを作るところは別のやってみた記事で説明されていますので、それらの記事も合わせてご参照下さい。