hiko1129’s blog

開発に関することを記録するためのブログ

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は後ほど設定する。

hiko1129.hatenablog.com

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

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に載せた。 github.com

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

sls remove