この記事に書いてあること
初めてHubotスクリプトを書いた時に調べたこと(Hubotのドキュメントに書いていなかったこと)をまとめました。
- 発言者のnameの取得
- 発言時刻の取得
- KVSへ配列で要素追加/抽出したい時
CoffeeScriptなんて触ったことないけど何か作ってみたいなぁ、という方の背中をそっと押せれば幸いです。
※ほぼほぼ同内容を弊社ブログにも投稿してます
作ったものと、その動機
簡単なタスクトラッキングができるbotを作りました。
-
now hogehoge
と発言すると、発言内容hogehoge
と時刻と発言者を記録 -
hubot today
と発言すると、今日分の発言内容と時刻を全て出力
こんな仕様です。シンプルですね。
使用感はこんな感じ。一日中ブログしかやってないなこいつ
作った動機ですが、
弊社では日報作成時に、その日1日の作業内容と時刻を報告しています。
適当なタイムトラッキングツールなどを利用してもよかったのですが、
- あんまり大したものでなくていいのに見つけられなかった
- hubotスクリプト作ってみたいという自分のモチベーション
及び、
- 誰が今何を手がけているか、をチームへゆるく共有できれば便利ではないか
という副次的効果も狙ってslack経由でタイムトラッキングさせることにしました。
というわけで実装です。
「このデータ欲しいときどう書くの」集
主にHubotのドキュメントを読めばそれなりのことはできるようになるのですが、
上記の仕様を実現する際に、ドキュメントだけでは足りなかった知識をまとめます。
「javascript,CoffeeScriptは普段ほとんど書かないがなんか作りたいなー」ぐらいの方向けです。
なお、環境構築周りの内容は含みません。
発言者のnameの取得
msg
で受けた場合、 msg.message.user.name
で取得できます。
robot.hear /^now (.*)/i, (msg) ->
user = msg.message.user.name
こんな感じ。
これに限らずですが、一度は console.log
で中身を覗いてみることをオススメします。
発言時刻の取得
発言時刻ってどこに格納されてるんだろう?とずいぶん探してしまったのですが、普通にnew Date
すれば良いだけの話でした。
robot.hear /^now (.*)/i, (msg) ->
date = new Date
但し、未検証ですが恐らくサーバの内部時計の時刻が反映されてしまうので、日本時間で動いていない場合は別途調整が必要です。
KVSへ配列で要素追加/抽出したい時
これはhubot云々というよりKVSの使い方?寄りの話なのかなと思いますが、
発言内容の記録部分を実装するにあたり、当初は連想配列のような形でレコードを保存し、
発言日時をキーとしてレコードを引っ張ってくるような設計をイメージしていましたが、途中で行き詰まってしまいました。
なので、jsonで全部取得→末尾に要素追加→全部保存、という形で実装しました。
# keyを設定
key = "timeTracker"
# 要素の保存
tasks = robot.brain.get(key) ? [] # keyを元に全要素を持ってくる。なければ空配列をセット
task = { text:"文字列" } # 追加要素を作成
tasks.push task # 全要素の末尾に追加
robot.brain.set key, tasks # すべての要素を保存
特定の発言日時の要素を取得する場合はfilter
で抽出すればOKでした。
# keyを設定
key = "timeTracker"
tasks = robot.brain.get(key) ? [] # keyを元に全要素を持ってくる。なければ空配列をセット
message = tasks.filter (task) ->
task.date == '日時' # 日時で抽出
.map (task) ->
"#{task.text}" # 発言内容を組み立てる
.join '\n'
できあがり
後は日時の成型用の関数とか発言内容の保存したい内容とか諸々を付け加えて、最終的に出来上がったのがこちらです。
# Description:
# simple time tracker.
#
# Commands:
# now <text> - save datetime, <text>
# hubot today - export all todays datetime, <text>
# 時刻を受け取ってYYYY-mm-dd形式で返す
toYmdDate = (date) ->
Y = date.getFullYear()
m = ('0' + (date.getMonth() + 1)).slice(-2)
d = ('0' + date.getDate()).slice(-2)
return "#{Y}-#{m}-#{d}"
# 時刻を受け取ってhh:mm形式で返す
tohhmmTime = (date) ->
hh = ('0' + date.getHours()).slice(-2)
mm = ('0' + date.getMinutes()).slice(-2)
return "#{hh}:#{mm}"
module.exports = (robot) ->
# keyを設定
key = "timeTracker"
# hubot now <test> に反応させる
robot.hear /^now (.*)/i, (msg) ->
# 発言から内容を取得。date,text,userの3つ
date = new Date
text = msg.match[1]
user = msg.message.user.name
tasks = robot.brain.get(key) ? []
task = { user: user, date: toYmdDate(date), time: tohhmmTime(date), task: text }
tasks.push task
robot.brain.set key, tasks
msg.reply "task saved! #{tohhmmTime(date)} #{text}"
robot.respond /today$/, (msg) ->
date = new Date
user = msg.message.user.name
tasks = robot.brain.get(key) ? []
message = tasks.filter (task) ->
task.date == toYmdDate(date)
.filter (task) ->
task.user == user
.map (task) ->
"#{task.time} #{task.task}"
.join '\n'
msg.reply "#{message}"
雑感
- 大雑把に1日を振り返るにはちょうど良い使用感
- 自分で作ったものはやっぱり愛着が湧くので、三日坊主になってないです。今の所は。
- ゆるく宣言してから作業開始するので、集中モードへ頭を切り替えるスイッチとして機能している嬉しい副作用もあった