Liminal Existence

Clouds in Iceland

Thursday, November 09, 2006

Announcing Jabber::Simple

Jabber::Simple [src, doc] is a simple (duh!) Ruby library that aims to make the implementation of basic Jabber functionality trivial. It is an extraction of the Jabber support that was added to Twitter, and is released under the GPL by Obvious. A line of code is worth a thousand words, so here is the complete code for sending a simple message to a Jabber user:

jabber = Jabber::Simple.new('rex@friendosaurus.com', 'password')
jabber.deliver("bront@friendosaurus.com", "Hey! I'm thinking of going Vegetarian - Any suggestions?")
Getting incoming messages is just as easy:

jabber.received_messages do |msg|
  puts "#{msg.body}" if msg.type == :chat
You can also set your status, and get information about your friends' statuses:

jabber.status(:away, "Eating at the Tree Cafe. I need a ladder.")

jabber.presence_updates do |update|
  friend = update[0]
  presence = update[2]
  puts "#{friend.jid} is #{presence.status}"


sudo gem install xmpp4r-simple
or download the package from RubyForge. Source code is also available, licensed under the GPLv2.

Yet Another Jabber Library?

There are a number of existing Jabber libraries for Ruby (jabber4r, xmpp4r, and Net::XMPP), so why Jabber::Simple? First off, Jabber::Simple does not aim to replicate any core XMPP protocol functionality present in these libraries — in fact, Jabber::Simple depends on xmpp4r and the Jabber::Simple#client and Jabber::Simple#roster methods expose all of xmpp4r's awesome functionality. When I started building in Jabber support for Twitter I'd used various Jabber clients, and even set up a simple Jabber server. Writing my own client, however, was a bit more complex. It turns out that the seamless experience of "adding a friend" and chatting with them is (unsurprisingly) comprised of a series of disjoint steps, and fraught with the peril of threads, XML streams, and arcane magic. The available libraries handle these tasks and many more admirably, but lack in elegance. My hope is that Jabber::Simple provides a sufficiently obvious interface with which to develop tools that use the Jabber protocol.

But Wait! There's More!

Now, you might shy away from writing that really cool chat-bot you've been meaning to write, saying "Wow, this is great, but setting up a Jabber server is a pain." --- but fear not! Go over to Google Talk and sign up for an account. Once you're done, use your Google Talk username and password, and start Jabbering. No really, it's that simple.

jabber = Jabber::Simple.new("you@gmail.com", "password")

Labels: , , ,


Blogger necrodome said...

this is just great. is there a simple way to use transports with the library so other networks(msn,etc) are supported to?

and can you give you a general overview usage of the lib in twitter? for ex, how do you check users' presence regularly, connection status, etc.

and did you scale the twitter bor or is it a single instance?

Saturday, 18 November 2006 17:49:00 GMT  
Blogger Blaine said...

You can absolutely use the lib with other networks; AIM is the most straightforward, because they have a developer program that actually makes sense. MSN is theoretically possible, but requires interacting with a Microsoft ISV. Yahoo is in the dark ages and it is impossible to use bots in any way that deviates from "normal" usage pattern on their platform.

In terms of configuring those platforms, I'll probably write up another post sometime soon, but in the meantime Jeff Hester has an excellent writeup to get you started.

Using the library in Twitter is pretty much as above; we receive incoming messages, and then run them through the Twitter processing logic — nothing surprising, really. So far we're running just a single instance, and it's doing fine. Scaling will happen later, and there are a number of mechanisms for doing it elegantly.

Saturday, 18 November 2006 18:14:00 GMT  
Blogger necrodome said...

Using the library in Twitter is pretty much as above; we receive incoming messages, and then run them through the Twitter processing logic — nothing surprising, really.

yeah, but since the lib is not based on events - callacks i have to check periodically received messages, contacts' presences etc, right?

Saturday, 18 November 2006 23:00:00 GMT  
Blogger Daniel said...

Great work! After using the other Ruby libraries, its nice to see a much Simpler version.

Tuesday, 21 November 2006 19:39:00 GMT  
Blogger Rufan-Redi said...

the world of MSN connected bots is getting a lot easier with the list of IM Prov Center - hopefully this will be enough to fast-track an MSN Bot for Twitter so I don't need to run Gaim or GTalk

Tuesday, 21 November 2006 20:53:00 GMT  
Blogger Blaine said...

necrodome: yes, just check periodically. If you're operating in a thread-safe environment, then you can use callbacks. ActiveRecord, on the other hand, is not threadsafe; callbacks will destroy your database. The main reason I built Jabber::Simple without requiring threads is because it's simpler, and threads are really unnecessary for most applications (i.e., unless you're sending 1000s of messages per minute, you won't need them).

rufan-redi: thanks for the tip! working on it. :-)

Wednesday, 29 November 2006 22:26:00 GMT  
Blogger HH said...

Hmmm - I hope people are still reading these comments.

First off - GREAT gem - thank you VERY MUCH for this. Simplicity is always appreciated.

My question is how can you build a bot that is less susceptible to disconnects. For example, if I have a bot running, I have yet to be able to catch the exceptions and recover (by allow the bot to retry a connection until the connection comes back up).

I get the following when I pull the network connection and I cannot find a way to recover. It may have to do with threading, but I'm not sure. Here's the typical error message from a physical disconnect:

Exception caught in Parser thread!
Exception caught while sending!

Then the bot is pretty much dead. I'm using the received_message with in a loop and I have rescue / retry statements that never catch the exception.

Any thoughts on addressing this would be greatly appreciated, Blaine!

Thanks again.

Thursday, 11 January 2007 04:31:00 GMT  
Anonymous Anonymous said...

I'm getting the "Exception caught in Parser thread!" error on the Jabber constructor. Perhaps I'm doing something stupid.

A sample application would be great.

Thursday, 15 March 2007 20:18:00 GMT  
Anonymous Anonymous said...


I'm also not able to connect to my local wildfire server.

I installed the gem using

gem install xmpp4r-simple

I'm using the rails console

ruby script/console

Also, I do the following...

require 'xmpp4r-simple'

Now, I'm getting the following stak trace...

>> jabber = Jabber::Simple.new("playnow@hanuman", "asdfklsfg")
NoMethodError: You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.[]
from C:/Software/InstantRails/ruby/lib/ruby/gems/1.8/gems/xmpp4r-0.3/lib/xmpp4r/rexmladdons.rb:239:in `expr'
from C:/Software/InstantRails/ruby/lib/ruby/gems/1.8/gems/xmpp4r-0.3/lib/xmpp4r/rexmladdons.rb:201:in `match'
from C:/Software/InstantRails/ruby/lib/ruby/gems/1.8/gems/xmpp4r-0.3/lib/xmpp4r/rexmladdons.rb:134:in `parse'
from C:/Software/InstantRails/ruby/lib/ruby/1.8/rexml/xpath.rb:53:in `each'
from C:/Software/InstantRails/ruby/lib/ruby/1.8/rexml/element.rb:934:in `each'
from C:/Software/InstantRails/ruby/lib/ruby/1.8/rexml/element.rb:398:in `each_element'
from C:/Software/InstantRails/ruby/lib/ruby/gems/1.8/gems/xmpp4r-0.3/lib/xmpp4r/rexmladdons.rb:35:in `first_element'

from C:/Software/InstantRails/ruby/lib/ruby/gems/1.8/gems/xmpp4r-0.3/lib/xmpp4r/rexmladdons.rb:21:in `replace_elemen
from C:/Software/InstantRails/ruby/lib/ruby/gems/1.8/gems/xmpp4r-0.3/lib/xmpp4r/presence.rb:171:in `status='
from C:/Software/InstantRails/ruby/lib/ruby/gems/1.8/gems/xmpp4r-0.3/lib/xmpp4r/presence.rb:179:in `set_status'
from C:/Software/InstantRails/ruby/lib/ruby/gems/1.8/gems/xmpp4r-0.3/lib/xmpp4r/presence.rb:23:in `initialize'
from C:/Software/InstantRails/ruby/lib/ruby/gems/1.8/gems/xmpp4r-simple-0.8.7/lib/xmpp4r-simple.rb:146:in `new'
from C:/Software/InstantRails/ruby/lib/ruby/gems/1.8/gems/xmpp4r-simple-0.8.7/lib/xmpp4r-simple.rb:146:in `status'
from C:/Software/InstantRails/ruby/lib/ruby/gems/1.8/gems/xmpp4r-simple-0.8.7/lib/xmpp4r-simple.rb:90:in `initialize
from (irb):7:in `new'
from (irb):7

I've tested the wildfire server and the account. I'm able to login to the account using a standalone jabber client.

My nvironment is WinXP2 and I'm using InstantRails 1.7.


Wednesday, 4 April 2007 08:24:00 GMT+01:00  
Blogger apardo said...

Hi, I'm testing this library with BackgrounDRb and Rails and I'm very happy with it. I'm running it with some AR callbacks and with some loops.

Good work guys!

Hasta luego :)

PD: Sorry for my english.

Wednesday, 13 June 2007 19:15:00 GMT+01:00  
OpenID mlemos said...


I'm from Brazil and I'm writing a nice app with your Gem, but the message reception is somehow unstable.

I mean, it doesn't get update in a smooth way. Sometimes it tooks a long time to actually receive messages sent a long way in the past.

Is this ok?

PS:. Awesome tool... if things go fine it will be presented live in the Campus Party Brazil 2008.

Saturday, 5 January 2008 04:14:00 GMT  
Anonymous Anonymous said...

hey blaine - very cool. do you know if this can support setting chat state notifications?

Saturday, 23 February 2008 06:00:00 GMT  

Post a Comment

Links to this post:

Create a Link

<< Home