Object
The Roster helper intercepts <iq/> stanzas with Jabber::IqQueryRoster and <presence/> stanzas, but provides cbs which allow the programmer to keep track of updates.
A thread for any received stanza is spawned, so the user can invoke accept_subscription et al in the callback blocks, without stopping the current (= parser) thread when waiting for a reply.
Initialize a new Roster helper
Registers its cbs (prio = 120, ref = self)
Request a roster (Remember to send initial presence afterwards!)
The initialization will not wait for the roster being received, use wait_for_roster.
Attention: If you send presence and receive presences before the roster has arrived, the Roster helper will let them pass through and does not keep them!
# File lib/xmpp4r/roster/helper/roster.rb, line 39 def initialize(stream, startnow = true) @stream = stream @items = {} @items_lock = Mutex.new @roster_wait = Semaphore.new @query_cbs = CallbackList.new @update_cbs = CallbackList.new @presence_cbs = CallbackList.new @subscription_cbs = CallbackList.new @subscription_request_cbs = CallbackList.new # Register cbs stream.add_iq_callback(120, self) { |iq| if iq.query.kind_of?(IqQueryRoster) Thread.new do Thread.current.abort_on_exception = true handle_iq_query_roster(iq) end true else false end } stream.add_presence_callback(120, self) { |pres| Thread.new do Thread.current.abort_on_exception = true handle_presence(pres) end } get_roster if startnow end
Get an item by jid
If not available tries to look for it with the resource stripped
# File lib/xmpp4r/roster/helper/roster.rb, line 247 def [](jid) jid = JID.new(jid) unless jid.kind_of? JID @items_lock.synchronize { if @items.has_key?(jid) @items[jid] elsif @items.has_key?(jid.strip) @items[jid.strip] else nil end } end
Accept a subscription request
Sends a <presence type='subscribed'/> stanza
Adds the contact to your roster
jid |
|
iname |
|
# File lib/xmpp4r/roster/helper/roster.rb, line 350 def accept_subscription(jid, iname=nil) pres = Presence.new.set_type(:subscribed).set_to(jid.strip) @stream.send(pres) unless self[jid.strip] request = Iq.new_rosterset request.query.add(Jabber::Roster::RosterItem.new(jid.strip, iname)) @stream.send_with_id(request) end end
Add a user to your roster
Threading is encouraged as the function waits for a result. ServerError is thrown upon error.
See Jabber::Roster::Helper::RosterItem#subscribe for details about subscribing. (This method isn't used here but the same functionality applies.)
If the item is already in the local roster it will simply send itself
jid |
|
iname |
|
subscribe |
|
# File lib/xmpp4r/roster/helper/roster.rb, line 326 def add(jid, iname=nil, subscribe=false) if self[jid] self[jid].send else request = Iq.new_rosterset request.query.add(Jabber::Roster::RosterItem.new(jid, iname)) @stream.send_with_id(request) # Adding to list is handled by handle_iq_query_roster end if subscribe # Actually the item *should* already be known now, # but we do it manually to exclude conditions. pres = Presence.new.set_type(:subscribe).set_to(jid.strip) @stream.send(pres) end end
Add a callback for Jabber::Presence updates
This will be called for <presence/> stanzas for known RosterItems. Unknown JIDs may still pass and can be caught via Jabber::Stream#add_presence_callback.
The block receives three objects:
the old Jabber::Presence (or nil)
the new Jabber::Presence (or nil)
# File lib/xmpp4r/roster/helper/roster.rb, line 119 def add_presence_callback(prio = 0, ref = nil, &block) @presence_cbs.add(prio, ref, block) end
Add a callback to be called when a query has been processed
Because update callbacks are called for each roster item, this may be appropriate to notify that anything has updated.
Arguments for callback block: The received <iq/> stanza
# File lib/xmpp4r/roster/helper/roster.rb, line 92 def add_query_callback(prio = 0, ref = nil, &block) @query_cbs.add(prio, ref, block) end
Add a callback for subscription updates, which will be called upon receiving a <presence/> stanza with type:
:subscribed
:unsubscribe
:unsubscribed
The block receives two objects:
the Jabber::Roster::Helper::RosterItem (or nil)
the <presence/> stanza
# File lib/xmpp4r/roster/helper/roster.rb, line 134 def add_subscription_callback(prio = 0, ref = nil, &block) @subscription_cbs.add(prio, ref, block) end
Add a callback for subscription requests, which will be called upon receiving a <presence type='subscribe'/> stanza
The block receives two objects:
the Jabber::Roster::Helper::RosterItem (or nil)
the <presence/> stanza
Response to this event can be taken with accept_subscription and decline_subscription.
Example usage:
my_roster.add_subscription_request_callback do |item,presence| if accept_subscription_requests my_roster.accept_subscription(presence.from) else my_roster.decline_subscription(presence.from) end end
# File lib/xmpp4r/roster/helper/roster.rb, line 157 def add_subscription_request_callback(prio = 0, ref = nil, &block) @subscription_request_cbs.add(prio, ref, block) end
Add a callback for Jabber::Roster::Helper::RosterItem updates
Note that this will be called much after initialization for the answer of the initial roster request
The block receives two objects:
# File lib/xmpp4r/roster/helper/roster.rb, line 105 def add_update_callback(prio = 0, ref = nil, &block) @update_cbs.add(prio, ref, block) end
Decline a subscription request
Sends a <presence type='unsubscribed'/> stanza
# File lib/xmpp4r/roster/helper/roster.rb, line 364 def decline_subscription(jid) pres = Presence.new.set_type(:unsubscribed).set_to(jid.strip) @stream.send(pres) end
Returns the list of RosterItems which, stripped, are equal to the one you are looking for.
# File lib/xmpp4r/roster/helper/roster.rb, line 264 def find(jid) jid = JID.new(jid) unless jid.kind_of? JID j = jid.strip l = {} @items_lock.synchronize { @items.each_pair do |k, v| l[k] = v if k.strip == j end } l end
Get items in a group
When group is nil, return ungrouped items
group |
|
result |
Array of [RosterItem] |
# File lib/xmpp4r/roster/helper/roster.rb, line 300 def find_by_group(group) res = [] @items_lock.synchronize { @items.each_pair do |jid,item| res.push(item) if item.groups.include?(group) res.push(item) if item.groups == [] and group.nil? end } res end
# File lib/xmpp4r/roster/helper/roster.rb, line 72 def get_roster # Request the roster rosterget = Iq.new_rosterget @stream.send(rosterget) end
Groups in this Roster, sorted by name
Contains nil if there are ungrouped items
result |
|
# File lib/xmpp4r/roster/helper/roster.rb, line 283 def groups res = [] @items_lock.synchronize { @items.each_pair do |jid,item| res += item.groups res += [nil] if item.groups == [] end } res.uniq.sort { |a,b| a.to_s <=> b.to_s } end
Generated with the Darkfish Rdoc Generator 2.