CoffeeScript
Hubot
Heroku
Slack

褒めあえる仕組みをslack hubot で作る

ベイエリアで働くエンジニアがやりやすいと感じる会社の特徴5つの中で、”Traveling Narwhal"という仕組みがあり、ウチの会社でもやってみたいと思いました。どんな仕組みかといいますと、

変なぬいぐるみが数体おり、これを受け取った社員は2週間後に、自分が最もお世話になった相手にこれを渡すというルール

というものだそうです。

本家と同様、可愛いぬいぐるみでマニュアルでやるのが良いかと思ったけど、slackのbotにしちゃうのも更に気軽に触れるし、みんなで認知できるからいいんじゃないかと思い作ってみました。

要件

  • メンバー同士で定期的にお互いを褒め合える
  • メンバーみんなが褒められた人となぜ褒められたかを認知できる

そんな訳で、下記の様な仕様で考えました。本家の traveling という部分を生かして、botが、メンバーという旅先を渡り歩く様なイメージで考えています。

仕様

  • 旅先リストに登録する(=メンバー登録)
  • 旅先リストを見る(=メンバー一覧)
  • 次の行先を指示する(=誰かを褒め称える)
  • 今どこに居るの?(=誰が褒め称えられてるかを見る)
  • そろそろ別の場所に旅したい(=一定期間後に別の人を褒める為のリマインダ)
  • 滞在先の感想をつぶやく(=褒められた人を認知してもらうための遊びツィートをする)

etc...

実装

開発は終わっちゃっているようだけどネットの情報量が多いのでhubotを使って実装してます。hubot用意する部分迄はslack用hubot作成時のメモの通り。

▽スクリプト部分

traveling.coffee
cronJob = require('cron').CronJob
random = require('hubot').Response::random

module.exports = (robot) ->
  keydest = 'dest'
  keystay = 'stay'
  keytime = 'deptime'
  envelope = room: "#general"
  length = 6044800 # 滞在期間をミリ秒で指定

  getMembers = ->
    robot.brain.get(keydest) ? []

  # get registerd members
  robot.hear /traveling dest list/i, (msg) ->
    members = getMembers()
    msg.send members.toString()

  # 今どこに居るの?
  robot.hear /traveling where/i, (msg) ->
    stay = robot.brain.get(keystay)
    unless stay?
      msg.send "今家にいるよ"
      return

    msg.send "#{stay} に滞在中だよ"

  # 旅先リストの登録
  robot.hear /traveling dest add (.+)/i, (msg) ->
    member = msg.match[1]
    members = getMembers()
    if member in members
       msg.send "#{member}は既に行き先の一つだよ"
       return

    if members.length is 0
       tmpMembers = []
    else
       tmpMembers = members

    tmpMembers.push member

    robot.brain.set keydest, tmpMembers
    msg.send "旅先候補地 -> #{tmpMembers.toString()}"

  # 行先の指示
  robot.hear /traveling recommend (.+) (.+)/i, (msg) ->
    user = msg.message.user.name
    member = msg.match[1]
    reason = msg.match[2]
    members = getMembers()
    if member not in members
       msg.send "#{member}?知らないなー"
       return

    # 規定の期間迄は旅に出ない
    tmpTime = robot.brain.get(keytime) ? 0
    d = new Date
    if d.getTime() - tmpTime < length
       msg.send "もうちょっとここに居たいよー"
       return

    msg.send "@#{user} 分かった! 次は#{member}に行こうと思うよ。今日までありがとう!さよなら!"
    msg.send "@#{member} こんにちは #{member}! #{user}に< #{reason} > とお薦めされて来ました。しばらく厄介になるね!"
    robot.brain.set keytime, d.getTime()
    robot.brain.set keystay, member

  # 滞在先の感想をつぶやく
  new cronJob('0 0 13,18 * * 1-5', () ->
    stay = robot.brain.get(keystay)
    unless stay?
      return

    result = random [
        "#{stay} は居心地が良くて楽しい!"
        "また #{stay} に来たいと今から思っちゃう!"
        "#{stay}の素晴らしさをみんなに伝えたい!"
    ]
    robot.send envelope, "#{result}"
  ).start()

  # そろそろ別の場所に旅したい
  new cronJob('0 30 9-12 * * 1-5', () ->
    tmpTime = robot.brain.get(keytime)
    unless tmpTime?
      return

    d = new Date
    if d.getTime() - tmpTime > length
       stay = robot.brain.get(keystay)
    robot.send envelope, "@#{stay} そろそろ別の場所に行きたいな。お薦めはどこかある?"
  ).start()

デプロイ

後はslackにてお決まりの形でデプロイ。永続化の為 heroku redis も利用。

heroku login

heroku create [app_name]
heroku git:remote -a [app_name]
git init
git add .
git commit -m "first commit"
git push heroku master

heroku addons:create heroku-redis:hobby-dev
heroku config # REDIS_URLのセットを確認
heroku addons | grep heroku-redis # redis_nameの確認
heroku redis:timeout [redis_name] --seconds 60 --app [app_name]

heroku config:set HUBOT_SLACK_TOKEN=[slackにて控えておいたAPIトークン]
heroku config:set HUBOT_SLACK_BOTNAME=[app_name]
heroku config:set HUBOT_HEROKU_KEEPALIVE_URL=[appのURL]

heroku restart --app [app_name]