LoginSignup
35
40

More than 3 years have passed since last update.

Rails+heroku+LINE Messager APIで秘書的なLINEbotを作ってみた(ゴミ出しの通知編)

Last updated at Posted at 2019-12-01

IMG_7844.PNG

作るもの

毎日決まった時間になるとゴミ出しについて通知してくれる簡単なLINEbot。
ゆくゆくは天気/交通情報/イベントなども共有してくれるbotにしたいと思っています。
アイアンマンに出てくる人工知能ジャーヴィスをお節介おばさんにしたイメージです。

dims.jpg

使用した言語/フレームワーク/ライブラリ/サービス

-Ruby
-Ruby On Rails6
-Heroku
-LINE Messager API

大まかな手順

1.メッセージをオウム返しするLINEbotを作る
2.LINEにメッセージをpushしてみる
3.Herokuにデプロイして定期実行する

STEP1 メッセージをオウム返しするLINEbotを作る

LINE MessagerAPI

作成したbotのメッセージ周りのやり取りを担当してくれるのがLINEMessage APIです。
まず、自分のメッセージの内容をそのまま返してくれるbotを作ります。
LINE Messager APIの概要はDeveloperページを確認。
LINE Developers

APIの準備

APIを使用する前にやるべきことがいくつかあります。ざっくりとこんな感じ。
1. ビジネスアカウントの登録
2. プロバイダーの作成
3. チャンネルの作成
4. グループ・複数人チャットへの参加を許可するにチェック
5. Messaging APIの「Channel access token」と「channel Secret」を控える

LINEのBot開発 超入門(前編) ゼロから応答ができるまで」 登録周りを丁寧に説明しているので、わからなくなったらこっちを参考にしてください。

Rails側の実装

ここからは、「今更ながらRails5+line-bot-sdk-ruby+HerokuでLineBot作成してみたら、色々詰まったのでまとめました。」を参考に実装します。

まずRailsのプロジェクトを作ります。herokuがデフォルトでpostgresqlなので、合わせます。

$Rails new mother_bot --database=postgresql
$rails db:create

Line APIを使う為のgemをインストールします。

Gemfile.rb
#LINE API用
gem 'line-bot-api'

#access tokenなどを管理する用
gem 'dotenv-rails' 
$bundle install

LINE API登録時に控えた情報をアプリのルート直下に.envファイルを作成して保存

#.env
LINE_CHANNEL_SECRET=XXXXXX
LINE_CHANNEL_TOKEN=XXXXXX

コントローラーの準備をしてきます。

$rails g controller Linebot
linbot_controller.rb
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
    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|
      case event
      when Line::Bot::Event::Message
        case event.type
        when Line::Bot::Event::MessageType::Text
          message = {
            type: 'text',
            text: event.message['text']
          }
        end
      end
    }

    head :ok
  end
end
config/route.rb
Rails.application.routes.draw do
  post '/callback' => 'linebot#callback'
end

ローカルでデバッグしてみる

herokuにpushしておしまい!のような記事が多いので、ローカルのデバッグで苦労しました。
ローカルからAPIを操作するためにはまずngrokを使う必要があります。参考記事を読みながら、デバッグ環境を構築してください。

公式サイト
https://ngrok.com/

参考記事(ローカルで動かす セクションからが重要)
LINE Botをローカル環境で動かしたりデバッグしたりする方法

TIPS

  • ngrokuを導入する際は、公式サイトからemailを登録してインストラクションに剃ってダウンロード、コマンドを叩いてくと正常に動くようになります。
  • LINE DevelopersからWebhook URLを設定を正しくするというのが、一番のミソだと思います。
  • ngrokuは無料プランだと起動するたびにエンドポイントが変わるので、Webhook URLを毎回変えましょう。

STEP1終了
これでうまく実装できていれば、自分のLINEから作成したアカウントを友達登録して、メッセージを投げると同じ内容のメッセージを投げ返してくれます。友達登録は、LINE DeveloperのチャンネルページのQRコードを使うと簡単です。

IMG_7845.PNG

初期メッセージはLINE Developersから編集できます。

STEP2 LINEにメッセージpushする

STEP1では、自分のメッセージをトリガーに、LINE Message APIを操作しました。
今回は、チャンネルがこちらのアクションなしで、テキストを送信できるよう実装していきます。

ユーザーモデルの追加

messageをAPIから一方的に送りつけるためには、rails側で送り先のuserIDを知っている必要があります。
送るユーザーが決まっていればIDをメモして、環境変数に設定してもいいと思いますが、今回はお友達登録でユーザーIDを保存できるように、実装します。

$rails g model user uid:string
$rails db:migrate

controllerに追記

linebot_controller.rb
        #省略 
        #29行目ぐらい
        when Line::Bot::Event::MessageType::Text
          message = {
            type: 'text',
            text: event.message['text']
          }
          client.reply_message(event['replyToken'], message)
        when Line::Bot::Event::MessageType::Follow #友達登録イベント
          userId = event['source']['userId'] 
          User.find_or_create_by(uid: userId)
        when Line::Bot::Event::MessageType::Unfollow #友達削除イベント
          userId = event['source']['userId']  
          user = User.find_by(uid: userId)
          user.destroy if user.present?
        end

タスクを追加

決まった時間になったら、メッセージを送りつける為のタスクを作成します。

lib/tasks/push.rake
namespace :push_line do 
    desc "LINEBOT:ゴミ出しの通知" 
    task push_line_message_trash: :environment do
        trash_day = TrashDay.new
        message = {
            type: 'text',
            text: trash_day.text
        }
        client = Line::Bot::Client.new { |config|
            config.channel_secret = ENV["LINE_CHANNEL_SECRET"]
            config.channel_token = ENV["LINE_CHANNEL_TOKEN"]
        }
        User.all.each do |user|
            client.push_message(user.uid, message)
        end
    end
end

曜日によってメッセージが違うので、メソッドを切り出しました。必要ない人は無視で!

trash.rb
class TrashDay
    def text
      date = Date.today

      case date.strftime('%a')
        when "Mon"
            "ちょっとあんた!今日は月曜日、普通ゴミの日だわ!" + metal_text
        when "Tue"
            "ちょっとあんた!今日は火曜日、空き缶・ペットボトル・空き瓶・使用済み乾電池の日だわ!"
        when "Wed"
            "ちょっとあんた!今日は水曜日、プラスチック製容器包装の日だわ!"
        when "Thu"
            "ちょっとあんた!今日は木曜日、普通ゴミの日だわ!"
        when "Fri"
            "HEY BUDDY! It's Friday. Party hard. Don't drink too much.(ゴミ無しの日)"
        when "Sat"
            "ちょっとあんた!今日は土曜日、ミックスペーパーの日だわ!"
        else
            ""
        end
    end

    def metal_text
        date = Date.today
        week = DateHelper.new.week_of_month_for_date(date)
        day = date.strftime('%a')
        if week == 2 || week == 4
            "2・4回目の月曜日だから小物金属も忘れちゃダメよ!"
        else
            ""
        end
    end
end

隔週で回すタスク用のメソッドです。

date_helper.rb
class DateHelper
    def week_of_month_for_date(date)
        my_date = Time.zone.parse(date.to_s)
        week_of_target_date = my_date.strftime("%U").to_i
        week_of_beginning_of_month = my_date.beginning_of_month.strftime("%U").to_i
        week_of_target_date - week_of_beginning_of_month + 1
    end
end

タスクが登録されたか確認

$rails -T

実行してみる

rails push_line:push_line_message_trash

メッセージが届いたら成功です!
STEP2終了

STEP3 Herokuにデプロイして定期実行する

これで9割完成です。あとはherokuにアップして、定期実行の設定をしてみましょう。

まずherokuのアカウントとアプリを作成します。
この辺は、記事を参考に進めてください。

HerokuにRailsアプリをデプロイする手順
https://qiita.com/NaokiIshimura/items/eee473675d624a17310f

一通りherokuデプロイの手順が終わったら、LINEAPIの環境変数を設定していきます。

$heroku config:set LINE_CHANNEL_SECRET=xxxx
$heroku config:set LINE_CHANNEL_TOKEN=xxx

#herokuの時間を日本時間に合わせます
$heroku config:add TZ=Asia/Tokyo

herokuのURLをAPIのWebhookURLに設定するのを忘れないでください。
スクリーンショット 2019-12-01 16.16.48.png

定期実行の設定

通常であれば、wheneverみたいなgemを使ってcronを操作すると思いますが、今回はherokuでのデプロイなので、heroku schedulerというaddonを使って実装します。無料です。

参考記事
Herokuでスケジューラ(cron)を設定する方法【Heroku Scheduler】
https://reasonable-code.com/heroku-cron/

#addonの追加
$heroku addons:create scheduler:standard --app アプリ名

#heroku上でタスクが動くか確認
$heroku run bundle exec rails push_line:push_line_message_trash --app アプリ名

実際に定期実行してみる

#GUI上でスケジュールを設定
$heroku addons:open scheduler

#実行されてるか確認
$heroku logs --app アプリ名

以上です。これで決まった時間にメッセージが送られてきたら成功です!
お疲れ様でした。

感想

簡単なLINEbotでしたが、とても楽しかったです。機会があればgoogle calendar APIなどと連携してbotの秘書力を高めて行きたいです。

35
40
0

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
35
40