LINE BOTを動かす環境を調べてみた
1万人限定に反応してアカウントを作ってしまったので、
とりあえずbotを動かしてみるところまでやってみた
今回のbot環境を構築するにあたってSSL対応と固定IPが必要という2点が悩みどころ
現状トライアルなので、できるだけ安く、できれば無料で環境構築をしたい
ということで、以下の二つを試してみた
AWS Lambda + API Gateway
API Gatewayはデフォルトでhttpsなので
SSLの点では良さそうと最初に思い試してみた
詳細な実装方法はこちらの記事が参考になる
AWS Lambda + API GatewayでLINE BOT APIを叩いてみた
ただし、API GatewayはIPを固定できないので時間が経つと変わってしまう
別途プロキシをEC2なりで立てる必要が出てくるので今回は諦めた
Heroku + fixie
最終的にこの形に落ち着いた
HerokuはSSLにも対応している
さらに、fixieというアドオンを使ってプロキシを挟むことでIPの固定化もできる
しかも最小構成なら無料という素晴らしさ
awsの世界でサーバーレスっていうのも捨てがたいけど、
herokuの場合はnodeとかpyton以外も使える自由度もあるし、
これが今のところ一番良さそうかなと思っている
以下、ruby(sinatra)+HerokuでのLine Bot環境構築手順のメモ
heroku環境を構築する
herokuを利用するのが初めての場合は以下からアカウントを作成
https://www.heroku.com/
続いてherokuをコマンドラインから扱うためのheroku toolbeltをインストール
https://toolbelt.heroku.com/
上記リンクのgetting startに従ってログインから試してみる
$ heroku login
=> 途中でemailとpasswordを要求され、ログインする
とりあえずアプリをデプロイしてみる
$ mkdir firstsample && cd $_
$ heroku create
成功するとgitのURLとサイトURLが出力されるのでサイトURLへブラウザからアクセスしてみる
Heroku | Welcome to your new app!
みたいな文言が出るページが表示される
これでheroku上にアプリを公開する準備が整った
sinatraアプリを作成する
Gemfileを生成
bundle init
Gemfileに書きを追加
gem 'sinatra'
sinatraをインストール
bundle install --path vendor/bundle
シンプルなアプリをapp.rbに記述
# coding: utf-8
require 'sinatra'
get '/' do
  'hello!'
end
ローカルで起動してみる
bundle exec ruby app.rb
ブラウザでアクセス、localhost:4567にアクセス、helloが表示されればOK
アプリをHerokuに公開する
herokuでsinatraを起動するためにProcfileを追加
# Procfile
web: bundle exec ruby app.rb -p $PORT
gitを設定
git init
herokuのリモートリポジトリを設定(heroku createした時に出力されたgitのURL)
heroku git:remote -a xxxxx
# 確認
git remote -v
=> set git remote heroku to https://git.heroku.com/xxxxx.git
gitignore設定
.DS_STORE
*.swp
/Gemfile.lock
/vendor/
/.bundle
作成したファイルをgitにコミット
git add
git commit -m "initial commit"
herokuのリモートリポジトリにpush
git push heroku master
成功すると以下のようなメッセージが表示される
~ 中略 ~
remote:        https://xxxxx.herokuapp.com/ deployed to Heroku
~ 中略 ~
表示されたURLにアクセスして先ほどのhelloが表示されればデプロイ完了
fixieで固定IP対応(プロキシ)
herokuのアドオンを使用する場合は無料のアドオンしか使わなくても最初にクレジットカードの登録が必要になる
こんなエラーメッセージが出る
Please verify your account to install this add-on plan (please enter a credit card) For more information, see https://devcenter.heroku.com/categories/billing Verify now at https://heroku.com/verify
カード情報を登録後以下のコマンドを実行するとアドオンが追加されてIPアドレスが表示される
$ heroku addons:create fixie:tricycle
=> Your IP addresses are xx.xx.xx.xx, xx.xx.xx.xx
表示されたIPアドレスをLINE DevelopersのServer IP Whitelistに追加する
LINE BOTを実装する
最初にLine developersのbotのcallbackURLに
herokuで作成したアプリのURLを設定する
サンプルはとりあえずオウム返し
# coding: utf-8
require 'sinatra'
require 'json'
require 'base64'
require 'net/https'
require 'uri'
post '/' do
  channel_secret = "自分のChannel Secret"
  http_request_body = request.body.read
  hash = OpenSSL::HMAC::digest(OpenSSL::Digest::SHA256.new, channel_secret, http_request_body)
  signature = Base64.strict_encode64(hash)
  # requestヘッダを取得
  http_headers = request.env.select { |k, v| k.start_with?('HTTP_')}
  if signature != http_headers["X-LINE-CHANNELSIGNATURE"]
    {status: :error}.to_json
  end
  params = JSON.parse http_request_body
  from = params["result"][0]["content"]["from"]
  text = params["result"][0]["content"]["text"]
  # リクエストヘッダ
  request_headers = {
      "Content-Type" => "application/json",
      "X-Line-ChannelID" => "自分のChannelID",
      "X-Line-ChannelSecret" => channel_secret,
      "X-Line-Trusted-User-With-ACL" => "自分のMID"
  }
  # リクエストボディ
  request_params = {
      "to" => [from],
      "toChannel" => 1383378250, # 固定値
      "eventType" => "138311608800106203", # 固定値
      "content" => {
          "contentType" => 1,
          "toType" => 1,
          "text" => text
      }
  }
  # message send endpoint
  uri = "https://trialbot-api.line.me/v1/events"
  uri_parsed = URI.parse uri
  # ref : https://devcenter.heroku.com/articles/fixie
  _, username, password, host, port = ENV["FIXIE_URL"].gsub(/(:|\/|@)/,' ').squeeze(' ').split
  # fixieのproxy情報とline botのendpoint情報をセット
  http = Net::HTTP.new(uri_parsed.host, uri_parsed.port, host, port, username, password)
  http.use_ssl = true
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE
  http.post(uri_parsed.path, request_params.to_json, request_headers)
  data = {status: 'OK'}
  data.to_json
end
LINE Developers のBot Channelsページの下の方にある
QRを使ってbotをLINEで友達追加してbotに話しかけてみる
botからレスがくれば無事成功
気づいたらLine Botの説明というよりHerokuの使い方説明になってしまった。。。