Class | Jabber::Roster::Helper |
In: |
lib/xmpp4r/roster/helper/roster.rb
|
Parent: | 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.
items | [R] |
All items in your roster
|
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 39: def initialize(stream, startnow = true) 40: @stream = stream 41: @items = {} 42: @items_lock = Mutex.new 43: @roster_wait = Semaphore.new 44: @query_cbs = CallbackList.new 45: @update_cbs = CallbackList.new 46: @presence_cbs = CallbackList.new 47: @subscription_cbs = CallbackList.new 48: @subscription_request_cbs = CallbackList.new 49: 50: # Register cbs 51: stream.add_iq_callback(120, self) { |iq| 52: if iq.query.kind_of?(IqQueryRoster) 53: Thread.new do 54: Thread.current.abort_on_exception = true 55: handle_iq_query_roster(iq) 56: end 57: 58: true 59: else 60: false 61: end 62: } 63: stream.add_presence_callback(120, self) { |pres| 64: Thread.new do 65: Thread.current.abort_on_exception = true 66: handle_presence(pres) 67: end 68: } 69: get_roster if startnow 70: 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 247: def [](jid) 248: jid = JID.new(jid) unless jid.kind_of? JID 249: 250: @items_lock.synchronize { 251: if @items.has_key?(jid) 252: @items[jid] 253: elsif @items.has_key?(jid.strip) 254: @items[jid.strip] 255: else 256: nil 257: end 258: } 259: end
Accept a subscription request
jid: | [JID] of contact |
iname: | [String] Optional roster item name |
# File lib/xmpp4r/roster/helper/roster.rb, line 350 350: def accept_subscription(jid, iname=nil) 351: pres = Presence.new.set_type(:subscribed).set_to(jid.strip) 352: @stream.send(pres) 353: 354: unless self[jid.strip] 355: request = Iq.new_rosterset 356: request.query.add(Jabber::Roster::RosterItem.new(jid.strip, iname)) 357: @stream.send_with_id(request) 358: end 359: 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: | [JID] to add |
iname: | [String] Optional item name |
subscribe: | [Boolean] Whether to subscribe to this jid |
# File lib/xmpp4r/roster/helper/roster.rb, line 326 326: def add(jid, iname=nil, subscribe=false) 327: if self[jid] 328: self[jid].send 329: else 330: request = Iq.new_rosterset 331: request.query.add(Jabber::Roster::RosterItem.new(jid, iname)) 332: @stream.send_with_id(request) 333: # Adding to list is handled by handle_iq_query_roster 334: end 335: 336: if subscribe 337: # Actually the item *should* already be known now, 338: # but we do it manually to exclude conditions. 339: pres = Presence.new.set_type(:subscribe).set_to(jid.strip) 340: @stream.send(pres) 341: end 342: 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:
# File lib/xmpp4r/roster/helper/roster.rb, line 119 119: def add_presence_callback(prio = 0, ref = nil, &block) 120: @presence_cbs.add(prio, ref, block) 121: 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 92: def add_query_callback(prio = 0, ref = nil, &block) 93: @query_cbs.add(prio, ref, block) 94: end
Add a callback for subscription updates, which will be called upon receiving a <presence/> stanza with type:
The block receives two objects:
# File lib/xmpp4r/roster/helper/roster.rb, line 134 134: def add_subscription_callback(prio = 0, ref = nil, &block) 135: @subscription_cbs.add(prio, ref, block) 136: end
Add a callback for subscription requests, which will be called upon receiving a <presence type=‘subscribe’/> stanza
The block receives two objects:
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 157: def add_subscription_request_callback(prio = 0, ref = nil, &block) 158: @subscription_request_cbs.add(prio, ref, block) 159: 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 105: def add_update_callback(prio = 0, ref = nil, &block) 106: @update_cbs.add(prio, ref, block) 107: end
Decline a subscription request
# File lib/xmpp4r/roster/helper/roster.rb, line 364 364: def decline_subscription(jid) 365: pres = Presence.new.set_type(:unsubscribed).set_to(jid.strip) 366: @stream.send(pres) 367: 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 264: def find(jid) 265: jid = JID.new(jid) unless jid.kind_of? JID 266: 267: j = jid.strip 268: l = {} 269: @items_lock.synchronize { 270: @items.each_pair do |k, v| 271: l[k] = v if k.strip == j 272: end 273: } 274: l 275: end
Get items in a group
When group is nil, return ungrouped items
group: | [String] Group name |
result: | Array of [RosterItem] |
# File lib/xmpp4r/roster/helper/roster.rb, line 300 300: def find_by_group(group) 301: res = [] 302: @items_lock.synchronize { 303: @items.each_pair do |jid,item| 304: res.push(item) if item.groups.include?(group) 305: res.push(item) if item.groups == [] and group.nil? 306: end 307: } 308: res 309: end
# File lib/xmpp4r/roster/helper/roster.rb, line 72 72: def get_roster 73: # Request the roster 74: rosterget = Iq.new_rosterget 75: @stream.send(rosterget) 76: end
Groups in this Roster, sorted by name
Contains nil if there are ungrouped items
result: | [Array] containing group names (String) |
# File lib/xmpp4r/roster/helper/roster.rb, line 283 283: def groups 284: res = [] 285: @items_lock.synchronize { 286: @items.each_pair do |jid,item| 287: res += item.groups 288: res += [nil] if item.groups == [] 289: end 290: } 291: res.uniq.sort { |a,b| a.to_s <=> b.to_s } 292: end