---
layout: post
title: "XMPP4R: Get client's complete roster the right way"
date: 2013-03-25 00:28
comments: true
categories: []
cover: /images/cover/avatar.png
keywords:
description:
---
Connect to Jabber. With [XMPP4R](http://home.gna.org/xmpp4r/), a library for
Ruby, it is possible, but not as easy as you could think.
*One could ask "Why don't you use
[xmpp4r-simple?](http://xmpp4r-simple.rubyforge.org/)". My answer: "I'm not a
pussy!".*
There are many little bastards you should know before fetching client's
roster with contacts' vcard (nickname, full name, avatar, ...), status (online,
away, ...) or status message. This is how I do this task. It works flawlessly.
This is simplified code I use in my chat application. Reading comments might be
helpful.
{% codeblock lang:ruby %}
# Enable to see requests and responses between your machine and your jabber
# server (easy to read XML). Recommended.
Jabber::debug = true
# first, sign in to your jabber account with your Jabber ID and password
client = Jabber::Client.new("someuser@somejabberserver.tld")
client.connect()
client.auth("my password")
# now we are authenticated, let's fetch roster with all information we want
# initialize roster
roster = Jabber::Roster::Helper.new(client)
# request roster from jabber server, wait for response
roster.get_roster()
roster.wait_for_roster()
# now we know your friends' Jabber Ids
roster.items.each do |jid, contact|
puts "In roster I have: " + jid
end
# we don't know their status and status message, let's do it
# First, add presence callback. If anyone in roster change his/her state
# (e.g. come online), you will know it.
roster.add_presence_callback do |roster_item, old_presence, new_presence|
puts "Somebody changed his/her state to " + new_presence.status.to_s
# new_presence also offers status message and other stuff
end
# To start receiving presence messages from your jabber server, you have to
# send your presence first. It's really important to send your presence
# AFTER roster.add_presence_callback, because the callback will not catch
# every presence message which your jabber server sent to you.
client.send(Jabber::Presence.new.set_type(:available))
# Now you know who is online in your roster. If somebody from your
# roster won't be caught in roster.add_presence_callback block, then
# it just means he/she is offline.
# get vcard
roster.items.each do |jid, contact|
# According to documentation, fetching vcard can take longer time.
# Use threads if you think it is a good idea.
Thread.new do
vcard = Jabber::Vcard::Helper.get(client, jid)
nickname = vcard && vcard["FN"] || ''
#get avatar or other information here
end
end
{% endcodeblock %}
What I've learned from using XMPP4R library in my project -- callbacks are good
thing and use them.