LoginSignup
28
31

More than 5 years have passed since last update.

【slack】 ちゃんと声を出して返答してくれるbotをrubyで作ろう

Last updated at Posted at 2015-12-17

はじめに

皆さん、1週間後の12/25は何の日か分かりますか?
そうですね、Ruby2.3のリリース予定日ですね!
サンプルコードでわかる!Ruby 2.3の主な新機能

世間一般ではクリスマスです。
残り一週間もあればslackの中に簡単に彼女を作ることが出来ます。

というわけで、Rubyを使って、slack上のメッセージ「Merry Christmas!」に対して「Merry Christmas!」とちゃんと声で返答してくれる彼女(bot)を作ります。

今回、以下の「slack-ruby-bot」というgemのお力をお借りして作成していきます。
https://github.com/dblock/slack-ruby-bot

こちらのtutorialを参考にしているので合わせてお読み頂ければと思います。
https://github.com/dblock/slack-ruby-bot/blob/master/TUTORIAL.md

* ローカル環境で立ち上げたときだけ声が返ってくるのでサーバーにアップはしません。
* 完成版はこちら -> https://github.com/kuboshizuma/nami

それでは作っていきましょう!

実装

Gemfile

今回は「nami」という名前のbotを作成します。名前は好みの名前に変えて下さい。

まずはアプリケーションのディレクトリを作成します。

$ mkdir nami

ではこのフォルダの中にファイルを作成していきます。
まず、Gemfileを作成しましょう。

Gemfile
source 'http://rubygems.org'

gem 'slack-ruby-bot'
gem 'puma'
gem 'sinatra'
gem 'rake'
gem 'foreman'

その後にbundle installをしましょう。

$ bundle install

Application

「slack-speakbot」というフォルダを作成し、その中で「app.rb」を作成します。
以下を書くだけでオーケーです。

slack-speakbot/app.rb
module SlackSpeakbot
  class App < SlackRubyBot::App
  end
end

Commands

コマンドを作成します。
Aloudというクラスを作ってその中に処理を書いていきます。
Aloudクラスの中の記述の意味ですが、「Merry Christmas!」って言われたら(slack上でコメントしたら)、「speak」というメソッドを実行するよ、という意味です。

slack-speakbot/commands/aloud.rb
module SlackSpeakBot
  module Commands
   class Aloud < SlackRubyBot::Commands::Base

      match "Merry Christmas!" do |client, data, match|
        speak
      end

    end
  end
end

それでは、speakメソッドのほうも作っていきたいと思います。
slack上で喋ってくれているように声をだすのにはMacではsayコマンド、linuxではespeckを使います。(今回はこれだけの対応です)
speakメソッドが呼び出されたら、rubyのsystemコマンドで「sayコマンド(Mac)またはespeak」を実行するようにします。optionはいい感じに設定していますが、適当に変えていいです。

slack-speakbot/commands/aloud.rb
module SlackSpeakBot
  module Commands
   class Aloud < SlackRubyBot::Commands::Base

      def self.speak
        speak_text = "\"Merry Christmas!\""
        command = if /darwin/ === RUBY_PLATFORM
                    "say -v Agnes -r 130 #{speak_text}"
                  else
                    "echo #{speak_text} | espeak -s 120 -p 99"
                  end
        system(command)
      end

      match "Merry Christmas!" do |client, data, match|
        speak
      end

    end
  end
end

声を出したタイミングでbotがメッセージでも返事するようにspeakメソッドの実行前に一行記述を付け足します。

slack-speakbot/commands/aloud.rb
module SlackSpeakBot
  module Commands
   class Aloud < SlackRubyBot::Commands::Base

      def self.speak
        speak_text = "\"Merry Christmas!\""
        command = if /darwin/ === RUBY_PLATFORM
                    "say -v Agnes -r 130 #{speak_text}"
                  else
                    "echo #{speak_text} | espeak -s 120 -p 99"
                  end
        system(command)
      end

      match "Merry Christmas!" do |client, data, match|
        send_message client, data.channel, 'Merry Christmas!'
        speak
      end

    end
  end
end

Require Everything

root直下にslack-speakbot.rb を作成し、これまでの作成ファイル等を読み込みます。

slack-speakbot.rb
require 'slack-ruby-bot'
require 'slack-speakbot/commands/aloud'
require 'slack-speakbot/app'

Web server

ルート直下に。そのままどうぞ。

web.rb
require 'sinatra/base'

module SlackSpeakbot
  class Web < Sinatra::Base
    get '/' do
      "I'd like to talk to you."
    end
  end
end

Config.ru

これまた、ルート直下にどうぞ。

config.ru
$LOAD_PATH.unshift(File.dirname(__FILE__))

require 'slack-speakbot'
require 'web'

Thread.abort_on_exception = true

Thread.new do
  begin
    SlackSpeakbot::App.instance.run
  rescue Exception => e
    STDERR.puts "ERROR: #{e}"
    STDERR.puts e.backtrace
    raise e
  end
end

run SlackSpeakbot::Web

Create a Bot User

ここで、slackでbotを登録しましょう。

slack名の右の「下向き矢印のような部分」をクリックし、その中の「Configure Integrations」を選択して下さい。

スクリーンショット_2015-12-14_22_15_17.png

表示された画面の検索で「bots」とかやると出てきます。そしてクリック。

スクリーンショット 2015-12-14 22.15.50.png

Usernameを決めてあげて「Add Bot Integration」とすると登録完了です。

スクリーンショット 2015-12-14 22.16.44.png

詳細でavatar画像も設定出来るのでいい感じの写真を使って下さい。そしてAPIトークンを取得して下さい。

.env

環境変数を設定するために.envを作成しましょう。

.env
# 値は自分のものを使う
SLACK_API_TOKEN=xoxb-erfijadjsvkdaKJDFSJOWf049

環境変数が記述されたこのファイルは.gitignoreに追加しておきましょう。(.gitignoreファイルを作成)

.gitignore
.env

Procfile

Procfileにforeman起動時に実行するコマンドを記述します。

Procfile
web: bundle exec puma -p $PORT

Run the Bot

下記コマンドでbotを起動させて見て下さい!

$ foreman start

これで、slackのチャンネルのどこかにbotを招待して、Merry Christmas!とコメントしてみましょう!きっと返事をくれるはずです!

Only for you

これでもいいんですけど、これだとどのchannelの誰が「Merry Christmas!」って言っても返してくれるのでちょっとさびしいです。
そこで、特定のチャンネルで自分に対してのみ返してくれるようにします。

以下で、新しく set_env? というメソッドとwatching? というメソッドを作り、それがtrueならば speak メソッドを実行します。channelとuserは後で環境変数の設定をするのでENV['WATCHING_USER']ENV['WATCHING_CHANNELL']にそれぞれuserとchannelのidがセットされているとして作成します。
set_env?が環境変数に上記の環境変数がセットされているか確認するメソッドで、watching?がuserとchannelが指定したものか判断するメソッドです。

slack-speakbot/commands/aloud.rb
module SlackSpeakBot
  module Commands
    class Aloud < SlackRubyBot::Commands::Base

      def self.speak
        speak_text = "\"Merry Christmas!\""
        command = if /darwin/ === RUBY_PLATFORM
                    "say -v Agnes -r 130 #{speak_text}"
                  else
                    "echo #{speak_text} | espeak -s 120 -p 99"
                  end
        system(command)
      end

      def self.set_env?(client, data)
        if ENV['WATCHING_USER'] && ENV['WATCHING_CHANNELL']
          true
        else
          send_message client, data.channel, "'watching_user' or 'watching_channel' is not defined in slack-speakbot."
          false
        end
      end

      def self.watching?(user, channel)
        user == ENV['WATCHING_USER'] && channel == ENV['WATCHING_CHANNEL']
      end

      match "Merry Christmas!" do |client, data, match|
        if set_env?(client, data) && watching?(data.user, data.channel)
          send_message client, data.channel, 'Merry Christmas!'
          speak if set_env?(client, data) && watching?(data.user, data.channel)
        end
      end

    end
  end
end

ここで、userとchannelのidを取得するための実行ファイルを作成しておきます。

exec というフォルダを作成してそのフォルダ内にファイルを作成していきます。

exec/check-userid.rb
require 'slack-ruby-client'
require 'dotenv'
require_relative '../config/initialize.rb'

client = Slack::Web::Client.new

user = client.users_list['members'].detect{ |u| u['name'] == ARGV[0] }

if user.nil?
  puts "I can not find this user. Please confirm that this user exist."
else
  puts user['id']
end
exec/check-channel.rb
require 'slack-ruby-client'
require 'dotenv'
require_relative '../config/initialize.rb'

client = Slack::Web::Client.new

channel = client.channels_list['channels'].detect{ |u| u['name'] == ARGV[0] }

if channel.nil?
  puts "I can not find this channel. Please confirm that this channel exist."
else
  puts channel['id']
end

また、下記ファイルを用意します。

config/initialize.rb
Dotenv.load

Slack.configure do |config|
    config.token = ENV['SLACK_API_TOKEN']
    fail 'Missing ENV[SLACK_API_TOKEN]! Please set up .env.' unless config.token
end

その後に、botから返事がほしいチャンネル名と自分のユーザー名を用意します。

第一引数にチャンネル名で、

$ ruby exec/check-channel.rb test

第一引数にユーザー名で、

$ ruby exec/check-userid.rb shizuma

返り値として、それぞれidが返ってくるので、それを.env に記述します。

.env
# 値は自分のものを使う
SLACK_API_TOKEN=xoxb-erfijadjsvkdaKJDFSJOWf049
WATCHED_USER=SDR43SF
WATCHED_CHANNEL=SEW3295D

その後、起動し直して見て下さい。

$ foreman start

これで、特定のチャンネルのあなただけに返事をするようになりました!

28
31
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
28
31