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


[ベイエリアで働くエンジニアがやりやすいと感じる会社の特徴５つ](https://qiita.com/hiroyamada/items/aa12af972075919eeba1)の中で、”Traveling Narwhal"という仕組みがあり、ウチの会社でもやってみたいと思いました。どんな仕組みかといいますと、
> 変なぬいぐるみが数体おり、これを受け取った社員は２週間後に、自分が最もお世話になった相手にこれを渡すというルール

というものだそうです。

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

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

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

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

etc...

# 実装
開発は終わっちゃっているようだけどネットの情報量が多いのでhubotを使って実装してます。hubot用意する部分迄は[slack用hubot作成時のメモ](https://qiita.com/tmkt/items/4e6aaac0711da937384a)の通り。


▽スクリプト部分

```coffeescript: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]
```