36
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

DMM WEBCAMPAdvent Calendar 2018

Day 24

【LINEBot】クリスマスは1人映画でええじゃないか

Last updated at Posted at 2018-12-20

#クリスマスって辛くないですか?
辛いですよね。僕は辛いです。え?別に辛くない?、あ、そうですか。
外は寒いし、どこに行ってもカップルや家族づれで、お一人様お断りみたいな雰囲気出てますよね。出てない?いや、出てますよ。
そんな日はさっさと家に帰って映画です。
#映画っていいですよ
家で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

まずはユーザー登録をして、サイトの右上のアイコン/リストから自分の映画リストを作成します。
image.png

次に、画面右上の自分のアイコン/設定/APIからAPIキーを生成します。あとで使うので、メモをとるか、その画面を開いておきます。

image.png

##3. Railsの実装
###Railsアプリケーションの作成

$ rails new film_line_bot

$ cd film_line_bot
Gemfile
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を適用する

film.rb
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
linebot_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)
		   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末尾に書いてあります。

###ルーティング

routes.rb
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に追加します。
image.png

参考サイトhttps://qiita.com/NoharaMasato/items/6fb1ac277c965905e019 
にもあるように

$ heroku logs -t

でlogを見ながらデプロイやデバッグをすると何が起こっているか分かりやすいです。

#うまくいくとこんな感じ

IMG_0647.PNG

今回はジャンルを英語でしか(クリスマスは例外)受け取れませんでしたが、他のAPIと組み合わせれば改良できそうです。おすすめの方法を知っていたらコメントで教えて頂けると嬉しいです。

#ちなみに
クリスマスに観たい僕一押しの映画はホームアローンです。いつ観てもお腹が壊れそうなくらい笑えます。

ではでは、ごきげんよう。

追記

【翻訳APIを使って日本語に対応】https://mt-auto-minhon-mlt.ucri.jgn-x.jp/content/api/

まずは認証に必要なgemを追加

Gemfile
gem 'oauth'
bundle install
linebot_controller.rb
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

これで日本語メッセージに対応できるようになります。

参考までに

36
10
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
36
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?