Serverless + Ruby で作る LINE Bot

まずLINE Developers にて Messaging API でチャネルを作成する。

LINE周りは、1時間でLINE BOTを作るハンズオン (資料+レポート) in Node学園祭2017 #nodefestなどを参考にすると良いと思う。Qiitaにいろいろ記事があるので誰でも作れるはず。

流れとしては下記のような形になる。
プロバイダー作成→Messaging APIでチャネル作成→アクセストークン発行、「Webhook送信」を「利用する」に設定、「LINE@機能」全て「利用しない」に設定。

* 2019年1月4日時点では「Webhook送信」を「利用する」に設定しても反映されないバグがある模様。リロードすると、「利用しない」に戻っていることがある。接続確認は動いてしまうようなので注意。

WebhookURLは後ほど設定する。

lambdaがruby対応したので今更ながらlambdaでrubyを使ってみる。

上記リンク先の作業に続けて行う。

bundle init

上記コマンド実行後、生成されたGemfileに下記を追加する。

gem 'line-bot-api', '~> 1.3'

その後下記コマンドを実行する。

bundle install --path vendor/bundle

serverless.ymlは下記のような形に変更する。secret.ymlファイルからLINEのシークレットやトークンを読み込む形にしてある。

service: aws-ruby-example  

provider:  
  name: aws  
  runtime: ruby2.5  
  region: ap-northeast-1  
  stage: ${opt:stage, self:custom.defaultStage}  
  environment:  
    LINE_CHANNEL_SECRET: ${self:custom.lineChannelSecret.${self:provider.stage}}  
    LINE_CHANNEL_ACCESS_TOKEN: ${self:custom.lineChannelAccessToken.${self:provider.stage}}  

custom:  
  defaultStage: dev  
  lineChannelSecret:  
    dev: ${file(./secret.yml):lineChannelSecret.dev}  
    prod: ${file(./secret.yml):lineChannelSecret.prod}  
  lineChannelAccessToken:  
    dev: ${file(./secret.yml):lineChannelAccessToken.dev}  
    prod: ${file(./secret.yml):lineChannelAccessToken.prod}  

functions:  
  handle:  
    handler: handler.handle  
    memorySize: 128  
    events:  
      - http:  
          path: handle  
          method: post

handler.rbは下記のような形に変更する。Follow時、Join時に特定のメッセージを返し、メッセージが送られてきた場合にオウム返しする実装。

require 'json'  
require 'line/bot'  

def client  
  @client ||= Line::Bot::Client.new do |config|  
    config.channel_secret = ENV["LINE_CHANNEL_SECRET"]  
    config.channel_token = ENV["LINE_CHANNEL_ACCESS_TOKEN"]  
  end  
end  

def reply_text(event, text)  
  client.reply_message(  
    event['replyToken'],  
    { type: 'text', text: text }  
  )  
end  

def handle_message(event)  
  case event.type  
  when Line::Bot::Event::MessageType::Text  
    reply_text(event, event.message['text'])  
  else   
    reply_text(event, "I don't know.")  
  end  
end  

def handle(event:, context:)  
  body = event['body']  
  signature = event['headers']['X-Line-Signature']  
  return { statusCode: 400 } unless client.validate_signature(body, signature)  

  events = client.parse_events_from(body)  
  events.each do |_event|  
    case _event  
    when Line::Bot::Event::Message  
      handle_message(_event)  
    when Line::Bot::Event::Follow  
      reply_text(_event, "Thank you for following")  
    when Line::Bot::Event::Join  
      reply_text(_event, "Thank you for joining")  
    end  
  end  

  { statusCode: 200 }  
end

色々したい場合には、kitchensinkを参考にすると良いと思う。
Messaging APIリファレンスにコードも載っているのでリファレンスも参考にすると良いと思う。

secret.ymlファイルを生成して、下記のsecretとtokenをLINE developersから取得したものに変更する。

lineChannelSecret:  
  dev: dev_secret  
  prod: prod_secret  
lineChannelAccessToken:  
  dev: dev_token  
  prod: prod_token

下記コマンドを実行してデプロイする。

sls deploy

WebhookURLにAPI Gatewayから取得したURLを設定して完成。

完成後のものをgithubに載せた。
line-bot-for-aws-ruby-example

掃除は下記コマンド実行で行える

sls remove