Class: Blather::Stanza::Message
- Inherits:
-
Blather::Stanza
- Object
- Niceogiri::XML::Node
- XMPPNode
- Blather::Stanza
- Blather::Stanza::Message
- Defined in:
- lib/blather/stanza/message.rb,
lib/blather/stanza/message/muc_user.rb
Overview
# Message Stanza
[RFC 3921 Section 2.1 - Message Syntax](xmpp.org/rfcs/rfc3921.html#rfc.section.2.1)
Exchanging messages is a basic use of XMPP and occurs when a user generates a message stanza that is addressed to another entity. The sender’s server is responsible for delivering the message to the intended recipient (if the recipient is on the same local server) or for routing the message to the recipient’s server (if the recipient is on a remote server). Thus a message stanza is used to “push” information to another entity.
## “To” Attribute
An instant messaging client specifies an intended recipient for a message by providing the JID of an entity other than the sender in the ‘to` attribute of the Message stanza. If the message is being sent outside the context of any existing chat session or received message, the value of the `to` address SHOULD be of the form “user@domain” rather than of the form “user@domain/resource”.
msg = Message.new '[email protected]/resource'
msg.to == '[email protected]/resource'
msg.to = '[email protected]/resource'
msg.to == '[email protected]/resource'
The ‘to` attribute on a Message stanza works like any regular ruby object attribute
## “Type” Attribute
Common uses of the message stanza in instant messaging applications include: single messages; messages sent in the context of a one-to-one chat session; messages sent in the context of a multi-user chat room; alerts, notifications, or other information to which no reply is expected; and errors. These uses are differentiated via the ‘type` attribute. If included, the `type` attribute MUST have one of the following values:
-
‘:chat` – The message is sent in the context of a one-to-one chat session. Typically a receiving client will present message of type `chat` in an interface that enables one-to-one chat between the two parties, including an appropriate conversation history.
-
‘:error` – The message is generated by an entity that experiences an error in processing a message received from another entity. A client that receives a message of type `error` SHOULD present an appropriate interface informing the sender of the nature of the error.
-
‘:groupchat` – The message is sent in the context of a multi-user chat environment (similar to that of [IRC]). Typically a receiving client will present a message of type `groupchat` in an interface that enables many-to-many chat between the parties, including a roster of parties in the chatroom and an appropriate conversation history.
-
‘:headline` – The message provides an alert, a notification, or other information to which no reply is expected (e.g., news headlines, sports updates, near-real-time market data, and syndicated content). Because no reply to the message is expected, typically a receiving client will present a message of type “headline” in an interface that appropriately differentiates the message from standalone messages, chat messages, or groupchat messages (e.g., by not providing the recipient with the ability to reply).
-
‘:normal` – The message is a standalone message that is sent outside the context of a one-to-one conversation or groupchat, and to which it is expected that the recipient will reply. Typically a receiving client will present a message of type `normal` in an interface that enables the recipient to reply, but without a conversation history. The default value of the `type` attribute is `normal`.
Blather provides a helper for each possible type:
Message#chat?
Message#error?
Message#groupchat?
Message#headline?
Message#normal?
Blather treats the ‘type` attribute like a normal ruby object attribute providing a getter and setter. The default `type` is `chat`.
msg = Message.new
msg.type # => :chat
msg.chat? # => true
msg.type = :normal
msg.normal? # => true
msg.chat? # => false
msg.type = :invalid # => RuntimeError
## “Body” Element
The ‘body` element contains human-readable XML character data that specifies the textual contents of the message; this child element is normally included but is optional.
Blather provides an attribute-like syntax for Message ‘body` elements.
msg = Message.new '[email protected]', 'message body'
msg.body # => 'message body'
msg.body = 'other message'
msg.body # => 'other message'
## “Subject” Element
The ‘subject` element contains human-readable XML character data that specifies the topic of the message.
Blather provides an attribute-like syntax for Message ‘subject` elements.
msg = Message.new '[email protected]', 'message body'
msg.subject = 'message subject'
msg.subject # => 'message subject'
## “Thread” Element
The primary use of the XMPP ‘thread` element is to uniquely identify a conversation thread or “chat session” between two entities instantiated by Message stanzas of type `chat`. However, the XMPP thread element can also be used to uniquely identify an analogous thread between two entities instantiated by Message stanzas of type `headline` or `normal`, or among multiple entities in the context of a multi-user chat room instantiated by Message stanzas of type `groupchat`. It MAY also be used for Message stanzas not related to a human conversation, such as a game session or an interaction between plugins. The `thread` element is not used to identify individual messages, only conversations or messagingg sessions. The inclusion of the `thread` element is optional.
The value of the ‘thread` element is not human-readable and MUST be treated as opaque by entities; no semantic meaning can be derived from it, and only exact comparisons can be made against it. The value of the `thread` element MUST be a universally unique identifier (UUID) as described in [UUID].
The ‘thread` element MAY possess a ’parent’ attribute that identifies another thread of which the current thread is an offshoot or child; the value of the ‘parent’ must conform to the syntax of the ‘thread` element itself.
Blather provides an attribute-like syntax for Message ‘thread` elements.
msg = Message.new
msg.thread = '12345'
msg.thread # => '12345'
Parent threads can be set using a hash:
msg.thread = {'parent-id' => 'thread-id'}
msg.thread # => 'thread-id'
msg.parent_thread # => 'parent-id'
Direct Known Subclasses
Defined Under Namespace
Constant Summary collapse
- VALID_TYPES =
[:chat, :error, :groupchat, :headline, :normal].freeze
- VALID_CHAT_STATES =
[:active, :composing, :gone, :inactive, :paused].freeze
- CHAT_STATE_NS =
'http://jabber.org/protocol/chatstates'.freeze
- HTML_NS =
'http://jabber.org/protocol/xhtml-im'.freeze
- HTML_BODY_NS =
'http://www.w3.org/1999/xhtml'.freeze
Constants inherited from XMPPNode
Instance Attribute Summary
Attributes inherited from Blather::Stanza
Class Method Summary collapse
- .import(node) ⇒ Object
-
.new(to = nil, body = nil, type = :chat) ⇒ Object
Create a new Message stanza.
Instance Method Summary collapse
-
#body ⇒ String
Get the message body.
-
#body=(body) ⇒ Object
Set the message body.
-
#chat? ⇒ true, false
Check if the Message is of type :chat.
-
#chat_state ⇒ Symbol
Get the message chat state.
-
#chat_state=(chat_state) ⇒ Object
Set the message chat state.
- #delay ⇒ Object
- #delayed? ⇒ Boolean
-
#error? ⇒ true, false
Check if the Message is of type :error.
-
#form ⇒ Object
Returns the message’s x:data form child.
-
#groupchat? ⇒ true, false
Check if the Message is of type :groupchat.
-
#headline? ⇒ true, false
Check if the Message is of type :headline.
-
#inherit(node) ⇒ Object
Overrides the parent method to ensure the current chat state is removed.
-
#normal? ⇒ true, false
Check if the Message is of type :normal.
-
#parent_thread ⇒ String?
Get the parent thread.
-
#subject ⇒ String
Get the message subject.
-
#subject=(subject) ⇒ Object
Set the message subject.
-
#thread ⇒ String
Get the message thread.
-
#thread=(thread) ⇒ Object
Set the thread.
-
#type=(type) ⇒ Object
Ensures type is :get, :set, :result or :error.
-
#xhtml ⇒ String
Get the message xhtml.
-
#xhtml=(xhtml_body) ⇒ Object
Set the message xhtml This will use Nokogiri to ensure the xhtml is valid.
-
#xhtml_node ⇒ XML::Node
Get the message xhtml node This will create the node if it doesn’t exist.
Methods inherited from Blather::Stanza
#as_error, #from, #from=, handler_list, #id, #id=, #initialize, next_id, register, #reply, #reply!, #to, #to=, #type
Methods inherited from XMPPNode
class_from_registration, #decorate, decorator_modules, parse, register, #to_stanza
Constructor Details
This class inherits a constructor from Blather::Stanza
Class Method Details
.import(node) ⇒ Object
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
# File 'lib/blather/stanza/message.rb', line 176 def self.import(node) klass = nil node.children.detect do |e| ns = e.namespace ? e.namespace.href : nil klass = class_from_registration(e.element_name, ns) end if klass == Blather::Stanza::Presence::MUCUser klass = Blather::Stanza::Message::MUCUser end if klass && klass != self && ![Blather::Stanza::X, Blather::Stanza::Iq].include?(klass) klass.import(node) else new(node[:type]).inherit(node) end end |
.new(to = nil, body = nil, type = :chat) ⇒ Object
Create a new Message stanza
199 200 201 202 203 204 205 206 |
# File 'lib/blather/stanza/message.rb', line 199 def self.new(to = nil, body = nil, type = :chat) node = super :message node.to = to node.type = type node.body = body node.chat_state = :active if [:chat, :groupchat].include?(type) node end |
Instance Method Details
#body ⇒ String
Get the message body
264 265 266 |
# File 'lib/blather/stanza/message.rb', line 264 def body read_content :body end |
#body=(body) ⇒ Object
Set the message body
271 272 273 |
# File 'lib/blather/stanza/message.rb', line 271 def body=(body) set_content_for :body, body end |
#chat? ⇒ true, false
Check if the Message is of type :chat
219 220 221 |
# File 'lib/blather/stanza/message.rb', line 219 def chat? self.type == :chat end |
#chat_state ⇒ Symbol
Get the message chat state
360 361 362 363 364 |
# File 'lib/blather/stanza/message.rb', line 360 def chat_state if (elem = find_first('ns:*', :ns => CHAT_STATE_NS)) && VALID_CHAT_STATES.include?(name = elem.name.to_sym) name end end |
#chat_state=(chat_state) ⇒ Object
Set the message chat state
369 370 371 372 373 374 375 376 377 378 379 380 381 |
# File 'lib/blather/stanza/message.rb', line 369 def chat_state=(chat_state) if chat_state && !VALID_CHAT_STATES.include?(chat_state.to_sym) raise ArgumentError, "Invalid Chat State (#{chat_state}), use: #{VALID_CHAT_STATES*' '}" end xpath('ns:*', :ns => CHAT_STATE_NS).remove if chat_state state = XMPPNode.new(chat_state, self.document) state.namespace = CHAT_STATE_NS self << state end end |
#delay ⇒ Object
383 384 385 386 387 |
# File 'lib/blather/stanza/message.rb', line 383 def delay if d = find_first('ns:delay', :ns => "urn:xmpp:delay") Delay.new d end end |
#delayed? ⇒ Boolean
389 390 391 |
# File 'lib/blather/stanza/message.rb', line 389 def delayed? !!delay end |
#error? ⇒ true, false
Check if the Message is of type :error
226 227 228 |
# File 'lib/blather/stanza/message.rb', line 226 def error? self.type == :error end |
#form ⇒ Object
Returns the message’s x:data form child
353 354 355 |
# File 'lib/blather/stanza/message.rb', line 353 def form X.find_or_create self end |
#groupchat? ⇒ true, false
Check if the Message is of type :groupchat
233 234 235 |
# File 'lib/blather/stanza/message.rb', line 233 def groupchat? self.type == :groupchat end |
#headline? ⇒ true, false
Check if the Message is of type :headline
240 241 242 |
# File 'lib/blather/stanza/message.rb', line 240 def headline? self.type == :headline end |
#inherit(node) ⇒ Object
Overrides the parent method to ensure the current chat state is removed
211 212 213 214 |
# File 'lib/blather/stanza/message.rb', line 211 def inherit(node) xpath('ns:*', :ns => CHAT_STATE_NS).remove super end |
#normal? ⇒ true, false
Check if the Message is of type :normal
247 248 249 |
# File 'lib/blather/stanza/message.rb', line 247 def normal? self.type == :normal end |
#parent_thread ⇒ String?
Get the parent thread
333 334 335 336 |
# File 'lib/blather/stanza/message.rb', line 333 def parent_thread n = find_first('thread') n[:parent] if n end |
#subject ⇒ String
Get the message subject
312 313 314 |
# File 'lib/blather/stanza/message.rb', line 312 def subject read_content :subject end |
#subject=(subject) ⇒ Object
Set the message subject
319 320 321 |
# File 'lib/blather/stanza/message.rb', line 319 def subject=(subject) set_content_for :subject, subject end |
#thread ⇒ String
Get the message thread
326 327 328 |
# File 'lib/blather/stanza/message.rb', line 326 def thread read_content :thread end |
#thread=(hash) ⇒ Object #thread=(thread) ⇒ Object
Set the thread
346 347 348 349 350 |
# File 'lib/blather/stanza/message.rb', line 346 def thread=(thread) parent, thread = thread.to_a.flatten if thread.is_a?(Hash) set_content_for :thread, thread find_first('thread')[:parent] = parent end |
#type=(type) ⇒ Object
Ensures type is :get, :set, :result or :error
254 255 256 257 258 259 |
# File 'lib/blather/stanza/message.rb', line 254 def type=(type) if type && !VALID_TYPES.include?(type.to_sym) raise ArgumentError, "Invalid Type (#{type}), use: #{VALID_TYPES*' '}" end super end |
#xhtml ⇒ String
Get the message xhtml
297 298 299 |
# File 'lib/blather/stanza/message.rb', line 297 def xhtml self.xhtml_node.inner_html.strip end |
#xhtml=(xhtml_body) ⇒ Object
Set the message xhtml This will use Nokogiri to ensure the xhtml is valid
305 306 307 |
# File 'lib/blather/stanza/message.rb', line 305 def xhtml=(xhtml_body) self.xhtml_node.inner_html = Nokogiri::XML::DocumentFragment.parse(xhtml_body) end |
#xhtml_node ⇒ XML::Node
Get the message xhtml node This will create the node if it doesn’t exist
279 280 281 282 283 284 285 286 287 288 289 290 291 292 |
# File 'lib/blather/stanza/message.rb', line 279 def xhtml_node unless h = find_first('ns:html', :ns => HTML_NS) || find_first('ns:html', :ns => HTML_BODY_NS) self << (h = XMPPNode.new('html', self.document)) h.namespace = HTML_NS end unless b = h.find_first('ns:body', :ns => HTML_BODY_NS) b = XMPPNode.new('body', self.document) b.namespace = HTML_BODY_NS h << b end b end |