SlackのEmoji reactionsを集計してコミュニケーションの可視化を図った話

こんにちは。yoshitsuguといいます。 しくみブログでは初寄稿です。

この記事は 『Slack Advent Calendar 2016』14日目の記事です。

皆さんはチャットツールをどのくらい活用されているでしょうか?

フルリモートワークの弊社にとって、SlackでのやりとりはDiscordと同様、なくてはならないものとなっています。

SlackではEmoji reactionsという、発言に対してEmojiで反応できる機能があります。 弊社でもEmoji reactionsはよく活用されていて、独自のEmojiもたくさん追加されています。

日頃頻繁にreactionのやりとりをしていると、誰がどのくらいreactionを受け取ったんだろう?というのが気になってきませんか?

受け取ったreactionの数を見せることで次のreactionの動機にもつながりそうです。 そこで今回は、誰がどのくらいのreactionを受け取ったのか、可視化してみることにしました。

今回のゴール

今回はhubotに組み込む形でEmoji reactionsの集計と集計結果を出力をすることにします。

どう集計するか、についてですが、例えば、「昨日、yoshitsuguは :ok: 2個、 :+1: 1個もらった」という感じの出力を想定します。

hubotの活用

弊社Slackにはkibotという名前のbotが住んでいます。彼(彼女?)はDocomo雑談APIなど、巷にあふれるhubotプラグインを搭載しており、Slackを和やかにするという大切な役目を担っています。

image

今回はこのkibotに組み込んでいきます。

Slack APIの確認

さて、reactionの集計にはどのような情報が必要になるでしょうか?

Emoji reactionsは発言にひもづく形式なので、

  • 昨日の発言一覧
  • 各発言に対するreaction一覧

が必要そうです。

Slack APIのドキュメントを眺めてみると、channels.history で上にあげた両方がとれそうです。

また、Slack API上はユーザーがSlack内部IDのような形式でやりとりされます。実際のユーザー名をひいてくるためには、

を使うとよさそうです。

作ってみる

上記のSlack APIを使って集計できるように、以下のように書いてみました。

cron = require('cron').CronJob
dateformat = require('dateformat')
Q = require('q')
Slack = require('slack-node')

to_unixtime = (time) -> Math.floor(time.getTime()/1000)

module.exports = (robot) ->
  slack = new Slack(process.env.HUBOT_SLACK_TOKEN)
  weekdays = [ "日", "月", "火", "水", "木", "金", "土" ]

  countEmoji = ->
    today = new Date()
    yesterday = new Date(new Date(today.toString()).setDate(today.getDate() - 1))
    # 月曜なら金曜日をみる
    if today.getDay() is 1
      yesterday = new Date(new Date(today.toString()).setDate(today.getDate() - 3)) 
    date = dateformat(yesterday, 'yyyymmdd')
    date_str = "#{dateformat(yesterday, 'yyyy/mm/dd')}(#{weekdays[yesterday.getDay()]})"
    yesterday_begin = new Date(dateformat(yesterday, 'yyyy/mm/dd') + " 00:00:00")
    yesterday_end = new Date(dateformat(yesterday, 'yyyy/mm/dd') + " 23:59:59")
    api = Q.denodeify slack.api
    apis_by_channel = []
    apis_by_channel_options = []
    result = {}

    api("channels.list").then (response) ->
      for c in response.channels
        option = {channel: c.id, latest: to_unixtime(yesterday_end), oldest: to_unixtime(yesterday_begin), count: 1000}
        apis_by_channel_options.push(option)
        apis_by_channel.push(api("channels.history", option))
      return Q.all(apis_by_channel)
    .then (values) ->
      for i in [0..(values.length-1)]
        reactions_get_qs = []
        v = values[i]
        for m in v.messages
          reactions = m.reactions
          reactions = m.file.reactions if m.file?.reactions
          if reactions
            user = robot.adapter.client.rtm.dataStore.getUserById(m.user)?.name
            result[user] = {} unless result[user]
            for r in reactions
              result[user][r.name] = 0 unless result[user][r.name]
              result[user][r.name] += r.count
      results_str = "#{date_str}の集計結果です。\r\n"
      for name, r of result
        results_str += "#{name}: \t"
        for emoji, count of r
          results_str += ":#{emoji}:: #{result[name][emoji]}, "
        results_str += "\r\n"
      robot.send {room: '#general'}, results_str
    .catch (err) ->
      robot.logger.error(err)
      robot.send {room: '#general'}, '集計中にエラーがおきました'

   # 平日のみ、12時に集計
   new cron '0 0 12 * * 1-5', () ->
     countEmoji()
   , null, true, "Asia/Tokyo"


試してみる

実際にこのコードを動かしてみると以下のようにkibotが集計結果を投げてくれるようになります。

image

人ごとに絵文字が集計されていることがわかります。 次のコミュニケーションにつながりそうですね。

今後の展望

現状、誰の発言が盛り上がったか、という点で可視化できましたが、以下のような問題もあります。

  • 集計結果をテキストで並べるだけだとわかりにくい
  • 誰の発言だけではなく、どの発言に注目が集まったかも見たい

今後の展望として、少しフォーマットを変えて提供してみることを検討しています。

検討中のフォーマットの例をあげると、以下のように、「今日の神」を表示する、というものです。

image

弊社ではよくカスタムEmojiの :kami: を使います。

image

これは「すごく助かった」、「すごく有用」、「すばらしい仕事」などをあらわす時に使います。 この「神」reactionをたくさんもらった人を「今日の神」として崇めるようなフォーマットを提供できると楽しそうだなーと思っています。

最後に

今回、hubotをベースに、SlackのEmoji reactionsを集計した話をご紹介しました。

皆さんもSlackでのコミュニケーションを活性化して、楽しく仕事ができるよう、工夫してみてはいかがでしょうか。

それでは。