Class: Jabber::MUC::MUCClient
- Inherits:
-
Object
- Object
- Jabber::MUC::MUCClient
- Defined in:
- lib/xmpp4r/muc/helper/mucclient.rb
Overview
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.
Direct Known Subclasses
Instance Attribute Summary collapse
-
#jid ⇒ Object
readonly
- MUC JID jid
- JID
-
room@component/nick.
-
#my_jid ⇒ Object
- Sender JID, set this to use MUCClient from Components my_jid
- JID
-
Defaults to nil.
-
#roster ⇒ Object
readonly
- MUC room roster roster
- Hash
-
of [String] Nick => [Presence].
Instance Method Summary collapse
-
#active? ⇒ Boolean
Is the MUC client active?.
-
#add_join_callback(prio = 0, ref = nil, &block) ⇒ Object
Add a callback for <presence/> stanzas indicating availability of a MUC participant.
-
#add_leave_callback(prio = 0, ref = nil, &block) ⇒ Object
Add a callback for <presence/> stanzas indicating unavailability of a MUC participant.
-
#add_message_callback(prio = 0, ref = nil, &block) ⇒ Object
Add a callback for <message/> stanza directed to the whole room.
-
#add_presence_callback(prio = 0, ref = nil, &block) ⇒ Object
Add a callback for a <presence/> stanza which is neither a join nor a leave.
-
#add_private_message_callback(prio = 0, ref = nil, &block) ⇒ Object
Add a callback for <message/> stanza with type=‘chat’.
-
#exit(reason = nil) ⇒ Object
Exit the room.
-
#from_room?(jid) ⇒ Boolean
- Does this JID belong to that room? jid
- JID
- result
- true
-
or [false].
-
#initialize(stream) ⇒ MUCClient
constructor
Initialize a MUCClient.
-
#join(jid, password = nil) ⇒ Object
Join a room.
-
#nick ⇒ Object
- The MUCClient’s own nick (= resource) result
- String
-
Nickname.
-
#nick=(new_nick) ⇒ Object
Change nick.
-
#room ⇒ Object
- The room name (= node) result
- String
-
Room name.
-
#send(stanza, to = nil) ⇒ Object
Send a stanza to the room.
Constructor Details
#initialize(stream) ⇒ MUCClient
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
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/xmpp4r/muc/helper/mucclient.rb', line 42 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 |
Instance Attribute Details
#jid ⇒ Object (readonly)
MUC JID
- jid
- JID
-
room@component/nick
33 34 35 |
# File 'lib/xmpp4r/muc/helper/mucclient.rb', line 33 def jid @jid end |
#my_jid ⇒ Object
Sender JID, set this to use MUCClient from Components
- my_jid
- JID
-
Defaults to nil
23 24 25 |
# File 'lib/xmpp4r/muc/helper/mucclient.rb', line 23 def my_jid @my_jid end |
#roster ⇒ Object (readonly)
MUC room roster
- roster
- Hash
-
of [String] Nick => [Presence]
28 29 30 |
# File 'lib/xmpp4r/muc/helper/mucclient.rb', line 28 def roster @roster end |
Instance Method Details
#active? ⇒ Boolean
Is the MUC client active?
This is false after initialization, true after joining and false after exit/kick
153 154 155 |
# File 'lib/xmpp4r/muc/helper/mucclient.rb', line 153 def active? @active end |
#add_join_callback(prio = 0, ref = nil, &block) ⇒ Object
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.
260 261 262 |
# File 'lib/xmpp4r/muc/helper/mucclient.rb', line 260 def add_join_callback(prio = 0, ref = nil, &block) @join_cbs.add(prio, ref, block) end |
#add_leave_callback(prio = 0, ref = nil, &block) ⇒ Object
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.
276 277 278 |
# File 'lib/xmpp4r/muc/helper/mucclient.rb', line 276 def add_leave_callback(prio = 0, ref = nil, &block) @leave_cbs.add(prio, ref, block) end |
#add_message_callback(prio = 0, ref = nil, &block) ⇒ Object
Add a callback for <message/> stanza directed to the whole room.
See MUCClient#add_private_message_callback for private messages between MUC participants.
293 294 295 |
# File 'lib/xmpp4r/muc/helper/mucclient.rb', line 293 def (prio = 0, ref = nil, &block) @message_cbs.add(prio, ref, block) end |
#add_presence_callback(prio = 0, ref = nil, &block) ⇒ Object
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.
284 285 286 |
# File 'lib/xmpp4r/muc/helper/mucclient.rb', line 284 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) ⇒ Object
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.
302 303 304 |
# File 'lib/xmpp4r/muc/helper/mucclient.rb', line 302 def (prio = 0, ref = nil, &block) @private_message_cbs.add(prio, ref, block) end |
#exit(reason = nil) ⇒ Object
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
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/xmpp4r/muc/helper/mucclient.rb', line 122 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) ⇒ Boolean
Does this JID belong to that room?
- jid
- JID
- result
- true
-
or [false]
310 311 312 |
# File 'lib/xmpp4r/muc/helper/mucclient.rb', line 310 def from_room?(jid) @jid.strip == jid.strip end |
#join(jid, password = nil) ⇒ Object
Join a room
This registers its own callbacks on the stream provided to initialize and sends initial presence to the room. May throw ErrorException if joining fails.
- jid
- JID
-
room@component/nick
- password
- String
-
Optional password
- return
- MUCClient
-
self (chain-able)
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/xmpp4r/muc/helper/mucclient.rb', line 69 def join(jid, password=nil) 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 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 handle_presence(r, false) true else # Everything else false end } if error deactivate raise ErrorException.new(error) end self end |
#nick ⇒ Object
The MUCClient’s own nick (= resource)
- result
- String
-
Nickname
161 162 163 |
# File 'lib/xmpp4r/muc/helper/mucclient.rb', line 161 def nick @jid ? @jid.resource : nil end |
#nick=(new_nick) ⇒ Object
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, ErrorException will be raisen.
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 |
# File 'lib/xmpp4r/muc/helper/mucclient.rb', line 174 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 ErrorException.new(error) end # Apply new JID @jid = new_jid end |
#room ⇒ Object
The room name (= node)
- result
- String
-
Room name
228 229 230 |
# File 'lib/xmpp4r/muc/helper/mucclient.rb', line 228 def room @jid ? @jid.node : nil end |
#send(stanza, to = nil) ⇒ Object
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
- XMLStanza
-
to send
- to
- String
-
Stanza destination recipient, or room if
nil
240 241 242 243 244 245 246 247 |
# File 'lib/xmpp4r/muc/helper/mucclient.rb', line 240 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 |