Robut

The friendly plugin-enabled HipChat bot.

Installation and usage

Robut can be installed by running gem install robut. This installs the robut binary. When run, robut reads a Chatfile, connects to the specified HipChat server and chatroom, and feeds every line said in the chatroom through the plugins configured by the Chatfile.

Once robut is running, the plugins listen to what’s being said in the chatroom. Most plugins listen for @replies to robut:

@robut lunch? # => "Banh Mi!"
@robut calc 1 + 1 # => 2

Others listen to everything, and don’t require an @reply.

Some of the included plugins require extra gems to be installed:

Robut::Plugin::TWSS

requires the twss gem.

Robut::Plugin::Calc

requires the calc gem.

Robut::Plugin::Weather

requires the nokogiri gem.

Robut::Plugin::GoogleImages

requires the google-search gem.

A list of known 3rd-party plugins is available on the wiki: github.com/justinweiss/robut/wiki/Robut-Plugins Feel free to add your own creations!

The Chatfile

When the robut command runs, it looks for and evals ruby code in a file called Chatfile in the current directory. You can override the configuration file by passing robut a path to a Chatfile as the first parameter:

robut /path/to/Chatfile

The Chatfile is just ruby code. A simple example can be found here: Chatfile

Robut::Web

You can run Robut as a rack application, which allows it to accept incoming post requests (e.g. Heroku deploy hooks, GitHub post-recieve hooks, etc.) that can send messages to all connected rooms. Have a look at config.ru for an example.

Adding and configuring plugins

Plugins are ruby classes, so enabling a plugin just requires requiring the plugin file, optionally configuring the plugin class, and adding the class to the global plugin list:

require 'robut/plugin/lunch'
Robut::Plugin::Lunch.places = ["Banh Mi", "Mad Oven", "Mod Pizza", "Taphouse"]
Robut::Plugin.plugins << Robut::Plugin::Lunch

Each plugin can be configured differently, or not at all. It’s best to look at the docs for the plugins you want to use to figure out what kind of configuration they support.

Some plugins might require storage (like the ‘lunch` plugin). You can configure the type of storage you want to use based on the need for persistence. The default is the HashStore which is in-memory only. Below is an example of using the YamlStore.

Robut::Connection.configure do |config|
  # ...
  Robut::Storage::YamlStore.file = "~/.robut_store"
  config.store = Robut::Storage::YamlStore
end

Configuring the HipChat connection

The Chatfile also configures the HipChat connection. This is done in a Robut::Connection.configure block:

# Configure the robut jabber connection and you're good to go!
Robut::Connection.configure do |config|
  config.jid = '[email protected]/bot'
  config.password = 'password'
  config.nick = 'Bot Nick'
  config.rooms = ['[email protected]', '[email protected]']

  # Custom @mention name
  config.mention_name = 'Bot'

  # Example of the YamlStore which uses a yaml file for persistence
  Robut::Storage::YamlStore.file = "~/.robut_store"
  config.store = Robut::Storage::YamlStore

  # Add a logger if you want to debug the connection
  # config.logger = Logger.new(STDOUT)
end

This block usually goes at the end of the Chatfile.

Built-in plugins

Robut includes a few plugins that we’ve found useful:

Robut::Plugin::Calc

a simple calculator.

@robut calc 1 + 1 # => 2
Robut::Plugin::Lunch

a random decider for lunch locations.

@robut lunch? # => "Banh Mi!"
Robut::Plugin::Meme

generates meme images using memecaptain.

@robut meme all_the_things drink; all the beer
Robut::Plugin::GoogleImages

does a google image search for a query and returns the first result.

@robut image ship it
Robut::Plugin::Sayings

a simple regex listener and responder.

You're the worst robot ever, @robut. # => I know.
Robut::Plugin::TWSS

an interface to the TWSS gem. Listens to anything said in the chat room and responds “That’s what she said!” where appropriate.

well hurry up, you're not going fast enough # => "That's what she said!"
Robut::Plugin::Echo

echo back whatever it gets.

@robut echo hello world # => "hello world"
Robut::Plugin::Say

invokes the “say” command (text-to-speech).

@robut say this rocks # (make sure robut is running on a machine with speakers :)
Robut::Plugin::Ping

responds with “pong”.

@robut ping # => "pong"
Robut::Plugin::Later

performs the given command after waiting an arbitrary amount of time.

@robut in 5 minutes echo @justin wake up! # => (5 minutes later) "@justin wake up!"
Robut::Plugin::Weather

uses Google Weather to fetch for the weather for a given location and day.

@robut seattle weather saturday? # => "Forecast for Seattle, WA on Sat: Sunny, High: 77F, Low: 55F"
Robut::Plugin::Alias

creates aliases to other robut commands.

@robut alias "cowboy" "@robut play bon jovi wanted dead or alive" # Cuz somtimes you need it.
@robut alias w weather? # less typing for common stuff
Robut::Plugin::Quips

stores and posts Bugzilla-style quips.

@robut add quip It was great when I wrote it!
@robut quip # => It was great when I wrote it!
@robut remove quip It was great when I wrote it!
Robut::Plugin::Help

lists usage for all the plugins loaded into robut

@robut help # => command usage

Writing custom plugins

You can supply your own plugins to Robut. To create a plugin, include the Robut::Plugin module and implement the handle(time, sender_nick, message) to perform any plugin-specific logic.

Robut::Plugin provides a few helper methods that are documented in its class definition.

Contributing

To test your changes:

  1. Install Bundler

  2. Run ‘bundle install`

  3. Make your changes and run ‘bundle exec ruby -Ilib bin/robut ~/MyTestingChatfile`

  4. Add tests and verify by running ‘bundle exec rake test`

Once your changes are ready:

  1. Fork robut

  2. Create a topic branch: ‘git checkout -b my_branch`

  3. Commit your changes

  4. Push to your branch: ‘git push origin my_branch`

  5. Send me a pull request

  6. That’s it!

Todo

  • More plugins!