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=, #iname, #iname=, #jid, #jid=, #subscription, #subscription=

Methods inherited from XMPPElement

class_for_name_xmlns, #clone, force_xmlns, force_xmlns?, import, name_xmlns, name_xmlns_for_class, #parent=, #set_xml_lang, #typed_add, #xml_lang, #xml_lang=

Methods inherited from REXML::Element

#==, #delete_elements, #each_elements, #first_element, #first_element_content, #first_element_text, #import, import, #replace_element_content, #replace_element_text, #typed_add

Constructor Details

#initialize(stream) ⇒ RosterItem

Initialize an empty RosterItem



379
380
381
382
383
384
# File 'lib/xmpp4r/roster/helper/roster.rb', line 379

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

Instance Attribute Details

#presencesObject (readonly)

Tracked (online) presences of this RosterItem



375
376
377
# File 'lib/xmpp4r/roster/helper/roster.rb', line 375

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. Old presence stanzas with type == :unavailable will be deleted.

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



466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
# File 'lib/xmpp4r/roster/helper/roster.rb', line 466

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? or pres.type == :unavailable
    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'.



525
526
527
528
# File 'lib/xmpp4r/roster/helper/roster.rb', line 525

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



425
426
427
428
429
430
# File 'lib/xmpp4r/roster/helper/roster.rb', line 425

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

#online?Boolean

Is any presence of this person on-line?

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

Returns:

  • (Boolean)


415
416
417
418
419
420
421
# File 'lib/xmpp4r/roster/helper/roster.rb', line 415

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

#presenceObject

Get presence of highest-priority available resource of this person

Returns nil if contact is offline



448
449
450
451
452
453
454
# File 'lib/xmpp4r/roster/helper/roster.rb', line 448

def presence
  @presences_lock.synchronize {
    @presences.select { |pres|
      pres.type.nil?
    }.max { |pres1, pres2| (pres1.priority || 0) <=> (pres2.priority || 0) }
  }
end

#presence_of(jid) ⇒ Object

Get specific presence

jid
JID

Full JID with resource



435
436
437
438
439
440
441
442
# File 'lib/xmpp4r/roster/helper/roster.rb', line 435

def presence_of(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 ServerError upon failure.



403
404
405
406
407
408
# File 'lib/xmpp4r/roster/helper/roster.rb', line 403

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

#sendObject

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



389
390
391
392
393
# File 'lib/xmpp4r/roster/helper/roster.rb', line 389

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. ;-)



494
495
496
497
# File 'lib/xmpp4r/roster/helper/roster.rb', line 494

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 ServerError 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.



509
510
511
512
513
514
515
# File 'lib/xmpp4r/roster/helper/roster.rb', line 509

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