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



#クリスマスって辛くないですか？
辛いですよね。僕は辛いです。え？別に辛くない？、あ、そうですか。
外は寒いし、どこに行ってもカップルや家族づれで、お一人様お断りみたいな雰囲気出てますよね。出てない？いや、出てますよ。
そんな日はさっさと家に帰って映画です。
#映画っていいですよ
家で1人暇な時。僕はよく映画を観ます。
今までに500本以上の映画を観て、~~時間を無駄に浪費してきました。~~多くの映画に感動させられました。
映画は日常を忘れ、非日常に没頭できる素敵なものです。
<h4>だから、クリスマスは家で映画を観ましょう。</h4>
#何の映画を見ればいいか分からない
分かります。映画って短くても１時間、長いもので３時間以上もありますからね。どうせなら面白い映画を観たい。
でも映画サイトのレビューは当てにならないし、周りに詳しい人はいない。
僕に聞いてくれれば、いくらでもおすすめの映画を教えてあげられるのですが...
#課題
・映画は観たい、でもおもしろい映画が分からない。
・@Ndo に聞きたいけど、話しかけづらい(そんなことはありませんよ〜)。
・もっと気軽に知りたい(はい、ここ大事！)。

#【解決策】LINEBotに聞く
やっとここまでたどり着きました。話の枕が長すぎる！
@NoharaMasato が先にLINEBotについてQiitaに記事を書いているので、完全に二番煎じ。
ですが、クリスマスには僕のBotの方が活躍します。（たぶん）
まずはお試しあれ👇

<img src="https://qiita-image-store.s3.amazonaws.com/0/211627/18244894-fa03-6831-af18-c3276f598aaa.png" width=50%>



#参考
「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](https://qiita-image-store.s3.amazonaws.com/0/211627/f9aa768b-9d63-026b-67ac-34be2b14198e.png)

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

![image.png](https://qiita-image-store.s3.amazonaws.com/0/211627/03983570-e208-8f44-34d4-f94f208d5bd9.png)


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

```ターミナル
$ rails new film_line_bot

$ cd film_line_bot
```

```ruby: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}")　#リストから２０件しか持って来れないので、ある分だけ繰り返し叩く
			     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へデプロイ（２回目）

この辺りで詰まったら参考サイトへ👇
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-image-store.s3.amazonaws.com/0/211627/f5322731-ef2f-a21e-6583-d098811864e6.png)



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

```
$ heroku logs -t
```

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

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

<img width="320" alt="IMG_0647.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/211627/e7b06bd6-f193-af19-37e5-9ddbb9e4b31f.png">

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


#ちなみに
クリスマスに観たい僕一押しの映画は[ホームアローン](https://www.youtube.com/watch?v=E9YU5aeg_pw)です。いつ観てもお腹が壊れそうなくらい笑えます。

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

# 追記

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

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

```ruby: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
```

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

参考までに