| 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)
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:
70: # Request the roster
71: rosterget = Iq.new_rosterget
72: stream.send(rosterget)
73: 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 244
244: def [](jid)
245: jid = JID.new(jid) unless jid.kind_of? JID
246:
247: @items_lock.synchronize {
248: if @items.has_key?(jid)
249: @items[jid]
250: elsif @items.has_key?(jid.strip)
251: @items[jid.strip]
252: else
253: nil
254: end
255: }
256: end
Accept a subscription request
| jid: | [JID] of contact |
| iname: | [String] Optional roster item name |
# File lib/xmpp4r/roster/helper/roster.rb, line 347
347: def accept_subscription(jid, iname=nil)
348: pres = Presence.new.set_type(:subscribed).set_to(jid.strip)
349: @stream.send(pres)
350:
351: unless self[jid.strip]
352: request = Iq.new_rosterset
353: request.query.add(Jabber::Roster::RosterItem.new(jid.strip, iname))
354: @stream.send_with_id(request)
355: end
356: 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 323
323: def add(jid, iname=nil, subscribe=false)
324: if self[jid]
325: self[jid].send
326: else
327: request = Iq.new_rosterset
328: request.query.add(Jabber::Roster::RosterItem.new(jid, iname))
329: @stream.send_with_id(request)
330: # Adding to list is handled by handle_iq_query_roster
331: end
332:
333: if subscribe
334: # Actually the item *should* already be known now,
335: # but we do it manually to exclude conditions.
336: pres = Presence.new.set_type(:subscribe).set_to(jid.strip)
337: @stream.send(pres)
338: end
339: 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 116
116: def add_presence_callback(prio = 0, ref = nil, &block)
117: @presence_cbs.add(prio, ref, block)
118: 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 89
89: def add_query_callback(prio = 0, ref = nil, &block)
90: @query_cbs.add(prio, ref, block)
91: 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 131
131: def add_subscription_callback(prio = 0, ref = nil, &block)
132: @subscription_cbs.add(prio, ref, block)
133: 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 154
154: def add_subscription_request_callback(prio = 0, ref = nil, &block)
155: @subscription_request_cbs.add(prio, ref, block)
156: 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 102
102: def add_update_callback(prio = 0, ref = nil, &block)
103: @update_cbs.add(prio, ref, block)
104: end
Decline a subscription request
# File lib/xmpp4r/roster/helper/roster.rb, line 361
361: def decline_subscription(jid)
362: pres = Presence.new.set_type(:unsubscribed).set_to(jid.strip)
363: @stream.send(pres)
364: 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 261
261: def find(jid)
262: jid = JID.new(jid) unless jid.kind_of? JID
263:
264: j = jid.strip
265: l = {}
266: @items_lock.synchronize {
267: @items.each_pair do |k, v|
268: l[k] = v if k.strip == j
269: end
270: }
271: l
272: 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 297
297: def find_by_group(group)
298: res = []
299: @items_lock.synchronize {
300: @items.each_pair do |jid,item|
301: res.push(item) if item.groups.include?(group)
302: res.push(item) if item.groups == [] and group.nil?
303: end
304: }
305: res
306: 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 280
280: def groups
281: res = []
282: @items_lock.synchronize {
283: @items.each_pair do |jid,item|
284: res += item.groups
285: res += [nil] if item.groups == []
286: end
287: }
288: res.uniq.sort { |a,b| a.to_s <=> b.to_s }
289: end