ローファイ日記

出てくるコード片、ぼくが書いたものは断りがない場合 MIT License としています http://udzura.mit-license.org/

In-house Domoraen

Domoraen は、 id:tily さんが作った最強のTwitter botなのだが、
実装が公開されている。

この実装をもとに、Domoraen botを社内運用できる気がしたので色々試した。

前提として、 Domoraen は非常に厳しいライセンスのソフトウェアで、経緯は

とのことだった。なので利用者もフェアユースの範囲でのインハウス運用等でお願いしたい。

HTTP API の追加

コードを読んだ所 Domoraen に必要な機能は一つのモジュールに集約されていたので、それをそのまま用いて Sinatra ベースで HTTP API を作った。この API サーバを社内に立てておく。

Hubot 経由で API を叩く


domoraen-hubot

こんな感じの雑なラッパーを書く。 `request` ドチャクソ便利だと思う。Hubot標準のHTTP Clientはなんとなく好かんので。

余談だけど、コールバック関数を

accessDomoraen "#{apiRoot}/tools.json",
  onSuccess: (data) -> msg.send data.message
  onError: (err) -> msg.send "失敗したよ...: #{err}"

こんな感じでオプションで書けるようにするとCoffeeScript的にはコードが書きやすくなると言う気付きがあった。基本CoffeeScriptではぼくはクソコードしか書けないっすけど...

とつぜん Domoraen が便利な道具を出す

hubot, domoraen で道具を出してくれるけど、全然何の脈絡もなく道具を出してくれる方が面白いので、発言を拾ったりするようにする。

ランダムで拾う実装
  robot.hear /(.*)/, (msg) ->
    return if Math.random() > 0.05
    seed = encodeURIComponent(msg.match[1])
    accessDomoraen "#{apiRoot}/tools/#{seed}.json",
      onSuccess: (data) ->
        return if data.message.match(/もう大人でしょ|自分でなんとかしろよ|それ無理/)
        msg.send data.message
      onError:   (err)  -> 'pass' # do nothing

道具の取得に失敗した場合は何も出力しない。ランダムで発言を拾っといて「自分でなんとかしろよ...」とかしゃべるのはそれはそれで面白いが、そのうちイラっとしそう。

いきなり狂ったようにアイテムを出す実装

Hubotの機能では「入っている部屋一覧」は取得できないので、自力で作る。

  robot.enter (msg) ->
    if msg.message.user.name == robot.name
      robot.joinedRooms ?= []
      robot.joinedRooms.push msg.message.room

あとはおもむろにランダムに部屋を取得して道具を取り出せば良い。
ncb000gt/node-cron · GitHubのようなオシャレなものを使わなくても、setTimeoutで問題なし。あと、 robot.on('start') みたいなイベントがあれば良いんだけど、無いんで、トップレベルにズバっと書いて初期化するイメージ。

  nextDomoraenTickSeconds = () ->
    Math.round(Math.random() * 90 * 60) + 30 * 60

  invokeDomoraen = () ->
    if robot.joinedRooms?.length
      room = robot.joinedRooms[ Math.floor(Math.random() * robot.joinedRooms.length) ]
      accessDomoraen "#{apiRoot}/tools.json",
        onSuccess: (data) -> robot.messageRoom room, data.message
        onError:   (err)  -> 'pass' # do nothing
    robot.logger.info nextDomoraenTickSeconds() * 1000
    setTimeout invokeDomoraen, nextDomoraenTickSeconds() * 1000

  setTimeout invokeDomoraen, nextDomoraenTickSeconds() * 1000


なお、ここまでのコードは全部hubot-irc前提なので、ほかの環境の方はがんばってほしい。そこまでがんばらなくても大丈夫だと思うけど。

まとめ

こんな感じで思いつきのプラグインや機能をどんどんHubotに搭載すると、CoffeeScriptの勉強にもなるし、良い。

Hubotはドキュメントが微妙に足りないので、本体のCoffeeScriptをちゃんと読むことになる。それも勉強になる(ポジティブ)。

あと、tilyさんの設計が奇麗すぎてHTTP APIを秒速で実装できたのが便利だった...。