Lambda@RubyでサーバーレスLINE BOTを作ってみた


みなさま、はじめまして！
この記事はエイチームブライズ/エイチームコネクト/エイチーム引越し侍 Advent Calendar 2018　22日目の記事です。
22日目はインフルエンザ予防接種でフラフラの、エイチーム引越し侍@ysysysysが担当いたします。

# 概要
さて、ご存知のようにさる先月末からAWS LambdaでRubyがつかえるようになりました。RubyおよびRailsからプログラミングの世界に迷いんこんだ私としては嬉しい限りです。ということで今回はLambda@RubyでLINE Messaging APIを動かしてみます。

#下準備
## LINE Messaging API
Messaging APIの概要は[こちら](https://developers.line.biz/ja/services/messaging-api)から
公式のドキュメント通りにアカウント、channelを作成し設定します。
Channel Secretとアクセストークンは使用するので控えておきましょう。
![スクリーンショット 2018-12-22 2.37.42.png](https://qiita-image-store.s3.amazonaws.com/0/308953/c87315a2-14e1-a881-1bdf-6b222ac2e8b2.png)
![スクリーンショット 2018-12-22 2.37.27.png](https://qiita-image-store.s3.amazonaws.com/0/308953/2fb5c3b5-9ed2-468d-4f95-c9f37cf0f57d.png)


## AWS Lambda
AWSで提供されているLambdaというサービスは、サーバーいらずで任意のプログラムを実行できる優れものです。
BOTを動かすにはweb上になんらかの実行環境が必要です。
通常であればVPSを立てるなり、HerokuなどのPaasなどを使う必要がありますが、Lambdaはコンソールにソースコードを書くだけで簡単に実行環境を手に入れることができるのです。

それではLambdaの設定をしていきます。
AWSのコンソール画面からLambdaを探し出してください。
作成画面から次のように設定しました。

<img width="1355" alt="スクリーンショット 2018-12-21 22.34.10.png" src="https://qiita-image-store.s3.amazonaws.com/0/308953/5867a0cc-8557-c9dc-fff2-2890cd1217e5.png">
ランタイムはもちろん「Ruby2.5」です。

続いてLambdaを発火させるトリガーを設定します。
今回はMessaging APIからHTTPリクエストを受けつけるためにAPI Gatewayを使用します。

下記のように左のメニューからAPI Gatewayを選択します。
<img width="1339" alt="スクリーンショット 2018-12-21 22.34.58.png" src="https://qiita-image-store.s3.amazonaws.com/0/308953/08021029-5dc1-842f-6dfb-471556bb4343.png">


「必要な設定」から下記のように設定しました。
<img width="1426" alt="スクリーンショット 2018-12-21 22.22.16.png" src="https://qiita-image-store.s3.amazonaws.com/0/308953/360ce7b3-44ce-5e2d-aee8-90cf4372236e.png">

さらに進みAPIの設定を続けます。
リソースを作成します。
<img width="1149" alt="スクリーンショット 2018-12-22 1.50.23.png" src="https://qiita-image-store.s3.amazonaws.com/0/308953/df5051f3-fe95-7404-fe05-b61e92b9c293.png">

Messaging API側からのリクエストはPOST形式で送られてきます。したがって下記のように「リソースのアクション」からPOSTメソッドを追加します。
<img width="1245" alt="スクリーンショット 2018-12-21 22.35.38.png" src="https://qiita-image-store.s3.amazonaws.com/0/308953/37c00404-b450-5153-9cb5-acb750278158.png">


Lambda関数の部分には先ほど作成した「line_bot」を入れておきます。

保存したらAPIをデプロイします。
<img width="358" alt="スクリーンショット 2018-12-22 0.55.28.png" src="https://qiita-image-store.s3.amazonaws.com/0/308953/b266463c-33e3-6b7b-917f-41a7fecf4a5a.png">
<img width="613" alt="スクリーンショット 2018-12-22 0.55.44.png" src="https://qiita-image-store.s3.amazonaws.com/0/308953/5f51e2c5-bb9b-a5db-d994-356f6ac9d19b.png">
表示されるURLは後ほどMessaging APIのwebhookに登録します。
<img width="907" alt="スクリーンショット 2018-12-22 2.45.45.png" src="https://qiita-image-store.s3.amazonaws.com/0/308953/07c85de4-abf1-a305-bcca-aa189fc4ddc7.png">


これで一通りの下準備は終了です。

# ソースコード
いよいよLambdaにコードを書いていきます。
再びLambdaの画面にいきます。
<img width="1306" alt="スクリーンショット 2018-12-21 23.14.07.png" src="https://qiita-image-store.s3.amazonaws.com/0/308953/bbdbfaee-2d03-dd6b-ea92-b11333732575.png">

ご覧の通りコンソール画面からコードを直接書くことができます。
ですが今回は簡単にLINE側とのやり取り行いためGemを使いたいです。
その場合はローカルでGemのインストールとコーディングを済ませてからZipファイルでLambdaにアップします。

せっかくなので開発はAWS Cloud9からやってみます。
Cloud9のページから「create environment」へ
<img width="1064" alt="スクリーンショット 2018-12-21 23.12.02.png" src="https://qiita-image-store.s3.amazonaws.com/0/308953/fcb44eb0-32fb-02c8-fb3e-c454c4261d04.png">


２ページほどの簡単な設定をすませると開発環境がブラウザ上に立ち上がります。

下部のコンソールから

```
bundle init
```
Gemfileが生成されたら下記を追記。

```Gemfile
gem 'line-bot-api'
```

その後Gemをvendor以下にインストールします。

```
bundle install --path vendor/bundle
```

あとは[こちら](https://github.com/line/line-bot-sdk-ruby)を参考におうむ返しするBOTをコーディングしていきます。

```line_bot.rb
  require 'line/bot'

  def handler(event:, context:)
    body = event["body"]
    signature = event["headers"]["X-Line-Signature"]
    unless client.validate_signature(body, signature)
      error 400 do 'Bad Request' end
    end
    requests = client.parse_events_from(body)
    requests.each do |req|
      case req
      when Line::Bot::Event::Message
        case req.type
        when Line::Bot::Event::MessageType::Text
          mes = req.message['text']
          token = req['replyToken']
          message = {
            type: 'text',
            text: mes
          }
          client.reply_message(token, message)
        end
      end
    end
  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
```
書き終わったらvendor以下とスクリプトファイルをzipに圧縮します。

```
zip -r linebot.zip vendor line_bot.rb 
```
あとはコンソール上部のメニューからプロジェクトをダウンロードして一旦ローカルに落としましょう。
<img width="397" alt="スクリーンショット 2018-12-22 2.24.27.png" src="https://qiita-image-store.s3.amazonaws.com/0/308953/943bf6d0-587a-d35b-a182-3d69f8c57e0c.png">

zipをアップロード。
<img width="550" alt="スクリーンショット 2018-12-22 0.47.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/308953/4abe9eee-0efa-a0ad-5216-e2010f6e5e8e.png">
これでコンソールにコードが表示されているはずです。

次いで環境変数を設定します。
<img width="1303" alt="スクリーンショット 2018-12-22 2.34.35.png" src="https://qiita-image-store.s3.amazonaws.com/0/308953/b5a62101-0f48-7d28-8d9f-4bfb06cf7a15.png">
ついでにハンドラの設定も`line_bot.handler`に変えてやります。

さて、これで実装が終わりました。

##### ※注
なかなか動かず小一時間悩んでいたのですが、原因はCloud9のRubyのバージョンが2.4だったからでした。
無理やりvendor配下のディレクトリ名を変更してごまかしています、、
<img width="168" alt="スクリーンショット 2018-12-22 0.57.10.png" src="https://qiita-image-store.s3.amazonaws.com/0/308953/d7473f6a-b71c-9411-c326-871dae0a215d.png">

# 動かしてみる
Messaging APIのチャンネル基本設定画面からwebhookURLを登録します。
接続確認をして成功しましたと出ればOKです。
![スクリーンショット 2018-12-22 0.56.56.png](https://qiita-image-store.s3.amazonaws.com/0/308953/f1cc23fe-6662-e6e0-2f97-17bde472b6ae.png)
BOTを友達登録して、LINEを送ります。
<img width="200" src="https://qiita-image-store.s3.amazonaws.com/0/308953/ac3fbe64-ec3f-5262-08f0-98f83eeb69d8.jpeg">
無事おうむ返ししてくれました。にしても時間帯よ、、、

# お知らせ
エイチームグループでは一緒に活躍してくれる優秀な人材を募集中です。
興味のある方はぜひとも[エイチームグループ採用ページ](http://www.a-tm.co.jp/recruit/)（[Webエンジニア詳細ページ](http://www.a-tm.co.jp/recruit/requirements/career/lifestylesupport-webengineer/)）よりお問い合わせ下さい。

#最後に
明日のAdvent Calender23日目は@GakuYasuiさんがDAppsのことについて書いていただけるみたいです（初めて聞いた）。ブロックチェーン関連のことのようですがどのようなことを教えていただけるのでしょうか？？みなさんお楽しみに！