こんばんは
たまにはエンジニアっぽいところを見せようと思い、遅ればせながら、流行りのLINE BOTを試してみました。
今回作ったBOTの返答のロジックはいたってシンプル。
会社名の由来である「タマゴが先か、ニワトリが先か」という言葉にちなみ、「(前の人が話した言葉)が先か、(送ったメッセージ)が先か」という言葉をBOTが返すものを作ってみました。
(会社名の由来はドリルを買う人はドリルが欲しい。を参照)
LINE BOTの仕組みとしてはこんな感じです。
LINE BOTにはSSLが必要なのと固定IPが必要なので、YOUR SYSEMの部分のサーバにはherokuを使います。
herokuは固定IPではないのですが、Fixieというアドオンを使うと、プロキシを経由してくれるのでIPを固定できます。
LINEへの登録
LINE BOT APIのトライアルはhttps://business.line.me から登録できます。
すでにトライアルの配布は上限に達してしまい終わっているのですが、私はこっそり登録してあったものを使います。
デベロッパー登録が終わると、以下の3つが取得できます。
Channel ID
Channel Secret
MID
後でアプリで利用しますのでメモっておきます。
herokuにアプリ作成
herokuにアプリを作成します。
herokuはIPが固定ではないのですが、Fixieというアドオンを追加します。
Fixieを使うとプロキシを経由するようになるので、接続元IPを固定できます。
$ heroku login $ heroku create your_app $ heroku addons:create fixie:tricycle
Server IP Whitelistに固定IPを登録
LINE BOT APIを呼ぶにはLINE BOT APIにFixieで固定した接続元IP(Whitelist)を登録する必要があります。
heroku上で作ったアプリの設定画面から Fixie の画面を開くと次のような画面になるので、
Outbound IPs
の2つの値をメモっておきます。
さらに
Proxy URL
もあとで使うのでメモっておきます。
https://business.line.meから
Channels → Server IP Whitelistを選び、「Server IP Whitelist」にメモったOutbound IPsを登録します。
コールバックURLの登録
コールバックURLをLINE BOT APIに登録します。
今回はhttp://xxx.com:443/callbackというURLで後述のアプリを作成しようとおもいます。(xxx.comの部分はherokuのURL)
https://business.line.meから
Channels → Basic Infomationを選び、下の方にあるEDITボタンより「Callback URL」を登録します。
その際プロトコルはhttps、ポート番号は443を必ず指定します。(指定しないと正しく呼び出せないらしい。)
https://xxxx.com:443/callback
これで事前準備は終わりです。
次からは本題のBOT用アプリ作成です。
Railsアプリの作成
次に、自分のマシンに新しいRailsプロジェクト作成します。
$ rails new your_app
herokuのDBにはPostgreSQL、LINE BOT APIとのHTTP接続にはFaradayを使うので、Gemfileに以下を追加。
gem "pg" gem "faraday" gem "faraday_middleware"
前の人が話した言葉や、ユーザの管理にはherokuで利用できるPostgresqlを使うので、database.ymlに以下を追加。
database、username、passwordに関してはherokuにログインすると確認できます。
production: adapter: postgresql encoding: utf8 database: your_database port: 5432 username: your_username password: your_password
route.rbにLINE BOT APIに登録するコールバックURLのルーティング設定
Rails.application.routes.draw do post '/callback' => 'webhook#callback' end
ユーザを管理するモデルの作成
$ rails generate model users mid:string display_name:string status:integer
前の人が話した言葉を管理するユーザの管理するモデルの作成
$ rails generate model messages user_id:integer text_message:string
次にコントローラ。
class WebhookController < ApplicationController protect_from_forgery with: :null_session CHANNEL_ID = ENV['LINE_CHANNEL_ID'] CHANNEL_SECRET = ENV['LINE_CHANNEL_SECRET'] CHANNEL_MID = ENV['LINE_CHANNEL_MID'] OUTBOUND_PROXY = ENV['LINE_OUTBOUND_PROXY'] def callback unless is_validate_signature render :nothing => true, status: 470 end result = params[:result][0] logger.info({from_line: result}) if result['content']['opType'].present? mid = result['content']['params'][0] client = LineClient.new(CHANNEL_ID, CHANNEL_SECRET, CHANNEL_MID, OUTBOUND_PROXY) res = client.profile(mid) if res.status == 200 logger.info({success: res}) display_name = res.body['contacts'][0]['displayName'] opType = result['content']['opType'] case opType when 4 then user = User.create_with(display_name: display_name, status: 4).find_or_create_by(mid: mid) user.display_name = display_name user.status = 4 user.save! when 8 then user = User.create_with(display_name: display_name, status: 8).find_or_create_by(mid: mid) user.display_name = display_name user.status = 8 user.save! else end else logger.info({fail: res}) end else text_message = result['content']['text'] from_mid = result['content']['from'] last_message = Message.last.text_message user = User.find_by(mid: from_mid) Message.create(user_id: user.id, text_message: text_message) message = last_message + "が先か、" + text_message + "が先か" client = LineClient.new(CHANNEL_ID, CHANNEL_SECRET, CHANNEL_MID, OUTBOUND_PROXY) res = client.send([from_mid], message) if res.status == 200 logger.info({success: res}) else logger.info({fail: res}) end end render :nothing => true, status: :ok end private def is_validate_signature signature = request.headers["X-LINE-ChannelSignature"] http_request_body = request.raw_post hash = OpenSSL::HMAC::digest(OpenSSL::Digest::SHA256.new, CHANNEL_SECRET, http_request_body) signature_answer = Base64.strict_encode64(hash) signature == signature_answer end end
LINE BOT APIを呼ぶライブラリの作成。
require "faraday" require "faraday_middleware" require "json" require "pp" class LineClient module ContentType TEXT = 1 IMAGE = 2 VIDEO = 3 AUDIO = 4 LOCATION = 7 STICKER = 8 CONTACT = 10 end module ToType USER = 1 end END_POINT = "https://trialbot-api.line.me" TO_CHANNEL = "1383378250" # Fixed value EVENT_TYPE = "138311608800106203" # Fixed value def initialize(channel_id, channel_secret, channel_mid, proxy = nil) @channel_id = channel_id @channel_secret = channel_secret @channel_mid = channel_mid @proxy = proxy end def post(path, data) client = Faraday.new(:url => END_POINT) do |conn| conn.request :json conn.response :json, :content_type => /\bjson$/ conn.adapter Faraday.default_adapter conn.proxy @proxy end res = client.post do |request| request.url path request.headers = { 'Content-type' => 'application/json; charset=UTF-8', 'X-Line-ChannelID' => @channel_id, 'X-Line-ChannelSecret' => @channel_secret, 'X-Line-Trusted-User-With-ACL' => @channel_mid } request.body = data end res end def get(path, data) client = Faraday.new(:url => END_POINT) do |conn| conn.request :json conn.response :json, :content_type => /\bjson$/ conn.adapter Faraday.default_adapter conn.proxy @proxy end res = client.get do |request| request.url path, data request.headers = { 'Content-type' => 'application/json; charset=UTF-8', 'X-Line-ChannelID' => @channel_id, 'X-Line-ChannelSecret' => @channel_secret, 'X-Line-Trusted-User-With-ACL' => @channel_mid } end res end def send(line_ids, message) post('/v1/events', { to: line_ids, content: { contentType: ContentType::TEXT, toType: ToType::USER, text: message }, toChannel: TO_CHANNEL, eventType: EVENT_TYPE }) end def profile(mids) get('/v1/profiles', { mids: mids }) end end
heroku ENVの設定
LINE BOT APIの情報
Channel ID
Channel Secret
MID
とFIXIEのアカウント情報にあった
PROXY URL
を設定します。
このENVはRailsプログラムから参照します。
$ heroku config:add LINE_CHANNEL_ID="xxxxxx" $ heroku config:add LINE_CHANNEL_SECRET="xxxxxx" $ heroku config:add LINE_CHANNEL_MID="xxxxxx" $ heroku config:add FIXIE_URL="http://xxxxxx"
herokuへデプロイ
最後にherokuへデプロイします
$ git add . $ git commit -m 'xxxxxx' $ git push heroku master
DBがあるのでマイグレートします。
$ heroku run rake db:migrate
これで準備完了です。
LINEから確認してみましょう。
LINEが入っているスマホから友達追加。
うまく動いてそうです。
まだトライアルなので50人までしか友達増やせないみたいです。
今回はシンプルなロジックのBOTをつくりましたが、工夫次第で面白いものが作れそうです。
[…] 前回、LINE BOTを無料で試してみました。heroku + RailsでLINE BOTを試してみたのですが、社内でロジックが単純すぎでくだらないという批判が多かったので、ロジックを少し改良しました。 […]
[…] https://www.cotegg.com/blog/?p=436 […]