The Messages interface is the preferred interface for text messaging, because it supports the full range of messaging features exposed by the protocols.
Some older connection managers may not support this interface. If this is the case, or if you really only want to send simple messages (e.g. for a status reporting system), you can use the simple messaging interface documented below.
Telepathy provides support for rich-text messaging via the Messages interface. Rich-text messaging can include features like formatted (rich text) messages, alternatives (similar to MIME's multipart/alternative) and attachments. Messages are formatted in XHTML-IM.
Messages are sent and received as an array of Message_Part key-value mappings, the first of which contains the message headers. Example 8-1 shows an example message.
An example message consisting of four Message_Parts: the headers, two alternatives and an attachment.
|content||"""Here is a photo of my cat:<br /><img src="cid:catphoto" alt="lol!" /><br />Isn't it cute?"""|
|content||"""Here is a photo of my cat:\n[IMG: lol!]\nIsn't it cute?"""|
The known headers for a message are:
|message-token||String||An opaque, globally-unique identifier for the entire message. Which may be treated the same as a MIME message-id for the mid: and cid: URI schemes. Not always present.|
|message-sent, message-received||Unix_Timestamp64||The time the message was sent and received respectively. May not be present if a time cannot be determined.|
|message-sender||Contact_Handle||The handle id of the contact who sent the message. May be 0 or ommitted, if the sender cannot be determined.|
|message-type||Channel_Text_Message_Type||The type of message. Defaults to Channel_Text_Message_Type_Normal if ommitted.|
The incoming message ID, only valid for as long as the message
This header is important for acknowledging the received message.
|interface||DBus_Interface||This message is specific to the given interface, which is neither Text nor Messages. This key can also appear in subsequent parts of the message.|
|scrollback||Boolean||If true, the incoming message was part of a replay of message history. Defaults to false.|
|rescued||Boolean||If true, the incoming message has been seen in a previous channel during the lifetime of the Connection, but had not been acknowledged when that channel closed. Defaults to false.|
Alternatives with the same name should be ordered from highest fidelity to lowest fidelity (i.e. rich text before plain text). Clients should display the first alternative they understand.
When a remote user initiates a new text chat, Telepathy will automatically create a new channel for the chat (see Section 6.2 ― Incoming Channels). Filter on the channels given for channels of type Channel_Type_Text. Example 8-2 shows how to discover this channel using the NewChannels signal.
def get_interfaces_cb (self, interfaces): conn = self.conn print "Connection Interfaces:" for interface in interfaces: print " - %s" % interface if CONNECTION_INTERFACE_REQUESTS in interfaces: conn[CONNECTION_INTERFACE_REQUESTS].connect_to_signal('NewChannels', self.new_channels_cb) def new_channels_cb (self, channels): for channel, props in channels: if props[CHANNEL + '.ChannelType'] == CHANNEL_TYPE_TEXT: print 'New chat from %s' % props[CHANNEL + '.TargetID'] # let's hook up to this channel TextChannel(self, channel)
Incoming messages are announced with the MessageReceived signal, which places them on the pending message queue. To remove messages from the pending message queue, they must be acknowledged with Text.AcknowledgePendingMessages. There will already be messages pending, the ones that caused the creation of the channel. These can be accessed via the PendingMessages property. See Example 8-3.
The message id to acknowledge the message is contained in the headers of the message as the key pending-message-id (see Section 8.1.1 ― Message Structure).
You must always acknowledge a received message, but you should only do so after you have attempted to parse it.
Failure to acknowledge a message will result in a new channel being created with the pending messages when the current channel is closed.
It's posssible that a bug in your application's message parser could cause an application crash. You should attempt to parse the message before acknowledging it. Thus, if your application has a crash, the message will still be pending when the client reloads.
def interfaces_cb (self, interfaces): channel = self print "Channel Interfaces:" for interface in interfaces: print " - %s" % interface if CHANNEL_INTERFACE_MESSAGES in interfaces: channel[CHANNEL_INTERFACE_MESSAGES].connect_to_signal( 'MessageReceived', self.message_received_cb) channel[CHANNEL_INTERFACE_MESSAGES].connect_to_signal( 'PendingMessagesRemoved', self.pending_messages_removed_cb) # find out if we have any pending messages channel[DBUS_PROPERTIES].Get(CHANNEL_INTERFACE_MESSAGES, 'PendingMessages', reply_handler = self.get_pending_messages, error_handler = self.parent.error_cb) def get_pending_messages (self, messages): for message in messages: self.message_received_cb (message) def message_received_cb (self, message): channel = self # we need to acknowledge the message msg_id = message['pending-message-id'] channel[CHANNEL_TYPE_TEXT].AcknowledgePendingMessages([msg_id], reply_handler = self.parent.generic_reply, error_handler = self.parent.error_cb)