Class: Jabber::Roster::Helper

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.

### Methods

[] accept_subscription add add_presence_callback add_query_callback add_subscription_callback add_subscription_request_callback add_update_callback decline_subscription find find_by_group groups new wait_for_roster

### Classes and Modules

Class Jabber::Roster::Helper::RosterItem

### Attributes

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

### Public Class methods

new(stream)

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!

[Source]

        # 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

### Public Instance methods

[](jid)

Get an item by jid

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

[Source]

         # 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_subscription(jid, iname=nil)

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

[Source]

         # 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(jid, iname=nil, subscribe=false)

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

[Source]

         # 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_presence_callback(prio = 0, ref = nil, &block)

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)

[Source]

         # 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_query_callback(prio = 0, ref = nil, &block)

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/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_subscription_callback(prio = 0, ref = nil, &block)

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

[Source]

         # 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_subscription_request_callback(prio = 0, ref = nil, &block)

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

[Source]

         # 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_update_callback(prio = 0, ref = nil, &block)

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

[Source]

         # 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_subscription(jid)

Decline a subscription request

- Sends a <presence type=‘unsubscribed’/> stanza

[Source]

         # 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

find(jid)

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

[Source]

         # 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

find_by_group(group)

Get items in a group

When group is nil, return ungrouped items

group: | [String] Group name
result: | Array of [RosterItem]

[Source]

         # 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()

Groups in this Roster, sorted by name

Contains `nil` if there are ungrouped items

result: | [Array] containing group names (String)

[Source]

         # 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

wait_for_roster()

Wait for first roster query result to arrive

[Source]

        # File lib/xmpp4r/roster/helper/roster.rb, line 77
    77:       def wait_for_roster
    78:         @roster_wait.wait
    79:         @roster_wait.run
    80:       end

[Validate]