フリーランス 技術調査ブログ

フリーランス/エンジニア Ruby Python Nodejs Vuejs React Dockerなどの調査技術調査の備忘録

Rails環境でLineBotAPIを実装する

LineBotAPIを実装する

LINE Developerの登録と設定

  • LINE Developerに登録して、MessageAPIを利用する設定をする f:id:PX-WING:20200211235214p:plain
  • チャンネルを登録すると、チャンネル情報を取得できる(channel_id・channel_secretの情報) f:id:PX-WING:20200211235248p:plain
  • channel_tokenのトークンを取得する f:id:PX-WING:20200211235244p:plain

環境構築 (docker-composeを使用する)

version: '3'
services:
  db:
    image: postgres
    volumes:
      - ./tmp/db:/var/lib/postgresql/data
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid &&  bundle install --path vendor/bundle && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db
  nginx-ssl:
    build:
      context: ./
      dockerfile: ./frontend/Dockerfile
    container_name: frontend-ssl
    volumes:
     - ./frontend/:/srv/wwww/src/
    ports:
      - 80:80
      - 443:443

Rails Dockerfile

FROM ruby:2.7
RUN apt-get update -qq && apt-get install -y nodejs postgresql-client
RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
COPY . /myapp

# Add a script to be executed every time the container starts.
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

# Start the main process.
CMD ["rails", "server", "-b", "0.0.0.0"]

nginx Dockerfile

  • LINE APIを利用する際にSSL通信が必要なため、NginxにLet's EncryptをインストールしてSSL環境を構築する
FROM alpine:latest

## Install Nginx
RUN apk --update add nginx && rm -rf /var/cache/apk/*
RUN chmod 755 /var/lib/nginx /var/lib/nginx/tmp
RUN mkdir -p /run/nginx
ADD ./frontend/nginx/config.d/default.conf /etc/nginx/conf.d/
ADD ./frontend/nginx/config.d/default.ssl_conf /etc/nginx/conf.d/

## Install certbot
RUN apk add certbot
RUN apk add openssl

RUN mkdir -p /srv/wwww/src/
ADD ./frontend/index.html /srv/wwww/src/

## SSL証明書インストールは下記のコマンドをDocker起動後に実行しました。
#RUN nginx
#RUN certbot certonly -n --keep-until-expiring --agree-tos --webroot -w /srv/wwww/src/ -d yourdomein-m your mailaddress

## start shell
COPY ./frontend/start.sh /start.sh
RUN chmod +x /start.sh

RUN apk add yarn

CMD ["sh", "/start.sh"]

Railsの実装

  • Gmefile
gem 'line-bot-api'
  • routesの設定
Rails.application.routes.draw do
  post '/lines/callback', to: 'lines#callback'
end
  • コントローラーの実装
require 'line/bot'

class LinesController < ApplicationController
  before_action :set_line, only: [:show, :edit, :update, :destroy]
  protect_from_forgery with: :null_session 

  def callback
    @client ||= Line::Bot::Client.new { |config|
      config.channel_id = "<チャンネルIDを指定>"
      config.channel_secret = "シークレットを指定"
      config.channel_token = "トークンIDを指定"
    }

    body = request.body.read

    signature = request.env['HTTP_X_LINE_SIGNATURE']
    unless @client.validate_signature(body, signature)
      error 400 do 'Bad Request' end
    end

    events = @client.parse_events_from(body)
    events.each do |event|
      case event
      when Line::Bot::Event::Message
        case event.type
        when Line::Bot::Event::MessageType::Text
          message = {
            type: 'text',
            text: event.message['text']
          }
          @client.reply_message(event['replyToken'], message)
        when Line::Bot::Event::MessageType::Image, Line::Bot::Event::MessageType::Video
          response = @client.get_message_content(event.message['id'])
          File.binwrite("/myapp/public/hogehoge.jpg", response.body)
          message = {
            type: 'image',
            originalContentUrl: "https://yourdomain/hogehoge.jpg",
            previewImageUrl: "https://yourdomain/hogehoge.jpg"
          }
          @client.reply_message(event['replyToken'], message)
        end
      end
    end
    "OK"
  end
end

所感

  • 環境構築が手間だが実装自体は簡単にできました。
  • 画像のURLを返す際は常にユニークした方がよい。プレビューの画像がキャッシュが強すぎて、ファイル名を変えないと常に同じ画像が表示され続けるので注意した方がよいです。