Quantcast
Channel: DMM WEBCAMP Advent Calendarの記事 - Qiita
Viewing all articles
Browse latest Browse all 25

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

$
0
0

クリスマスって辛くないですか?

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

映画っていいですよ

家で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と組み合わせれば改良できそうです。おすすめの方法を知っていたらコメントで教えて頂けると嬉しいです。

ちなみに

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

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


Viewing all articles
Browse latest Browse all 25

Trending Articles