rubyxmppxmpp4r

Using the xmpp4r Ruby gem, how can I synchronously discover if a contact is online?


I'm new to XMPP and the xmpp4r library, so please forgive my noob question if this is obviously documented somewhere.

What's the most straightforward way, in a synchronous manner, to find out if a given JID is online? (so that I can call something like is_online?(jid) in an if statement)

My details:

I'm writing a Sinatra app that will attempt to send a message to a user when a particular url gets requested on the web server, but it should only try to send the message to the user if that user is currently online. Figuring out if a given JID is online is my problem.

Now, I know that if I connect and wait a few seconds for all the initial presence probe responses to come back to the Roster helper, then I can inspect any of those presences from my Roster and call #online? on them to get the correct value. But, I don't know when all of the presence updates have been sent, so there's a race condition there and sometimes calling #online? on a presence from my roster will return false if I just haven't received that presence probe response yet.

So, my current thinking is that the most straightforward way to find out if someone is online is to construct a new Presence message of type :probe and send that out to the JID that I'm interested in. Here's how I'm doing it right now:

#jabber is the result of Client::new
#email is the jid I'm interested in polling
def is_online?(jabber, email)
      online = false
      p = Presence.new
      p.set_to(email)
      p.set_from(jabber.jid)
      p.set_type(:probe)
      pres = jabber.send(p) do |returned_presence|
        online = returned_presence.nil?
      end

     return online
end

Now, this works in cases where the user is actually online, but when the user is offline, it looks like the presence probe message that comes back is being caught by some other presence_callback handler that doesn't know what to do with it, and my is_online? function never finishes returning a value.

Can anyone help me by providing a simple example is_online? function that I can call, or point me in the right direction for how I can detect when the roster is done getting all the initial presence updates before I try checking a presence for #online?


Solution

  • As it turns out, there's not a synchronous way to ask for a JID presence. You've just got to ask for what you want, then wait for your response handler to fire when the response arrives.