Building a bot with hubot



Written By : Josh Nichols


May 23, 2012

At Rails Machine, we’ve had our very own Campfire bot powered by firetower for just over a year now, but it was time for a change. And so, I set out to rebuild our bot with hubot. While there was a lot of hype around hubot, I didn’t find a lot of information about specifics. So here is me creating the blog post I wanted to see :)

Downloading, installing, running:

First, go over to hubot.github.com, and hit ‘I would like to obtain my own hubot’. This downloads a tarball like ‘hubot-2.1.3.tar.gz’. Once you untar it, this directory is going to be home to your new and shiny hubot.

And one thing to note, the hubot repository is different than this tarball you just downloaded. The former is the source code for the core of hubot, where the tarball is an new bot setup to use that core.

Before we can get started, we’ll need to install Node.js, npm, and redis. As it were, Joyent has excellent documentation for this Node.js, and npm comes with Node.js nowadays, and redis is available through most package managers. Redis also needs to be running once it’s installed.

Once we’ve finished that, hop into the hubot directory, and run bin/hubot:

$ bin/hubot 
npm http GET https://registry.npmjs.org/hubot/2.1.3
npm http GET https://registry.npmjs.org/hubot-scripts
npm http GET https://registry.npmjs.org/optparse/1.0.3
npm http 304 https://registry.npmjs.org/optparse/1.0.3
npm http 304 https://registry.npmjs.org/hubot/2.1.3
npm http 200 https://registry.npmjs.org/hubot-scripts
npm http GET https://registry.npmjs.org/coffee-script/1.2.0
npm http GET https://registry.npmjs.org/scoped-http-client/0.9.6
npm http GET https://registry.npmjs.org/connect/1.8.5
npm http GET https://registry.npmjs.org/log/1.2.0
npm http 304 https://registry.npmjs.org/coffee-script/1.2.0
npm http 200 https://registry.npmjs.org/connect/1.8.5
npm http GET https://registry.npmjs.org/connect/-/connect-1.8.5.tgz
npm http 304 https://registry.npmjs.org/scoped-http-client/0.9.6
npm http 304 https://registry.npmjs.org/log/1.2.0
npm http GET https://registry.npmjs.org/redis/0.6.7
npm http 200 https://registry.npmjs.org/connect/-/connect-1.8.5.tgz
npm http 200 https://registry.npmjs.org/redis/0.6.7
npm http GET https://registry.npmjs.org/redis/-/redis-0.6.7.tgz
npm http 200 https://registry.npmjs.org/redis/-/redis-0.6.7.tgz
npm http GET https://registry.npmjs.org/qs
npm http GET https://registry.npmjs.org/mime
npm http GET https://registry.npmjs.org/formidable
npm http 304 https://registry.npmjs.org/qs
npm http 304 https://registry.npmjs.org/formidable
npm http 304 https://registry.npmjs.org/mime
optparse@1.0.3 ./node_modules/optparse

hubot-scripts@2.0.8 ./node_modules/hubot-scripts
└── redis@0.6.7

hubot@2.1.3 ./node_modules/hubot
├── log@1.2.0
├── scoped-http-client@0.9.6
├── coffee-script@1.2.0
└── connect@1.8.5 (mime@1.2.5, formidable@1.0.9, qs@0.5.0)
[Tue, 22 May 2012 15:03:07 GMT] INFO Loading scripts from /Users/technicalpickles/Downloads/hubot/scripts
[Tue, 22 May 2012 15:03:07 GMT] INFO Loading scripts from /Users/technicalpickles/Downloads/hubot/src/scripts
Hubot> [Tue, 22 May 2012 15:03:07 GMT] INFO Loading hubot-scripts from /Users/technicalpickles/Downloads/hubot/node_modules/hubot-scripts/src/scripts
The 'sys' module is now called 'util'. It should have a similar interface.
[Tue, 22 May 2012 15:03:07 GMT] INFO Successfully connected to Redis

That’s a lotta output! A large chunk of it is npm install running for the first time. We can see info logs for loading scripts and connecting to redis (this is used for hubot’s brain).

To make sure everything is working, hit enter, and send hubot help:

Hubot> hubot help
Hubot> <keyword> tweet - Returns a link to a tweet about <keyword>
<user> is a badass guitarist - assign a role to a user
<user> is not a badass guitarist - remove a role from a user
animate me <query>  - The same thing as `image me`, except adds a few
convert me <expression> to <units> - Convert expression to given units.
help - Displays all of the help commands that Hubot knows about.
help <query> - Displays all help commands that match <query>.
image me <query>    - The Original. Queries Google Images for <query> and
map me <query> - Returns a map view of the area returned by `query`.
math me <expression> - Calculate the given expression.
mustache me <query> - Searches Google Images for the specified query and
mustache me <url>   - Adds a mustache to the specified URL.
pug bomb N - get N pugs
pug me - Receive a pug
ship it - Display a motivation squirrel
show storage - Display the contents that are persisted in redis
show users - Display all users that hubot knows about
translate me <phrase> - Searches for a translation for the <phrase> and then
translate me from <source> into <target> <phrase> - Translates <phrase> from <source> into <target>. Both <source> and <target> are optional
who is <user> - see what roles a user has
youtube me <query> - Searches YouTube for the query and returns the video

These are all included out of the box. They live in scripts, and can be deleted or modified as needed.

Now we know the basics are working, we can hit Control-d to exit.

So far, this has been only running locally using the shell adapter. This is extremely useful for testing and development, but we’ll want to connect to Campfire for real at some point. Check out the Adapter: Campfire wiki for details on configuring and running.

Creating hubot scripts

Scripts are kept in the scripts directory. They can be coffee or js files, but I tend to like coffee.

Here’s the barest script you can have:

module.exports = (robot) ->

For our first example, we’re going to make scripts/business.coffee. It hears ‘business’, and exlaims in reply.

module.exports = (robot) ->
  robot.hear /business/, (msg) ->
    msg.send "HAHA BUSINESS!"

It’s usually a good idea to document the script, and include example usages. Comments are good for this in general, but for hubot help know about it, you need a comment with a hyphen in it:

# A hubot script for serious business
# 
# … business … - Exclaim HAHA BUSINESS anytime someone mentions business
module.exports = (robot) ->
  robot.hear /business/, (msg) ->
    msg.send "HAHA BUSINESS!"

Next, we’re going to make hubot respond to a message directed at it. He’s pretty smart, and will respond to messages that begin like:

  • Hubot:
  • Hubot
  • hubot
  • hubot:

So basically it’s case insensitive and can optionally include : (like if you are doing Propane tab completion).

# A hubot script for serious business
# 
# … business … - Exclaim HAHA BUSINESS anytime someone mentions business
# hubot are you late for business? - Answer if hubot is late for business
module.exports = (robot) ->
  robot.hear /business/, (msg) ->
    msg.send "HAHA BUSINESS!"
  robot.respond /are you late for business/, (msg) ->
    msg.send "http://i.imgur.com/WkQlv.jpg"

To be continued?

So far we have our own hubot, and a funny script to reply with things about the business. It’s kind of trivial to start, but it’s a gateway to do lots of other interesting and exciting things!