はじめに
先日、このTweetを見かけてしまいました。
Slackで絵文字つけるだけでGitHubにissue化できるようにするとめっちゃ便利…
— uiu (@uiu______) 2019年4月18日
スマホからでもいつでもすぐissue作れて、あとから文脈をSlackのリンクから辿れるので内容を思い出せる pic.twitter.com/LWsy4pXkZg
「これは...圧倒的に便利すぎる!」 と衝撃を受け、有り余る好奇心で開発を試みたのが始まりです。(しかもGWで割と時間もあったので)
今回はRubyとSlack Bot、Github APIを使用して、Slackのリアクションでissueを作成してみました。ちなみにSlack Botほぼ初心者でも2日くらいでだいたい動くものは完成したので、サクッと作れます。
完成イメージ

この記事を読んでできること
- 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
# frozen_string_literal: true
source "https://rubygems.org"
ruby "2.6.3"
gem 'http'
gem 'json'
# websocketを使用する
gem 'faye-websocket'
gem 'eventmachine'
bundle install
しておく。
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

作成したSlackBotの入っているチャンネルで、メッセージを送信したり、リアクションしてみるとBotが動いて、挙動が確認できると思われます。
まとめ
これでエンジニアではなくても、困っているメンバーが簡単にIssueを作成できるようになりました。(使われると嬉しい。。)Issue Boadは毎週エンジニアMTGで確認して、社内メンバーの困っているIssueを改修して参ります。
おまけ🥟
折角SlackBotを作ったので、多少ユーモアを入れてみました。
(割と開発の醍醐味だと思っています)
非常に共感したので引用させて頂きました。↓
くだらないBotを運用する一番のメリットは、楽しく技術の勉強ができるという点です。
失敗をおそれず色々な技術を試せる
工夫次第でどんな技術でも自由に取り入れられる
得た知見を業務に役立てられる
車輪の再開発/overkillが気にならない
フロント側のコードを書かなくても目に見える楽しいアウトプットがある
https://tech.dely.jp/entry/slack_bot_philosophy
今回は餃子が震えているリアクションをするとBotが反応してくれます。

折角なので、社内の餃子部イベントでLTした内容もよかったらどうぞ!
何か間違えている部分など気になる点があれば、優しく教えて頂けると励みになります。
推奨記事
-
Slack API
https://qiita.com/namutaka/items/233a83100c94af033575 -
WebSocketについて
https://qiita.com/south37/items/6f92d4268fe676347160