Python
Heroku
Flask
linebot
LINEmessagingAPI

FlaskでLINE botを実装し,herokuにdeployするまで

はじめに

注:2017/9/21にLINE Business centerが廃止され,Messaging API関連の設定コンソールがLINE Developersに一元化され簡単に行えるようになりました

PythonのWebアプリケーションフレームワークであるFlaskを使ってLINE botを構築します.
ここでは一通りの流れを記述するため,構築するLINE botはユーザから送信されたメッセージをオウム返しするだけとします.
ローカルで構築・テストしたbotはherokuへdeployします.
参考にしたサイト等は末尾に列挙しています.

開発環境

  • Mac OS Sierra
  • Homebrew 環境構築済み
  • Python 環境構築済み
  • LINEの個人アカウントを持っている

LINE Developersでの設定

チャネルの作成

公式のチュートリアルが詳しいので,これに従って設定を行ってください.
Messaging APIを利用するには - LINE Developers

  1. LINE DevelopersでBOT用チャネルを作成
  2. プランはDeveloper Trialとフリーの2種類ありますが,Push APIの有無と友達登録数50人の上限を天秤にかけて選んでください.

plan.png
プランの詳細は以下から.
プラン・料金 - LINE@でファン獲得!無料アプリで簡単に始めるビジネスLINE

コンソールの設定

こちらも公式のチュートリアルが充実してます.
ボットを作成する - LINE Developers
以前はMessaging APIを設定する場所が複数箇所に分かれていたのですが,
現在ではLINE Developersのコンソールから簡単に設定できます.
今後もこのコンソールから各種設定をします.

  1. 作成したチャネルの基本設定から,メッセージ送受信設定 -> Webhook送信を利用するにチェック
  2. 同じく基本設定から,メッセージ送受信設定 -> アクセストークンを発行
  3. 基本設定にあるChannel Secretと発行したChannel Access Tokenを控えておく

Flaskを使ってLINE botを作成

まずはローカル環境で一通り開発します.
Flaskのdevelopment serverで実行したあと,一時的にngrokで外部に公開しテストします.
LINEのプラットフォームにngrokのURLを登録し,メッセージをローカルのFlaskで処理するためです.

環境構築

Flask・SDK of the LINE Messaging API for Python・ngrokをインストールします.
Python環境をanacondaで構築している人は元からFlaskが入っていると思います.

$ pip install flask 
$ pip install line-bot-sdk
$ brew install ngrok
$ pip install gunicorn % optional

サンプルプログラムの作成

line-bot-sdk-pythonのサンプルプログラムを実行してみましょう.
https://github.com/line/line-bot-sdk-python
上記URLのUsageにあるサンプルプログラムをapp.pyとして保存します.
下記のapp.pyではデバッグのためにhello_worldを追加しています。
LINE Developersの設定で控えたChannel SecretとChannel Access TokenをYOUR_CHANNEL_SECRETとYOUR_CHANNEL_ACCESS_TOKENに書きます.
(本来なら環境変数に持たせるなどするべきですが,一旦ここではこのまま実行します.)

app.py
from flask import Flask, request, abort

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

app = Flask(__name__)

line_bot_api = LineBotApi('YOUR_CHANNEL_ACCESS_TOKEN')
handler = WebhookHandler('YOUR_CHANNEL_SECRET')

@app.route("/")
def hello_world():
    return "hello world!"

@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:
        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__":
    app.run()

Flaskの実行とngrokによる公開

Flaskのdevelopment severの実行

app.pyのあるディレクトリに移動して,以下のコマンドを実行

$ export FLASK_APP=app.py
$ export FLASK_DEBUG=1
$ flask run --host=0.0.0.0

ブラウザで http://localhost:5000 にアクセスしhello world!と出ればOK.

ngrokによる外部への公開

Flaskでプログラムが問題なく起動したら,ngrokを実行し外部へ一時的に公開しましょう.
以下のコマンドを実行してテストします.

$ ngrok http 5000

Forwarding https://[乱数].ngrok.com -> 0.0.0.0:5000
と表示されているURLをメモっておきます.

webhook URLの登録

LINE developersのコンソールにアクセスし,チャネルの基本設定ページに行きます.
そこでWebhook URLに先程ngrokで取得したhttpsのURLを登録します.
ただし https://[乱数].ngrok.com/callback としてください.
サンプルプログラムでは/callbackにきたpostリクエストを処理するようになっているので.

オウム返しの確認

作成したbotと友達になり,適当にメッセージを送ってみましょう.
以下のようにオウム返ししてくれば一旦は完成です.

LINE botをherokuにdeploy

ローカルで作ったbotをherokuにdeployします.
herokuでの最適な開発フローは模索中ですが自分用メモとして公開します.

herokuに登録

まだherokuに登録してない人は以下から登録します.
Cloud Application Platform | Heroku

登録後,ターミナルからherokuを操作するためheroku-cliをインストールし,ログインしておきます.

$ brew install heroku/brew/heroku
$ heroku login

heroku用ファイル準備

以下のファイルをapp.pyと同じディレクトリ内に作成します.
app.pyも環境変数からchannel secret等を読み込む用に書き換えます.
Pythonのversionやrequirements.txtの内容などは適宜読み替えてください.
(本来ならvirtualenvしてpip freezeすべきですが・・・)

  • app.py
    • flaskの実行ファイルです.
  • .gitignore
    • gitignore
  • .env
  • Procfile
    • heroku上で実行するコマンドを書く.
  • requirements.txt
    • pipでインストールしたライブラリの管理.
    • ここに書かれたライブラリ(version)がheroku上でもインストールされる.
  • runtime.txt
    • pythonのversionを書く.
app.py
import os
import sys
from flask import Flask, request, abort

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

app = Flask(__name__)

# 環境変数からchannel_secret・channel_access_tokenを取得
channel_secret = os.environ['LINE_CHANNEL_SECRET']
channel_access_token = os.environ['LINE_CHANNEL_ACCESS_TOKEN']

if channel_secret is None:
    print('Specify LINE_CHANNEL_SECRET as environment variable.')
    sys.exit(1)
if channel_access_token is None:
    print('Specify LINE_CHANNEL_ACCESS_TOKEN as environment variable.')
    sys.exit(1)

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

@app.route("/")
def hello_world():
    return "hello world!"

@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:
        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__":
    app.run()
.gitignore
.env
__pycache__
.env
LINE_CHANNEL_SECRET=hogehoge
LINE_CHANNEL_ACCESS_TOKEN=fugafuga
Procfile
web: gunicorn app:app --log-file -
requirements.txt
Flask==0.12.2
gunicorn==19.6.0
line-bot-sdk==1.3.0
runtime.txt
python-3.5.2

herokuにdeploy

gitを使ってherokuにdeployします.

$ cd path/to/your/linebot/directory
$ git init
$ git add . 
$ git commit -m "first commit Yeaahhhh"
$ heroku create [Your bot name] % http://[your bot name].herokuapp.com/ になる.指定しないとランダム文字列.
$ git push heroku master

dynoの数を1にし,
LINE messaging APIのChannel secret等はherokuの環境変数に持たせます.

$ heroku ps:scale web=1
$ heroku config:set LINE_CHANNEL_SECRET=hogehoge
$ heroku config:set LINE_CHANNEL_ACCESS_TOKEN=fugafuga

heroku openでhello world!を確認できればOKです.

$ heroku open

最後に先程と同様にLINE developersのコンソールにアクセスし,
Webhook URLにherokuのアドレスを登録すればbotの完成です.
(登録するのは,https://[your bot name].herokuapp.com/callback )

herokuでよく使うコマンド

$ heroku logs % logの確認
$ heroku open % ブラウザでherokuのappのURLを開く
$ heroku run ls
$ heroku run python

参考