Class: Jabber::Roster::Helper::RosterItem

Inherits:
RosterItem show all
Defined in:
lib/xmpp4r/roster/helper/roster.rb

Overview

These are extensions to RosterItem to carry presence information. This information is not stored in XML!

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from RosterItem

#ask, #ask=, #groups, #groups=, import, #iname, #iname=, #jid, #jid=, #subscription, #subscription=

Methods inherited from REXML::Element

#delete_elements, #first_element, #first_element_text, import, #replace_element_text, #typed_add

Constructor Details

#initialize(stream) ⇒ RosterItem

Initialize an empty RosterItem


371
372
373
374
375
376
# File 'lib/xmpp4r/roster/helper/roster.rb', line 371

def initialize(stream)
  super()
  @stream = stream
  @presences = []
  @presences_lock = Mutex.new
end

Instance Attribute Details

#presencesObject (readonly)

Tracked (online) presences of this RosterItem


367
368
369
# File 'lib/xmpp4r/roster/helper/roster.rb', line 367

def presences
  @presences
end

Instance Method Details

#add_presence(newpres) ⇒ Object

Add presence and sort presences (unless type is :unavailable or :error)

This overwrites previous stanzas with the same destination JID to keep track of resources. Presence stanzas with type == :unavailable or type == :error will be deleted as this indicates that this resource has gone offline.

If type == :error and the presence's origin has no specific resource the contact is treated completely offline.


462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
# File 'lib/xmpp4r/roster/helper/roster.rb', line 462

def add_presence(newpres)
  @presences_lock.synchronize {
    # Delete old presences with the same JID
    @presences.delete_if do |pres|
      pres.from == newpres.from or pres.from.resource.nil?
    end

    if newpres.type == :error and newpres.from.resource.nil?
      # Replace by single error presence
      @presences = [newpres]
    else
      # Add new presence
      @presences.push(newpres)
    end

    @presences.sort!
  }
end

#cancel_subscriptionObject

Deny the contact to see your presence.

This method will not wait and returns immediately as you will need no confirmation for this action.

Though, you will get a roster update for that item, carrying either subscription='to' or 'none'.


521
522
523
524
# File 'lib/xmpp4r/roster/helper/roster.rb', line 521

def cancel_subscription
  pres = Presence.new.set_type(:unsubscribed).set_to(jid)
  @stream.send(pres)
end

#each_presence(&block) ⇒ Object

Iterate through all received <presence/> stanzas


431
432
433
434
435
436
# File 'lib/xmpp4r/roster/helper/roster.rb', line 431

def each_presence(&block)
  # Don't lock here, we don't know what block does...
  @presences.each { |pres|
    yield(pres)
  }
end

#import(xe) ⇒ Object

Import another element, also import presences if xe is a RosterItem

return
RosterItem

self


382
383
384
385
386
387
388
389
390
# File 'lib/xmpp4r/roster/helper/roster.rb', line 382

def import(xe)
  super
  if xe.kind_of?(RosterItem)
    xe.each_presence { |pres|
      add_presence(Presence.new.import(pres))
    }
  end
  self
end

#online?Boolean

Is any presence of this person on-line?

(Or is there any presence? Unavailable presences are deleted.)

Returns:

  • (Boolean)

421
422
423
424
425
426
427
# File 'lib/xmpp4r/roster/helper/roster.rb', line 421

def online?
  @presences_lock.synchronize {
    @presences.select { |pres|
      pres.type.nil?
    }.size > 0
  }
end

#presence(jid) ⇒ Object

Get specific presence

jid
JID

Full JID


441
442
443
444
445
446
447
448
# File 'lib/xmpp4r/roster/helper/roster.rb', line 441

def presence(jid)
  @presences_lock.synchronize {
    @presences.each { |pres|
      return(pres) if pres.from == jid
    }
  }
  nil
end

#removeObject

Remove item

This cancels both subscription from the contact to you and from you to the contact.

The methods waits for a roster push from the server (success) or throws ErrorException upon failure.


409
410
411
412
413
414
# File 'lib/xmpp4r/roster/helper/roster.rb', line 409

def remove
  request = Iq.new_rosterset
  request.query.add(Jabber::Roster::RosterItem.new(jid, nil, :remove))
  @stream.send_with_id(request) { true }
  # Removing from list is handled by Roster#handle_iq
end

#sendObject

Send the updated RosterItem to the server, i.e. if you modified iname, groups, …


395
396
397
398
399
# File 'lib/xmpp4r/roster/helper/roster.rb', line 395

def send
  request = Iq.new_rosterset
  request.query.add(self)
  @stream.send(request)
end

#subscribeObject

Send subscription request to the user

The block given to Jabber::Roster::Roster#add_update_callback will be called, carrying the RosterItem with ask=“subscribe”

This function returns immediately after sending the subscription request and will not wait of approval or declination as it may take months for the contact to decide. ;-)


490
491
492
493
# File 'lib/xmpp4r/roster/helper/roster.rb', line 490

def subscribe
  pres = Presence.new.set_type(:subscribe).set_to(jid.strip)
  @stream.send(pres)
end

#unsubscribeObject

Unsubscribe from a contact's presence

This method waits for a presence with type='unsubscribed' from the contact. It may throw ErrorException upon failure.

subscription attribute of the item is from or none afterwards. As long as you don't remove that item and subscription='from' the contact is subscribed to your presence.


505
506
507
508
509
510
511
# File 'lib/xmpp4r/roster/helper/roster.rb', line 505

def unsubscribe
  pres = Presence.new.set_type(:unsubscribe).set_to(jid.strip)
  @stream.send(pres) { |answer|
    answer.type == :unsubscribed and
    answer.from.strip == pres.to
  }
end