71
80

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Django+HerokuでLINE Messaging APIのおそ松botを作るまで

Last updated at Posted at 2016-11-13

概要

おそ松のセリフをランダムに返す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を以下のように編集します。

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行目以降を以下のように編集します。

osomatsu_bot/urls.py
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の一行目に以下を忘れずに追加。

osomatsu_bot/urls.py
# -*- encoding: utf-8 -*-

次に、bot/の下にurls.pyというファイルを新規作成し、以下のように編集します。

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からクロールしたものを用いました

bot/osomatsu_serif.txt
ねぇ君、ちょっと聞いて〜
俺、松野家長男、松野おそ松でーす!
リーダーシップにあふれたアイドル!
夢はビッグなカリスマレジェンド!!

また、これをあらかじめ読み込んでおくためのpythonスクリプト bot/load_serif.py を作ります。

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関数を作ります。

bot/views.py

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関数を追加します。

bot/views.py

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をインストール後、以下のようにデータを入力します。

{
  "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系だと不要?)

runtime.txt
python-2.7.11

requirements.txtを作成
manage.pyと同じディレクトリに、pythonのライブラリを記載したrequirements.txtを配置します。

$ pip freeze > requirements.txt

いろいろインストールしてる人は以下のツールあたりを残すとよさげです。

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に以下を追記。(どこでもよい)
osomatsu_bot/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のアプリ名を追加する。
osomatsu_bot/setings.py
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のアドレスを追加。
スクリーンショット 2016-11-12 23.01.31.png

8. 会話してみる

こんな感じ
スクリーンショット 2016-11-12 23.36.18.png

$ heroku logs --tail

でログ監視しながらテストするといいです。

自動応答メッセージをオフにする
初期設定だとLINE@の自動応答メッセージが返ってしまうので、オフにする。
スクリーンショット 2016-11-12 23.32.31.png

LINE@Managerにアクセス->メッセージ->自動応答メッセージ
で、初期設定の自動応答メッセージが表示されるので、deleteします。

お疲れ様でした。

雑感

  • Djangoじゃなくてよかったな...wsgiとかflaskのがお手軽だな...
  • 公式で作ってくれえ

参考サイト

全体的に参考にしました

herokuデプロイ時のエラー対策

botのセリフ

71
80
2

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
71
80

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?