Rocket.Chat用のHubot作成手順です。
2018/06/14追記
https://rocket.chat/docs/bots/ にはbotkitなどの記載もありますが、現在は開発中で未リリースです。
また、hubotも https://rocket.chat/docs/bots/running-a-hubot-bot/ にはボイラープレートからの作成なども記載されていますが、これも開発中です。
bot系は開発フレームワークなども含め、強化検討されているようです。 slack の Interactive messages のような機能も検討されています。
2018/07/26追記
- hubot-rocketchat v1.0.12 に気づいたので追記。
- hubot-rocketchat v1.0.9 からenvelope, message, userのroomの値がIDから名称に変更されたのに気づいたので追記。
-
yo hubot
すると、hubot-rocketchat v2.0.0 が入ってしまう問題に気付いたので追記。
2018/10/15追記
ボイラープレートを使用するv3系については、ボイラープレートは未だ NB: THIS IS A WORK IN PROGRESS
だし、アダプタもv2系リリースタグ無し(なぜかnpmにはv2が上がっている)。またアダプタ内で使用されている @rocket.chat/sdk のバージョンが古い(v0.1.0)などにより、 still beta と判断。
-
yo hubot
すると、hubot v3.1.1 が入ってしまう問題に気付いたので追記。
2018/12/14追記
一昨日くらいにSnapでRocket.Chat 0.72.1 が降ってきたタイミングで、botが一部反応しなくなった。
ROCKETCHAT_ROOM
でroomを指定していると反応しない。hear, respondなどの応答系が全滅。。
LISTEN_ON_ALL_PUBLIC=true
付けると反応する。が、、全roomで反応。
1つ前のバージョンの Rocket.Chat 0.71.2 を立てて正常に動作することを確認。
rocketchat_driver.coffee 内の setupReactiveMessageList メソッド内の changedMsg.args[1] が {}
になっている所まで確認。
試しにhubot 3系で動作確認したが、同様に動作しない。
このissueか?
2018/12/16追記
SnapでRocket.Chat 0.72.3 が降ってきて、正常に戻った。
changedMsg.args[1]
に値が入ってくるように戻っていた。
対象
Rocket.Chat : 0.55.0 くらいで動作確認。
node : 6.10.x
開発言語 : JavaScript(≠CoffeeScript)
Hubotの開発環境作成
node, npmをインストールします。
その後、Hubot開発に必要な yo
, generator-hubot
をインストールします。
参考:https://hubot.github.com/docs/
# 未インストール時のみ
npm install -g yo generator-hubot
Hubot作成
雛型生成
yoで雛型生成します。
mkdir myhubot
cd myhubot
yo hubot
# 対話式で色々聞かれるが、adapterに rocketchat を指定すればとりあえずはOK
# hubot-rocketchatも一緒にインストールされる
# ******** 2018/10/15追記 ********
# yoがv3.1.1を入れてしまうので、ダウングレードする。
npm install hubot@2.19.0
# ******** 2018/07/26追記 ********
# yoがv2.0.0を入れてしまうので、ダウングレードする。
npm install hubot-rocketchat@1.0.12
2017/09/07 現在、ここでインストールされるhubotはnpmに登録されているv2.19.0です。
githubのv3.0.1を使用すると、正常に動作しないようです。
2018/10/15 現在、ここでインストールされるhubotはnpmに登録されているv3.1.1です。
v2系にダウングレードする必要があります。
hubot-rocketchat
は Rocket.Chat用のHubot adapter で https://github.com/RocketChat/hubot-rocketchat で開発されています。
2018/05/01 v2.0.0 リリース ※don't use this!! yoでの生成とhubot v2が非サポートになったので使ってはいけない。
2017/10/10 v1.0.12 リリース ※githubでタグ打ちされていないバージョン。 npm に登録されていた。
2017/08/08 v1.0.11 リリース
2017/07/26 v1.0.10 リリース
2017/07/14 v1.0.9 リリース ※破壊的変更あり
とりあえず動作確認
環境変数を設定し、Hubotを起動します。
# 環境変数設定
export ROCKETCHAT_URL=http://192.168.0.123:3000
export ROCKETCHAT_ROOM=general
export ROCKETCHAT_USER=chabot # botのユーザー
export ROCKETCHAT_PASSWORD=chabotpassword # botのパスワード
export ROCKETCHAT_AUTH=password
# adapterにrocketchatを指定して起動
bin/hubot -a rocketchat
以下を確認。
- Rocket.Chat の general にボットユーザーが参加されていることを確認。
-
chabot ping
と打ち、PONG
と帰ってくることを確認。
Ctrl+Cで終了。
ここまでで、基本的な枠の作成は完了です。
不要なパッケージ削除
yoで生成した雛型には不要なパッケージが色々入っているので削除します。
私はデータ保持にはredisは使わず、代わりにnedbをよく使用している為、以下ではhubot-redis-brain
も消してます。
# 全無まとめて削除Ver.
npm uninstall hubot-diagnostics hubot-google-images hubot-google-translate hubot-help hubot-heroku-keepalive hubot-maps hubot-pugme hubot-redis-brain hubot-rules hubot-scripts hubot-shipit --save
# ping等
npm uninstall hubot-diagnostics --save
# リスの画像
npm uninstall hubot-shipit --save
# heroku用
npm uninstall heroku-keepalive --save
# map
npm uninstall hubot-maps --save
# help
npm uninstall hubot-help --save
# google-translate
npm uninstall hubot-google-translate --save
# google-images
npm uninstall hubot-google-images --save
# パグの画像
npm uninstall hubot-pugme --save
# ロボット3原則
npm uninstall hubot-rules --save
# DEPRECATED
npm uninstall hubot-scripts --save
# redisを使ってデータを保持したい場合使用。
# 私はnedb使ったりするので削除。
npm uninstall hubot-redis-brain --save
不要なファイル削除
以下のファイルを削除します。
-
external-script.json
外部botコードを使用しないので削除します。 -
hubot-script.json
hubot-scriptを使わないので削除します。 -
bin/hubot.cmd
本番でwindowsで動作させたい場合などは残します。
windowsで開発する場合もGit for Windowsが入っていると思うのでbash.exeで問題なければ基本使わないハズ。 -
scripts/example.coffee
サンプルコードなので削除します。
nodeのバージョン変更
package.jsonに記載されているenginesのバージョンが古いので動作させるnodeのバージョンに書き換えます。
"engines": {
"node": "6.10.x"
}
起動スクリプト編集
私は bin/hubot
に環境変数などを以下のように書いて起動しています。
また、本番環境では Systemdに登録して起動しています。
#!/bin/sh
set -e
export ROCKETCHAT_URL=http://192.168.0.123:3000
export ROCKETCHAT_ROOM=wg-sandbox
export ROCKETCHAT_USER=chabot
export ROCKETCHAT_PASSWORD=chabotpassword
export ROCKETCHAT_AUTH=password
npm install
export PATH="node_modules/.bin:node_modules/hubot/node_modules/.bin:$PATH"
exec node_modules/.bin/hubot --name "chabot" -a rocketchat
メイン処理ファイル作成
scripts
ディレクトリ以下にjsファイルを作成します。ファイル名は任意です。
私は main.js
を作成しています。
// Description:
// 先頭に"// Description:"コメントを書いておかないと起動時に警告(INFOだが)が出る。
module.exports = (robot) => {
// ここに処理を記述する。
robot.respond(/hoge/i, (res) => {
res.send("hoge!!!");
});
};
※開発言語について
Hubotのデフォルト開発言語はCoffeeScriptですが(v3系(#1347)からJavaScriptに移行してました)、scriptsフォルダにJavaScriptファイルを置いても実行されます。Rocket.ChatもCoffeeScriptからJavaScriptに移行していますし、私はJavaScriptで書いています。
参考:https://github.com/RocketChat/Rocket.Chat/issues/796
メッセージ投稿処理について
基本応答
ユーザーの投稿に反応して応答を返す場合、robot.hear
や robot.respond
の応答関数の引数のメソッド res.send
を使用します。
デフォルトでは新規投稿にしか反応しません。編集投稿に反応するようにするためには環境変数 RESPOND_TO_EDITED=true
を設定する必要があります。
2017/09/07 現在 hear
内でメッセージ( res.message
)が新規か編集かを判別する手段は無いようです。どうしても必要な場合、Rocket.Chat用のHubot adapterの recketchat.coffee
にコードを1行追加して hear
内で判別可能なようにできます。
// Description:
// 先頭に"// Description:"コメントを書いておかないと起動時に警告が出る。(INFOだが)
module.exports = (robot) => {
robot.hear(/hoge/i,(res) => {
res.send("hoge! 全ての投稿でhearが含まれる投稿に反応して発言する。");
});
robot.respond(/piyo/i,(res) => {
res.send("piyo! botの名前+piyoが含まれる投稿に反応して発言する。");
// 注意:
// ここでのbotの名前はbin/hubotの中に書かれている --name 【名前】でも反応する。
// これはyo hubot時に質問されるbotname。
// ボット名はアットマークなしで反応する。
});
};
能動的に投稿
cron
や node-schedule
などを使用して、定時に投稿する場合などは、 robot.send
を使用します。
2017/09/07 今更ながら robot.messageRoom
を発見。こちらの方がシンプル。
// チャンネル名を指定する必要があります。
robot.send({ room: "wg-hoge" }, "hogeeeee!");
// こっちのほうがシンプル。
robot.messageRoom("wg-hoge", "hogeeeee!");
テキスト以外の情報を含むメッセージ投稿
テキスト以外の情報を含める場合、メッセージオブジェクトを作成して send に渡します。
robot.hear(/hoge/ig, (res) => {
// 文字列のみ
res.send("hoge?!");
// 絵文字もOK
res.send("emoji! :ok:");
// メッセージオブジェクトを作って送信
const message = {
msg: "message here!",
attachments: [{
"text": "text here! :tada:",
"color": "#ff0000",
"alias": "別名を表示させたいときに設定",
"avatar": "投稿者アイコンにアバターを表示させたいときに設定。URLを指定する。",
"emoji": "投稿者アイコンに絵文字を表示させたいときに設定。ex. :ok:",
"fields": [{
"short": true,
"title": "ok (no title emoji :ok: )",
"value": "[Link](https://google.com/) *bold* _italic_ "
},{
"short": true,
"title": "ng",
"value": "no emoji :tada: , \r\n %0a no newline, no `inline` "
}]
}]
};
res.send(message);
});
// 自発的に投稿、またはチャンネルを指定して送る場合、robot.sendを使う。
robot.send({ room: "wg-hoge" }, "hogeeeee!");
// メッセージオブジェクトを作って送信
const message = {
msg:"send to wg-hoge!",
attachments: [{
"text": ":ok: emoji OK!",
"color": "#FF0000"
}]
};
robot.send({ room: "wg-hoge" }, message);
// こっちのほうがシンプル。
robot.messageRoom("wg-hoge", message);
Hubotのsend時のメッセージオブジェクトのドキュメントは今のところ発見できず、rest-api や realtime-api 見ながら探してます。
今のところ msg
, attachment
でほぼ事足りています。
avatar
は自分のQiitaのアイコンURLでも表示されました。
res(RocketChatResponseオブジェクト)の中身
robot.hear
やrobot.respond
などのコールバック関数の引数のres
について。
Rocket.Chat Hubot adapter定義クラス(Hubot定義クラスを継承)。
メソッド
メソッド | 実装箇所 |
---|---|
sendDirect | RocketChatBotAdapterのsendDirect |
sendPrivate | RocketChatBotAdapterのsendDirect |
send | RocketChatBotAdapterのsend |
emote | RocketChatBotAdapterのemote |
reply | RocketChatBotAdapterのreply |
その他topicやplayなどもあるがRocketChatBotAdapterで未実装のため使用不可。
プロパティ
いろんなところにroomやmessage, userが入ってて紛らわしいですが、全て同じ情報が入っています。
2018/07/26追記
※1: roomについて、1.0.9からルームIDではなくルーム名が入るようになったようです。(破壊的変更)
また、1.0.10からダイレクトメッセージ、ライブチャットの場合はIDがセットされています。
プロパティ | 内容 |
---|---|
robot | 上位のrobotと同じ。 |
message | TextMessageオブジェクト |
match | マッチ配列。String.match()の戻り値と同様(g付き時にinput, indexが無いとかナントカ) |
envelope | エンベロープ。room, user, messageが入っています。 |
res.envelope
プロパティ | 内容 |
---|---|
room | ルーム名 ※1 |
user | Userオブジェクト |
message | TextMessageオブジェクト |
TextMessageオブジェクト
Hubot定義クラス。
メッセージ内容が入っています。出現箇所は以下。
- res.message
- res.envelope.message
プロパティ | 内容 |
---|---|
user | Userオブジェクト |
text | 投稿メッセージ内容 |
id | メッセージID(内部ID) |
done | 処理済みフラグ。これを true にすると後続のhear やrespond が処理しない。listenは通った。 |
room | ルーム名 ※1 |
Userオブジェクト
Hubot定義クラス。 id
, name
以外は自由っぽい。
投稿したユーザーの情報が入っています。出現箇所は以下。
- res.message.user
- res.envelope.user
- res.envelope.message.user
プロパティ | 内容 |
---|---|
id | ユーザーID(内部ID) |
name | ユーザー名(名前ではない) |
alias | エイリアス(無い場合undefined) |
room | ルーム名 ※1 |
roomID | ルームID(内部ID)※1.0.9で追加された。 |
roomType | ルームタイプ ※1.0.12で追加された。※2 |
※2: ルームタイプ(他にもあるかも)
値 | 内容 |
---|---|
c | パブリックチャンネル |
p | プライベートチャンネル |
d | ダイレクトメッセージ |
Hubotの運用環境
基本node, npmが入っていれば問題ないです。
環境変数について
https://rocket.chat/docs/administrator-guides/hubot#configuration-options https://rocket.chat/docs/bots/configure-bot-environment/ に説明は書いてありますが、ハマったり、よくわからなかった設定値について動作確認した記録です。
2018/06/14追記
URLが変わってました。
ROCKETCHAT_URL
ROCKETCHAT_URL=http://192.168.0.123:3000/
のように最後に /
を付けると正しく動作しません。
0.46.0以前くらいでは起動していた時期がありました。
LISTEN_ON_ALL_PUBLIC
基本的にボットが参加しているチャンネルすべてでlistenしますが、
LISTEN_ON_ALL_PUBLIC=true
を指定して起動した場合、ボットが参加していないチャンネルもlistenします。
応答した場合は、ボットは未参加のままメッセージが投稿されます。
この値が設定された場合、 ROCKETCHAT_ROOM=''
とするべき、と書いてあります、理由は不明。
hubot-rocketchat内部で LISTEN_ON_ALL_PUBLIC=true
の場合、 ROCKETCHAT_ROOM=''
が設定されるようになっていました。
ROCKETCHAT_ROOM
ROCKETCHAT_ROOM=random
ボット起動時、ボットが指定チャンネルに参加していない場合、参加します。
ここに記載していないチャンネルでもユーザーがボットを参加させると listen するようです。
RESPOND_TO_EDITED
ボットはデフォルトでは新規投稿時にしか反応しません。(default: false)
RESPOND_TO_EDITED=true
とすることにより、編集時にも反応するようになります。
PORT
Hubotのパラメーター。
HubotにはExpressが内蔵されていて、ポートを指定しない場合、デフォルトの8080が使用されます。
そのため、同一端末で2つのHubotを起動すると、後から起動したHubotの8080が使えず、起動時にエラーログが出力されます。
Expressの機能を使わない場合、hubot起動オプションで--disable-httpd
または-d
を指定します。