読者です 読者をやめる 読者になる 読者になる

#15 「人体錬成に近いものの仕方、もしくはhubotの使い方」tech.kayac.com Advent Calendar 2012

どう? 蕎麦の巻き方の練習してる? ずるってる?
どうもマコピーです。最近はふぐおじさんになったりフードファイターにされそうになったり大変です。

さて、このAdvent Calendarですが、着々とクリスマスに向かって続々と記事が書かれていってあと11日。
さきほど所用で街に出かけましたが、なるほど、世間はクリスマス色ですね、つらぽよ。

つらいし誰もかまってくれないし、@hisaichi5518くんには「めんどくせぇ!」って言われるし、外も寒くなってきたので、一人でもさみしくないようにIRCのボットを作ってみようと思います。
とはいえ、IRCのボットで彼女を作るとか二番煎じもいいところなので、そういうことはしません。
淡々とボットを作ってなんとかイノベーションに紐づけてみようと思います。

hubotって

HUBOT

CoffeeScriptで作られたボットのフレームワークです。node.js上で動き、npmから入れることが出来ます。
また、JSは書いたことあるけれどCoffeeScriptの文法がよくわからないという方もJavaScriptで書くことができます。
とりあえず何らかの方法でnode.jsを入れてください。
僕はnodebrewからinstall-binaryで入れました。環境によっては入りませんが、brewしないので速いです。
以下はMac OS X Lionで作業を行いました。

$ npm install hubot -g

これでhubotコマンドが使えるようになります。
あとこれだけではIRCの発言に応答したりは出来ないのでhubot-ircを入れましょう。これはアダプターと呼ばれるもので、単体では標準入出力しか扱えないhubotをIRCでやり取りできるようにさせるものです。
いろいろ試して気づいたのですがnpmに上がっているhubot-ircではIRCの接続にSSLを使っている場合に起動時にコケるようです。githubに上がっているバージョンだとうまくいったのでそれを入れてしまいます。

$ git clone https://github.com/nandub/hubot-irc
$ npm install hubot-irc -g

さて、準備は整ったのでボットのためのディレクトリを作ります。ここではkokorochanとします。

$ mkdir kokorochan
$ cd kokorochan

これからはkokorochanディレクトリでの作業となります。 さらに、ボットの動作を記述するためのスクリプトを置くフォルダを作ります。

$ mkdir -p node_modules/hubot-scripts/src/scripts

スクリプトを作っていきます。まずはkokorochanにkokorochanと呼びかけた場合の動作を記述します。

$ vim node_modules/hubot-scripts/src/scripts/kokorochan.coffee
module.exports = (robot) ->   
    robot.hear /kokorochan.*/i, (msg) ->
        msg.send msg.message.user.name + ': ' + 'こころちゃんゆーな!'

これだけです。robot.head /正規表現/, callback という形式でIRC上の発言に対する挙動を記述していきます。
robot.respond /正規表現/, callbackという形式もあります。これはkokorochan: ほげほげ と呼びかけた場合にのみ反応するときに使います。
この場合はkokorochanと呼びかけられた場合に「こころちゃんゆーな!」と返すようです。kokorochanと呼ばれたくないようですね。 respondじゃなくてhearを使うのは伏線です。
callbackにはResponseオブジェクトが渡ってくるのでそこに生えているmsg.sendというメソッドで返答します。これはhubot-irc(IRCアダプター)だけではなく、他のアダプターを使った場合も一緒です。

さて、準備が整ったところで試してみましょう。
入るIRCサーバやチャンネル設定は環境変数で渡します。この際なのでシェルスクリプトで書いちゃいましよう。

#!/bin/sh
export HUBOT_IRC_ROOMS="#yokohama" # チャンネル名
export HUBOT_IRC_SERVER="irc.xxxx.com" # IRCサーバ
export HUBOT_IRC_PORT=6667 # IRCサーバのポート
export HUBOT_IRC_PASSWORD="milyhomes" # IRCサーバのパスワード
export HUBOT_IRC_USESSL="true" 
export HUBOT_IRC_SERVER_FAKE_SSL="true" # 自己証明証明書を使う場合はtrue

hubot -a irc -n kokoro -d

先ほどの伏線を回収しますが、kokoroという名前でログインするようにします。明智小衣は明智小衣であって小衣ちゃんではないので。
hubotの引数を説明すると、

  1. -a irc 使うアダプタ名 省いたら標準入出力を使います
  2. -n kokoro ボットの名前 respondで反応するときの名前はこれ
  3. -d Webサーバの起動はしない。有効化するとWebAPIでボットの挙動を操作するなどのスクリプトが書けますが今回は使いません

さらに、先ほど書いたスクリプトを有効化するために、hubot-script.jsonというのを書きます。

$ vim hubot-scripts.json
["kokorochan.coffee"]

さてやっと起動する瞬間がやって来ました。たちあげてみます。

$ sh kokorochan.sh

そうするとおもむろに立ち上がってチャンネルにインしてきます。

00:00 kokoro has joined (~nodebot@)
00:00 macopy: kokorochan
00:00 kokoro: macopy: こころちゃんゆーな!

なんどでもやってくれます。

00:00 macopy: kokorochan
00:00 kokoro: macopy: こころちゃんゆーな!
00:00 macopy: kokorochan
00:00 kokoro: macopy: こころちゃんゆーな!
00:00 macopy: kokorochan
00:00 kokoro: macopy: こころちゃんゆーな!

はあ、小衣ちゃん。。。心が温まる。。。
続いて小衣ちゃんのIQを聞いてみましょう。噂によると小衣ちゃんのIQは1300にも達するそうです。先ほどのスクリプトに追加してみます。

$ vim node_modeules/hubot-scripts/src/kokorochan.coffee
iqlist = [1300, 13e3, 13e4, 13e9, 13e10, 13e11, 1400, 14e4, 14e5, 14e9, 14e11, 14e16, 14e20, 14e52, 14e-13, 14e-20, 14e56, 14e68]

module.exports = (robot) ->
    robot.respond /iq$/i, (msg) ->
        if (iqlist.length isnt 0)
            iq = iqlist.shift()
            msg.send iq.toString(10)
        else
            msg.send '1300'

再び立ち上げ直して kokoro: iqと呼びかけると

00:00 macopy: kokoro: iq
00:00 kokoro: 1300
00:00 macopy: kokoro: iq
00:00 kokoro: 13000
00:00 macopy: kokoro: iq
00:00 kokoro: 130000
00:00 macopy: kokoro: iq
00:00 kokoro: 13000000000
00:00 macopy: kokoro: iq
00:00 kokoro: 130000000000
00:00 macopy: kokoro: iq
00:00 kokoro: 1300000000000
00:00 macopy: kokoro: iq
00:00 kokoro: 1400
00:00 macopy: kokoro: iq
00:00 kokoro: 140000
00:00 macopy: kokoro: iq
00:00 kokoro: 1400000
00:00 macopy: kokoro: iq
00:00 kokoro: 14000000000
00:00 macopy: kokoro: iq
00:00 kokoro: 1400000000000
00:00 macopy: kokoro: iq
00:00 kokoro: 140000000000000000
00:00 macopy: kokoro: iq
00:00 kokoro: 1.4e+21
00:00 macopy: kokoro: iq
00:00 kokoro: 1.4e+53
00:00 macopy: kokoro: iq
00:00 kokoro: 1.4e-12
00:00 macopy: kokoro: iq
00:00 kokoro: 1.4e-19
00:00 macopy: kokoro: iq
00:00 kokoro: 1.4e+57
00:00 macopy: kokoro: iq
00:00 kokoro: 1.4e+69
00:00 macopy: kokoro: iq
00:00 kokoro: 1300
00:00 macopy: kokorochan
00:00 kokoro: macopy: こころちゃんゆーな!

さすが小衣ちゃんや、天才美少女なだけある。。。 という感じでございます。小衣ちゃんのIQは最終的に14無量大数までいくみたいですね。
他の機能としてhubotはBrainという機能を使ってRedisサーバに情報を貯めこんでおくこともできるようです。npmに上がっている、hubot-scriptsというモジュールを入れると様々なサンプルスクリプトが使えるので試してみてください。

参考: hubotスクリプトの書き方とサンプル集
github社製ボットフレームワーク、hubotをIRCボットとして導入した話(修正あり
hubot jotei > 女帝 Advent Calendar 2012(3日目)

ではではー。
次はダーツ部部長の――

アカンアカン、自分イノベーションしたけれど、自分だけや

ちょっとこれだとほんとひどいので、最近の僕のhubotの使い方を紹介します。

例えばあなたは運用兼開発エンジニア

弊社のソーシャルゲームのサーバサイドエンジニアは大抵の場合、運用も兼ねており、本番化作業や運用中でサーバ関連の問題が起こった場合の担当もしております。
僕も例外ではなく、さらにチームのサーバサイドエンジニアの数が少ないためあっぷあっぷしてしまうときがあります。
そんな時に小衣ちゃ……じゃなかった、hubotにがんばってもらいましょう。
僕の案件の開発環境でマスタデータを流し込みたい時、今までは僕がサーバに入っていちいちコマンドを叩かなければなりませんでした。
hubotを使えばその代わり叩くなんてこともできます。

00:00 <macopy> kokoro: master import item
00:00 <kokoro> よいしょ♪
00:00 <kokoro> はいったー
00:00 <macopy> kokorochan: ありがとう
00:00 <kokoro> こころちゃんゆーな!

中身は以下のようにコマンドを実行しているだけです。

fs = require('fs')
exec = require('child_process').exec

basePath = '/path/to/home/'

module.exports = (robot) ->
    robot.respond /master import (.*)$/i, (msg) ->
        tableName = msg.match[1]
        filename  = basePath + 'csv/' + tableName + '.csv'
        msg.send 'よいしょ♪'
        fs.exists filename, (exists) ->
            if exists
                loadFromCsv filename
            else
                msg.send 'くうきよめー(csv not found)'

        loadFromCSV = (filename) ->
            loadCommand = 'perl -I ' + basePath + 'lib ' + basePath + 'scripts/load_master_data.pl ' + filename
            exec loadCommand, {}, (error, stdout, stderr) ->
                if error != null
                    msg.send 'くうきよめー(load failed)'
                else
                    msg.send 'はいったよー'

ボットを開発サーバ上に(もしくはSSHなどで開発サーバにログイン出来る環境)置けば可能です。 さらにnode.jsなのでコマンドを取りこぼすことはありません。
IRCに入ってれば使える気軽なコマンド環境を用意することでいろいろ楽になると思います。事故るとヤバイところでは使いませんが。
こういうときは管理画面を作るのが一般的ですが、この方法のメリットはIRCに実行したログが残ることです。
幸いなことに僕の案件ではディレクターさんもIRCに入っていただいているので管理画面ではなくとりあえずhubotでやるという感じです。

実はまだこいつは先週こっそり開発していて先ほど完成したばっかりなので来週投入します。開発上のボトルネックが解消されたらいいですね。

次はダーツ部部長の@kubosho_さんです。ちなみに僕は自称副部長です。