はじめに
皆さん、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を作成しましょう。
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」を作成します。
以下を書くだけでオーケーです。
module SlackSpeakbot
class App < SlackRubyBot::App
end
end
Commands
コマンドを作成します。
Aloudというクラスを作ってその中に処理を書いていきます。
Aloudクラスの中の記述の意味ですが、「Merry Christmas!」って言われたら(slack上でコメントしたら)、「speak」というメソッドを実行するよ、という意味です。
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はいい感じに設定していますが、適当に変えていいです。
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メソッドの実行前に一行記述を付け足します。
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
を作成し、これまでの作成ファイル等を読み込みます。
require 'slack-ruby-bot'
require 'slack-speakbot/commands/aloud'
require 'slack-speakbot/app'
Web server
ルート直下に。そのままどうぞ。
require 'sinatra/base'
module SlackSpeakbot
class Web < Sinatra::Base
get '/' do
"I'd like to talk to you."
end
end
end
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」を選択して下さい。
表示された画面の検索で「bots」とかやると出てきます。そしてクリック。
Usernameを決めてあげて「Add Bot Integration」とすると登録完了です。
詳細でavatar画像も設定出来るのでいい感じの写真を使って下さい。そしてAPIトークンを取得して下さい。
.env
環境変数を設定するために.env
を作成しましょう。
# 値は自分のものを使う
SLACK_API_TOKEN=xoxb-erfijadjsvkdaKJDFSJOWf049
環境変数が記述されたこのファイルは.gitignore
に追加しておきましょう。(.gitignoreファイルを作成)
.env
Procfile
Procfileにforeman起動時に実行するコマンドを記述します。
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が指定したものか判断するメソッドです。
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
というフォルダを作成してそのフォルダ内にファイルを作成していきます。
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
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
また、下記ファイルを用意します。
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
に記述します。
# 値は自分のものを使う
SLACK_API_TOKEN=xoxb-erfijadjsvkdaKJDFSJOWf049
WATCHED_USER=SDR43SF
WATCHED_CHANNEL=SEW3295D
その後、起動し直して見て下さい。
$ foreman start
これで、特定のチャンネルのあなただけに返事をするようになりました!