wolfmasa's blog

フロンターレとプログラミング関係の話題を、気が向いたときにつぶやくブログです。

LINE botをRails6で作ってみた

はじめに

LINEのBOT API(厳密にはMessaging API)をHerokuとRailsを使って実装してみました。

ちなみに、Rails6で作ってみましたが、5と特に変わりはありませんでした。webpackerとか一応叩いてみたけど、あまり関係なかったっぽい。。。

developers.line.biz

今更〜という記事を見て、更に今更ですが(苦笑)、こんな手軽に使うRailsもあるのか、という感じで作れたので記録に残しておきます。

準備

  • Railsのインストール
  • herokuのアカウント+CLIツールインストール
  • LINE Developerアカウント作成

LINEのアカウントは、BOTAPIがリリースされた直後に作ったものがありましたが、気づいたらLINE Developerということでサイトも内容も一新されておりました。

f:id:wolfmasa:20191007182118j:plain

今回は参考サイトでも取り上げられているような、話しかけられたら適当に返事をするだけのアプリケーション。

Ruby on Railsの開発

rails new sarabot -d postgresql

が、いきなりポスグレのbundle installがこける!

調べると(よく考えれば当たり前だが)、ローカルサービスを立ち上げる必要があり、macの場合appをインストールするのが手っ取り早いとのことなので、公式HPからappをインストールし、セットアップ。

bundle config build.pg --with-pg-config=/Applications/Postgres.app/Contents/Versions/latest/bin/pg_config
bundle
bin/rails db:create

これでRailsアプリが立ち上がるので、あとは実装。

bin/rails g scaffold Post name:string
bin/rails db:migrate

まず、返答のデータベースとなるPostモデルを作る。返答は、いくつかの決められたパターンは固定で返答し、それ以外はPostsからランダムで返す単純なもの。

class LinebotController < ApplicationController
    require 'line/bot'  # gem 'line-bot-api'
  
    # callbackアクションのCSRFトークン認証を無効
    protect_from_forgery :except => [:callback]
  
    def client
      @client ||= Line::Bot::Client.new { |config|
        config.channel_secret = ENV["LINE_CHANNEL_SECRET"]
        config.channel_token = ENV["LINE_CHANNEL_TOKEN"]
      }
    end
  
    def callback
  
      # Postモデルの中身をランダムで@postに格納する
      @post=Post.offset( rand(Post.count) ).first
      body = request.body.read
  
      signature = request.env['HTTP_X_LINE_SIGNATURE']
      unless client.validate_signature(body, signature)
        head :bad_request
      end
  
      events = client.parse_events_from(body)
  
      events.each { |event|
  
        # event.message['text']でLINEで送られてきた文書を取得
        if event.message['text'].include?("好き")
          response = "いひひ"
        elsif event.message["text"].include?("行ってきます")
          response = "はーい"
        elsif event.message['text'].include?("おはよう")
          response = "うーーーーーーーん。。。(また寝る)"
        elsif event.message['text'].include?("さら")
          response = "さらちゃん!"
        elsif event.message['text'].include?("ママ")
          response = "ママたん!"
        elsif Post.count == 0
            response = event.message['text']
        else
          response = @post.name
        end
        #if文でresponseに送るメッセージを格納
  
        case event
        when Line::Bot::Event::Message
          case event.type
          when Line::Bot::Event::MessageType::Text
            message = {
              type: 'text',
              text: response
            }
            client.reply_message(event['replyToken'], message)
          end
        end
      }
  
      head :ok
    end
  end

ほとんど参考サイトのコピペ(すみません)。。。 コピペしながら、Messaging APIの仕様をなんとなく理解。

難しいのは、実際にherokuにデプロイしてみないと、APIが叩かれた後の確認やデバッグができないこと。

Rails.application.routes.draw do
  resources :posts
  post '/callback' => "linebot#callback"
end

ちなみに、routes.rbはこんな感じ。

動くか心配のまま、herokuにデプロイ。(上のコードは修正済みなので動きます)

heroku login
heroku create
heroku config:set LINE_CHANNEL_SECRET=xxxxx
heroku config:set config:set LINE_CHANNEL_TOKEN=xxxxxx  #(私のはめっちゃ長かった)
git push heroku master
heroku run

herokuのURLが決まったら、/callbackを含めてLINE Developer設定のWebHookに追記。

これで呼び出されるはず、だが最初は動かず、heroku上のデバッグどうするんだ!?となったので、

heroku run rails c #consoleを開く
heroku run rails tail #ログを確認する

こんな感じでできるよう。ローカルとほぼ同等のことができて素晴らしい(これで今回は十分だったのでこれ以上調べてない)

結局、callbackが呼ばれた後に例外で落ちていたのがログから確認できたので、修正して動きました。

めでたしめでたし。

f:id:wolfmasa:20191007184740p:plain

参考

qiita.com

qiita.com

qiita.com