51
27

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

GLOBISAdvent Calendar 2019

Day 18

Lineのやり取りをSlackに通知する

Last updated at Posted at 2019-12-18

この記事は GLOBIS Advent Calendar 2019 - Qiita の18日目です。

こんにちは、グロービスでエンジニアをしている @shifumin です。
皆さん、Lineを使っていますか? 僕は通知オフで使っています。理由は通知で集中力が切れるのが嫌だからです。
しかし、通知オフ設定だと送られたメッセージに長時間気づかずに怒られイベントがたまに発生しますよね? 僕はたびたび発生しています。
皆さん、Slackを使っていますか?使っていますよね。凝視していますよね。
Slackなら常に見ているから見逃さないんだけどなあ。

というわけで、多少矛盾を孕んでいますが、通知オフにしたLineで送られたメッセージをSlackに通知させるためのbotを作っていきたいと思います!

概要を3行で

  • 通知させたいLineグループにLine botをjoinさせてLine Messaging APIでメッセージを取得する
  • 上記で取得したメッセージをSlack botとしてSlackに通知する
  • botはRailsに乗せてHerokuで動かす

はい、やっていきましょう。

Line Messaging APIを利用する準備

Lineの送られてきたメッセージを取得するのに LINE Messaging API を利用します。

LINE Developersコンソールでチャンネルの作成とbotの設定を行います。
設定方法は公式のドキュメントが詳しいので、 Messaging APIを利用するにはボットを作成する を参考にするのが楽です。

botの作成まで終えた後に各種設定を変更します。

  • グループ・複数人チャットへの参加を許可する
    • オン
  • あいさつメッセージ(Greeting messages)
    • オフ
  • 応答メッセージ(Auto-reply messages)
    • オフ
  • Webhook
    • オン

それぞれの設定は下記画像左の Edit からいけます。
Image from Gyazo

Image from Gyazo
Image from Gyazo

Webhook設定はURLももちろん設定する必要があるのですが、これは後でHerokuでappを作成後に設定します。
設定後は下記の2つの値が必要になるため、メモります。
発行されていなければ、それぞれ Issue , Reissue から発行できると思います。

  • Channel secret (Basic settingsの中)
  • Channel access token (Messaging APi settingsの中)
    です。

Image from Gyazo
Image from Gyazo

botとフレンドになる

MessagingAPi > QR code にQRコードが表示されているのでbotをフレンド登録します。
また、複数人でのグループチャットを通知させたい場合はグループに招待します。

Slackの設定

続いて、SlackのApp設定とbot追加を行います。
https://api.slack.com/appsCreate New App からAppを作成します
まず、Appの名前と導入するWorkspaceを入力します。

Image from Gyazo

その後Appの設定をいくつか行う必要があります。

Image from Gyazo

Botの作成

  • Botsから Add a Bot User をクリックしてbotを作成する

Permissionsの設定

  • PermissionsをクリックしOAuth & Permissions画面へ移動する
  • OAuth Tokens & Redirect URLs > Install App to Workspace をクリックしてAppをインストールする
  • Scopesで下記のScopeを追加する
    • chat:write:bot
    • chat:write:user
    • files:write:user

Image from Gyazo

また、下記の値が必要になるため、メモります。

  • OAuth Access Token (OAuth & Permissions画面)

Image from Gyazo

Railsアプリ作成

ここからようやくBotの実装に進めていきます。

rails new

rails newまではよしなにやってください。
とりあえず最速でrails new。

# Railsをインストールまで
bundle init
vim Gemfile # Gemfileの `# gem "rails"` 行のコメントアウトを外す
bundle install

rails new は今回は画面描画系がいらないのでAPIモードかつ必要ないものを全てスキップしています。
参考: 小さく薄くrails newする(ViewやJSが必要ない場合) - Qiita

bundle exec rails new . --skip-yarn --skip-git --skip-action-mailer --skip-action-mailbox --skip-action-text --skip-active-record --skip-active-storage --skip-action-cable --skip-sprockets --skip-javascript --skip-turbolinks --skip-test --api --skip-bundle

SDKのインストール

Line、Slackそれぞれ公式が出しているSDKのgemを使います。
line-bot-apislack-ruby-client です。
この2つをGemfileに追加して bundle install します。

# Gemfile
# add
gem 'line-bot-api'
gem 'slack-ruby-client'
bundle install

コード実装

各SDKの設定

Slackは configure で設定できたので config/initializers/ 以下に設定を用意し、 Line::bot::Client はできなかったので仕方なくApplicationControllerでクライアントを作成する際に設定するようにしました。

# config/initializers/slack_ruby_client.rb
require 'slack'

Slack.configure do |config|
  config.token = ENV['SLACK_API_TOKEN']
end

Slack::Web::Client.configure do |config|
  config.user_agent = 'Slack Ruby Client/1.0'
end
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  private

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

  def slack_client
    @slack_client ||= Slack::Web::Client.new
  end
end

routes

Webhookはpostでリクエストが来るので、 /callback で受けて WebhookController#callbackに渡すようにしました。

# config/routes.rb 
Rails.application.routes.draw do
  post '/callback' => 'webhook#callback'
end

Blocked Hostの設定

Rails6から導入されたBlocked hostの設定は良しなにやってください。
今回はHerokuでdevelopmentで動かすかつ何も考えずに全開放ということで
下記のようにしています。
Rails6でrails newするのは今回が初めてでWebhookが届かないなあと記事を書くにあたりここでめっちゃ嵌った。嵌りポイント1

# config/environments/development.rb
Rails.application.configure do
  # 略
  config.hosts.clear
end

controller

line-bot-apislack-ruby-client のREADMEとサンプル実装を見ながらbotの本実装である WebhookController#callback を書いていきます。 今回は

  • メッセージが送られた場合はそのメッセージをそのままSlackに送る
  • 写真が送られてきた場合はその写真を保存して(Herokuなのでそのうち消えるけど)、Slackにアップロードする
  • ビデオ、スタンプの場合はそれぞれが送られてきた旨のメッセージを送る

ようにしました。

# app/controllers/webhook_controller.rb
class WebhookController < ApplicationController
  CHANNEL = '#{botに通知させるチャンネル名: 例: #hoge}'

  def callback
    body = request.body.read

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

    events = line_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
          post_message(event.message['text'])
        when Line::Bot::Event::MessageType::Image
          image_response = line_client.get_message_content(event.message['id'])
          file = File.open("/tmp/#{Time.current.strftime('%Y%m%d%H%M%S')}.jpg", 'w+b')
          file.write(image_response.body)

          slack_client.files_upload(channels: CHANNEL,
                                    file: Faraday::UploadIO.new(file.path, 'image/jpeg'),
                                    as_user: true,
                                    title: File.basename(file.path),
                                    filename: File.basename(file.path),
                                    initial_comment: '写真が送信されました')
        when Line::Bot::Event::MessageType::Video
          post_message('ビデオが送信されました。')
        when Line::Bot::Event::MessageType::Sticker
          post_message('スタンプが送信されました。')
        end
      end
    end

    head :ok
  end

  private

  def post_message(text)
    slack_client.chat_postMessage(channel: CHANNEL, text: text)
  end
end

Herokuのデプロイと設定

あとはHerokuでアプリを作成してデプロイして設定したら完了です。
アプリを作成してデプロイする方法はそこら辺に転がっているので割愛します。

環境変数の設定

上の方でメモっておいた下記の環境変数を設定します。

  • LINE_CHANNEL_SECRET
    • Lineの Channel secret
  • LINE_CHANNEL_TOKEN
    • Lineの Channel access token
  • SLACK_API_TOKEN
    • Slackの OAuth Access Token

Image from Gyazo

Dynoの起動

Dynoも忘れずに起動させます。
Herokuを触るのが久しぶりで起動を忘れていて、動いていないHerokuに対してWebhookを大量に空振りさせていた。嵌りポイント2

Image from Gyazo

Webhook URLの設定

最後にWebhook URLを設定したら完了です。
Settngs > Domains のURLを

Image from Gyazo

Line DevelopersコンソールのMessaging API > Webhook settingsのURLに設定します。
エンドポイントは /callback としているので忘れないようにします。

Image from Gyazo

実際の動作

グループにbotを招待してLineからメッセージを送ると下記のようにSlackに通知されます。
(左: Line, 右: Slack)

Image from Gyazo

また、Lineの通知をオフにしていても下記のような重要なメッセージを見逃すことが減ります
(なぜならSlackは見ているので)

Image from Gyazo

終わりに

今回はLineのやり取りをSlackに通知するbotを作ってみました。
公式で用意されているIntegration等でSlackとLineを直接繋ぐことはできないですが、それぞれのアプリがAPIとそのSDKを用意してくれているので、少しコードを書けばこの記事のようにそれぞれのアプリを連携させることができます。
個人開発といえばアプリ作成をまず思い浮かべるかと思いますが、APIを利用したbot開発や便利スクリプト作成も手間の割に日々の生活が便利になったりするのでオススメです!!

51
27
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
51
27

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?