Create your own IM bot

by Pandafox | Posted in Ruby, Tutorials

In this tutorial we are going to write our very own IM bot using the ruby language and XMPP through a neat little jabber bot library.

Requirements

– A basic ruby install along with the rubygems package manager
– A Jabber/XMPP account

Why XMPP?

XMPP (Extensible Messaging and Presence Protocol) is a great open XML-based protocol used by services such as Google Talk, Google Wave and a myriad of other IM-clients.

XMPP can be used just like other services like MSN and AIM etc, but the neat thing about XMPP is that it’s completely open. And because the protocol is open and very flexible, people have developed all kinds of nifty extensions such as interoperability with other services like MSN, AIM and even IRC. In other words, you can, for example, use XMPP to chat with your friends on MSN.

This is what makes XMPP perfect for writing IM-bots, because our bot will automatically work with all the IM services our XMPP has to offer.

Installing the gems

Let’s start by grabbing a couple of gems which we will be needing:

  • xmpp4r
  • xmpp4r-simple
  • jabber-bot

All these gems can easily be obtained using rubygems:

gem install xmpp4r xmpp4r-simple jabber-bot

or if that doesn’t work:

sudo gem install xmpp4r xmpp4r-simple jabber-bot

The code

Once the gems are installed, we should be ready to write some code. So fire up your favourite code editor and create a new ruby file.

Let’s start by including the libraries we will be needing and configure our bot, like so:

require 'rubygems'
require 'jabber/bot'

bot = Jabber::Bot.new(
  :jabber_id => 'bot_account@example.com', 
  :password  => 'bot account password goes here', 
  :master    => 'your_account@example.com',
  :presence  => :chat,
  :status    => 'I\'m a bot!',
  :is_public => true
)

Here we are instantiating a new object of the Bot class, which will handle all the jabber communication for us. We also provide some initial configuration:

jabber_id – Your jabber id… duh…
password – The password for your jabber account.
master – Another jabber account which will be able to run private commands. Pretty much like an admin account.
presence – The bots presence. e.g. :chat, :busy, :away, etc.
status – The bots status message.
is_public – Whether or not the bot should be able to interact with the public. If this is set to false, only the master will be able to run the commands.

Adding commands

Now, let’s start teaching our bot some new tricks!

bot.add_command(
  :syntax => 'time',
  :description => 'Returns the current timestamp',
  :is_public => true,
  :regex => /^time$/
) do
  Time.now.to_s
end

Yes, that’s all the code you need to add a new command. The add_command method takes in a couple of parameters and we pass along a block of code which tells the bot what to do with the input.

Here’s a quick overview of the add_command parameters:

syntax – This is solely for documentation purposes which we will look closer at in a bit. It should only contain the command name and input types (if any).
description – A short description of the command.
is_public – Should everyone have access to this command? If this is set to false, only “masters” will be able to run this command.
regex – A regular expression used for parsing and validating the command.

Now, lets have a closer look at our first command. As you probably can see, this command is called “time” and it returns the current timestamp using the Time-class. Our regex-expression is as simple as can be, the input just has to start and end with “time”. If the input matches this expression, the bot will use the block we provided to return the value of Time.now.to_s to the user who ran the command. Easy peasy.

Command arguments

As mentioned earlier, the bot can also receive arguments with its commands, so lets look at another command:

bot.add_command(
  :syntax => 'reverse <string>',
  :description => 'Reverses and returns the given string',
  :is_public => true,
  :regex => /^reverse\s.*$/
) do |from, msg|
  msg.reverse
end    

The things to take note of in this command is the regex-expression and the block arguments.

Our regex-expression says that the command has to start with the word “reverse” followed by a whitespace character, then zero or more characters (of any type).

We also have two block parameters:

from
– The jabber id who called the command.

msg
– Which is the string after the first piece of whitespace in the input string. So if the bot received “reverse hello, world!”, msg would contain “hello, world!”.

The block simply reverses and returns the msg argument and that’s it.

How about some privacy?

bot.add_command(
  :syntax => 'shutdown',
  :description => 'Shut down the bot.',
  :is_public => false,
  :regex => /^shutdown$/
) do |from, msg|           
  puts "#{from} shut down the bot."
  bot.disconnect     
  exit
end

Here’s a command we don’t want to be open to the public. This is a simple shutdown-command, which is only available to the bots master because “is_public” is set to false. The command prints out who called the command to the standard output channel before calling bot.disconnect and exiting the whole .

The connection

The only thing left to do is to connect the bot to its server:

bot.connect

And we’re done!

Bot in action

Here’s a sample conversation with the bot:

Screenshot of a sample conversation with the IM bot
(“Thomas” is me, and “wooptoot” is the bot, in case you were wondering.)

You can also see all the syntax and description parameters in action in the “help” response.

What’s next?

The bot we’ve created in this tutorial isn’t very exciting, but adding more interesting commands couldn’t be easier! Here’s a couple of ideas of what to do:

Jabber to twitter

Use the twitter API to create a tweet-command.

Google search

Make a command that searches Google and returns a bunch of results.

Zork?

Or what about porting the Zork game to this bot?