| 1 | 1 | new file mode 100644 | 
                    
                | ... | ... | @@ -0,0 +1,83 @@ | 
                    
                |  | 0 | +--- | 
                    
                |  | 1 | +layout: post | 
                    
                |  | 2 | +title: "XMPP4R: Get client's complete roster the right way" | 
                    
                |  | 3 | +date: 2013-03-25 00:28 | 
                    
                |  | 4 | +comments: true | 
                    
                |  | 5 | +categories: [] | 
                    
                |  | 6 | +cover: /images/cover/avatar.png | 
                    
                |  | 7 | +keywords:  | 
                    
                |  | 8 | +description:  | 
                    
                |  | 9 | +--- | 
                    
                |  | 10 | + | 
                    
                |  | 11 | +Connect to Jabber. With [XMPP4R](http://home.gna.org/xmpp4r/), a library for | 
                    
                |  | 12 | +Ruby, it is possible, but not as easy as you could think.  | 
                    
                |  | 13 | + | 
                    
                |  | 14 | +*One could ask "Why don't you use | 
                    
                |  | 15 | +[xmpp4r-simple?](http://xmpp4r-simple.rubyforge.org/)". My answer: "I'm not a | 
                    
                |  | 16 | +pussy!".* | 
                    
                |  | 17 | + | 
                    
                |  | 18 | +There are many little bastards you should know before fetching client's | 
                    
                |  | 19 | +roster with contacts' vcard (nickname, full name, avatar, ...), status (online, | 
                    
                |  | 20 | +away, ...) or status message. This is how I do this task. It works flawlessly. | 
                    
                |  | 21 | + | 
                    
                |  | 22 | +This is simplified code I use in my chat application. Reading comments might be | 
                    
                |  | 23 | +helpful. | 
                    
                |  | 24 | + | 
                    
                |  | 25 | +{% codeblock lang:ruby %} | 
                    
                |  | 26 | +# Enable to see requests and responses between your machine and your jabber  | 
                    
                |  | 27 | +# server (easy to read XML). Recommended. | 
                    
                |  | 28 | +Jabber::debug = true | 
                    
                |  | 29 | + | 
                    
                |  | 30 | +# first, sign in to your jabber account with your Jabber ID and password | 
                    
                |  | 31 | +client = Jabber::Client.new("someuser@somejabberserver.tld") | 
                    
                |  | 32 | +client.connect() | 
                    
                |  | 33 | +client.auth("my password") | 
                    
                |  | 34 | + | 
                    
                |  | 35 | +# now we are authenticated, let's fetch roster with all information we want | 
                    
                |  | 36 | + | 
                    
                |  | 37 | +# initialize roster | 
                    
                |  | 38 | +roster = Jabber::Roster::Helper.new(client) | 
                    
                |  | 39 | + | 
                    
                |  | 40 | +# request roster from jabber server, wait for response | 
                    
                |  | 41 | +roster.get_roster() | 
                    
                |  | 42 | +roster.wait_for_roster() | 
                    
                |  | 43 | + | 
                    
                |  | 44 | +# now we know your friends' Jabber Ids | 
                    
                |  | 45 | +roster.items.each do |jid, contact| | 
                    
                |  | 46 | +  puts "In roster I have: " + jid | 
                    
                |  | 47 | +end | 
                    
                |  | 48 | + | 
                    
                |  | 49 | +# we don't know their status and status message, let's do it | 
                    
                |  | 50 | + | 
                    
                |  | 51 | +# First, add presence callback. If anyone in roster change his/her state  | 
                    
                |  | 52 | +# (e.g. come online), you will know it. | 
                    
                |  | 53 | +roster.add_presence_callback do |roster_item, old_presence, new_presence| | 
                    
                |  | 54 | +  puts "Somebody changed his/her state to " + new_presence.status.to_s | 
                    
                |  | 55 | +  # new_presence also offers status message and other stuff | 
                    
                |  | 56 | +end | 
                    
                |  | 57 | + | 
                    
                |  | 58 | +# To start receiving presence messages from your jabber server, you have to  | 
                    
                |  | 59 | +# send your presence first. It's really important to send your presence  | 
                    
                |  | 60 | +# AFTER roster.add_presence_callback, because the callback will not catch  | 
                    
                |  | 61 | +# every presence message which your jabber server sent to you. | 
                    
                |  | 62 | +client.send(Jabber::Presence.new.set_type(:available)) | 
                    
                |  | 63 | + | 
                    
                |  | 64 | +# Now you know who is online in your roster. If somebody from your  | 
                    
                |  | 65 | +# roster won't be caught in roster.add_presence_callback block, then  | 
                    
                |  | 66 | +# it just means he/she is offline. | 
                    
                |  | 67 | + | 
                    
                |  | 68 | +# get vcard | 
                    
                |  | 69 | + | 
                    
                |  | 70 | +roster.items.each do |jid, contact| | 
                    
                |  | 71 | +  # According to documentation, fetching vcard can take longer time. | 
                    
                |  | 72 | +  # Use threads if you think it is a good idea. | 
                    
                |  | 73 | +  Thread.new do | 
                    
                |  | 74 | +    vcard = Jabber::Vcard::Helper.get(client, jid) | 
                    
                |  | 75 | +    nickname = vcard && vcard["FN"] || '' | 
                    
                |  | 76 | +    #get avatar or other information here | 
                    
                |  | 77 | +  end | 
                    
                |  | 78 | +end | 
                    
                |  | 79 | +{% endcodeblock %} | 
                    
                |  | 80 | + | 
                    
                |  | 81 | +What I've learned from using XMPP4R library in my project -- callbacks are good | 
                    
                |  | 82 | +thing and use them. |