paiza times

paizaがお届けする、テック・キャリア・マネジメント領域における「今必要な情報」を届けるWebメディア

logo

paizaがお届けする、テック・キャリア・マネジメント領域の「今必要な情報」を届けるWebメディア

Rubyを使ったSlackボットが5分で作れた!PaizaCloudならサーバ構築不要

f:id:paiza:20180115170315p:plain
(English article is here)

f:id:paiza:20151217152725j:plainこんにちは、吉岡([twitter:@yoshiokatsuneo])です。

皆さんはチャットツールのSlackを使っていますか?

今や社内やグループでのコミュニケーションに欠かせないSlackですが、ボット(Bot)というプログラムを作ると、自動的に会話をさせることができます。

Slackボットは文字列だけを取り扱うので、比較的簡単にプログラミングして開発することができます。また、一緒にSlackチャットを使っている社内やグループ内のユーザー達にもすぐに使ってもらえます。自分が作ったものをすぐに使ってもらって、フィードバックがもらえるのは楽しいものです。Slackボット作りは、プログラミング初心者が初めて作って公開するモノとしても最適です。

ただ、実際にSlackボットを作って動かすには、開発環境やサーバの設定が必要です。プログラミング自体は簡単でも、実際に作って動かすところまで持っていくのはなかなか面倒な作業も伴います。

そこで、今回はPaizaCloudを利用してみます。

PaizaCloudは、クラウド上で動く開発環境です。PaizaCloudでは、面倒なインストールや環境設定をすることなく、Web開発やアプリケーション開発を簡単・手軽に始められます。

PaizaCloudでは、Slackボットの開発に適した環境も用意されているので、ブラウザさえあれば、すぐにSlackボットをプログラミングして開発することができます。

開発環境がクラウド上で動作しているので、自分でサーバなどを用意しなくても、作ったボットはその場ですぐに動かせます!

ここでは、実際にPaizaCloud上で、Rubyを使ってSlackボットを作ってみます。

手順に沿っていけば、誰でも5分程度でSlackボットを作り、その場で動かしてみることができます。

PaizaCloud Cloud IDEを使う

それでは、始めていきましょう。まずは、PaizaCloudにログインします。

PaizaCloud Cloud IDEのサイトはこちらです。

https://paiza.cloud/

メールアドレスなどを入力して登録すると、登録確認メールが送られてきます。GitHubやGoogle(Gmail)ログインを利用すると、ボタン一つで登録することもできます。

サーバを作る

次は、開発環境となるサーバを作ります。

f:id:paiza:20171213234155p:plain

「新規サーバ作成」ボタンを押して、サーバ作成画面を開きます。

f:id:paiza:20171218232242p:plain

特に何も変更せずに、もう一度「新規サーバ作成」ボタンを押すと、3秒程度でSlackボットの開発環境がブラウザ上にできあがります。

f:id:paiza:20180115174407p:plain

Slackアプリケーションを作る

SlackボットはSlackアプリケーションとして作りますので、Slackアプリケーションページを開きます。

https://api.slack.com/apps

f:id:paiza:20180115170344p:plain

サインアップしていない場合は、「sign in to your Slack account」リンクをクリックしてサインアップし、再度 https://api.slack.com/apps を開きます。

f:id:paiza:20180115170402p:plain

アプリケーション一覧が表示されます。アプリケーションを作るので、「Create New App」ボタンをクリックします。

f:id:paiza:20180115170417p:plain

アプリケーション作成ダイアログが表示されるので、アプリケーション名を入力し、Slackワークスペースを選択します。

ここでは、アプリケーション名は"MyBot"としています。設定したら、「Create App」ボタンをクリックしてアプリケーションを作成します。

アプリケーションが作成されました。以下のようなアプリケーションページが表示されます。

f:id:paiza:20180115170432p:plain

Slackコマンドを作る

まずは、Slackコマンドを作ってみましょう。Slackコマンドはスラッシュで始まるコマンドです。例えばチャネルで"/who"とメッセージを入れると、チャネルのユーザ一覧が表示されます。

ここでは、日時を表示する、/time コマンドを作ってみます。

アプリケーションページの"Add features and functionality"の、"Slash Commands"をクリックします。

f:id:paiza:20180115170456p:plain

"Create New Command"ボタンをクリックします。

f:id:paiza:20180115170919p:plain

コマンド作成ページが表示されるので、Commandにはコマンド名「/time」を入れます。

Request URLには、PaizaCloudで作成するサーバプログラムのURLを入れます。

PaizaCloudで動かすサーバのホスト名は「サーバ名.paiza-user.cloud」になります。

また、Sinatraで作成する場合ポート番号は4567番になります。PaizaCloudで立ち上げたサーバは自動的にSSLを利用できますので、プロトコルはHTTPではなく、HTTPSにします。結果、 URLは https://サーバ名.paiza-user.cloud:4567/ となります。(「サーバ名」は、作成したサーバの名前に 置き換えてください)

Short Descriptionにはプログラムの説明を、Usage Hintにはコマンドの利用方法をそれぞれ適当に書いておきます。

設定ができたら「Save」ボタンで保存します。

コマンドが作成されて、コマンド一覧が表示されました。

f:id:paiza:20180115170938p:plain

作成したSlackアプリケーションは利用できるようにSlackのワークスペースにインストールします。

メニューから、"Install App"を選択します。

インストール画面が表示されるので、"Install App to Workspace"ボタンを押します。

f:id:paiza:20180115173815p:plain

認証画面が表示されるので、"Authorize"ボタンを押して認証します。

f:id:paiza:20180115173829p:plain

今度は、コマンドが入力されたときに実行されるプログラムを書いていきます。

PaizaCloudでは、ブラウザ上でファイルの作成・編集ができます。

PaizaCloudの画面左側の「新規ファイル」アイコンをクリックしてみましょう。

f:id:paiza:20171218232330p:plain

ファイル名を入力する画面がでてくるので、ファイル名を"command.rb"として、「作成」ボタンを押します。

f:id:paiza:20180115171000p:plain

ファイルが作成されました!

まずは簡単なコマンドを作ってみます。

以下のようにプログラムを作成してみましょう。

ここでは、RubyとSinatraを使っています。

command.rb:

require 'sinatra'
require 'sinatra/reloader'
require 'sinatra/json'

post '/slack/command' do
    text = params['text']
    return json({
        text: "コマンドを実行しました! パラメータは#{text}です。",
        response_type: 'in_channel',
    })
end

get '/' do
  return "Hello World"
end

f:id:paiza:20180115171842p:plain

作成できたら、「保存」ボタンで保存します。

このプログラムでは、"post '/slack/command'"ブロックで、/slack/commandへのPOSTメソッドのリクエストを処理します。リクエストのパラメータはparamsでアクセスできます。

メッセージで、コマンドの後に続く、パラメータテキストを params['text']として取得します。このブロックが返すオブジェクトが、/slack/command リクエストへの応答となります。JSON形式で返すので、jsonメソッドを利用します。textフィールドに表示するメッセージを入れます。response_typeを'in_channel'にすると、他の人にもメッセージが表示されるようになります。

ここでは、"コマンドを実行しました!"と、コマンドのパラメータを表示するようにします。

また、必要はありませんが、確認のためGET "/"に"Hello World"と応答するようにしておきます。

それでは、このプログラムを実行して動かしてみましょう。

実行するには、"ruby ./command.rb -o 0"のようにコマンドを実行します。sinatraはデフォルトではlocalhostのみで待ち受けて外部から接続できません。そこで、このように、"-o 0"(又は"-o 0.0.0.0")オプションを追加してグローバルアドレスで待ち受けて外部から接続できるようにします。

PaizaCloudでは、ブラウザ上で、コマンドを入力するための「ターミナル」を使うことができます。

画面左側の、「ターミナル」のボタンをクリックします。

f:id:paiza:20171213234317p:plain

ターミナルが起動しますので、"ruby ./command.rb -o 0"と、実行するコマンドを入れて改行キー(エンターキー)を押します。

$ ruby ./command.rb -o 0

f:id:paiza:20180115171054p:plain

コマンドが実行されました。"tcp://0:4567"と表示されており、ポート番号4567でサーバが動作していることがわかります。

また、画面の左側に、"4567"と書かれたボタンが追加されています。

f:id:paiza:20180115171204p:plain

Sinatraの開発環境では、4567番ポートでサーバが起動します。

PaizaCloudでは、この4567番ポートに対応したブラウザ起動ボタンを自動で追加しています。

ボタンをクリックすると、ブラウザ(PaizaCloudの中で動くブラウザ)が起動して、"Hello World"と表示されました!

f:id:paiza:20180115171236p:plain

今度はSlackでコマンドを送ってみましょう。

ここでは、「/time てすとてすと」と入れてみました。

コマンドへの返事が返ってきました!Slackコマンドが動いています!

f:id:paiza:20180115171927p:plain

今度は日時を返すようにしてみましょう。

先ほどのプログラムを以下のように変更します。

command.rb:

require 'sinatra'
require 'sinatra/reloader'
require 'sinatra/json'

ENV['TZ'] = 'JST-9' # Timezone

post '/slack/command' do
    text = params['text']
    if text =~ /何時/
        now = Time.now
        responseText = "今は#{now.hour}#{now.min}#{now.sec}秒です。"
    elsif text =~ /今日/
        today = Time.now
        responseText = "今日は#{today.year}#{today.month}#{today.day}日です。"
    elsif text =~ /明日/
        tomorrow = Time.now + (60*60*24)
        responseText = "明日は#{tomorrow.year}#{tomorrow.month}#{tomorrow.day}日です。"
    else
        responseText = "例: 何時 / 今日 / 明日"
    end
    json({
        text: responseText,
        response_type: 'in_channel',
    })
end

get '/' do
  return "Hello World"
end

このコードでは、メッセージに含まれる文字列(何時/今日/明日)を正規表現で確認し返事をしています。

コマンド("ruby ./command.rb -o 0")をCtrl-Cキーで一度終了し、再度実行します。

確認してみましょう。以下のようなコマンドを入れてみます。

/time 今は何時?
/time 今日は何日?
/time 明日は何日?

返事がきました! 日時を返すSlackコマンドの完成です!

f:id:paiza:20180115172001p:plain

Slackボットの作成

Slackコマンドでも自動的に応答できますが、特定のコマンドを入れる必要があります。

より自然な会話に近くなるよう、特定のコマンドを入れなくても発言するには、Slackボットを作成します。

Slackボットを作成するには、Slackのアプリケーションページ(https://api.slack.com/apps)からアプリケーションを選択し、メニューからBasic informationを選択します。

f:id:paiza:20180115174145p:plain

"Add features and functionality"をクリックし、表示される一覧から"Bots"を選んでクリックします。

f:id:paiza:20180115172052p:plain

"Add a Bot User"をクリックすると、ボットユーザ作成画面が表示されるので、"Add Bot User"ボタンをクリックします。

f:id:paiza:20180115172103p:plain

パーミッションの変更が必要と表示されたら、"Click Here"と選択し、変更画面で"Authorize"をクリックして、変更を許可します。

f:id:paiza:20180115172119p:plain f:id:paiza:20180115172129p:plain

Slackボットのプログラムを作成するには、Bot User OAuth Access Tokenが必要です。

アプリケーションページのメニューから"Features"の"Auth & Permission"を選択し、 "Bot User OAuth Access Token"の部分に表示される"xoxb-"ではじまる文字列をメモしておきます。

f:id:paiza:20180115172349p:plain

Slackアプリケーションの設定ができたので、ボットのプログラムを作成しましょう。

Slackボットの作成にはWebSocketを利用します。ここでは、"faye-websocket"というRubyのgemライブラリを利用します。

"faye-websocket" gemをインストールするため、PaizaCloudのターミナルから以下のコマンドを入力します。

$ sudo gem install faye-websocket

f:id:paiza:20180115172448p:plain

bot.rbというファイルを作成して、以下のようにコードを入力します。

slackコマンドの時と同じく、日時を返すプログラムです。

ここで、"OAUTH-TOKEN"は、先ほど取得した"xoxb-"ではじまるBot User OAuth Access Tokenに置き換えます。

bot.rb:

require 'http'
require 'json'
require 'eventmachine'
require 'faye/websocket'

TOKEN='***OAUTH-TOKEN***'

ENV['TZ'] = 'JST-9' # Timezone

response = HTTP.get("https://slack.com/api/rtm.connect", params: {token: TOKEN})
resposeObj = JSON.parse(response.body)

url = resposeObj['url']

EM.run do
  puts "Connecting to #{url}..."
  ws = Faye::WebSocket::Client.new(url)

  ws.on :open do |event|
    p [:open]
  end

  ws.on :message do |event|
    msg = JSON.parse(event.data)
    p [:message, JSON.parse(event.data)]
    
    if msg["type"] != 'message'
        next
    end
    text = msg["text"]

    if text =~ /何時/
        now = Time.now
        responseText = "今は#{now.hour}#{now.min}#{now.sec}秒です。"
    elsif text =~ /今日/
        today = Time.now
        responseText = "今日は#{today.year}#{today.month}#{today.day}日です。"
    elsif text =~ /明日/
        tomorrow = Time.now + (60*60*24)
        responseText = "明日は#{tomorrow.year}#{tomorrow.month}#{tomorrow.day}日です。"
    else
        responseText = "例: 何時 / 今日 / 明日"
    end
    
    reply = {
        type: 'message',
        text: responseText,
        channel: msg['channel'],
    }
    puts "Replying: #{reply}"
    ws.send(reply.to_json)
  end

  ws.on :close do |event|
    p [:close, event.code, event.reason]
    ws = nil
    EM.stop
  end

end

このプログラムでは、"https://slack.com/api/rtm.connect"にTOKENをパラメータとしてアクセスし、ウェブソケットのURLをurl変数に取得します。eventmachine(EM)とfaye-weboskcket(Faye::WebSocket::Client)を利用して、このウェブソケットURLに接続します。

"ws.on"ではウェブソケットのメッセージに応答します。チャネル上で流れたメッセージは"ws.on :message"で受け取ります。メッセージは、typeが'message'なので、それ以外の場合は処理しません。

msg["text"]でメッセージテキストを取得し、メッセージに含まれる文字列(何時/今日/明日)を正規表現で確認し、"ws.send"メソッドで応答します。応答では、typeに'message'を、textに応答するメッセージのテキストを、channelには応答するチャネル(ここではメッセージを受け取ったチャネル)を指定します。

それでは、ボットを動かしてみましょう。"ruby ./bot.rb"コマンドをPaizaCloudのターミナルで実行します。

$ ruby ./bot.rb

ボットが取得できるメッセージは、ボットが参加しているチャネルだけですので、ボットを利用するチャネルに招待します。

メッセージを送ってみましょう!

f:id:paiza:20180115172515p:plain

返事がもらえました!完成です!

なお、PaizaCloudの無料プランでは、一定時間が経つとサーバは停止します。継続的にbotを動かしたい場合は、ベーシックプランへアップデートしてください。 詳しくはこちら https://paiza.cloud

まとめ

PaizaCloudで、Rubyを使ってSlackボットを作りその場で実際に動かしてみました。

Slackボットは簡単に作れてすぐに動かせますし、改造するのも簡単です。どんなメッセージにどう応答するかを考えながら作ったり、使いながら改良したりするのは楽しいですね。興味のある方は、ぜひ作ってみてください!

(botを作ってみたらpaiza(@paiza_official)まで教えてくれるとうれしいです!)

 


  「PaizaCloud」では、環境構築に悩まされることなく、ブラウザだけで簡単にウェブサービスやサーバアプリケーションの開発や公開ができます。 https://paiza.cloud

 


  paizaラーニング」では、未経験者でもブラウザさえあれば、今すぐプログラミングの基礎が動画で学べるレッスンを多数公開しております。

詳しくはこちら

paizaラーニング

そしてpaizaでは、Webサービス開発企業などで求められるコーディング力や、テストケースを想定する力などが問われるプログラミングスキルチェック問題も提供しています。

スキルチェックに挑戦した人は、その結果によってS・A・B・C・D・Eの6段階のランクを取得できます。必要なスキルランクを取得すれば、書類選考なしで企業の求人に応募することも可能です。「自分のプログラミングスキルを客観的に知りたい」「スキルを使って転職したい」という方は、ぜひチャレンジしてみてください。

詳しくはこちら

paizaのスキルチェック

paizaのおすすめコンテンツ

Webセキュリティ入門 ハッカー入門 Webセキュリティ講座がスタート!CVは内田真礼さん! Python✕AI 機械学習入門講座 CVに上坂すみれさんを起用!人気の機械学習講座を公開中!
paiza転職 paiza新卒 EN:TRY paizaラーニング 記事内に記載している情報は、記事公開時点でのものとなります。 Copyright Paiza, Inc, All rights reserved.