Edited at

簡単な Hubot スクリプトをもっとつくろう (おみくじ系)

More than 3 years have passed since last update.

これは Hubot Advent Calendar 2014 の 7 日目の記事です。

また、今回は @bouzuya の Hubot 連載の第 6 回です。目次は、第 1 回の記事にあるので、そちらをどうぞ。

前回は 簡単な Hubot スクリプトをゼロからつくろう ということで、generator-hubot という Yeoman ジェネレーターで Hubot スクリプトのひながたを用意し、そこから Hubot スクリプトをつくりました。

今回は Hubot が提供している機能をもうすこし知るために、Hubot スクリプト界隈では定番の「おみくじ」系のスクリプトをつくりたいと思います。

また、今回から Hubot 2.10.0 にバージョンアップされています。


スクリプトの完成イメージ

まず、今回つくろうとしている Hubot スクリプトのイメージを共有しましょう。

今回は「おみくじ」系スクリプトということで、選択肢を挙げて「選んで!」とお願いすると、ランダムにひとつを選んで返してくれる Hubot スクリプト hubot-choice をつくりましょう。

実行例はこんな感じです。

bouzuya> だいこん、たまご、こんにゃく、はんぺん、ちくわから選んで!

hubot> bouzuya: だいこんで!


さっそくつくる

とりあえず Hubot スクリプトのひながたを生成します。このへん分からないのであれば、過去の連載記事を参照してください。

$ mkdir hubot-choice

$ cd hubot-choice

$ yo hubot:script

次に src/choice.coffee を編集します。


src/choice.coffee

# Description

# A Hubot script for choosing at random
#
# Configuration:
# None
#
# Commands:
# <item1>、<item2>、<item3>から選んで - choose at random
#
# Author:
# bouzuya <m@bouzuya.net>

module.exports = (robot) ->
robot.hear /(.+)から選んで/, (msg) ->
items = msg.match[1].split(/[ ・、\s]+/)
item = msg.random items
msg.reply "#{item}で!"


こうだ!

実行してみましょう。

$ HUBOT_SHELL_USER_NAME='bouzuya' PATH="./node_modules/hubot/node_modules/.bin:$PATH" $(npm bin)/hubot -a shell -n hubot -r src

hubot> だいこん、たまご、こんにゃく、はんぺん、ちくわから選んで!
bouzuya: だいこんで!

長いですね。あと Hubot 2.10.0 からの機能をしれっと使っています。こちらの名前が 'bouzuya' になるようにしています。


今回の新しい要素

上記のスクリプトの新しい要素は、次の 4 つくらいでしょうか。


  • robot.hear

  • msg.match

  • msg.random

  • msg.reply

CoffeeScript 的に新しい "#{...}" なんてのもありますけど、そのあたりは http://coffeescript.org/ に任せるということで割愛します。 (Hubot さわりはじめたひとで CoffeeScript つらいという意見はよく聞きますが…… JavaScript でも書けるのでお好きにどうぞ)

適当に解説つけます。


robot.hear

https://github.com/github/hubot/blob/v2.10.0/src/robot.coffee#L77-L78

これは listener を登録するメソッドです。

robot.respond(pattern, cb) は指定した pattern が @hubot pattern などで動くように書き換えられるのに対して、robot.hear(pattern, cb) は指定した pattern がそのまま使われます。

当然ですが、誤爆(関係ないメッセージに誤ってマッチ)しやすいので注意が必要です。


msg.match

https://github.com/github/hubot/blob/v2.10.0/src/response.coffee#L8-L9

これは正規表現のマッチした結果を取り出しています。

今回の msg.match[1] は最初の例で言うと、正規表現が /(.+)から選んで/ で、入力が 'だいこん、たまご、こんにゃく、はんぺん、ちくわから選んで!' なんで、'だいこん、たまご、こんにゃく、はんぺん、ちくわ' になります。


msg.random

https://github.com/github/hubot/blob/v2.10.0/src/response.coffee#L69-L75

これは与えられた Array からランダムにひとつを返します。

今回は最初の例で言うと [だいこん', 'たまご', 'こんにゃく', 'はんぺん', 'ちくわ'] からひとつ ('だいこん') を選んでくれています。


msg.reply

https://github.com/github/hubot/blob/v2.10.0/src/response.coffee#L33-L40

これはアダプター依存ですが、メッセージを送信した個人に対して返信するメッセージをチャットに送信します。


補足

紛らわしいのですが、msg という変数は robot.Responsenew したものに相当します。ソースコード追うとわかります。ちなみに、ぼくの個人的な Hubot スクリプトでは res という変数名にしています。変数名なので、好きなようにすればいいと思います。


まとめ

今回は Hubot が提供している機能をもうすこし知ろうということで、いくつか標準の機能を紹介しました。

今回はソースコードを見てもらえるように GitHub のリンクを貼りました。Hubot のソースコードは大した量ではありません。ぼくのゴミみたいな解説を読む時間で、本体のソースコードを読むほうが速いし確実です。ぜひ、ソースコードを読んでください。

Response#http などで HTTP リクエストなどを紹介したいところですが、正直、使い勝手がたいへん悪いので、大多数の人が request などの他のメジャーな npm パッケージを使っているのが現実だと思います。外部の npm パッケージの利用については後日紹介します。

ちなみに今回のサンプルは bouzuya/hubot-choice にあります。うまく動かない、などがあれば参考にどうぞ。


最後に

Hubot のソースコードを読んだら、いかに Hubot がひどいかが分かり、クローンをつくりたい衝動にかられると思います。

最後に、のネタを考えてたら投稿が遅れて 2014-12-08 になってしまった。