Cinan's world

GNU/Linux & free software, howtos, web development, scripts and other geek stuff

XMPP4R: Get Client's Complete Roster the Right Way

Connect to Jabber. With 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?”. 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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# 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

What I’ve learned from using XMPP4R library in my project – callbacks are good thing and use them.

Comments