Rails LINEbot 入門

Rails×LINEbotの実装方法と一連の処理の流れを説明しています。
※Railsに関しては一通り学習を終えていることが前提
# まず一連の処理の流れ
※WEBサーバは何でも問題ないですが、以下の例ではHerokuを使用している想定です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199854/5c12234e-4d74-c6e6-5648-79534b1747f8.png)

①LINEアプリで自分が作成したチャネルを友達登録し、メッセージを送信します。
②LINEのサーバではそのメッセージを受信し、チャネルに設定したWebhook URLにリクエストを送信します。
③リクエストを受信したRailsサーバは受信した内容を参照し、色々と処理をした結果、最終的にレスポンスとなるメッセージを作成します。
④レスポンスメッセージをLINEサーバに返します。
⑤LINEサーバがレスポンスメッセージをLINEアプリに返します。

# 一つずつ解説
## ①LINEアプリで自分が作成したチャネルを友達登録し、メッセージを送信します。
まずLINEbotを作るにはLINE Developersに登録する必要があります。

https://developers.line.biz/ja/

こちらから登録しましょう。
LINEアカウントがあればすぐに登録できます。

登録が終わったらまずしなければいけないことは

- プロバイダーの作成
- チャネルの作成

になります。

プロバイダーとは今回の場合、開発者(=自分)のことを指します。
チャネルは要するにメッセージを受け取るための公式アカウントです。

https://developers.line.biz/ja/docs/line-developers-console/overview/

こちらのドキュメントに[プロバイダーの作成](https://developers.line.biz/ja/docs/line-developers-console/overview/#provider)、[チャネルの作成](https://developers.line.biz/ja/docs/line-developers-console/overview/#channel)の説明がありますので、確認しながら作成してください。

※作成するチャネルの種類は「Messaging API」になります。

## ②LINEのサーバではそのメッセージを受信し、チャネルに設定したWebhook URLにリクエストを送信します。

さてチャネルを作成したので、LINEアプリから友達登録をしてみましょう。

LINE Developersコンソールから
トップ > プロバイダー名 > チャネル名 > Messaging API設定 > ボット情報

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199854/3be4ba78-8662-3617-f3ed-57e7ebb84783.png)
を表示すると ボットのベーシックID というのがあり、このIDをLINEアプリで検索することで友達追加することが可能です。

### 応答メッセージの無効化
現時点でメッセージを送信すると

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199854/c6d8c20a-739a-523b-8b49-9ed1b9e413de.png)
このようなメッセージが返ってくると思います。
今回のLINEbot作成では不要な機能なので、設定を変更します。

LINE Developersコンソールから
トップ > プロバイダー名 > チャネル名 > Messaging API設定 > LINE公式アカウント機能

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199854/a4749823-68da-917d-b020-4a367d669aa3.png)
応答メッセージを無効にします。

### Webhook設定
LINEサーバから自分が開発したWEBアプリにリクエストを送信するための設定をします。

LINE Developersコンソールから
トップ > プロバイダー名 > チャネル名 > Messaging API設定 > Webhook設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199854/1c3b1de1-599d-12c8-c4b9-1b4085f36b19.png)

Webhook URLの設定とWebhookの利用をONにします。
※「www.example.com」は自分が作成したアプリのURLを設定してください。
※この例ではcallbackアクションがLINEbotのリクエストの受付先となります。

## ③リクエストを受信したRailsサーバは受信した内容を参照し、色々と処理をした結果、最終的にレスポンスとなるメッセージを作成します。

次にRails側の実装をしていきたいところですが、先にLINEサーバに接続するためのアクセストークンを発行しましょう。

LINE Developersコンソールから
トップ > プロバイダー名 > チャネル名 > チャネル基本設定 > チャネルシークレット
チャネルシークレットを発行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199854/31da243b-b008-daee-48b7-54cf9a4fce35.png)

LINE Developersコンソールから
トップ > プロバイダー名 > チャネル名 > Messaging API設定 > チャネルアクセストークン
チャネルアクセストークンを発行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199854/b94fbd4c-6db9-09bf-0193-2fb15167e67d.png)

上記の

- チャネルシークレット
- チャネルアクセストークン

がLINEサーバに接続するために必要な情報になります。
こちらが漏洩すると自分が作成したチャネルを悪用されてしまうので、注意しましょう。

今度こそRailsの実装をしていきたいと思います。
公式の説明はこちらです。

https://github.com/line/line-bot-sdk-ruby


まず、Gemfileに

```Ruby
gem 'line-bot-api'
```

を追加してbundle installをしましょう。

最初にルーティングの設定をします。

```ruby
Rails.application.routes.draw do
  post '/callback', to: 'linebot#callback'
end
```

そしてコントローラを作成します。

```Ruby
class LinebotController < ApplicationController
  # LINEbotを使用するための設定を読み込み
  require 'line/bot'
  # CSRFトークン認証を無効
  protect_from_forgery :except => [:callback]
  
  def client
    # LINE APIクライアントのインスタンスをアクセストークンなどを使用して生成
    @client ||= Line::Bot::Client.new { |config|
      # アクセストークンは環境変数に設定
      # トップ > プロバイダー名 > チャネル名 > チャネル基本設定 > チャネルシークレット
      config.channel_secret = ENV["LINE_CHANNEL_SECRET"]
      # トップ > プロバイダー名 > チャネル名 > Messaging API設定 > チャネルアクセストークン
      config.channel_token  = ENV["LINE_CHANNEL_TOKEN"]
    }
  end
  
  def callback
    body = request.body.read
    signature = request.env['HTTP_X_LINE_SIGNATURE']
    
    # 開発環境でやると認証が通らないことがあったため、本番環境でのみ署名の認証を行う
    # (LINEアプリからの送信ということを示すための署名)
    if Rails.env.production?
      unless client.validate_signature(body, signature)
        head :bad_request
        return
      end
    end
    
    # LINEサーバから送信されてきたメッセージ、各種情報を取得
    events = client.parse_events_from(body)

    events.each { |event|
      case event
      when Line::Bot::Event::Message
        case event.type
        when Line::Bot::Event::MessageType::Text
          # 送信されてきたメッセージを取得
          received_msg = event.message['text']
          # 今回はオウム返し
          message = [
            {
              type: "text",
              text: received_msg
            }
          ]
          # ④レスポンスメッセージをLINEサーバに返します。
          client.reply_message(event['replyToken'], message)
        end
      end
    }

    head :ok
  end
end
```
あとはデプロイをして動作確認をしましょう。
※環境変数の設定を忘れずに！
## ⑤LINEサーバがレスポンスメッセージをLINEアプリに返します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199854/517debcc-bf31-ab08-9d57-719f42bf7880.png)

ここまでできたらアプリの完成です。
うまくできたでしょうか。

今回はただのオウム返しアプリになりますが、受信したメッセージの内容によって処理を分岐すれば色々なことができると思います。

私の場合は、毎日出社したときにあるものを提出しなければならず、非常に面倒だったので、LINEbotから送信して提出できるようにしました。

LINEであれば毎日開くのでついでにルーチンワークができるようになれば楽ですよね。

## テキストメッセージ以外の受信

前述のコントローラでは

``` Ruby
      case event
      when Line::Bot::Event::Message
        case event.type
        when Line::Bot::Event::MessageType::Text
```

このように受信した情報がどいうものなのかを判断しています。

公式情報の例を覗いてみると

https://github.com/line/line-bot-sdk-ruby/blob/HEAD/examples/kitchensink/app.rb

```ruby
  events.each do |event|
    case event
    when Line::Bot::Event::Message
      handle_message(event)

    when Line::Bot::Event::Follow
      reply_text(event, "[FOLLOW]\nThank you for following")

    when Line::Bot::Event::Unfollow
      logger.info "[UNFOLLOW]\n#{body}"

    when Line::Bot::Event::Join
      reply_text(event, "[JOIN]\n#{event['source']['type']}")

    when Line::Bot::Event::Leave
      logger.info "[LEAVE]\n#{body}"

    when Line::Bot::Event::Postback
      message = "[POSTBACK]\n#{event['postback']['data']} (#{JSON.generate(event['postback']['params'])})"
      reply_text(event, message)

    when Line::Bot::Event::Beacon
      reply_text(event, "[BEACON]\n#{JSON.generate(event['beacon'])}")

    when Line::Bot::Event::Things
      reply_text(event, "[THINGS]\n#{JSON.generate(event['things'])}")

    when Line::Bot::Event::VideoPlayComplete
      reply_text(event, "[VIDEOPLAYCOMPLETE]\n#{JSON.generate(event['videoPlayComplete'])}")

    when Line::Bot::Event::Unsend
      handle_unsend(event)

    else
      reply_text(event, "Unknown event type: #{event}")
    end
```

色々あるようですね。

- 友達追加したとき
- ブロックしたとき
- グループに追加したとき
- グループから削除したとき
- ファイルが送信されたとき

etc...

友達追加のタイミングでユーザー登録処理などを実装することも可能です。