Class: Jabber::Roster::Helper

Inherits:
Object
  • Object
show all
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.

Defined Under Namespace

Classes: RosterItem

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(stream) ⇒ Helper

Initialize a new Roster helper

Registers its cbs (prio = 120, ref = self)

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



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/xmpp4r/roster/helper/roster.rb', line 28

def initialize(stream)
  @stream = stream
  @items = {}
  @items_lock = Mutex.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|
    handle_iq(iq)
  }
  stream.add_presence_callback(120, self) { |pres|
    handle_presence(pres)
  }
  
  # Request the roster
  rosterget = Iq.new_rosterget
  stream.send(rosterget)
end

Instance Attribute Details

#itemsObject (readonly)

All items in your roster

items
Hash

([JID] => [Roster::Helper::RosterItem])



19
20
21
# File 'lib/xmpp4r/roster/helper/roster.rb', line 19

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



224
225
226
227
228
229
230
231
232
233
234
235
236
# File 'lib/xmpp4r/roster/helper/roster.rb', line 224

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



327
328
329
330
331
332
333
334
335
336
# File 'lib/xmpp4r/roster/helper/roster.rb', line 327

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) { true }
  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. ErrorException 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



303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
# File 'lib/xmpp4r/roster/helper/roster.rb', line 303

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) { true }
    # Adding to list is handled by handle_iq
  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)



85
86
87
# File 'lib/xmpp4r/roster/helper/roster.rb', line 85

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



58
59
60
# File 'lib/xmpp4r/roster/helper/roster.rb', line 58

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



100
101
102
# File 'lib/xmpp4r/roster/helper/roster.rb', line 100

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


123
124
125
# File 'lib/xmpp4r/roster/helper/roster.rb', line 123

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



71
72
73
# File 'lib/xmpp4r/roster/helper/roster.rb', line 71

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



341
342
343
344
# File 'lib/xmpp4r/roster/helper/roster.rb', line 341

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.



241
242
243
244
245
246
247
248
249
250
251
252
# File 'lib/xmpp4r/roster/helper/roster.rb', line 241

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]



277
278
279
280
281
282
283
284
285
286
# File 'lib/xmpp4r/roster/helper/roster.rb', line 277

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

#groupsObject

Groups in this Roster, sorted by name

Contains nil if there are ungrouped items

result
Array

containing group names (String)



260
261
262
263
264
265
266
267
268
269
# File 'lib/xmpp4r/roster/helper/roster.rb', line 260

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