Date
May 30, 2017
はじめに
こんにちは yoshitsugu です。 普段Slackを使っていると、「この発言は流れてほしくない」というものがあると思います。
通常であればSlackのpin機能などで事足りると思いますが、バグの報告などはそのままGitHub Issue化できると便利です。そこで、今回はSlackの発言にreactionをつけることでGitHub Issue化するSlack botを作ってみました。
今回のゴール
- Slack上で発言にEmoji reactionをつけるとそのままGitHub Issueとして登録される
- 1チャンネル1リポジトリとしてSlackチャンネルとGitHubリポジトリとの紐付けができる
手順
hubotの下準備
スクリプトの作成
hubotディレクトリのscripts/ 以下に以下のようなスクリプトをおきます。
octonode = require('octonode')
Slack = require('slack-node')
truncate = require('truncate')
_ = require('lodash')
slack = new Slack(process.env.HUBOT_SLACK_TOKEN)
github = octonode.client(process.env.HUBOT_GITHUB_TOKEN)
module.exports = (robot) ->
robot.brain.data.repos = {} unless robot.brain.data.repos
getMsgFromTs = (channel_id, ts) ->
new Promise (resolve) ->
options = {
channel: channel_id,
latest: ts,
oldest: ts,
inclusive: true,
count: 1
}
slack.api 'channels.history', options, (err, res) ->
resolve res
getTeamInfo = ->
new Promise (resolve) ->
slack.api 'team.info', {}, (err, res) ->
resolve res
getChannels = (channel_id) ->
new Promise (resolve) ->
slack.api 'channels.list', {channel: channel_id}, (err, res) ->
resolve res
registerGitHubIssue = (ghrepo, title, body) ->
new Promise (resolve) ->
ghrepo.issue
"title": title,
"body": body,
, (err, issue, h) ->
resolve issue
slackMsgToPlainText = (msg, channels) ->
while result = (/<(.*?)>/g).exec(msg)
action = result[1].substr(0,1)
replaced = result[0]
switch action
when "#"
channel_id = /#(.*)/.exec(result[1].split("|")[0])[1]
channel_name = channels[channel_id]?.name
replaced = "##{channel_name}"
when "!"
replaced = ""
when "@"
user_id = /@(.*)/.exec(result[1].split("|")[0])[1]
user_name = robot.adapter.client.rtm.dataStore.getUserById(user_id)?.name
replaced = "@#{user_name}"
else
replaced = result[1]
msg = msg.replace(result[0], replaced)
return msg
registerIssue = (msg) ->
channel_id = msg.item.channel
ts = msg.item.ts
emoji = msg.reaction
if emoji == process.env.GITHUB_ISSUE_EMOJI
repo = robot.brain.data.repos[channel_id]
unless repo
robot.send {room: channel_id}, "リポジトリが設定されていません。@gh-bot set sikmi/xxx のような形式で設定してください"
return
msg = null
channels = null
getChannels().then( (d) ->
channels = _.keyBy(d.channels, (x) -> x.id)
return getMsgFromTs(channel_id, ts)
).then( (d) ->
msg = d.messages[0]
return getTeamInfo()
).then( (d) ->
text = slackMsgToPlainText(msg.text, channels)
url = "https://" + d.team.domain + ".slack.com/archives/" + channel_id + "/p" + ts.replace(/\./, "")
ghrepo = github.repo(repo);
return registerGitHubIssue(ghrepo, truncate(text, 50), url + "\n" + text)
).then( (issue) ->
robot.send {room: channel_id}, "Issue作成完了!\n" + issue.html_url
).catch( (e) ->
robot.logger.error e
robot.send {room: channel_id}, e
)
robot.respond /set (.+)$/i, (res) ->
r = res.match[1]
github.repo(r).info (err, s) ->
if err
res.send "リポジトリ設定に問題があります: #{err.message}"
else
robot.brain.data.repos[res.message.room] = r
res.send "リポジトリを設定しました: #{r}"
robot.respond /get/i, (res) ->
res.send "次のリポジトリが設定されています: " + robot.brain.data.repos[res.message.room]
robot.adapter.client?.rtm?.on? 'reaction_added', registerIssue
今回は、GitHub APIの操作に
、hubot外のSlack APIの操作に
を使いました。
hubotデプロイ
あとはherokuなどにhubotをデプロイして動くようにすれば完了です。
環境変数として、HUBOT_SLACK_TOKEN にSlackのアクセストークン、HUBOT_GITHUB_TOKENにGitHubのアクセストークン、GITHUB_ISSUE_EMOJIにIssue化するときに使うSlack Emoji名の設定が必要ですので、それだけ注意してください。
結果
set (リポジトリ名) で対象のリポジトリ名を設定します。
get で今設定されているリポジトリ名を確認できます
GITHUB_ISSUE_EMOJIのEmoji名で設定したEmoji reactionをつけることでIssueを作成できます。
まとめ
今回はSlackの発言をGitHub Issue化できるhubotの拡張スクリプトを紹介しました。
弊社でも議事録、バグ報告などいくつかの利用例で活用されています。
何かの参考になれば幸いです。