source/_posts/2013-03-25-xmpp4r-how-to-get-clients-roster.markdown
52ae2b31
 ---
 layout: post
 title: "XMPP4R: Get client's complete roster the right way"
 date: 2013-03-25 00:28
 comments: true
81419e46
 categories: [ruby, jabber]
52ae2b31
 cover: /images/cover/avatar.png
81419e46
 keywords: ruby, jabber, xmpp, xmpp4r, roster, client, xmpp4r-simple
 description: Fetch roster from jabber server
52ae2b31
 ---
 
 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.