### Home Classes Methods

### In Files

- lib/xmpp4r/muc/helper/mucclient.rb

### Parent

Object

### Methods

- ::new
- #active?
- #add_join_callback
- #add_leave_callback
- #add_message_callback
- #add_presence_callback
- #add_private_message_callback
- #configure
- #exit
- #from_room?
- #get_room_configuration
- #join
- #nick
- #nick=
- #owner?
- #room
- #send
- #send_affiliations
- #submit_room_configuration

### Files

- CHANGELOG
- COPYING
- LICENSE
- README.rdoc
- README_ruby19.txt

### Class/Module Index

Quicksearch

- Jabber
- Jabber::ArgumentError
- Jabber::Bytestreams
- Jabber::Bytestreams::IBB
- Jabber::Bytestreams::IBBInitiator
- Jabber::Bytestreams::IBBQueueItem
- Jabber::Bytestreams::IBBTarget
- Jabber::Bytestreams::IqQueryBytestreams
- Jabber::Bytestreams::IqSi
- Jabber::Bytestreams::IqSiFile
- Jabber::Bytestreams::IqSiFileRange
- Jabber::Bytestreams::SOCKS5Bytestreams
- Jabber::Bytestreams::SOCKS5BytestreamsInitiator
- Jabber::Bytestreams::SOCKS5BytestreamsPeer
- Jabber::Bytestreams::SOCKS5BytestreamsServer
- Jabber::Bytestreams::SOCKS5BytestreamsServerStreamHost
- Jabber::Bytestreams::SOCKS5BytestreamsTarget
- Jabber::Bytestreams::SOCKS5Socket
- Jabber::Bytestreams::StreamHost
- Jabber::Bytestreams::StreamHostUsed
- Jabber::Callback
- Jabber::CallbackList
- Jabber::Caps
- Jabber::Caps::C
- Jabber::Caps::Helper
- Jabber::Client
- Jabber::ClientAuthenticationFailure
- Jabber::Command
- Jabber::Command::IqCommand
- Jabber::Command::Responder
- Jabber::Component
- Jabber::ComponentAuthenticationFailure
- Jabber::Connection
- Jabber::Connection::SSLSocketUTF8
- Jabber::Dataforms
- Jabber::Dataforms::XData
- Jabber::Dataforms::XDataField
- Jabber::Dataforms::XDataInstructions
- Jabber::Dataforms::XDataReported
- Jabber::Dataforms::XDataTitle
- Jabber::Delay
- Jabber::Delay::XDelay
- Jabber::Discovery
- Jabber::Discovery::Feature
- Jabber::Discovery::Helper
- Jabber::Discovery::Identity
- Jabber::Discovery::IqQueryDiscoInfo
- Jabber::Discovery::IqQueryDiscoItems
- Jabber::Discovery::Item
- Jabber::Discovery::Responder
- Jabber::EntityTime
- Jabber::EntityTime::IqTime
- Jabber::EntityTime::Responder
- Jabber::ErrorResponse
- Jabber::FeatureNegotiation
- Jabber::FeatureNegotiation::IqFeature
- Jabber::FileTransfer
- Jabber::FileTransfer::FileSource
- Jabber::FileTransfer::Helper
- Jabber::FileTransfer::TransferSource
- Jabber::Framework
- Jabber::Framework::Base
- Jabber::Framework::Bot
- Jabber::HTTPBinding
- Jabber::HTTPBinding::Client
- Jabber::IdGenerator
- Jabber::InvalidChatState
- Jabber::Iq
- Jabber::IqQuery
- Jabber::JID
- Jabber::JabberError
- Jabber::LastActivity
- Jabber::LastActivity::Helper
- Jabber::LastActivity::IqQueryLastActivity
- Jabber::MUC
- Jabber::MUC::IqQueryMUCAdmin
- Jabber::MUC::IqQueryMUCAdminItem
- Jabber::MUC::IqQueryMUCOwner
- Jabber::MUC::MUCBrowser
- Jabber::MUC::MUCClient
- Jabber::MUC::SimpleMUCClient
- Jabber::MUC::UserItem
- Jabber::MUC::XMUC
- Jabber::MUC::XMUCUser
- Jabber::MUC::XMUCUserInvite
- Jabber::MUC::XMUCUserItem
- Jabber::Message
- Jabber::NoNameXmlnsRegistered
- Jabber::NotConnected
- Jabber::Observable
- Jabber::Observable::Contact
- Jabber::Observable::PubSub
- Jabber::Observable::PubSub::AlreadySet
- Jabber::Observable::PubSub::NoService
- Jabber::Observable::Subscriptions
- Jabber::Presence
- Jabber::PubSub
- Jabber::PubSub::Configuration
- Jabber::PubSub::Event
- Jabber::PubSub::EventItem
- Jabber::PubSub::EventItems
- Jabber::PubSub::IqPubSub
- Jabber::PubSub::IqPubSubOwner
- Jabber::PubSub::Item
- Jabber::PubSub::Items
- Jabber::PubSub::NodeBrowser
- Jabber::PubSub::NodeConfig
- Jabber::PubSub::NodeHelper
- Jabber::PubSub::OAuthPubSubStreamHelper
- Jabber::PubSub::OAuthServiceHelper
- Jabber::PubSub::OwnerNodeConfig
- Jabber::PubSub::Publish
- Jabber::PubSub::Retract
- Jabber::PubSub::ServiceHelper
- Jabber::PubSub::Subscription
- Jabber::PubSub::SubscriptionConfig
- Jabber::PubSub::Unsubscribe
- Jabber::RPC
- Jabber::RPC::Client
- Jabber::RPC::IqQueryRPC
- Jabber::RPC::Server
- Jabber::Reliable
- Jabber::Reliable::Connection
- Jabber::Reliable::Listener
- Jabber::Roster
- Jabber::Roster::Helper
- Jabber::Roster::Helper::RosterItem
- Jabber::Roster::IqQueryRoster
- Jabber::Roster::RosterItem
- Jabber::Roster::RosterX
- Jabber::Roster::RosterXItem
- Jabber::Roster::XRoster
- Jabber::Roster::XRosterItem
- Jabber::SASL
- Jabber::SASL::Anonymous
- Jabber::SASL::Base
- Jabber::SASL::DigestMD5
- Jabber::SASL::Plain
- Jabber::SOCKS5Error
- Jabber::Semaphore
- Jabber::ServerDisconnected
- Jabber::Stream
- Jabber::Stream::ThreadBlock
- Jabber::StreamParser
- Jabber::Test
- Jabber::Test::ListenerMocker
- Jabber::UserLocation
- Jabber::UserLocation::Helper
- Jabber::UserLocation::Location
- Jabber::UserTune
- Jabber::UserTune::Helper
- Jabber::UserTune::Tune
- Jabber::Vcard
- Jabber::Vcard::Helper
- Jabber::Vcard::IqVcard
- Jabber::Version
- Jabber::Version::IqQueryVersion
- Jabber::Version::Responder
- Jabber::Version::SimpleResponder
- Jabber::X
- Jabber::XHTML
- Jabber::XHTML::Body
- Jabber::XHTML::HTML
- Jabber::XMPPElement
- Jabber::XMPPStanza
- Jabber::XParent
- REXML
- REXML::Element
- REXML::IOSource
- XMLRPC
- XMLRPC::Create
- Base64
- ObservableThing
- QObserver
- ThreadStore

No matching classes.

# Jabber::MUC::MUCClient

The MUCClient Helper handles low-level stuff of the Multi-User Chat (JEP 0045).

Use one instance per room.

Note that one client cannot join a single room multiple times. At least the clients' resources must be different. This is a protocol design issue. But don't consider it as a bug, it is just a clone-preventing feature.

### Attributes

jid[R]

MUC JID

jid

JID

  room@component/nick

my_jid[RW]

Sender JID, set this to use MUCClient from Components

my_jid

JID

  Defaults to nil

roster[R]

MUC room roster

roster

Hash

  of [String] Nick => [Presence]

### Public Class Methods

new(stream) click to toggle source

Initialize a MUCClient

Call MUCClient#join after you have registered your callbacks to avoid reception of stanzas after joining and before registration of callbacks.

stream

Stream

  to operate on

    # File lib/xmpp4r/muc/helper/mucclient.rb, line 45
    def initialize(stream)
      # Attributes initialization
      @stream = stream
      @my_jid = nil
      @jid = nil
      @roster = {}
      @roster_lock = Mutex.new

      @active = false

      @join_cbs = CallbackList.new
      @leave_cbs = CallbackList.new
      @presence_cbs = CallbackList.new
      @message_cbs = CallbackList.new
      @private_message_cbs = CallbackList.new
    end

### Public Instance Methods

active?() click to toggle source

Is the MUC client active?

This is false after initialization, true after joining and false after exit/kick

    # File lib/xmpp4r/muc/helper/mucclient.rb, line 168
    def active?
      @active
    end

add_join_callback(prio = 0, ref = nil, &block) click to toggle source

Add a callback for <presence/> stanzas indicating availability of a MUC participant

This callback will not be called for initial presences when a client joins a room, but only for the presences afterwards.

The callback will be called from MUCClient#handle_presence with one argument: the <presence/> stanza. Note that this stanza will have been already inserted into MUCClient#roster.

    # File lib/xmpp4r/muc/helper/mucclient.rb, line 275
    def add_join_callback(prio = 0, ref = nil, &block)
      @join_cbs.add(prio, ref, block)
    end

add_leave_callback(prio = 0, ref = nil, &block) click to toggle source

Add a callback for <presence/> stanzas indicating unavailability of a MUC participant

The callback will be called with one argument: the <presence/> stanza.

Note that this is called just before the stanza is removed from MUCClient#roster, so it is still possible to see the last presence in the given block.

If the presence's origin is your MUC JID, the MUCClient will be deactivated afterwards.

    # File lib/xmpp4r/muc/helper/mucclient.rb, line 291
    def add_leave_callback(prio = 0, ref = nil, &block)
      @leave_cbs.add(prio, ref, block)
    end

add_message_callback(prio = 0, ref = nil, &block) click to toggle source

Add a callback for <message/> stanza directed to the whole room.

See MUCClient#add_private_message_callback for private messages between MUC participants.

    # File lib/xmpp4r/muc/helper/mucclient.rb, line 308
    def add_message_callback(prio = 0, ref = nil, &block)
      @message_cbs.add(prio, ref, block)
    end

add_presence_callback(prio = 0, ref = nil, &block) click to toggle source

Add a callback for a <presence/> stanza which is neither a join nor a leave. This will be called when a room participant simply changes his status.

    # File lib/xmpp4r/muc/helper/mucclient.rb, line 299
    def add_presence_callback(prio = 0, ref = nil, &block)
      @presence_cbs.add(prio, ref, block)
    end

add_private_message_callback(prio = 0, ref = nil, &block) click to toggle source

Add a callback for <message/> stanza with type='chat'.

These stanza are normally not broadcasted to all room occupants but are some sort of private messaging.

    # File lib/xmpp4r/muc/helper/mucclient.rb, line 317
    def add_private_message_callback(prio = 0, ref = nil, &block)
      @private_message_cbs.add(prio, ref, block)
    end

configure(options={}) click to toggle source

Use this method to configure a MUC room of which you are the owner.

options

Hash

  where keys are the features of the room you wish

to configure. See www.xmpp.org/extensions/xep-0045.html#registrar-formtype-owner

    # File lib/xmpp4r/muc/helper/mucclient.rb, line 406
    def configure(options={})
      get_room_configuration
      submit_room_configuration(options)
    end

exit(reason=nil) click to toggle source

Exit the room

- Sends presence with type='unavailable' with an optional reason in `<status/>`,

- then waits for a reply from the MUC component (will be processed by leave-callbacks),

- then deletes callbacks from the stream.

reason

String

  Optional custom exit message

    # File lib/xmpp4r/muc/helper/mucclient.rb, line 137
    def exit(reason=nil)
      unless active?
        raise "MUCClient hasn't yet joined"
      end

      pres = Presence.new
      pres.type = :unavailable
      pres.to = jid
      pres.from = @my_jid
      pres.status = reason if reason
      @stream.send(pres) { |r|
        Jabber::debuglog "exit: #{r.to_s.inspect}"
        if r.kind_of?(Presence) and r.type == :unavailable and r.from == jid
          @leave_cbs.process(r)
          true
        else
          false
        end
      }

      deactivate

      self
    end

from_room?(jid) click to toggle source

Does this JID belong to that room?

jid

JID

result

true

  or [false]

    # File lib/xmpp4r/muc/helper/mucclient.rb, line 325
    def from_room?(jid)
      @jid.strip == jid.strip
    end

get_room_configuration() click to toggle source

    # File lib/xmpp4r/muc/helper/mucclient.rb, line 411
    def get_room_configuration
      raise 'You are not the owner' unless owner?

      iq = Iq.new(:get, jid.strip)
      iq.from = my_jid
      iq.add(IqQueryMUCOwner.new)

      fields = []

      @stream.send_with_id(iq) do |answer|
        raise "Configuration not possible for this room" unless answer.query && answer.query.x(Dataforms::XData)

        answer.query.x(Dataforms::XData).fields.each do |field|
          if (var = field.attributes['var'])
            fields << var
          end
        end
      end

      fields
    end

join(jid, password=nil, opts={}) click to toggle source

Join a room

This registers its own callbacks on the stream provided to initialize and sends initial presence to the room. May throw ServerError if joining fails.

jid

JID

  room@component/nick

password

String

  Optional password

opts

Hash

  If the parameter :history => false is passed then you will receive no history messages after initial presence

return

MUCClient

  self (chain-able)

    # File lib/xmpp4r/muc/helper/mucclient.rb, line 73
    def join(jid, password=nil, opts={})
      if active?
        raise "MUCClient already active"
      end

      @jid = (jid.kind_of?(JID) ? jid : JID.new(jid))
      activate

      # Joining
      pres = Presence.new
      pres.to = @jid
      pres.from = @my_jid
      xmuc = XMUC.new
      xmuc.password = password

      # Add history/maxstanzas as requested. false=0
      xmuc.add_element REXML::Element.new('history').tap { |hist|
        hist.add_attribute 'maxstanzas', (opts[:history]||0).to_i.to_s
      } unless opts[:history].nil?

      pres.add(xmuc)

      # We don't use Stream#send_with_id here as it's unknown
      # if the MUC component *always* uses our stanza id.
      error = nil
      @stream.send(pres) { |r|
        if from_room?(r.from) and r.kind_of?(Presence) and r.type == :error
          # Error from room
          error = r.error
          true
        # type='unavailable' may occur when the MUC kills our previous instance,
        # but all join-failures should be type='error'
        elsif r.from == jid and r.kind_of?(Presence) and r.type != :unavailable
          # Our own presence reflected back - success
          if r.x(XMUCUser) and (i = r.x(XMUCUser).items.first)
            @affiliation = i.affiliation  # we're interested in if it's :owner
            @role = i.role                # :moderator ?
          end

          handle_presence(r, false)
          true
        else
          # Everything else
          false
        end
      }

      if error
        deactivate
        raise ServerError.new(error)
      end

      self
    end

nick() click to toggle source

The MUCClient's own nick (= resource)

result

String

  Nickname

    # File lib/xmpp4r/muc/helper/mucclient.rb, line 176
    def nick
      @jid ? @jid.resource : nil
    end

nick=(new_nick) click to toggle source

Change nick

Threading is, again, suggested. This method waits for two <presence/> stanzas, one indicating unavailabilty of the old transient JID, one indicating availability of the new transient JID.

If the service denies nick-change, ServerError will be raised.

    # File lib/xmpp4r/muc/helper/mucclient.rb, line 189
    def nick=(new_nick)
      unless active?
        raise "MUCClient not active"
      end

      new_jid = JID.new(@jid.node, @jid.domain, new_nick)

      # Joining
      pres = Presence.new
      pres.to = new_jid
      pres.from = @my_jid

      error = nil
      # Keeping track of the two stanzas enables us to process stanzas
      # which don't arrive in the order specified by JEP-0045
      presence_unavailable = false
      presence_available = false
      # We don't use Stream#send_with_id here as it's unknown
      # if the MUC component *always* uses our stanza id.
      @stream.send(pres) { |r|
        if from_room?(r.from) and r.kind_of?(Presence) and r.type == :error
          # Error from room
          error = r.error
        elsif r.from == @jid and r.kind_of?(Presence) and r.type == :unavailable and
              r.x and r.x.kind_of?(XMUCUser) and r.x.status_code == 303
          # Old JID is offline, but wait for the new JID and let stanza be handled
          # by the standard callback
          presence_unavailable = true
          handle_presence(r)
        elsif r.from == new_jid and r.kind_of?(Presence) and r.type != :unavailable
          # Our own presence reflected back - success
          presence_available = true
          handle_presence(r)
        end

        if error or (presence_available and presence_unavailable)
          true
        else
          false
        end
      }

      if error
        raise ServerError.new(error)
      end

      # Apply new JID
      @jid = new_jid
    end

owner?() click to toggle source

    # File lib/xmpp4r/muc/helper/mucclient.rb, line 397
    def owner?
      @affiliation == :owner
    end

room() click to toggle source

The room name (= node)

result

String

  Room name

    # File lib/xmpp4r/muc/helper/mucclient.rb, line 243
    def room
      @jid ? @jid.node : nil
    end

send(stanza, to=nil) click to toggle source

Send a stanza to the room

If stanza is a Jabber::Message, `stanza.type` will be automatically set to :groupchat if directed to room or :chat if directed to participant.

stanza

XMPPStanza

  to send

to

String

  Stanza destination recipient, or room if `nil`

    # File lib/xmpp4r/muc/helper/mucclient.rb, line 255
    def send(stanza, to=nil)
      if stanza.kind_of? Message
        stanza.type = to ? :chat : :groupchat
      end
      stanza.from = @my_jid
      stanza.to = JID.new(jid.node, jid.domain, to)
      @stream.send(stanza)
    end

send_affiliations(items) click to toggle source

Push a list of new affiliations to the room

items

Array

  of, or single [IqQueryMUCAdminItem]

    # File lib/xmpp4r/muc/helper/mucclient.rb, line 455
    def send_affiliations(items)
      iq = Iq.new(:set, jid.strip)
      iq.from = my_jid
      iq.add(IqQueryMUCAdmin.new)

      items = [items] unless items.kind_of? Array
      items.each { |item|
        iq.query.add(item)
      }

      @stream.send_with_id(iq)
    end

submit_room_configuration(options) click to toggle source

    # File lib/xmpp4r/muc/helper/mucclient.rb, line 433
    def submit_room_configuration(options)
      # fill out the reply form
      iq = Iq.new(:set, jid.strip)
      iq.from = my_jid
      query = IqQueryMUCOwner.new
      form = Dataforms::XData.new
      form.type = :submit
      options.each do |var, values|
        field = Dataforms::XDataField.new
        values = [values] unless values.is_a?(Array)
        field.var, field.values = var, values
        form.add(field)
      end
      query.add(form)
      iq.add(query)

      @stream.send_with_id(iq)
    end

[Validate]

Generated with the Darkfish Rdoc Generator 2.