#クリスマスって辛くないですか?
辛いですよね。僕は辛いです。え?別に辛くない?、あ、そうですか。
外は寒いし、どこに行ってもカップルや家族づれで、お一人様お断りみたいな雰囲気出てますよね。出てない?いや、出てますよ。
そんな日はさっさと家に帰って映画です。
#映画っていいですよ
家で1人暇な時。僕はよく映画を観ます。
今までに500本以上の映画を観て、~~時間を無駄に浪費してきました。~~多くの映画に感動させられました。
映画は日常を忘れ、非日常に没頭できる素敵なものです。
だから、クリスマスは家で映画を観ましょう。
#何の映画を見ればいいか分からない 分かります。映画って短くても1時間、長いもので3時間以上もありますからね。どうせなら面白い映画を観たい。 でも映画サイトのレビューは当てにならないし、周りに詳しい人はいない。 僕に聞いてくれれば、いくらでもおすすめの映画を教えてあげられるのですが... #課題 ・映画は観たい、でもおもしろい映画が分からない。 ・@Ndo に聞きたいけど、話しかけづらい(そんなことはありませんよ〜)。 ・もっと気軽に知りたい(はい、ここ大事!)。#【解決策】LINEBotに聞く
やっとここまでたどり着きました。話の枕が長すぎる!
@NoharaMasato が先にLINEBotについてQiitaに記事を書いているので、完全に二番煎じ。
ですが、クリスマスには僕のBotの方が活躍します。(たぶん)
まずはお試しあれ👇
#参考
「Web APIとは? (LINE bot API・グルナビAPI)」
https://qiita.com/NoharaMasato/items/6fb1ac277c965905e019
「今更ながらRails5+line-bot-sdk-ruby+HerokuでLineBot作成してみたら、色々詰まったのでまとめました。」
https://qiita.com/y428_b/items/d2b1a376f5900aea30dc%20
「【初心者向け】railsアプリをherokuを使って確実にデプロイする方法【決定版】」
https://qiita.com/kazukimatsumoto/items/a0daa7281a3948701c39
#作ってみましょう
参考サイトを見れば全体の80%は事足ります。
映画情報を取得するための手順は参考にしてください。
##1. LineBotAPIの設定
参考サイトを参照。
https://qiita.com/NoharaMasato/items/6fb1ac277c965905e019
https://qiita.com/y428_b/items/d2b1a376f5900aea30dc%20
##2. 映画情報をAPIで取得
映画情報を取得するために色々調べたのですが、海外のTheMovieDataBase(TMDB) https://www.themoviedb.org/ と言う映画データベースサイトがAPIを公開していて、それが利用できそうです。使い方も下記のサイトに詳しく載っていました。
https://developers.themoviedb.org/3
https://developers.themoviedb.org/4
まずはユーザー登録をして、サイトの右上のアイコン/リストから自分の映画リストを作成します。
次に、画面右上の自分のアイコン/設定/APIからAPIキーを生成します。あとで使うので、メモをとるか、その画面を開いておきます。
##3. Railsの実装
###Railsアプリケーションの作成
$ rails new film_line_bot
$ cd film_line_bot
gem 'line-bot-api'
パッケージのインストール
$ bundle install
動作の確認
$ rails s
http://localhost:3000 に接続できればOK。
###Herokuへデプロイ
下記の記事を参考にしてherokuへデプロイします
「【初心者向け】railsアプリをherokuを使って確実にデプロイする方法【決定版】」
https://qiita.com/kazukimatsumoto/items/a0daa7281a3948701c39
Herokuへログイン
$ heroku login
Herokuにアプリを作成
$ heroku create 好きなアプリ名
git repositoryを作成し、Herokuにデプロイ
$ git init
$ git add .
$ git commit -m "init"
$ git push heroku master
###Filmモデルの作成
Filmモデルにenumを実装
$ rails g model Film genre:integer
$ rails g migrate
TMDbのAPIドキュメントを参考にFilmモデルのgenreカラムにenumを適用する
class Film < ApplicationRecord
enum genre: {
Action: 28,
Adventure: 12,
Animation: 16,
Comedy: 35,
Crime: 80,
Documentary: 99,
Drama: 18,
Family: 10751,
Fantasy: 14,
History: 36,
Horror: 27,
Music: 10402,
Mystery: 9648,
Romance: 10749,
SF: 878,
TVMovie: 10770,
Thriller: 53,
War: 10752,
Western: 37,
}
end
###コントローラーの作成
$ 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)
error 400 do 'Bad Request' end
end
events = client.parse_events_from(body)
# ここでlineに送られてきたイベントを検出
# messageのtext: 指定すると、返信する文字を決定することができる
# event.message['text']で送られてきたメッセージを取得することができる
events.each {|event|
@genre = event.message['text'].gsub(" ", "") #ここでLINEで送った文章を取得。スペースなどの空白はAPI通信の妨げになるので削除
uri = URI.parse("https://api.themoviedb.org/4/list/自分の映画リストid?api_key=TMDbのAPIキー") #自分の映画リストにアクセスするためのuriを定義
json = Net::HTTP.get(uri) #NET::HTTPを利用してAPOを叩く
results = JSON.parse(json) #返ってきたjsonデータをrubyの配列に変換
movies = []
if @genre == "クリスマス" #lineから送られてきたメッセージがクリスマスかどうかで条件分岐
results['total_pages'].to_i.times do |f|
uri = URI.parse("https://api.themoviedb.org/4/list/自分の映画リストid?api_key=TMDbのAPIキ-&page=#{f+1}") #リストから20件しか持って来れないので、ある分だけ繰り返し叩く
json = Net::HTTP.get(uri) #NET::HTTPを利用してAPOを叩く
results = JSON.parse(json) #返ってきたjsonデータをrubyの配列に変換
movies += results['results'] #全映画リストの情報をハッシュの配列で取得
end
lists = movies #分かりやすいように入れ替え
else
results['total_pages'].to_i.times do |f|
uri = URI.parse("https://api.themoviedb.org/4/list/映画リストid?api_key=TMBdのAPIキー&page=#{f+1}")
json = Net::HTTP.get(uri) #NET::HTTPを利用してAPOを叩く
results = JSON.parse(json) #返ってきたjsonデータをrubyの配列に変換
movies += results['results'] #全映画リストの情報をハッシュの配列で取得
end
genre_id = Film.genres[@genre] #予めジャンルをenumで列挙型にしておき、送られてきたString型のジャンルを割り当てられた整数に変換する
lists = movies.select{|x| x["genre_ids"].include?(genre_id.to_i)} #genre_idが合致する映画だけをフィルタリング
end
list = lists.sample # リストから任意のものを一つ選ぶ
uri = URI.parse("https://api.themoviedb.org/3/movie/#{list['id']}?api_key=TMBdのAPIキー&append_to_response=videos") # listから選んだ映画ついての情報を取得
json = Net::HTTP.get(uri) #NET::HTTPを利用してAPOを叩く
results = JSON.parse(json) #返ってきたjsonデータをrubyの配列に変換
# 映画の情報
if results['videos']['results'] != nil #古い作品は予告動画が見つからないこともあるため条件分岐
video = "https://www.youtube.com/embed/#{results['videos']['results'][0]['key']}" #映画の予告動画のurlを生成
else
video = "見つかりませんでした"
end
movie_title = list['original_title'] #映画のタイトル
movie_score = list['vote_average'].to_s #float型をstring型に変換
response = "【タイトル】" + movie_title + "\n" + "【ジャンル】" + @genre + "\n" + "【スコア】" + movie_score + "\n" + "【Youtube】" + video
case event #case文 caseの値がwhenと一致する時にwhenの中の文章が実行される(switch文みたいなもの)
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
自分の映画リストのidはリストの詳細ページを表示した時のURL末尾に書いてあります。
###ルーティング
post '/callback' => 'linebot#callback'
###環境変数の設定
$ heroku config:set LINE_CHANNEL_SECRET=自分のChannelSecret
$ heroku config:set LINE_CHANNEL_TOKEN=自分のアクセストークン
###Herokuへデプロイ(2回目)
この辺りで詰まったら参考サイトへ👇
https://qiita.com/kazukimatsumoto/items/a0daa7281a3948701c39
$ git add .
$ git commit -m "update"
$ git push heroku master
$ heroku run rails db:migrate #本番環境でのマイグレーション
この時にhttpsのURLが与えられるのでLINE bot APIのWebhook URLに追加します。
参考サイトhttps://qiita.com/NoharaMasato/items/6fb1ac277c965905e019
にもあるように
$ heroku logs -t
でlogを見ながらデプロイやデバッグをすると何が起こっているか分かりやすいです。
#うまくいくとこんな感じ
今回はジャンルを英語でしか(クリスマスは例外)受け取れませんでしたが、他のAPIと組み合わせれば改良できそうです。おすすめの方法を知っていたらコメントで教えて頂けると嬉しいです。
#ちなみに
クリスマスに観たい僕一押しの映画はホームアローンです。いつ観てもお腹が壊れそうなくらい笑えます。
ではでは、ごきげんよう。
追記
【翻訳APIを使って日本語に対応】https://mt-auto-minhon-mlt.ucri.jgn-x.jp/content/api/
まずは認証に必要なgemを追加
gem 'oauth'
bundle install
require 'line/bot'
require 'oauth'
...
events.each do |event|
#### ↓ここを追加
# 自動翻訳API設定
translate_key = ENV["TRANSLATE_KEY"]
translate_secret = ENV["TRANSLATE_SECRET"]
url="https://mt-auto-minhon-mlt.ucri.jgn-x.jp/api/mt/generalNT_ja_en/"
minhon_user_name=ENV["MINHON_USER_NAME"]
# 認証
consumer = OAuth::Consumer.new(translate_key, translate_secret)
endpoint = OAuth::AccessToken.new(consumer)
#### ここまで
#ここでLINEで送った文章を取得。空白はAPI通信の妨げになるので削除
message = event.message['text'].gsub(' ', '')
####さらに追加↓
#messageの本文を翻訳APIにかける
response = endpoint.post(url,{key: translate_key, type: 'json', name: minhon_user_name, text: message})
results = JSON.parse(response.body)
@genre = results['resultset']['result']['text']
####ここまで
uri = URI.parse("https://api.themoviedb.org/4/list/自分の映画リストid?api_key=TMDbのAPIキー") #自分の映画リストにアクセスするためのuriを定義
#####あとは環境変数を追加設定
$ heroku config:set TRANSLATE_KEY=みんなの自動翻訳のAPI key
$ heroku config:set TRANSLATE_SECRET=みんなの自動翻訳のAPI secret
$ heroku config:set MINHON_USER_NAME=みんなの自動翻訳のログイン ID
これで日本語メッセージに対応できるようになります。
参考までに