ruby

Fun with Jabber bots

I’ve recently been playing with Jabber bots. Jabber is an instant messaging protocol (like MSN Instant Messenger or AIM). However, unlike those other protocols, Jabber is an open standard. Jabber was adopted by Google as the basis for their instant messaging service Google Talk.

A powerful way to play with Jabber is to make a bot. A bot acts like one of your chat buddies - you can have a conversation with it over IM - but it is actually a little program that follows your commands, or can notify you of things.

I found a great bot by Brett Stimmerman written in Ruby. It’s very easy to customize. I’ve programmed this bot to tell me via my Google Talk account when I have new mail. Since I use the mutt mail client on a remote server, normally I don’t receive new mail notification popups - I have to go to my terminal window to check for mail. Now with my bot and Growl, I get a nice shiny popup telling me about the mail, and an IM message with the sender and subject of the email.

There are many free, public Jabber servers you can use for your bot. I created a bot called ‘keith.grennan.notify@jabber.org’.

Bot reporting for duty

Bot reporting for duty

This only uses half of the bot’s capability however - I’ve got the bot notifying me, but I can also have it follow commands I send it over IM. For example, it would be cool use the bot to update my Facebook status (Facebook’s API doesn’t explicitly allow for this but it could probably be done with a little hacking).

Here’s my bot script:

#!/usr/bin/env ruby
require 'rubygems'
require 'jabber/bot'
require 'fileutils'

home = File.join(ENV['HOME'], ".jbot")
FileUtils.mkdir_p(home)

# Save my PID
pid = File.new(File.join(home, 'pid'), "w")
pid.write($$)
pid.close

# Create a public Jabber::Bot
bot = Jabber::Bot.new(
  :jabber_id => 'keith.grennan.notify@jabber.org', 
  :password  => 'xxxxxxxxxxxx', 
  :master    => 'keith.grennnan@gmail.com',
  :is_public => true
)

# Wait for the USR1 signal and read a message from ~/.jbot/message
trap("USR1") {
  begin
    bot.deliver(bot.master,File.new(File.join(home, "message")).read) 
  rescue Exception => e
    puts e
  end
}

# Bring the new bot to life
bot.connect

Here’s a little Perl script that parses an email message and signals the bot:

#!/usr/bin/perl
use strict;
use warnings;
use Mail::Message;
use File::Slurp;

use constant JBOT_HOME => $ENV{HOME} . "/.jbot";

# Parse an email message
my $email = Mail::Message->read(\*STDIN);

# Put a message where the bot will look for it
write_file(JBOT_HOME . "/message", "Mail from " . $email->sender->format . ": " . $email->subject);

# Signal the bot with USR1
if (my $pid = read_file(JBOT_HOME . "/pid")) {
    kill USR1 => $pid;
}

And I call the Perl script from this Procmail recipe:

:0c
| ~/bin/jbot-mail-notify.pl
Syndicate content