--- 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.