Class Jabber::Helpers::Roster
In: lib/xmpp4r/helpers/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.

Methods

Attributes

items  [R]  All items in your roster
items:[Hash] ([JID] => [Helpers::RosterItem])

Public Class methods

Initialize a new Roster helper

Registers its cbs (prio = 120, ref = "Helpers::Roster")

Request a roster (Remember to send initial presence afterwards!)

[Source]

    # File lib/xmpp4r/helpers/roster.rb, line 28
28:       def initialize(stream)
29:         @stream = stream
30:         @items = {}
31:         @query_cbs = CallbackList.new
32:         @update_cbs = CallbackList.new
33:         @presence_cbs = CallbackList.new
34:         @subscription_cbs = CallbackList.new
35: 
36:         # Register cbs
37:         stream.add_iq_callback(120, "Helpers::Roster") { |iq|
38:           handle_iq(iq)
39:         }
40:         stream.add_presence_callback(120, "Helpers::Roster") { |pres|
41:           handle_presence(pres)
42:         }
43:         
44:         # Request the roster
45:         rosterget = Iq.new_rosterget
46:         stream.send(rosterget)
47:       end

Public Instance methods

Get an item by jid

If not available tries to look for it with the resource stripped

[Source]

     # File lib/xmpp4r/helpers/roster.rb, line 188
188:       def [](jid)
189:         if @items.has_key?(jid)
190:           @items[jid]
191:         elsif @items.has_key?(jid.strip)
192:           @items[jid.strip]
193:         else
194:           nil
195:         end
196:       end

Add a user to your roster

If the item is already in the local roster it will simply send itself

[Source]

     # File lib/xmpp4r/helpers/roster.rb, line 244
244:       def add(jid)
245:         if self[jid]
246:           self[jid].send
247:         else
248:           request = Iq.new_rosterset
249:           request.query.add(Jabber::RosterItem.new(jid))
250:           @stream.send(request)
251:           # Adding to list is handled by handle_iq
252:         end
253:       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:

[Source]

    # File lib/xmpp4r/helpers/roster.rb, line 85
85:       def add_presence_callback(prio = 0, ref = nil, proc = nil, &block)
86:         block = proc if proc
87:         @presence_cbs.add(prio, ref, block)
88:       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

[Source]

    # File lib/xmpp4r/helpers/roster.rb, line 56
56:       def add_query_callback(prio = 0, ref = nil, proc = nil, &block)
57:         block = proc if proc
58:         @query_cbs.add(prio, ref, block)
59:       end

Add a callback for subscription updates, which will be called upon receiving a <presence/> stanza with type:

  • :subscribe (you may want to answer with :subscribed or :unsubscribed)
  • :subscribed
  • :unsubscribe
  • :unsubscribed

Warning: if you don’t add a callback here or all callbacks return false subscription requests will be agreed by default in Jabber::Helpers::Roster#handle_presence.

The block receives two objects:

Example usage:

 my_roster.add_subscription_callback do |item,presence|
   if presence.type == :subscribe
     answer = presence.answer(false)
     answer.type = accept_subscription_requests ? :subscribed : :unsubscribed
     client.send(answer)
     true
   else
     false
   end
 end

[Source]

     # File lib/xmpp4r/helpers/roster.rb, line 118
118:       def add_subscription_callback(prio = 0, ref = nil, proc = nil, &block)
119:         block = proc if proc
120:         @subscription_cbs.add(prio, ref, block)
121:       end

Add a callback for Jabber::Helpers::RosterItem updates

Note that this will be called much after initialization for the answer of the initial roster request

The block receives two objects:

[Source]

    # File lib/xmpp4r/helpers/roster.rb, line 70
70:       def add_update_callback(prio = 0, ref = nil, proc = nil, &block)
71:         block = proc if proc
72:         @update_cbs.add(prio, ref, block)
73:       end

Returns the list of RosterItems which, stripped, are equal to the one you are looking for.

[Source]

     # File lib/xmpp4r/helpers/roster.rb, line 201
201:       def find(jid)
202:         j = jid.strip
203:         l = {}
204:         @items.each_pair do |k, v|
205:           l[k] = v if k.strip == j
206:         end
207:         l
208:       end

Get items in a group

When group is nil, return ungrouped items

group:[String] Group name

[Source]

     # File lib/xmpp4r/helpers/roster.rb, line 230
230:       def find_by_group(group)
231:         res = []
232:         @items.each_pair do |jid,item|
233:           res.push(item) if item.groups.include?(group)
234:           res.push(item) if item.groups == [] and group.nil?
235:         end
236:         res
237:       end

Groups in this Roster, sorted by name

Contains nil if there are ungrouped items

result:[Array] containing group names (String)

[Source]

     # File lib/xmpp4r/helpers/roster.rb, line 216
216:       def groups
217:         res = []
218:         @items.each_pair do |jid,item|
219:           res += item.groups
220:           res += [nil] if item.groups == []
221:         end
222:         res.uniq.sort { |a,b| a.to_s <=> b.to_s }
223:       end

Handle received <iq/> stanzas, used internally

[Source]

     # File lib/xmpp4r/helpers/roster.rb, line 126
126:       def handle_iq(iq)
127:         if iq.query.kind_of?(IqQueryRoster)
128:           # If the <iq/> contains <error/> we just ignore that
129:           # and assume an empty roster
130:           iq.query.each_element('item') do |item|
131:             # Handle deletion of item
132:             if item.subscription == :remove
133:               @items.delete(item.jid)
134:               return(true)
135:             end
136:             
137:             olditem = nil
138:             if @items.has_key?(item.jid)
139:               olditem = RosterItem.new(@stream).import(@items[item.jid])
140:               @items[item.jid].import(item)
141:             else
142:               @items[item.jid] = RosterItem.new(@stream).import(item)
143:             end
144:             @update_cbs.process(olditem, @items[item.jid])
145:           end
146: 
147:           @query_cbs.process(iq)
148:         else
149:           false
150:         end
151:       end

Handle received <presence/> stanzas, used internally

[Source]

     # File lib/xmpp4r/helpers/roster.rb, line 156
156:       def handle_presence(pres)
157:         item = self[pres.from]
158:         if [:subscribe, :subscribed, :unsubscribe, :unsubscribed].include?(pres.type)
159:           unless @subscription_cbs.process(item, pres)
160:             @stream.send(Presence.new.set_to(pres.from.strip).set_type(:subscribed))
161:           end
162:           true
163:         else
164:           unless item.nil?
165:             update_presence(item, pres)
166:             true  # Callback consumed stanza
167:           else
168:             false # Callback did not consume stanza
169:           end
170:         end
171:       end

Remove item (also unsubscribes)

jid:[JID]

[Source]

     # File lib/xmpp4r/helpers/roster.rb, line 258
258:       def remove(jid)
259:         request = Iq.new_rosterset
260:         request.query.add(Jabber::RosterItem.new(jid, nil, :remove))
261:         @stream.send(request)
262:         # Removing from list is handled by handle_iq
263:       end

Update the presence of an item, used internally

Callbacks are called here

[Source]

     # File lib/xmpp4r/helpers/roster.rb, line 178
178:       def update_presence(item, pres)
179:         oldpres = item.presence(pres.from).nil? ? nil : Presence.new.import(item.presence(pres.from))
180:         item.add_presence(pres)
181:         @presence_cbs.process(item, oldpres, pres)
182:       end

[Validate]