RailsでSlackbotをはじめから丁寧に


こんにちは、プログラミング超初心者のゆりといいます。
サークルの都合でslackbotをrailsで作ることになったのですが、あらゆるステップでつまずきすごく手こずったので、備忘録としてSlackbotをRailsで作る方法を1から書いていきます。
https://api.slack.com/bot-users#responding-to-mentions
基本はこちらにそって作っています。プログラミングに慣れていらっしゃる方はこちらをみるだけで十分に作れるかと思いますが、Node.jsで書いてあるものをrailsに置き換えて考えるのが難しい方にはこの記事は有効なものになるかと思われます。
こちらの記事では、何かメッセージを送ったら返信がくる、という機能のみのシンプルなbotの作り方を紹介します。

Slackbotの土台を作る

まずは下記のページにアクセスします。
https://api.slack.com/apps?new_app=1

右上のCreate New Appをクリック

アプリの名前を入力し、アプリを導入したいワークスペースを選択します。
Create Appをクリック
はい、これだけでSlack appの基礎が出来上がりました!

アプリにSlackbotを追加する

画面が切り替わりBasic Informationと書かれたページに来ます。
左側のメニューの中からFeature>Bot Usersを選択。

Add a Bot Userをクリック

Botの表示選択画面に来ました。botの表示名はこちらで設定することができます。
Always Show My Bot as OnlineはOnにしておくことをおすすめします。
Add Bot Userをクリック
そして画面が切り替わったらSave Changesをクリックしましょう

Slackbotをワークスペースに追加する

とりあえず一旦こちらでSlackbotをワークスペースに追加してしまいましょう!
左メニューバーのSettings>Install Appをクリック

Install App to Workspaceをクリック

このような画面が出てきますが、許可すると押してしまって大丈夫です。

Installed App Settingsという画面が出てくれば成功です!
アプリを追加したワークスペースを見てください、左下のAppというコーナーに今追加したbotがあるはずです!
Bot User OAuth Access Tokenはしっかり保存しておきましょうね。
次は実際にrailsコマンドを使ってみましょう!

Railsでアプリの大枠を作る

$ rails new slackbot_on_rails --api -d mysql
$ cd slackbot_on_rails

rails new [アプリ名]で新しいアプリを作ることができます。今回はapiモード(viewが無効になる)、データベースの設定(mysqlを使用)という旨の文言を付け加えました。
ここまでやったら、とりあえずherokuにデプロイしてしまいましょう!
https://qiita.com/kazukimatsumoto/items/a0daa7281a3948701c39
こちらの記事がrailsのアプリをherokuにあげる方法を簡単に説明してくれています。

私がやったことを簡単にかくと、

config>routes.rb
Rails.application.routes.draw do
  get "/"=>"slack#index"
end
$ rails g controller slack
$ rails db:create
app>controllers>slack_controller.rb
class SlackController < ApplicationController
    def index
    end
end

appの下にservicesフォルダを追加、その下にbodyフォルダを追加、そこにtest_service.rbファイルを追加

githubのリポジトリを作る
あとはコマンドライン上で操作(herokuログイン済想定)

$ git init
$ git add .
$ git commit -m "first commit"
$ git remote add origin https://github.com/[githubユーザー名]/[リポジトリ名].git
$ git push -u origin master
$ heroku create qiita-slackbot
$ git push heroku master

これであなたの書いたコードにhttpリクエストを通してアクセスできるようになりました!

このあとはSlack apiとのやりとりをする部分です。

メッセージを受信する

Event APIを使う

Slackがメッセージを受信した時にあなたのソースコードにリクエストが飛ぶようにしなければいけません。
そこで必要なのがslackのEvent API
自分のslackbotの管理画面に行き、左側のメニューの中のFeatures>Event Subscriptionsにアクセス
Enable Eventsをオン、Request URLの欄に[今herokuで作ったurl]/receiveを入れてみましょう。

Your URL didn't respond with the value of the challenge parameter.

というメッセージが出てくるはず。これはあなたのこのurlがchallengeパラメータを捌けるようにできてないですよ、というお達しなのです。今から直すので問題はありません。

ソースコードに移り、

config>route.rb
post "/receive"=>"slack#create"

をendの前に追加、

app>controllers>slack_controller.rb
def create
        @body = JSON.parse(request.body.read)
        case @body['type']
        when 'url_verification'
            render json: @body
        when 'event_callback'
            # ..
        end
end

を追加、もう一度git add,commit, pushをしてみてください
先ほどのエラーメッセージが出ていたところがVerifiedになっているはずです!

これでEvent APIが使えるようになりました

下にあるSubscribe to bot events,Subscribe to workspace eventsから付け加えたい機能を選ぶことができます。今回はDMにメッセージを送るようにしたいので、message.imというイベントを選択します。
JSON形式で色々なデータが飛んでくるのですが、どんなものが送られるかはこちらから確認できます。

JSON形式のパラメーターのハッシュ化

初心者すぎてRailsでJSON形式で送られたものってどうさばくのかすらわからなかったので(おそらく一週間後にまた忘れる)すごく丁寧に書いていきます。
JSONのペイロードはEventapiで設定したurlに届くので、そちらで設定したコントローラのアクション(今回の場合はslackコントローラのcreateアクション)に書いていきます

app>controllers>slack_controller.rb
        json_hash  = params[:slack]

これで変数json_hashの中にはハッシュ化された送られてきたJSONの中身が入りました。これでrubyで扱いやすくなりましたね。
さあ、いつまでもコントローラでいじる訳にもいかないので先ほど作ったtest_service.rbにコードを書いていきましょう。

app>services>body>test_service.rb
module  Body
  class TestService
    def initialize(json)
        @json=json
    end
    def execute

    end
  end 
end

こう書いた上で、先ほど書いたコントローラーの先ほど書いた行の下に

app>controllers>slack_controller.rb
        Body::TestService.new(json_hash).execute 

こう付け加えましょう。こうするとコントローラでハッシュ化されたものがtest_service.rbで自由にいじれるようになりました。

簡単な返信機能をつける

では、DMで何か言われたら、
こんにちは、私はslackbotです!
と返すボットを作ってみましょう。

この時に使うapiはWeb apiのchat.postMessageです。詳しくはこちら
送るデータの型はjsonでなくてはいけません。HTTPのPOSTリクエストを送るためにHTTP クライアントライブラリFaradayを使いました。Faradayについて詳しくはこちら
Gemfileに

gem 'faraday'

と書き加えるのをお忘れなきよう

app>services>body>test_service.rb
def execute
#Faradayを使って、JSON形式のファイルをPOSTできるようにする
      conn = Faraday::Connection.new(:url => 'https://slack.com') do |builder|
        builder.use Faraday::Request::UrlEncoded  # リクエストパラメータを URL エンコードする
        builder.use Faraday::Response::Logger     # リクエストを標準出力に出力する
        builder.use Faraday::Adapter::NetHttp     # Net/HTTP をアダプターに使う
      end
  if @json[:event][:subtype] != "bot_message" #これがないと無限ループになる
    body = {
              :token => ENV['SLACK_BOT_USER_TOKEN'],#あとでherokuで設定します
              :channel => @json[:event][:channel],#こうするとDM内に返信できます
              :text  => "こんにちは、私はslackbotです!"
            }
    conn.post '/api/chat.postMessage',body.to_json, {"Content-type" => 'application/json',"Authorization"=>"Bearer #{ENV['SLACK_BOT_USER_TOKEN']}"}#ヘッダーはつけなければいけないらしい、このままで大丈夫です。
  end
end

私が詰まったポイント
ENV['SLACK_BOT_USER_TOKEN']を.envファイルに書いて.gitignoreに.envって書いてherokuにプッシュしてtokenがnilになるってしばらく頭を抱えていたけど、
、考える間も無くそれはそうでした。あとでherokuでセットします。
あと/api/chat.postMessageに送るjsonの形式について、ヘッダーにcontent typeとauthorizationを付け加える必要があるので注意
渡すパラメータは最低限、token,channel,textの3つがあれば大丈夫です。
さて、ここまででだいたいの準備はできました。
今度はherokuの設定をしていきます。

herokuのConfigをいじる

herokuの画面を開き、自分が今作ってるアプリの管理画面に行ったら、Settings>config varsへ行き、Reveal Config Varsを押すと、config varsがでてきます。
ここに追加するべきものは、
CLEARDB_DATABASE_URL
DATABASE_URL
SLACK_BOT_USER_TOKEN
の3つです。

CLEARDB_DATABASE_URLは、

$ heroku addons:add cleardb

とターミナルで打ち込むと設定することができます。
その後にConfig Varsを確認すると、mysql://something@somethingのような形でCLEARDB_DATABASE_URLが保存されていることが確認できます。

私はmysql2を使ったのでDATABASE_URLにmysql2://something@somethingを書き込みました。something@somethingは上下共に同じものです。

SLACK_BOT_USER_TOKENには、アプリをワークスペースにインストールした時に出てくるxoxb-somethingのようなものを書き込みます。

これで用意は終了です!
slackのアプリとのDMの欄で何かを打ってみてください!
このように出てくれば成功です!

お疲れ様でした!次の記事ではもっと複雑な情報処理をするslackbotを作っていこうと思います。
良いお年を!