LoginSignup
139
136

More than 1 year has passed since last update.

【個人開発】通勤時にQiitaのトレンド記事が届くLINE Botを開発した

Last updated at Posted at 2022-08-02

はじめに

今回は通勤時間を有効活用することができる、通勤時にQiitaのトレンド記事が届くLINE Botを開発しながらRailsと外部APIの連携LINE Messaging API SDKの使い方LINE Flex Messageの使い方を学んでいきます。

チュートリアル形式で実際にLINE Botの開発をしながら開発方法を解説していきます。

この記事の対象者

  • LINE Bot開発に入門したい人
  • Railsと外部APIの連携手法を学びたい人
  • 個人開発でLINE Botを作ってみたい人

目標成果物

LINE側から「出勤なう」と送られてきたタイミングでQiitaのトレンド記事上位5つを返すLINE Bot。

IMG_7062.jpg

LINE Botについて

LINE Botとは

LINE BotとはLINE上のメッセージの返答を自動化できるチャットボットです。

チャットボットとはユーザーからのメッセージに、自動で返答するプログラムです。

LINE Botを使うことで、ユーザーに対してカスタマーサポート、商品のクーポン送付、予約機能など様々なアプローチを行うことができますなどをすることができます。

【LINE Botでできること】

  • ユーザーからのメッセージに対して自動返信
  • 返答の出しわけ
  • 選択肢の提示
  • クーポンの発行や利用
  • Webサイトへの誘導

今回の開発ではユーザーへメッセージを自動送信する機能を開発します。

LINE Botの仕組み

LINE BotはLINEが提供するMessaging APIを利用して開発をすることができます。

このMessaging APILINE Developersコンソールという開発者向けの管理上で作成することができるチャネルを通信経路として利用する。

ユーザーがLINE Botに対してメッセージを送信してから返信が返ってくる流れは以下のように表すことができます。

スクリーンショット 2022-07-29 15.18.12.jpg

① ユーザーがスマホアプリでメッセージを送信
② 送信されたメッセージはチャネルを経由しLINEプラットフォームへいきRailsアプリへ
③ Railsアプリで受信したメッセージを解析
④ Railsはユーザーへ送信したいメッセージのリクエストをLINEプラットフォームへ
⑤ LINEプラットフォームからユーザーのスマホへメッセージが送信される

簡単なオーム返しアプリを作ってみる

まずは公式ドキュメントの手順に沿って簡易的なオーム返しアプリを開発していきます。

Messaging API のチャネルの作成

まずはじめに先ほど紹介したメッセージの経由を行うチャネルLINE Developersコンソールを利用して作成していきます。

スクリーンショット 2022-07-29 16.31.09.jpg

下記の公式サイトにまずはアクセスします。

まず初めに、自分の使っているLINEアカウントを用いてログインします。

スクリーンショット 2022-07-29 16.33.34.jpg

はじめての人はここからLINE Developersに新規のアカウントを登録してください。

登録が完了したらサイドバーよりProvidersを選択しcreateをクリックしてください。

スクリーンショット 2022-07-29 17.18.38.jpg

登録が完了すると、作成したプロバイダーが表示されています。

スクリーンショット 2022-07-29 17.20.18.jpg

下記より新規チャンネルを作成します。

スクリーンショット 2022-07-29 17.22.40.jpg

作成画面に行ったら上から下記の入力を行います。

  • チャンネルタイプ - Messaging API
  • プロバイダー - 先ほど登録した名前
  • 会社または所有の国 - Japan
  • チャンネルアイコン - 任意の画像
  • チャンネル名 - 任意の名前
  • チャンネルの説明 - 任意の説明
  • カテゴリー - Webサービス
  • サブカテゴリー - Webサービス

登録が完了したら下記のような画面が表示されます。

スクリーンショット 2022-07-29 17.31.54.jpg

Messaging APIのタブに切り替えるとQRコードが出てくるのでそこからLINE Botを自分のLINE上で登録することができます(まだ何も動きません)

スクリーンショット 2022-07-29 17.35.30.jpg

これでチャネルの作成はできたので、次にRailsアプリ側の準備をして行きます

LINE Messaging API SDKの準備

Railsの環境構築

該当のディレクトリ内で以下のコマンドを実行しRailsアプリを作成します。

rails new . --api

なおRubyおよびRailsの環境構築はできているものとして先に進めます。まだの方は各自環境構築を済ませてください。

LINE Messaging API SDK for Rubyのインストール

次に先程の図の下記の部分を行うためのgemをインストールします。

スクリーンショット 2022-07-29 17.46.08.jpg

LINE Messaging API SDKを利用することで簡単にLINE Botの開発をすることができます。

今回はRuby用に用意されているLINE Messaging API SDK for Rubyを利用します。

gemファイルに下記の記述を行います。

Gemfile
gem 'line-bot-api'

記述ができたら下記のコマンドでインストールを実行します。

bundle install

ルーティングの設定

次にLINEプラットフォームらか送信されるリクエストをRails側で受信できるように設定します。

config/routes.rb
Rails.application.routes.draw do
  post 'callback' => 'line_bot#callback'
end

コントローラーの設定

次にルーターと紐付けられるための処理をコントローラーを作成します。

 rails g controller LineBot

下記のファイルが作られます。

app/controllers/line_bot_controller.rb

下記の値を入力します

app/controllers/line_bot_controller.rb
class LineBotController < ApplicationController
  def callback
  end
end

これでRails側の準備も完了したので、LINEから送信されたメッセージを受け取る準備を進めて行きます。

ngrokの利用

次にngrokを利用してローカルで作成したアプリを一時的に外部に公開できるように設定します。

Homebrewngrokをインストールします。

brew install ngrok

インストールしたら下記のコマンドでバージョンが出て来れば完了です。

ngrok --version

次にngrokのサイトに行ってアカウントを登録します。

登録が完了したらサイドメニューのYour Authtokenよりトークンを取得します。

スクリーンショット 2022-07-29 18.39.23.jpg

下記のコマンドを実行してPCとngrokアカウントを連携します。

ngrok authtoken 作成したトークン

これでngrokの準備が完了したので実行をして行きます。

下記のコマンドでローカル環境を立ち上げます。

 rails s

その上で下記のコマンドを実行しngrokを実行します。

自分はポート番号が3000なので3000で設定しました。

ngrok http 3000

実行後に表示されているURLが外部からアクセスできるURLになります。

Forwarding  https://xxxx -> http://localhost:3000

最初はアクセスをしてもエラーが表示されます。

こちらのエラーはRailsで設定されているサイバー攻撃対策の影響で出てしまっているので設定を変更します。

Rails側のセキュリティー設定

Railsで標準のセキュリティー設定がされているので、セキュリティー対策を無効にする設定を行います。

Railsのセキュリティーについての詳しい内容は公式ドキュメントを参考にしてください。

今回は結論コードだけを記載します。

config/environments/development.rb
 Rails.application.configure do
    # 省略
    config.hosts.clear
  end

以上でLINEプラットフォームからのPOSTリクエストのRailsで受け取れるようになったので連携を進めて行きます

LINEのチャネルとRailsの連携

次にRailsアプリとLINEチャネルの連携をしメッセージのやりとりをおこなえるように設定します。

LINEのチャネルでトークンを取得

スクリーンショット 2022-07-31 8.24.15.jpg

チャネル作成時に発行されるチャネルシークレットとチャネルアクセストークンを取得しRailsアプリと連携をしていきます。

LINE Developersを開き先ほど作成プロバイダーページを確認します。

タブをBasic settingsに切り替えて下の方にスクロールします。

スクリーンショット 2022-07-31 8.27.40.jpg

下までスクロールするとChannel secretAssertion Signing Keyという項目があるので値を確認します。

スクリーンショット 2022-07-31 8.28.30.jpg

次にタブをMessaging APIに切り替え下までスクロールさせます。

するとチャネルのアクセストークンを発行する箇所があるのでトークンの発行を行います。

スクリーンショット 2022-07-31 8.30.55.jpg

これでチャネルシークレットとチャネルアクセストークンの準備が完了したのでRails側で値を設定していきます。

Railsの設定

Rails側の環境変数に先ほど取得したアクセストークンを設定します。

まずが環境変数を管理するためのgemを入れていきます。

Gemfile
gem 'dotenv-rails'
bundle install

環境変数を定義するファイルを作成

touch .env

先ほど発行したシークレットとトークンを入れます。

.env
LINE_CHANNEL_SECRET='xxxxxxxx'
LINE_CHANNEL_TOKEN='xxxxxxxx'

LINE Messaging API SDKの準備

LINE Messaging API SDKではLINE Botの処理を行うためのLine::Bot::Clienというクラスがあらかじめ用意されているので、このクラスをインスタンス化し、メッセージの解析と返信機能を作成していきます。

記述法についてはこちらを参考に書いてきます。

app/controllers/line_bot_controller.rb
class LineBotController < ApplicationController

  def callback
  end

  private
 
  def client
    @client ||= Line::Bot::Client.new { |config|
      config.channel_secret = ENV["LINE_CHANNEL_SECRET"]
      config.channel_token = ENV["LINE_CHANNEL_TOKEN"]
    }
  end
end

この記述によってLine::Bot::Clientクラスがインスタンス化できました。

LINEチャネルにRailsアプリを登録する

環境変数を元にRails側におけるチャネルとの連携は完了したので、次にチャネル側でRailsアプリを連携させていきます。

タブをMessaging APIに変えてWebhook URLに先ほどngrokで取得したURLを入れます。

Use WebhookもONに設定します。

スクリーンショット 2022-07-31 22.50.25.jpg

※ なおngrokから取得できるURLは有効期限があるので、ngrokを起動する度にURLの更新をする必要があります。

最後にLINE Botにメッセージを送った際に返信されるオートメッセージを無くす設定をします。

スクリーンショット 2022-07-31 9.44.38.jpg

遷移先で下記のように設定をします。

スクリーンショット 2022-07-31 9.46.01.jpg

これで準備は完了したのでユーザーが送信したメッセージをそのまま返すオーム返し機能を実装していきます。

LINEからRailsに送られてくるメッセージを確認する

Rails側のコントローラにコードを追加し、LINEから送信されたメッセージをRails側で確認できるようにします。

app/controllers/line_bot_controller.rb
class LineBotController < ApplicationController
  def callback
    
    puts "======="
    puts body = request.body.read
    puts "======="
  end

  private
 
  def client
    @client ||= Line::Bot::Client.new { |config|
      config.channel_secret = ENV["LINE_CHANNEL_SECRET"]
      config.channel_token = ENV["LINE_CHANNEL_TOKEN"]
    }
  end
end

この記述を書いた上でLINEでメッセージを送信してみます。

スクリーンショット 2022-07-31 22.55.02.jpg

するとコマンドライン上で下記のようにメッセージを取得できていることを確認できます。
スクリーンショット 2022-07-31 22.57.20.jpg

次に実際にLINEから届いたメッセージをそのまま返信するような実装をしていきます。

callbackメソットをGitHubを参考に下記のように書き換えます。

app/controllers/line_bot_controller.rb
  def callback
    body = request.body.read
    events = client.parse_events_from(body)
  end
  • parse_events_fromで引数にbodyを入れることでevents配列を取得できます

実際にevents配列の中は下記のようなデータが入ってきています。(messageの部分のみ表示)

"{
  "events":
  [
    {
    // 省略
      "message":
      {
        "type":"text",
        "id":"xxxxxxxxx",
        "text":"Hello world"
      }
    }
  ],
}"

eventsは配列なのでeachメソットを利用しmessage["text"]を取得しLINEから送信されてきたメッセージを取得します。

app/controllers/line_bot_controller.rb
  def callback
    body = request.body.read
    events = client.parse_events_from(body)
    events.each do |event|
      case event
      when Line::Bot::Event::Message
        case event.type
        when Line::Bot::Event::MessageType::Text
          message = {
            type: "text",
            text: event.message["text"]
          }
          client.reply_message(event['replyToken'], message)
        end
      end
    end
  end

コードを詳しく解説していきます。
まず下記のコードでループされているeventLine::Bot::Event::Messageクラスであるかのチェックをしています。

    events = client.parse_events_from(body)
    events.each do |event|
      case event
      when Line::Bot::Event::Message
        case event.type
        when Line::Bot::Event::MessageType::Text

こちらの処理でLINEから受けととったイベントがメッセージイベントかをチェックしています。

なお、メッセージイベント以外については公式ドキュメントに掲載されているので確認してみてください。

次に実際にメッセージだった場合に受信したtextの値をmessageというハッシュに格納します。

また応答トークンを利用して返信機能を付与しています。

        case event.type
        when Line::Bot::Event::MessageType::Text
          message = {
            type: "text",
            text: event.message["text"]
          }
          client.reply_message(event['replyToken'], message)
        end

応答トークンの処理については下記を参考にしてみてください。

実際でLINEでメッセージを送信するとデータが返ってきていることを確認できます。

スクリーンショット 2022-07-31 23.37.37.jpg

目標物の開発

ここまででLINE Bot開発の基礎を学んできました。

ここからは今回の目標物である「通勤時にQiitaのトレンド記事が届くLINE Bot」の開発を進めていきます。

機能としては下記のようになっています。

  • LINE Botに対して「出勤なう」というメッセージを送るとトレンド記事が届く

なおQiitaのトレンド記事はQiita公式APIでは取得できないので、非公式で作られているQiitaトレンドAPIを利用します。

実装方針

目標物は下記の手順で実装していきます

  1. RailsからLINEへ複数メッセージが送れるように設定
  2. RailsでQiitaのトレンドAPIを叩いてレスポンスデータを取得
  3. 出勤なう」というメッセージが来たタイミングでLINEへレスポンスを返す

さっそく実装の方を進めていきます。

RailsからLINEへ複数メッセージが送れるように設定

まずはRailsからLINEへ複数メッセージを送る記述法を確認します。

先ほど実装していたclient.reply_messageの記述において第二引数で渡すメッセージを配列のオブジェクト形式にすることで複数のメッセージをLINEへ送信することができます。

app/controllers/line_bot_controller.rb
    message = [{type: "text", text: "メッセージ1"}, {type: "text", text: 'メッセージ2'}]
    client.reply_message(event['replyToken'], message)

LINEが確認するとメッセージが2つ受信されていることを確認できます。

スクリーンショット 2022-08-02 8.22.12.jpg

つまりQiitaトレンドAPIを叩いてトレンド記事のURLを取得し、ハッシュとして格納することで複数のトレンド記事のURLを作成します。

RailsでQiitaのトレンドAPIを叩いてレスポンスデータを取得

次にQiitaトレンドAPIを叩いてURLを取得しLINEアプリへ送信するデータを作成します。

目標の形は下記のようになります。

app/controllers/line_bot_controller.rb
    message = [{type: "text", text: "トレンドURL1"}, {type: "text", text: 'トレンドURL2'}]
    client.reply_message(event['replyToken'], message)

Net::HTTP.get_responseを利用してQiitaトレンドAPIを叩いてデータを取得します。

下記の記述を追加しLINEのメッセージが送信されたタイミングでQiitaトレンドAPIからデータが取得されているかを出力してみます。

app/controllers/line_bot_controller.rb
    when Line::Bot::Event::MessageType::Text
        uri = URI('https://qiita-api.vercel.app/api/trend')
        res = Net::HTTP.get_response(uri)
        puts res.body if res.is_a?(Net::HTTPSuccess) # 出力の確認
          message = [
            {type: "text", text: "メッセージ1"}, {type: "text", text: 'メッセージ2'}
          ]
          client.reply_message(event['replyToken'],  message)
      end

ターミナルを確認するとQiitaのトレンドAPIのデータが表示されていることを確認できます。

スクリーンショット 2022-08-02 8.38.33.jpg

この中からlinkの値だけを取り出します。試しにレスポンスデータの1番目の値のトレンド記事URLを取得します。

    uri = URI('https://qiita-api.vercel.app/api/trend')
    response = Net::HTTP.get_response(uri)
    response = JSON.parse(response.body)
    puts "==========="
    p response[0]["node"]["linkUrl"] //  # 出力
    puts "==========="

下記のようにデータが取得できていることを確認できます。
スクリーンショット 2022-08-02 9.00.56.jpg

実際にループしてLINEに返すメッセージを作成します。

    uri = URI('https://qiita-api.vercel.app/api/trend')
    response = Net::HTTP.get_response(uri)
    response = JSON.parse(response.body)
    # LINEへ返すレスポンス
    message = []
    # トレンド上位5記事のみ抽出
    5.times {|i|
      hash = {}
      hash[:type] = "text"
      hash[:text] = response[i]["node"]["linkUrl"]
      message.push(hash)
    }
    client.reply_message(event['replyToken'],  message)
  • message = []でLINEに返すデータの初期値を準備しています
  • 5.timesトレンドの上位5記事を取得するため5回ループさせます
  • hash[:text] = response[i]["node"]["linkUrl"]でトレンドi位のULRを取得
  • message.push(hash)で取得したデータを配列に追加

実際に確認するとデータが返ってきています。

IMG_7061.jpg

出勤なう」というメッセージが来たタイミングでLINEへレスポンスを返す

最後にLINE側から「出勤なう」という文言が送られてきた場合のみレスポンスを返すように条件分岐を付与します。

app/controllers/line_bot_controller.rb
  def callback
    body = request.body.read
    events = client.parse_events_from(body)
    events.each do |event|
      case event
      when Line::Bot::Event::Message
        case event.type
        when Line::Bot::Event::MessageType::Text
          # ユーザーからのメッセージが「出勤なう」だった場合のみにメッセージを返す
          if event.message["text"] == "出勤なう"
            uri = URI('https://qiita-api.vercel.app/api/trend')
            response = Net::HTTP.get_response(uri)
            response = JSON.parse(response.body)
            # LINEへ返すレスポンス
            message = []
            # トレンド上位5記事のみ抽出
            5.times {|i|
              hash = {}
              hash[:type] = "text"
              hash[:text] = response[i]["node"]["linkUrl"]
              message.push(hash)
            }
            client.reply_message(event['replyToken'],  message)
          end
        end
      end
    end
  end

実際に挙動を確認してみましょう。

IMG_7062.jpg

データが返ってきました。

以上で目標物が完成しました。

最後に

いかがだったでしょうか。今回はチュートリアル形式でLINE Botの開発をしました。

今回は返信メッセージにスタイルを当てていないのでそのままURLが表示される形式なっていますが、Flex Messageを利用することでこの辺もカスタマイズできそうなので挑戦したいと思います。

加えて時間設定で自動で出勤時間にメッセージが届く挙動にできるようにアップデート等も加えていけたらなと思っています。

この辺ができた上で一般には公開する予定です。(現状だと公開するのが恥ずかしい笑)

ぜひこの記事を参考にLINE Bot開発や個人開発に挑戦していただけたらなと思います。

他にもいろいろ記事を書いているので読んでいただけると嬉しいです。

139
136
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
139
136