LineBotAPIを実装する
LINE Developerの登録と設定
- LINE Developerに登録して、MessageAPIを利用する設定をする
- チャンネルを登録すると、チャンネル情報を取得できる(channel_id・channel_secretの情報)
- channel_tokenのトークンを取得する
環境構築 (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"]
gem 'line-bot-api'
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を返す際は常にユニークした方がよい。プレビューの画像がキャッシュが強すぎて、ファイル名を変えないと常に同じ画像が表示され続けるので注意した方がよいです。