#作るもの
毎日決まった時間になるとゴミ出しについて通知してくれる簡単なLINEbot。
ゆくゆくは天気/交通情報/イベントなども共有してくれるbotにしたいと思っています。
アイアンマンに出てくる人工知能ジャーヴィスをお節介おばさんにしたイメージです。
#使用した言語/フレームワーク/ライブラリ/サービス
-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を使用する前にやるべきことがいくつかあります。ざっくりとこんな感じ。
- ビジネスアカウントの登録
- プロバイダーの作成
- チャンネルの作成
- グループ・複数人チャットへの参加を許可するにチェック
- 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をインストールします。
#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
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
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コードを使うと簡単です。
初期メッセージは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に追記
#省略
#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
###タスクを追加
決まった時間になったら、メッセージを送りつける為のタスクを作成します。
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
曜日によってメッセージが違うので、メソッドを切り出しました。必要ない人は無視で!
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
隔週で回すタスク用のメソッドです。
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に設定するのを忘れないでください。
###定期実行の設定
通常であれば、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の秘書力を高めて行きたいです。