概要
おそ松のセリフをランダムに返すLINE BOTを作ります。
環境はDjango+Heroku。細かいトラップを回避しながら頑張って作ります。
友だち追加
- あまり会話は成立しないです (セリフをランダムに返すだけなので)
- 当然ですが非公式です
ソースコード
開発環境
- Mac OS X 10.11.6
- python 2.7.11
- Django 1.10.3
おおまかな手順
1. LINE Messaging API登録
2. Djangoインストール
3. Djangoプロジェクト作成+動作確認
4. Djangoでbotアプリケーション作成+動作確認
5. おそ松のセリフをランダムで返す部分を作成
6. Herokuにデプロイ
7. LINE側にHerokuのアドレスをセット
8. 会話してみる
詳細な手順
0. 前提
- python, pipはインストール済み
- Herokuアカウント作成済み & Heroku Toolbeltインストール & SSH鍵設定済み
Herokuことはじめはこちらなど参考になります。
1. LINE Messaging API登録
こちらのページから登録できます。
名前を「おそ松bot」、画像をおそ松のアイコンにして作成します。
登録手順の説明(動画つき)はこちら
システム構築時に「Channel access token」が必要になるのでコピペしておきます。
ちなみに、LINE BUSINESS CENTER -> アカウントリスト と選択すると
作成したアカウント一覧が見られます。
1つのアカウントに「LINE@」と「Messaging API」の2つの機能がくっついていて、
LINE@ が、 LINEのアカウント全般の設定、
Meesaging API が、これから構築する自動応答システムの設定になります。
Channel Access TokenはMessaging APIの方の設定から確認できます。
##2.Djangoインストール
$ pip install --upgrade pip # 自分の環境ではpip 8.1.2だったので、9.0.1にupgrade
$ pip install django-toolbelt
もし
Error: pg_config executable not found.
と出てインストールできない場合はpostgresqlをインストールします。
$ brew install postgresql
3. Djangoプロジェクト作成+動作確認
プロジェクト作成
$ django-admin startproject osomatsu_bot
osomatsu_botというディレクトリが作成され、その中にdjangoのファイルが配置されます。
動作確認
$ cd osomatsu_bot
$ python manage.py runserver
Performing system checks...
System check identified no issues (0 silenced).
You have 13 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
November 12, 2016 - 09:11:06
Django version 1.10.3, using settings 'osomatsu_bot.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
http://127.0.0.1:8000 にアクセスして「It worked!」が表示されればOK。
「You have 13 ...」とメッセージが出ますが、今回の場合、'python manage.py migrate'はやらなくても問題ないです。
4. Djangoでbotアプリケーション作成+動作確認
botアプリケーション作成
$ python manage.py startapp bot
botというディレクトリが作成され、その中にアプリケーションに必要なファイルが配置されます。
indexを作成
LINEのBOTとは直接関係ありませんが、動作確認のためにindexを作成します。
bot/views.pyを以下のように編集します。
from django.shortcuts import render
from django.http import HttpResponse
def index(request):
return HttpResponse("This is bot api.")
ルーティング設定
http://localhost:8000/bot にアクセスすると、bot/views.pyのindex関数を実行するようにルーティングします。
osomatsu_bot/urls.pyの16行目以降を以下のように編集します。
from django.conf.urls import url, include # includeを追加
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^bot/', include('bot.urls')), # bot/ディレクトリへのルーティングを追加
]
日本語のコメントごと追加する場合は、osomatsu_bot/urls.pyの一行目に以下を忘れずに追加。
# -*- encoding: utf-8 -*-
次に、bot/の下にurls.pyというファイルを新規作成し、以下のように編集します。
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.index, name="index"),
]
動作確認
http://127.0.0.1:8000/bot/ にアクセス。
「This is bot api.」と表示されていれば成功。
5. おそ松のセリフをランダムで返す部分を作成
以下、bot/ディレクトリで作業していきます。
セリフの準備
1行1セリフが書かれたテキストファイルを用意します。
※ 今回は@osomatsu_botからクロールしたものを用いました
ねぇ君、ちょっと聞いて〜
俺、松野家長男、松野おそ松でーす!
リーダーシップにあふれたアイドル!
夢はビッグなカリスマレジェンド!!
また、これをあらかじめ読み込んでおくためのpythonスクリプト bot/load_serif.py を作ります。
osomatsu_serif = open("bot/osomatsu_serif.txt").read().split("\n")
osomatsu_serif.txtのパスにはディレクトリ名(bot/)を含めます。
views.pyに,LINEのrequest(json形式)を受信して解析する処理を追加
LINEのrequestを受信して結果を返すcallback関数を作ります。
import json
def callback(request):
reply = ""
request_json = json.loads(request.body.decode('utf-8')) # requestの情報をdict形式で取得
for e in request_json['events']:
reply_token = e['replyToken'] # 返信先トークンの取得
message_type = e['message']['type'] # typeの取得
if message_type == 'text':
text = e['message']['text'] # 受信メッセージの取得
reply += reply_text(reply_token, text) # LINEにセリフを送信する関数
return HttpResponse(reply) # テスト用
セリフをランダムに返す処理を追加
views.pyにセリフをランダムに選択してLINEにpostするreply_text関数を追加します。
import random
import requests
from load_serif import osomatsu_serif # 先ほどのおそ松のセリフ一覧をimport
REPLY_ENDPOINT = 'https://api.line.me/v2/bot/message/reply'
ACCESS_TOKEN = 'ENTER YOUR Channel Access Token'
HEADER = {
"Content-Type": "application/json",
"Authorization": "Bearer " + ACCESS_TOKEN
}
def reply_text(reply_token, text):
reply = random.choice(osomatsu_serif)
payload = {
"replyToken":reply_token,
"messages":[
{
"type":"text",
"text": reply
}
]
}
requests.post(REPLY_ENDPOINT, headers=HEADER, data=json.dumps(payload)) # LINEにデータを送信
return reply
views.pyの全体はgithubのソースコードをご参考ください。
ルーティング設定
bot/urls.pyにcallback関数へのルーティングを追加します。
:bot/urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.index, name="index"),
url(r'^callback', views.callback),
]
CSRFでPOSTが弾かれる対策
このままjsonをPOSTしてもCSRFで403 Forbiddenとなります。
osomatsu_bot/settings.pyの以下の行をコメントアウトします。
:osomatsu_bot/settings.py
MIDDLEWARE = [
...
# 'django.middleware.csrf.CsrfViewMiddleware',
...
]
動作確認
jsonをPOSTしてエラーが出ないか確かめます。
jsonをPOSTする方法はいろいろあると思いますが、ここではChromeのAdvanced REST clientを使ってPOSTしてみます。
Advanced REST clientをインストール後、以下のようにデータを入力します。
- URL : http://localhost:8000/bot/callback
- 「POST」 を選択
- methods 「application/json」を選択
- Raw Payloadに以下入力
{
"events" : [
{
"replyToken": "012345",
"message": {
"type": "text",
"text": "こんにちは"
}
}
]
}
※本物のLINEはもっといろいろな情報を送りますが、ここではひとまず、使う情報だけを書いたダミーデータでテスト。
- SENDボタンをクリック
-> bot/views.py の reply関数に上記jsonがpostされるはず。
6. Herokuにデプロイ
Procfileの作成
manage.pyと同じディレクトリにProcfile(拡張子なし)を作成し、以下のように記入します。
web: gunicorn osomatsu_bot.wsgi bot:app --log-file -
runtime.txtの作成
manage.pyと同じディレクトリにruntime.txtを作成し、以下のように記入します。(python2.X系だと不要?)
python-2.7.11
requirements.txtを作成
manage.pyと同じディレクトリに、pythonのライブラリを記載したrequirements.txtを配置します。
$ pip freeze > requirements.txt
いろいろインストールしてる人は以下のツールあたりを残すとよさげです。
Django==1.10.3
django-toolbelt==0.0.1
gunicorn==19.6.0
psycopg2==2.6.2
requests==2.10.0
git初期化
$ git init
$ git add .
$ git commit -m 'first commit'
herokuにリポジトリを作成
$ heroku create
自動作成されたアプリ名を覚えておく。
Creating app... done, ⬢ evening-depths-59364
https://evening-depths-59364.herokuapp.com/ | https://git.heroku.com/evening-depths-59364.git
Herokuへのデプロイ前に、settings.pyを追記
- デプロイ時の"Error while running '$ python manage.py collectstatic --noinput'." 対策
settings.pyに以下を追記。(どこでもよい)
PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))
STATIC_ROOT = os.path.join(PROJECT_ROOT, 'staticfiles')
STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(PROJECT_ROOT, 'static'),
)
そして、以下の設定を追加。
$ heroku config:set DISABLE_COLLECTSTATIC=1
- デプロイ後のアクセス時の"Invalid HTTP_HOST header" 対策
ALLOWED_HOSTSに先ほどcreateしたherokuのアプリ名を追加する。
ALLOWED_HOSTS = ['127.0.0.1', 'localhost', 'evening-depths-59364.herokuapp.com']
settings.pyをコミット
$ git add osomatsu_bot/settings.py
$ git commit -m "edit settings.py"
herokuにデプロイ
$ git push heroku master
アクセスしてみる
https://evening-depths-59364.herokuapp.com/bot
-> 「This is bot api.」と表示されるはず
7. LINE側にherokuのアドレスをセット
LINE Developersの方の「Webhook URL」に、herokuのbot/callbackのアドレスを追加。
8. 会話してみる
$ heroku logs --tail
でログ監視しながらテストするといいです。
自動応答メッセージをオフにする
初期設定だとLINE@の自動応答メッセージが返ってしまうので、オフにする。
LINE@Managerにアクセス->メッセージ->自動応答メッセージ
で、初期設定の自動応答メッセージが表示されるので、deleteします。
お疲れ様でした。
雑感
- Djangoじゃなくてよかったな...wsgiとかflaskのがお手軽だな...
- 公式で作ってくれえ
参考サイト
全体的に参考にしました
herokuデプロイ時のエラー対策
-
Django製apiをherokuでデプロイする(自分用メモ)
"Error while running '$ python manage.py collectstatic --noinput'." 対策 -
django 1.5 から ALLOWED_HOSTSが追加されたぞ!DEBUG=Falseのときは気をつけろ!
Herokuにブラウザでアクセスしたときに出る"Invalid HTTP_HOST header"対策