Messaging API(LINE)とCOTOHA API(NTT Com)を利用したBotアプリ(Python)をHerokuにデプロイする
はじめに
今年のゴールデンウィークは改元もあり10日間の大型連休だった。
平成から令和という節目を迎え、例年とはちょっと違い、年越しのような心持ちになった。
かねてから興味があったことにチャレンジするには良い機会になるよなぁ、ってことで始めてみた。
記事のタイトルはなかなか立派な感じがするが、今回やったことは、もうすでに多くの方がやりつくしていることの寄せ集め。
大切なのは手を動かして、自分なりのアウトプットをすることだと思っているので、あくまでもマイペース。
目次
- はじめに
- 目次
- Botアプリの概要
- Botアプリを構成するもの
- Botアプリ開発の前提条件
- Botアプリのソースコード
- BotアプリをHerokuにデプロイ
- LINE DevelopersでWebhook設定
- おわりに
- 参考にさせて頂いた記事
Botアプリの概要
友達登録したチャンネル上でLINEでメッセージ(文章)を送ると、原始人がカタコトの日本語で返事をしてくれるというもの。
返事といっても会話のキャッチボールが成立するわけではなく、こちらが送った文章をそのまま「原始人コトバ」に変換して送り返すだけのいわゆるエコーアプリである。
非IT(SEとかプログラマとかではない職業)の友人にお披露目してみたものの、何がおもしろいのか、何がすごいのか理解できないらしく反応はイマイチだった(まぁ当然だよね)。
やはり便利なものでないとウケない(会話が盛り上がらない)のはちょっと寂しい。
Botアプリを構成するもの
言語
API
サーバー
Botアプリ開発の前提条件
※ツールのインストールやアカウント作成方法については割愛
開発マシンのOS
今回はWindows10環境で作成。
ツール
以下のツールをインストールする必要がある。
- Git(https://git-scm.com/download/win)
- Windows PowerShell のターミナルで「
git --version
」コマンドがエラー無く実行できること
- Windows PowerShell のターミナルで「
- Heroku CLI(https://devcenter.heroku.com/articles/heroku-cli#download-and-install)
- Windows PowerShell のターミナルで「
heroku --version
」コマンドがエラー無く実行できること
- Windows PowerShell のターミナルで「
アカウント作成
以下のアカウント(無料)を作成する必要がある。
- LINE Developersアカウント
(https://developers.line.biz/ja/)
- 任意の「プロバイダー」を作成
- 作成したプロバイダー内にMessaging API用の「チャンネル」を作成
- COTOHA APIアカウント(https://api.ce-cotoha.com/contents/index.html)
- Herokuアカウント(https://signup.heroku.com/jp)
Botアプリのソースコード
ファイル構成
フォルダ名称は任意でOK。今回はline-bot-genshijin
という名称で作成。
直下に必要なファイルをすべて配置する。
line-bot-genshijin ├ main.py ├ genshijin.py ├ Procfile ├ requirements.txt └ runtime.txt
main.py LINE Messaging API を利用するための認証、APIの呼び出し、別モジュールに切り分けた「原始人コトバ」変換処理の呼び出しを行っている。
import os import sys import json import requests import genshijin as gj 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 Token channel_secret = os.getenv('LINE_CHANNEL_SECRET', None) channel_access_token = os.getenv('LINE_CHANNEL_ACCESS_TOKEN', None) 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("/callback", methods=['POST']) def callback(): signature = request.headers['X-Line-Signature'] body = request.get_data(as_text=True) app.logger.info("Request body: " + body) try: handler.handle(body, signature) except InvalidSignatureError: abort(400) return 'OK' @handler.add(MessageEvent, message=TextMessage) def handle_message(event): # ゲンシジン語に翻訳 result = gj.translate(event.message.text) # LINE APIによる応答メッセージ送信 line_bot_api.reply_message( event.reply_token, TextSendMessage(text=result) ) if __name__ == "__main__": port = int(os.getenv("PORT", 8000)) app.run(host="0.0.0.0", port=port)
genshijin.py 「原始人コトバ」変換処理の本体。LINEチャンネルに送信されたメッセージを受け取り、変換後の文字列をリターンする。COTOHA API を利用するための認証、APIの呼び出しはここで行っている。
import os import json import requests # cotoha Token BASE_URL = "https://api.ce-cotoha.com/api/dev/nlp/" client_id = os.getenv('COTOHA_CLIENT_ID', None) client_secret = os.getenv('COTOHA_CLIENT_SECRET', None) if client_id is None: print('Specify COTOHA_CLIENT_ID as environment variable.') sys.exit(1) if client_secret is None: print('Specify COTOHA_CLIENT_SECRET as environment variable.') sys.exit(1) def translate(document): def auth(client_id, client_secret): token_url = "https://api.ce-cotoha.com/v1/oauth/accesstokens" headers = { "Content-Type": "application/json", "charset": "UTF-8" } data = { "grantType": "client_credentials", "clientId": client_id, "clientSecret": client_secret } r = requests.post(token_url, headers=headers, data=json.dumps(data)) return r.json()["access_token"] def parse(sentence, access_token): base_url = BASE_URL headers = { "Content-Type": "application/json", "charset": "UTF-8", "Authorization": "Bearer {}".format(access_token) } data = { "sentence": sentence, "type": "default" } r = requests.post(base_url + "v1/parse", headers=headers, data=json.dumps(data)) return r.json() access_token = auth(client_id, client_secret) parse_document = parse(document, access_token) result_list = list() for chunks in parse_document['result']: for token in chunks["tokens"]: if token["pos"] != "格助詞" and token["pos"] != "連用助詞" and token["pos"] != "引用助詞" and token["pos"] != "終助詞": result_list.append(token["kana"]) return ' '.join(result_list)
Procfile Heroku用の設定ファイル。一番最初に起動させるプログラムは何かをHerokuに教えてあげるためのもの。
web: python main.py
requirements.txt 今回のPythonソースコードで利用しているライブラリを定義する。バージョンは記載しなくても動くが、仕事としての開発環境であればきちんと書くべきだと思う。
Flask==0.12.2 line-bot-sdk==1.5.0 requests
runtime.txt Herokuで実行したいPythonのバージョンを指定する。 (Heroku用の設定ファイル?きちんと理解していないのだが、PythonのフレームワークであるDjangoを利用する場合は必要かもしれないが、今回使用するFlaskフレームワークではなくて良いかもしれない…)
python-3.6.6
BotアプリをHerokuにデプロイ
Herokuアプリケーションの新規作成
まずは用意したソースコード一式を格納したフォルダに移動する。
cd line-bot-genshijin
Git管理するためにローカルリポジトリを作成する。
git init
Herokuに新規アプリケーション(サーバー)を作成する。aqueous-dusk-45716
という名称でアプリケーションが作成されたことがコマンドの実行結果からわかる。このタイミングでリモートリポジトリも作成される。
heroku create Creating app... done, ⬢ aqueous-dusk-45716
リモートリポジトリが作成されたことの確認。名称はheroku
に関連付けられたことがわかる。
git remote -v heroku https://git.heroku.com/aqueous-dusk-45716.git (fetch) heroku https://git.heroku.com/aqueous-dusk-45716.git (push)
ここでHerokuダッシュボードを確認してみる。aqueous-dusk-45716
という名称のアプリケーションが存在しているのがわかる。
Herokuサーバーの環境変数定義
ついでなのでサーバー環境変数を定義しておく。
LINEやCOTOHAのAPIを利用するために必要な認証用情報はLINE Developersのダッシュボード、COTOHA APIのダッシュボードでそれぞれ発行できるが、Pythonのソースコードに直接記入するのはスマートではない。
今回はそういった認証用の情報はサーバー環境変数に定義する。
アプリケーション内の Settingsタブ - Config Vars の Reveal Config Varsボタンを押下すると、隠されていた環境変数一覧が表示される(初期の段階は何も定義なし)。
変数名と値を入力し、Addボタンを押下。
定義したサーバー環境変数は以下のようにPythonコードから取得できる。os.getenv()
の第一引数はHerokuサーバーの環境変数で定義した変数名と一致させる必要がある。
main.py(抜粋)
channel_secret = os.getenv('LINE_CHANNEL_SECRET', None) channel_access_token = os.getenv('LINE_CHANNEL_ACCESS_TOKEN', None)
genshijin.py(抜粋)
client_id = os.getenv('COTOHA_CLIENT_ID', None) client_secret = os.getenv('COTOHA_CLIENT_SECRET', None)
正しく設定できたか確認(値は伏字にしている)。
heroku config === line-genshijin Config Vars COTOHA_CLIENT_ID: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx COTOHA_CLIENT_SECRET: xxxxxxxxxxxxxxxxx LINE_CHANNEL_ACCESS_TOKEN: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx…xxxxx LINE_CHANNEL_SECRET: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Herokuのアプリケーション名を任意の名称に変更
heroku create
コマンドで作成されるアプリケーションの名称はランダムに設定される。
動作には全く問題ないのだが、せっかく作るならば好きな名称にしたほうが愛着がわくし、アプリケーションが複数になると、どれに何をデプロイしたのかわからなくなってくる。
今回はランダムに設定されたアプリケーションの名称(aqueous-dusk-45716
)をline-genshijin
に変更する。
アプリケーション内の Settingsタブ - Nameの名称を変更するだけ。ただし、画面のWarningメッセージに表示されている通り、Gitのリモートリポジトリ名を変更する必要がある。
やり方についてはWarningメッセージ内のリンク先に記載された内容と全く同じ手順を行えばよい。
- 名称
heroku
は旧アプリケーション名(aqueous-dusk-45716
)のリモートリポジトリに関連付けられていのでいったん削除。 - 名称
heroku
にリモートリポジトリとして新アプリケーション名line-genshijin
を関連付ける。
git remote rm heroku heroku git:remote -a line-genshijin
リモートリポジトリと関連付けられた名称が更新されていることの確認。
git remote -v heroku https://git.heroku.com/line-genshijin.git (fetch) heroku https://git.heroku.com/line-genshijin.git (push)
Herokuへデプロイ
ローカルリポジトリへadd、commit、そしてリモートリポジトリへpush。pushすると自動でデプロイされる。
git add . git commit -m "first commit" git push heroku master
HerokuのDyno(プロセスのようなもの)が起動しているか確認。1つのDynoが動作しているようだ。
heroku ps:scale web=1 Scaling dynos... done, now running web at 1:Free
LINE DevelopersでWebhook設定
LINE Developersのダッシュボードで事前に作成しておいたMessaging APIのチャンネルでHerokuにデプロイしたBotアプリとの関連付けを行う。
メッセージ送受信設定
ここでは以下の設定を行う。
- Webhook送信
- [利用する]に設定する。
- Webhook URL
- 「
https://{HEROKU_APP_NAME}.herokuapp.com/callback
」の形式で入力する。 - 「
{HEROKU_APP_NAME}
」の箇所は、デプロイ済みのHerokuアプリケーション名称。 - 今回のケースだと「
https://line-genshijin.herokuapp.com/callback
」となる。
- 「
Webhook URLについては設定後確認できる。接続確認ボタンを押下するとエラーメッセージが表示されるが問題はない。
LINE Developersのデフォルト設定だと自動応答メッセージも一緒に送信されてしまうので「利用しない」に変更する。
ここまでで、今回のBotアプリは完成となる。
最後に作成したチャンネルをトモダチ登録。
LINE Developersダッシュボードの チャンネル基本設定タブ > 基本情報 > 変更はこちらリンク からLINE Official Account Managerダッシュボードを開く。
LINE Official Account Managerダッシュボードの ホーム > 友だち追加 で表示されるURLにアクセスするとチャンネルが追加できる。
その他の設定
アプリアイコンや友達追加時のあいさつメッセージを設定すればオリジナリティのあるチャンネルに仕上がる。
LINE Developersダッシュボードからいろいろとカスタムできるのでお好みであれこれ試してみると良い。
おわりに
はじめて技術系の記事を書いたがとても時間がかかり苦労した。ちょっと気合を入れて細かく書きすぎたような気がする。
しかし、自分自身分からないことが多い中でインターネットで調べてみても肝心なところが記載されていなくて理解できないことが多かったので、なるべくわからない人目線で書くように心がけた次第である。
技術系の内容にかかわらず、世の中、毎日のように記事を書いている人がいらっしゃるが、改めてすごいなぁと感じた。
これに懲りずに今後もアウトプットしていくようにがんばろうと思う。
参考にさせて頂いた記事
一人じゃ完成させることはできなかった…。
先人の方々が残された情報はとても勉強になった。感謝します。
【参考】