LoginSignup
3
1

More than 3 years have passed since last update.

Chalice を使って AWS Lambda 上に LINE Bot 用の Webhook を作成する

Posted at

はじめに

掲題通りです。
多くの記事では 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の実装」になります。

app.py
#!/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))
requirements.txt
line-bot-sdk==1.16.0
.chalice/config.json
{
  "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.headersrequest.get_data() で利用する
    • Chalice: app.current_request に入っている。 app.current_request.headersapp.current_request.raw_body でコンテンツを参照する
  • Webhook の検証結果が正常に終了せず、"ボットサーバーから200以外のHTTPステータスコードが返されました" と出てしまう
    • LINE Bot の Webhook URL を書き換えてすぐ検証した場合、新しいURLが反映されていないことがあった
    • 検証時に利用されるリプライトークンは 0 埋めのものが返されてしまうので、Githubのサンプルの通りにやると検証はOKにならない
    • 詳しくは Qiita - LINE DevelopesのWebhook URLの接続確認でエラーが出る件について で説明されている通り、検証時の場合は何もせずに処理を打ち切ればよい
      • このプログラムでは _valid_reply_token 関数で判定

参考

LINE Developers内でチャネルを作成・設定したり、トークンを作るところは別のやってみた記事で説明されていますので、それらの記事も合わせてご参照下さい。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1