こんにちは。麦芽系エンジニアasmzです。麦芽は東北産を使用しています。そろそろビアガーデンとか行きたいです。誰か誘って下さい。よろしくお願いします。
さて、私はこれまで
とかでちょいちょい弊社Hubot(otobot君)に機能追加してきて、「この人Hubotばっかりやってるけど、実はオトバンクのHubot開発担当の人なのかしら?何なのかしら?窓際社員なのかしら?」と思われがちです。違います。何ですかHubot開発担当って。
まぁ主に仕事に疲れた時の気晴らしとかに、一人で勝手に作ってます。何故か深夜にプルリク出ることが多いやつです。
otobot君も最初はそんなに社内で活用されてたわけでも無いのですが、otobot image me
でおもしろ画像表示して遊ばれたり(専用のSlackチャンネルまである)、ランチ情報を取ってこれるようにしたりしたおかげか、最近になってやっと社内でも日の目を見始めてきました。
で、「お前、ちょっとHubotのこと教えろや」と興味を持つ人が出てきたので、こないだ社内の開発チーム向けにHubotスクリプト勉強会を開催しました。ちなみに、勉強会はエンジニアだけでなくデザイナーさんとかも出席してくれているので、内容としてはだいぶ入門編的なものになっています。
そういう経緯なので、既にご存知の方は物足りない内容だと思いますし、ググればいろいろ似たような記事はあるんですが、せっかく作った資料が埋もれるのも勿体無いのでここで公開してみます。誰かの参考になれば幸いです。
それでは、はりきってどうそー
はじめに
Hubotとは
Hubot is your company's robot.
某Pep◯erさんとは無関係です。念のため。
Hubotのインストール
以下のドキュメントが参考になりますので、各自の環境に導入してみてください。
otobotはちょっとバージョン低いので若干違いますが、導入後の仕組みは概ね同じと思ってもらってよいです。
Hubotの構成と仕組み
Hubotプロジェクトは基本的に以下のようなディレクトリ構成
otobot(例) ├── Procfile ├── README.md ├── bin │ ├── hubot │ └── hubot.cmd ├── external-scripts.json ├── hubot-scripts.json ├──node_modules │ └── ... ├── package.json └── scripts └── *.coffee
Hubotの実行
./bin/hubot
が起動スクリプト
$ ./bin/hubot --adapter shell
--adapter
は「アダプター」(後述)を指定するオプション
まずは自分のターミナルで実行してみるためにshell
を指定(まぁデフォルト値なんですけど)
$ ./bin/hubot --adapter shell myhubot> (幾つかメッセージ出るけど、今はとりあえず無視) myhubot> myhubot ping PONG myhubot>
Hubotアダプター
- 特定のチャットに依存しないための仕組み
- チャットに対応したアダプターを用いることで、そのチャットと連携することができる(下図真ん中辺りの紫色の部分)
- otobotはSlack上で動作するので、実際は
./bin/hubot --adapter slack
みたいな感じで実行
POINT
- アダプターが実行環境周りのコトを吸収してくれる
- 実際のHubotの処理(図の緑色の部分)を作るときには環境のことは気にしなくていい
Hubotスクリプトを作ってみよう
Hubotスクリプトを作る前に
どうやってHubotスクリプトが読み込まれているのかを理解しましょう
./bin/hubot
実行後
scripts
ディレクトリ以下にある「*.coffee
」読み込みexternal-scripts.json
を読み込み、そこに記載のあるパッケージをnode_module
配下から読み込み
つまり↓
- 以下のどちらかの方法で使用可
scripts
ディレクトリにそのまま*.coffee
を置くnode_module
配下にnpmパッケージ形式で配置しexternal-scripts.json
にパッケージ名記載
ちなみにnpmパッケージとして配布するやり方はこちらのエントリにちょっと書いてあるので、参考にしてもらえるとよいですね。
Hello Worldスクリプトを作る
とりあえずscripts
ディレクトリに置く方法でやってみましょう
scripts/hello.coffee
# Description: # Hello World! # # Commands: # hubot hello : Returns "world!" module.exports = (robot) -> robot.respond /hello/i, (msg) -> msg.send "world!"
実行結果
myhubot> myhubot hello world! myhubot> # ちなみにスクリプト内のコメントに書いた「Commands:」の内容は、helpに表示されます myhubot> myhubot help ... myhubot hello : Returns "world!" ... myhubot>
コード解説
他の人の発言に反応する系(入力)
respond [正規表現]
話しかけられた発言が正規表現にマッチしたらに反応する(bot名 なんちゃら
のなんちゃら
とマッチング)
自分で発言する系(出力)
send
タイムライン上に発言する
ちなみに
CoffeeScriptなので省略されてますが、実際には以下の様なJavaScriptの意味になります
# CoffeeScript module.exports = (robot) -> robot.respond /hello/i, (msg) -> msg.send "world!"
# JavaScript module.exports = function(robot) { robot.respond(/hello/i, function(msg) { msg.send('World!'); }); };
robot.respond(pattern, callback)
はpattern
に指定した正規表現をリスナーとして登録し、マッチしたらcallback
を実行するメソッドmsg.send(message)
はmessage
を送信するメソッド
その他基本的な機能
他の人の発言に反応する系(入力)
hear [正規表現]
発言が正規表現にマッチしたら(Hubotに呼びかけなくても勝手に)反応する
自分で発言する系(出力)
reply
Hubotを呼び出した人に対してタイムライン上で返信する
hear, replyの例
robot.hear /カレー/i, (msg) -> msg.reply "カレー食べたいよねー" ## preview myhubot> そういえば、今晩はカレーだった Shell: カレー食べたいよねー myhubot> 誰だ貴様!
発言された内容をスクリプトで使う(パラメータ)
match
正規表現で括弧で囲んだ部分がmsg.match
に配列として格納される
robot.respond /santaku (.*) (.*) (.*)/i, (msg) -> msg.send msg.match[0] # <- マッチした発言全体が格納される msg.send msg.match[1] # <- 括弧の1つ目 msg.send msg.match[2] # <- 括弧の2つ目 msg.send msg.match[3] # <- 括弧の3つ目 msg.send msg.match.length ## preview myhubot> myhubot santaku aaa bbb ccc myhubot santaku aaa bbb ccc aaa bbb ccc 4 myhubot>
random
配列からランダムに1つ取り出す
robot.respond /santaku (.*) (.*) (.*)/i, (msg) -> if msg.match.length != 4 return choices = [msg.match[1], msg.match[2], msg.match[3]] choice = msg.random choices msg.send "これがいいんじゃない?" msg.send choice ## preview myhubot> myhubot santaku そば うどん ラーメン これがいいんじゃない? そば myhubot>
これくらいの機能を覚えれば、とりあえず簡単な機能は作れるんじゃないかなーと思います。あとはアイデア次第!
CoffeeScriptの構文
時間切れです。この辺をご参照くださいな。
以上が社内勉強会の内容です。まぁ内容どうこうより、こういった勉強会が毎週行われて日々切磋琢磨しているんだよ、という文化をお伝えできればいいですね。
ちなみにこの勉強会を受講した皆さんに「一人一つ機能追加してプルリク出して!」という宿題を課したはずだけど、まだ一件も来ないなぁ。おかしいなぁ。みんな体調でも悪いのかなぁ。
まとめ
これだけ言っておいてなんですが、Hubotに興味なくてもいいんで、Webサービスやスマホアプリの開発に興味ある方を募集中です! とりあえずビアガーデン一緒に行きましょう!