Class: Jabber::Roster::Helper
- Inherits:
-
Object
- Object
- Jabber::Roster::Helper
- Defined in:
- lib/xmpp4r/roster/helper/roster.rb
Overview
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.
Defined Under Namespace
Classes: RosterItem
Instance Attribute Summary collapse
-
#items ⇒ Object
readonly
- All items in your roster items
- Hash
-
([JID] => [Roster::Helper::RosterItem]).
Instance Method Summary collapse
-
#[](jid) ⇒ Object
Get an item by jid.
-
#accept_subscription(jid, iname = nil) ⇒ Object
- Accept a subscription request * Sends a <presence type=‘subscribed’/> stanza * Adds the contact to your roster jid
- JID
- of contact iname
- String
-
Optional roster item name.
-
#add(jid, iname = nil, subscribe = false) ⇒ Object
Add a user to your roster.
-
#add_presence_callback(prio = 0, ref = nil, &block) ⇒ Object
Add a callback for Jabber::Presence updates.
-
#add_query_callback(prio = 0, ref = nil, &block) ⇒ Object
Add a callback to be called when a query has been processed.
-
#add_subscription_callback(prio = 0, ref = nil, &block) ⇒ Object
Add a callback for subscription updates, which will be called upon receiving a
<presence/>
stanza with type: * :subscribed * :unsubscribe * :unsubscribed. -
#add_subscription_request_callback(prio = 0, ref = nil, &block) ⇒ Object
Add a callback for subscription requests, which will be called upon receiving a
<presence type='subscribe'/>
stanza. -
#add_update_callback(prio = 0, ref = nil, &block) ⇒ Object
Add a callback for Jabber::Roster::Helper::RosterItem updates.
-
#decline_subscription(jid) ⇒ Object
Decline a subscription request * Sends a <presence type=‘unsubscribed’/> stanza.
-
#find(jid) ⇒ Object
Returns the list of RosterItems which, stripped, are equal to the one you are looking for.
-
#find_by_group(group) ⇒ Object
Get items in a group.
- #get_roster ⇒ Object
-
#groups ⇒ Object
Groups in this Roster, sorted by name.
-
#initialize(stream, startnow = true) ⇒ Helper
constructor
Initialize a new Roster helper.
-
#wait_for_roster ⇒ Object
Wait for first roster query result to arrive.
Constructor Details
#initialize(stream, startnow = true) ⇒ Helper
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!
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# 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 |
Instance Attribute Details
#items ⇒ Object (readonly)
All items in your roster
- items
- Hash
-
([JID] => [Roster::Helper::RosterItem])
23 24 25 |
# File 'lib/xmpp4r/roster/helper/roster.rb', line 23 def items @items end |
Instance Method Details
#[](jid) ⇒ Object
Get an item by jid
If not available tries to look for it with the resource stripped
247 248 249 250 251 252 253 254 255 256 257 258 259 |
# 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_subscription(jid, iname = nil) ⇒ Object
Accept a subscription request
-
Sends a <presence type=‘subscribed’/> stanza
-
Adds the contact to your roster
- jid
- JID
-
of contact
- iname
- String
-
Optional roster item name
350 351 352 353 354 355 356 357 358 359 |
# 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(jid, iname = nil, subscribe = false) ⇒ Object
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
- JID
-
to add
- iname
- String
-
Optional item name
- subscribe
- Boolean
-
Whether to subscribe to this jid
326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 |
# 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_presence_callback(prio = 0, ref = nil, &block) ⇒ Object
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 Jabber::Roster::Helper::RosterItem
-
the old Jabber::Presence (or nil)
-
the new Jabber::Presence (or nil)
119 120 121 |
# 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_query_callback(prio = 0, ref = nil, &block) ⇒ Object
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
92 93 94 |
# 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_subscription_callback(prio = 0, ref = nil, &block) ⇒ Object
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
134 135 136 |
# 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_subscription_request_callback(prio = 0, ref = nil, &block) ⇒ Object
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
157 158 159 |
# 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_update_callback(prio = 0, ref = nil, &block) ⇒ Object
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:
-
the old Jabber::Roster::Helper::RosterItem
-
the new Jabber::Roster::Helper::RosterItem
105 106 107 |
# 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_subscription(jid) ⇒ Object
Decline a subscription request
-
Sends a <presence type=‘unsubscribed’/> stanza
364 365 366 367 |
# 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 |
#find(jid) ⇒ Object
Returns the list of RosterItems which, stripped, are equal to the one you are looking for.
264 265 266 267 268 269 270 271 272 273 274 275 |
# 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 |
#find_by_group(group) ⇒ Object
Get items in a group
When group is nil, return ungrouped items
- group
- String
-
Group name
- result
-
Array of [RosterItem]
300 301 302 303 304 305 306 307 308 309 |
# 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 |
#get_roster ⇒ Object
72 73 74 75 76 |
# File 'lib/xmpp4r/roster/helper/roster.rb', line 72 def get_roster # Request the roster rosterget = Iq.new_rosterget @stream.send(rosterget) end |
#groups ⇒ Object
Groups in this Roster, sorted by name
Contains nil
if there are ungrouped items
- result
- Array
-
containing group names (String)
283 284 285 286 287 288 289 290 291 292 |
# 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 |
#wait_for_roster ⇒ Object
Wait for first roster query result to arrive
80 81 82 83 |
# File 'lib/xmpp4r/roster/helper/roster.rb', line 80 def wait_for_roster @roster_wait.wait @roster_wait.run end |