10
7

More than 3 years have passed since last update.

RubyとSlackBotを使って、誰でもIssueを作成できるBotを作ってみた。

Last updated at Posted at 2019-07-29

はじめに

先日、このTweetを見かけてしまいました。

「これは...圧倒的に便利すぎる!」 と衝撃を受け、有り余る好奇心で開発を試みたのが始まりです。(しかもGWで割と時間もあったので)

今回はRubyとSlack Bot、Github APIを使用して、Slackのリアクションでissueを作成してみました。ちなみにSlack Botほぼ初心者でも2日くらいでだいたい動くものは完成したので、サクッと作れます。

完成イメージ

slack_bot.png

この記事を読んでできること

  • RubyとSlack Botを使って、SlackのリアクションでGithubのissueが作成できる。
  • Slack上の特定のメッセージ、リアクションに対して、決まった返答を返すことができる。

準備

言語:Ruby
API:Github API
Bot:Slack

Slack Botを使ったことのない方推奨の記事:
http://studio-andy.hatenablog.com/entry/ruby-bot
一度手を動かしてみると挙動が把握で切るのでオススメです!

SlackBotを作成しよう

https://amdlaboratory.com/amdblog/slack-bot%E3%81%AE%E4%BD%9C%E3%82%8A%E6%96%B9%E3%80%82/
こちらのSlack Botの作り方を参考にBotを作成してください。

APIの挙動確認、パラメータ、レスポンスなどはこちらからデモ操作できます。
https://api.slack.com/methods/chat.postMessage/test

Github APIを取得

こちらも公式APIドキュメントから細かいパラメータの設定や、レスポンスなどが確認できます。
https://developer.github.com

今回はissueを作成したいので、
https://developer.github.com/v3/issues/#create-an-issue

Rubyファイルを作成

作成するファイル構成
slack_bot
┣ slack_bot.rb
┣ Gemfile
┗ Gemfile.lock

Gemfile
# frozen_string_literal: true
source "https://rubygems.org"
ruby "2.6.3"

gem 'http'
gem 'json'
# websocketを使用する
gem 'faye-websocket'
gem 'eventmachine'

bundle install
しておく。

slack_bot.rb

require 'http'
require 'json'
require 'eventmachine'
require 'faye/websocket'
require 'uri'
require 'net/http'
require 'net/https'


# 環境変数を設定する
# export SLACK_API_TOKEN=xoxo-hogehoge-api
# export GITHUB_USERNAME=hoge
# export GITHUB_PASSWORD=hogepass

SLACK_RTM_URL="https://slack.com/api/rtm.start"
SLACK_REACTION_URL="https://slack.com/api/reactions.get"


response = HTTP.post(SLACK_RTM_URL, params: {
    token: ENV['SLACK_API_TOKEN']
})

rc = JSON.parse(response.body)
url = rc['url']

EM.run do
    # Web Socketインスタンスの立ち上げ
    ws = Faye::WebSocket::Client.new(url)

    #  接続が確立した時の処理
    ws.on :open do
        p [:open]
    end
    # RTM APIから情報を受け取った時の処理
    ws.on :message do |event|
        data = JSON.parse(event.data)
        p [:message, data]
        if data['text'] == '疲れた'
            ws.send({
                type: 'message',
                text: "お疲れ様です! <@#{data['user']}> さん",
                channel: data['channel']
            }.to_json)
        elsif data['text'] == ':github_issue:'
            ws.send({
                type: 'message',
                text: "<@#{data['user']}> さん!メッセージに、:github_issue:リアクションをするとissueが簡単に作成できますよ。",
                channel: data['channel']
            }.to_json)
        elsif data['text'] == 'グッときた'
            ws.send({
                type: 'message',
                text: "<@#{data['user']}> さん、:最高かよ:",
                channel: data['channel']
            }.to_json)
        end

        if data['reaction'] == 'github_issue'

            slack_response = HTTP.post(SLACK_REACTION_URL, params: {
                    token: ENV['SLACK_API_TOKEN'],
                    channel: data['item']['channel'],
                    timestamp: data['item']['ts']
                })
            slack_response = JSON.parse(slack_response)

            https = Net::HTTP.new('api.github.com', '443')
            https.use_ssl = true
            https.start do |https|
                # Issue を作る API: http://developer.github.com/v3/issues/#create-an-issue
                req = Net::HTTP::Post.new('/repos/githubアカウント名/リポジトリ名/issues')
                req.basic_auth ENV['GITHUB_USERNAME'],ENV['GITHUB_PASSWORD']
                issue_info = {
                'title': "#{slack_response['message']["text"]}",
                'body': "ヘルプです",
                "labels": [
                        "help wanted"
                    ]
                }

                # githubAPIを叩いて、issue作成
                req.body = JSON.generate issue_info
                github_response = https.request(req)

                # JSON.parseとは、JSON形式の文字列をRubyのHash形式に変換するためのメソッド
                github_response = JSON.parse(github_response.body)

                ws.send({
                    type: 'message',
                    text: "<@#{data['user']}> さんのために、issueを作成しました!issueボードを確認してください。 #{github_response["html_url"]}",
                    channel: data['item']['channel']
                }.to_json)
            end
        elsif  data['reaction'] == 'fish'
            slack_response = HTTP.post(SLACK_REACTION_URL, params: {
                    token: ENV['SLACK_API_TOKEN'],
                    channel: data['item']['channel'],
                    timestamp: data['item']['ts']
                })
            slack_response = JSON.parse(slack_response)

            ws.send({
                type: 'message',
                text: "魚のリアクションしましたね?",
                # text: "#{slack_response['message']['text']}に、魚のリアクションしましたね?",
                channel: data['item']['channel']
            }.to_json)
        elsif data['reaction'] == 'gyozabu'
            ws.send({
                type: 'message',
                text: "なるほど!<@#{data['user']}> さんは震えるほど餃子が食べたいみたいですよ! <@here> 今日は、餃子活動しないんですか?",
                channel: data['item']['channel']
            }.to_json)
        end
    end
    # 接続が切断した時の処理
    ws.on :close do
        p [:close, event.code]
        ws = nil
        EM.stop
    end

end

rubyスクリプト実行。
bundle exec ruby slack_bot.rb

rubyスクリプト起動.png

作成したSlackBotの入っているチャンネルで、メッセージを送信したり、リアクションしてみるとBotが動いて、挙動が確認できると思われます。

まとめ

これでエンジニアではなくても、困っているメンバーが簡単にIssueを作成できるようになりました。(使われると嬉しい。。)Issue Boadは毎週エンジニアMTGで確認して、社内メンバーの困っているIssueを改修して参ります。

おまけ🥟

折角SlackBotを作ったので、多少ユーモアを入れてみました。
(割と開発の醍醐味だと思っています)
非常に共感したので引用させて頂きました。↓

くだらないBotを運用する一番のメリットは、楽しく技術の勉強ができるという点です。
失敗をおそれず色々な技術を試せる
工夫次第でどんな技術でも自由に取り入れられる
得た知見を業務に役立てられる
車輪の再開発/overkillが気にならない
フロント側のコードを書かなくても目に見える楽しいアウトプットがある
https://tech.dely.jp/entry/slack_bot_philosophy

今回は餃子が震えているリアクションをするとBotが反応してくれます。

gyozabu.png
(@here がメンションになっていない部分の課題感は残りつつ)
SlackBotはアイディア次第でもっと面白くできそうです!

折角なので、社内の餃子部イベントでLTした内容もよかったらどうぞ!

何か間違えている部分など気になる点があれば、優しく教えて頂けると励みになります。

推奨記事

デプロイ編

SlackBotをHerokuでデプロイ

10
7
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
10
7