slackでは個別の発言に絵文字でリアクションを送る事ができる。
これをhubotに組み込むと
https://gist.github.com/shokai/d23607d91ea7885a8df7
configに書いてあるchannelにリアクションを通知してくれるようになる
自分が見ていないchannelに関しても、リアクションがあった == だいたいのダイジェストが見れるようになるので便利。
元々はstarを付けた物を通知していたんだけど、
→ slackでふぁぼったのをhubotで通知する
star_addedイベントが来なくなってreaction_addedが来るようになったので書き直した。
star_addedの頃は毎回本文が通知されていたけど、たぶんそれはreadが発生するから重かったんじゃないかと思う。reaction_addedは投稿のIDしか来ない。
hubot-slackアダプタ v3の中で使われているnode-slack-clientを見ていたら、slackで発言に星を付けた時に通知が来ていたのでそれを別のroomに流すようにしてみた。
slackには自分のstarを見る画面はあっても他人のstarを見れる画面がない。API使ってstars.listが取れるけど、starまとめ的なページを作るにはユーザの数だけ定期的にクロールしなきゃだめなのかー・・・と思ってたけど、hubotにサーバープッシュされて来ていた。
starsというroomをあらかじめ作って、hubotを/inviteしておく必要ある
https://gist.github.com/shokai/e52dd7fdd5d2592878b0
# Description:raw_messageイベントは、node-slack-clientがサーバーからwebsocketでJSONを受信してparseしてすぐemitされる。
# notify "star_added" event for slack.com
#
# Author:
# @shokai
debug = require('debug')('hubot:slack-star')
module.exports = (robot) ->
robot.adapter.client?.on? 'raw_message', (msg) ->
return unless msg.type is 'star_added'
debug msg
return unless msg.item.message.permalink
user = robot.adapter.client.getUserByID msg.user
text = ":star: @#{user.name} added star #{msg.item.message.permalink}"
debug text
robot.send {room: 'stars'}, text
これは通常のSlackのAPI(HTTPで使うやつ)ではなくhubot用のwebsocketので、一方通行に受信してるだけなので、こっちからslackに送信できるのはbotの発言命令だけのようだ。hubotにstarつけさせたり、発言を削除したりはできない。
getUserByIDはnode-slack-client内部でcacheされてるので呼び出しまくっても問題ない。
もしstar通知が多くて邪魔になってきたら、3人以上starした発言、とかで通知するroom作ったりしてみようかな
hubot-slackアダプタを今までv2.x系を使っていたんだけど、先月ぐらいに出てたv3系にアップデートした。
hubot-slack アダプタ v2 から v3 へ | 半月記が参考になった。
hubot-rss-readerがv3で動かない機能があったりしたのも直した。
結論
v3系は色々おかしい気がするのでまだv3にアップデートしないほうがいいと思う。とにかく今v2のhubot integrationをslackで使ってるなら、設定画面から削除はしないほうがいい。消したらv3しか使えなくなる。
slackの設定
slackに新規にhubot integrationを追加するとv3じゃないと使えないようになっている。今まで使っていたintegration消して、新しいintegration作ってつなげた。
新規作成時に、hubotにアカウントを設定されるようになった。
/invite @hubotとかして予めチャットメンバーに追加しておかなければならないが、そのかわりprivate roomに参加させられる。
アダプタv2とv3の違い
通信がHTTPからwebsocketになった。hubot側がclientなので、外に丸見えのサーバーじゃなくてもbotが動かせるのは良いと思う。
エラーの内容が読めない
なんかエラー出力がtoString使ってるので[object Object]とか言われて何だかわからない。[Sun Jan 11 2015 16:51:34 GMT+0900 (JST)] ERROR Received error [object Object]これはプルリク送っておいた。
mergeしてもらえればこういうエラーになるはず
[Sun Jan 11 2015 16:59:42 GMT+0900 (JST)] ERROR Received error {"code":-1,"msg":"slow down, too many messages..."}
マジで辛かったのは、これとbrainの爆発が同時に起こってて本当に何がなんだかわからなかった。
いきなりexitする
websocketが切断されたり、単にエラーが起こるだけでprocess.exitが呼ばれるのは豪快すぎる。存在しないroomに送信しようとするとエラー起こってprocess.exitする。
そうじゃなくても連続でsendしたらclientが落ちてプロセスも落ちる。hubot-rss-readerはqueueを作って500msecごとにsendするようにした。
いきなりexitする件は#127で議論されていて、slackのサーバー側が返すエラーコードに応じて自動再接続するか処理を分岐したいらしい。
room名の頭に#が付けられない
robot.send {room: "#hoge"}, "こんにちは"じゃだめで
robot.send {room: "news"}, "こんにちは"とする必要がある。
自分が使ってたスクリプトも#つけてるのが結構あったので、ここでエラーになってた。#つけても大丈夫にするプルリク送っておいた。
websocket接続するまでrobot.sendが無い
起動した時に通知を送るようにしている。
v2まではHTTPだったから、これでよかったけど
module.exports = (robot) ->
robot.send {room: "news"}, "Hubot、起動しました"
v3ではwebsocketが接続するまでrobot.send関数が存在しないので、sendが生えてくるまで待つようにした。
module.exports = (robot) ->
cid = setInterval ->
return if typeof robot?.send isnt 'function'
robot.send {room: "news"}, "Hubot、起動しました"
clearInterval cid
, 1000
hubotって、まずrobot.adapterがチャットサービスに接続してconnectedイベントをemitして、それを受けてからscripts以下のcoffeeやjsが読み込まれるはずなんだけど、slackアダプタはなぜかscripts読み込まれた後でもまだadapterが接続されてない。connectedとは一体何なのか。
これはhubot-slackの下で使われてるnode-slack-clientの問題だったので、プルリクしておいた。
作った。
https://github.com/masuilab/rss-slackbot
主にgithubと、研究室の人のblogの更新をSlackに通知するのに使ってる。
Slackに最初からあるRSS integrationは、entryのdescriptionを埋め込んでしまうのでgithubのRSSを読み込ませるとデカくなって邪魔だった。
githubとかはURLをpostすれば適当にかっこよくslackがチャットにembedしてくれるので、titleとURLだけpostする感じにした。
あとたくさんfeedを管理するのもwebで1つずつ登録したりとか面倒なのでgithubでプルリクとかでやりたい。
RSS追加したい人はconfig.json編集してください。
docker/dokkuで動かしたかったので、crontabとかDBとか使うのやめた。
titleとURLなんて大したサイズ量じゃないから全部オンメモリでいいやという事でsetIntervalで定期的に見に行くだけにしてみた。
slackでhubotに頼むとドアあけてくれるようになった。hubotはじめて使った。
増井研はインドア派なので、ハローワールドするためにドアを開ける。
あと部屋を指定してスピーカーからmacのsayが流せる。
iBeaconで位置をはかって、誰が近づいたとか通知される。
試験的に、近づいたらドア勝手に開くようにしてみた。
電気ついたりとか、そういうセンサー値の大きな変化も通知される。
hubotがslackにつながってて、コマンドを待ち受けたりしてる。センサーとか実世界系の操作はnode-lindaに投げてる。
node-lindaの下にはraspberry pi+arduino+センサやサーボモータ色々のセットとか、dockerコンテナとかがたくさんぶら下がってて、色々処理してる。
そのうちくわしく書く羽目になると思う