阿吽の呼吸でChatOps、標準入力と標準出力でハンドラがつくれるruboty-aunをつくった
標準入力にチャットの発言をすっ
と入れる。標準出力をふっ
と出せばハンドラーの出来上がり。Rubyでハンドラー書かなくてもいい。
使い方
Gemfile
に以下を書いてbundle install
gem 'ruboty-aun'
Rubotyと同じディレクトリの下にaun
を作って、その中に実行ファイルを置く。例えば、こんな感じ。
$ mkdir aun $ cat > aun/aun #!/usr/bin/env php <?php $body = trim(fgets(STDIN)); if ($body == 'あ') { fwrite(STDOUT, 'うん'); } $ chmod u+x aun/aun
アイデア
チャットの Bot 書くのに CoffeeScript とか Ruby とか書くのダルいし標準入力から標準出力返すだけでハンドラ実装できるフレームワークあればいいんじゃないかと思った。Golang で週末あたりやるか。
— Yuya Takeyama (@yuya_takeyama) 2014, 10月 23
なぜ阿吽
阿は口を開いて最初に出す音、吽は口を閉じて出す最後の音であり、そこから、それぞれ宇宙の始まりと終わりを表す言葉とされた。
今日でひとくぎり
Rubotyプラグインを1ヶ月かけて0b00011111
個つくった。バイナリ的にもぞろ目で切りがいいので、毎日作るのはこれで最後にする。明日になればまた書いているかもしれないけど。
次は0b0111
日で0b0001
個gemをつくるチャレンジしようかな。
Rubotyを書いていて、wsgiのタマネギ画像みたいなbotフレームワークが欲しくなったので、またbotを書くかもしれない。
まとめ
Rubotyが信ずる者の言葉にしか耳を貸さなくなるruboty-trust_meをつくった
簡単な名前による認証を提供します。
つくろうと思った理由
ruboty + twitter-adapter でボットを作っている人っているのかな?万人向けのコマンドと管理者(本人)向けのコマンドとかの区別が必要になりそうだけど、その辺りどうしているか気になる。ベタベタにif文? #ruboty
— tbpgr (@tbpgr) 2014, 11月 3
いい話
RubotyはRuboty自身のことを信じている
Redisのメモリ使用量を表示するruboty-redis-infoつくった
brainを結構つかうようになったのでRedisの使用率が気になった。
わからなかったこと
何MBまで使える、みたいな情報とれないのかな
余談
ruboty-gen g redis-info
すると生成されるgemがダメ。夜気分が乗ったら-
対応しよう。
おまえは今までOpsしたChatをおぼえているのか? ruboty-statsをつくりました
rubotyが反応したアクションを覚えていてくれる。
反応したチャットの文言、発言主などを表示できる。
まとめ
Module#prepend
だいすき
「ちょっとマイクラ鯖の様子みてくる」ruboty-minecraft_statusつくりました
機能的にはblockgiven/minecraft_logged_in_notifierとほぼいっしょ。
> @ruboty minecraft status minecraft.example.com
A Minecraft Server (0/20):
> @ruboty minecraft status minecraft.example.com
A Minecraft Server (1/20): blockgiven
JRubyかくぞ
Minecraftのプラグインを書くために環境を整えている。
まとめ
まとめたいことがとくにないひもある
暇なとき、チャットでよおよお! ruboty-yo!!
つかいかた
よ usaboty
/yo usaboty
とかくとYoが飛ぶよ。
恋の病の人向けの使い方
君のこと好きだよ usaboty
でもYoが飛ぶよ。Yoしか伝わらないから安心だよ。
テスト
yo.featureを書いた。
vcr
はじめて使ったけどそれなりにべんりだった。use_cassette
のキーの指定の仕方と録音の仕方がキモだと思う。
今回は出来なかったけど
# こういう感じの`shared_context`を定義しておくと便利そう RSpec.shared_context 'VCR', :vcr do around do |example| # metadataで指定する、あるいはfull_descriptionを使うとよさそう VCR.use_cassette(example.metadata[:cassette]) do example.run end end end RSpec.describe 'AKB48', :vcr, cassette: 'akb48' do # 〜 end RSpec.describe 'perfume', :vcr, cassette: 'perfume' do # 〜 end
WebAPI
どこでstubするか。シナリオを通して投げるリクエストが決まっているならvcr便利だと思う。 ざっとみた感じ録音したデータには秘密にしておかないとまずいデータも録音されてしまう。 今回は別途Rakefileにタスクを定義して、漏れるとまずそうな部分をマスクしてからコミットした。
APIのクライアントライブラリ
今回はライブラリをつかわず適当に実装した。最低限ひつYoなエンドポイントだけたたける。 自分で作るか、ライブラリ使うかでテストのやりかたが違ってきそう。
ハマったところ
まとめ
Yoではつたわらないこともあるよ
なんでも肯定してくれるruboty-yesを公開した
ハマった
- RSpecのTurnipを使うRakeタスクの定義
- Rubotyのreply時のto/fromの扱い
- Rubotyのテストをどうかくとうまくいくのか考える時間
Turnipのシナリオ
最初シナリオで使う人物名を実在の人物名にしてしまった。 架空の名前を考えてシナリオを書くのは難しい。
Rubotyのテスト
今回は受け入れテストだけ書いてみた。
テスト中で実際にRuboty::Robot
を作成し、動かしている。
Ruboty::Adapters::Base
を継承したアダプタを定義すると、最後に定義されたアダプタが使われるようになる。今回はMock
アダプタを定義した。Mock
アダプタは特に何もしない。
Ruboty::Robot
の発言を監視するためRuboty::Robot
を拡張するRuboty::Testable
モジュールをprepend
した。今回は、Rubotyの発言の記録を取れればいいので、say
を奪った、それに合わせて最小限のインターフェイスを定義してやった。
said
を直接のぞいてる部分はsaid?
で置き換えた方がうまくいきそうだなぁと書き終わってから気づいた。
まとめ
今回は簡単なテキスト処理のようなものなので、受け入れテストのみ書いた。 ハンドラーやアクションの中でもう少し複雑なことをしている場合は、個々のハンドラー/アクションのユニットテストも書いた方がよいかもしれない。
しかし基本的にはRubotyはチャットをインターフェイスにして動いているので、チャットをベースにした受け入れテストをしっかり書くのがいいんじゃないかと思っている。
READMEがそのままテストとして実行できる夢をみた。