message.py 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. """
  2. SleekXMPP: The Sleek XMPP Library
  3. Copyright (C) 2010 Nathanael C. Fritz
  4. This file is part of SleekXMPP.
  5. See the file LICENSE for copying permission.
  6. """
  7. from sleekxmpp.stanza.rootstanza import RootStanza
  8. from sleekxmpp.xmlstream import StanzaBase, ET
  9. class Message(RootStanza):
  10. """
  11. XMPP's <message> stanzas are a "push" mechanism to send information
  12. to other XMPP entities without requiring a response.
  13. Chat clients will typically use <message> stanzas that have a type
  14. of either "chat" or "groupchat".
  15. When handling a message event, be sure to check if the message is
  16. an error response.
  17. Example <message> stanzas:
  18. <message to="user1@example.com" from="user2@example.com">
  19. <body>Hi!</body>
  20. </message>
  21. <message type="groupchat" to="room@conference.example.com">
  22. <body>Hi everyone!</body>
  23. </message>
  24. Stanza Interface:
  25. body -- The main contents of the message.
  26. subject -- An optional description of the message's contents.
  27. mucroom -- (Read-only) The name of the MUC room that sent the message.
  28. mucnick -- (Read-only) The MUC nickname of message's sender.
  29. Attributes:
  30. types -- May be one of: normal, chat, headline, groupchat, or error.
  31. Methods:
  32. setup -- Overrides StanzaBase.setup.
  33. chat -- Set the message type to 'chat'.
  34. normal -- Set the message type to 'normal'.
  35. reply -- Overrides StanzaBase.reply
  36. get_type -- Overrides StanzaBase interface
  37. get_mucroom -- Return the name of the MUC room of the message.
  38. set_mucroom -- Dummy method to prevent assignment.
  39. del_mucroom -- Dummy method to prevent deletion.
  40. get_mucnick -- Return the MUC nickname of the message's sender.
  41. set_mucnick -- Dummy method to prevent assignment.
  42. del_mucnick -- Dummy method to prevent deletion.
  43. """
  44. name = 'message'
  45. namespace = 'jabber:client'
  46. plugin_attrib = name
  47. interfaces = set(['type', 'to', 'from', 'id', 'body', 'subject',
  48. 'thread', 'parent_thread', 'mucroom', 'mucnick'])
  49. sub_interfaces = set(['body', 'subject', 'thread'])
  50. lang_interfaces = sub_interfaces
  51. types = set(['normal', 'chat', 'headline', 'error', 'groupchat'])
  52. def __init__(self, *args, **kwargs):
  53. """
  54. Initialize a new <message /> stanza with an optional 'id' value.
  55. Overrides StanzaBase.__init__.
  56. """
  57. StanzaBase.__init__(self, *args, **kwargs)
  58. if self['id'] == '':
  59. if self.stream is not None and self.stream.use_message_ids:
  60. self['id'] = self.stream.new_id()
  61. def get_type(self):
  62. """
  63. Return the message type.
  64. Overrides default stanza interface behavior.
  65. Returns 'normal' if no type attribute is present.
  66. """
  67. return self._get_attr('type', 'normal')
  68. def get_parent_thread(self):
  69. """Return the message thread's parent thread."""
  70. thread = self.xml.find('{%s}thread' % self.namespace)
  71. if thread is not None:
  72. return thread.attrib.get('parent', '')
  73. return ''
  74. def set_parent_thread(self, value):
  75. """Add or change the message thread's parent thread."""
  76. thread = self.xml.find('{%s}thread' % self.namespace)
  77. if value:
  78. if thread is None:
  79. thread = ET.Element('{%s}thread' % self.namespace)
  80. self.xml.append(thread)
  81. thread.attrib['parent'] = value
  82. else:
  83. if thread is not None and 'parent' in thread.attrib:
  84. del thread.attrib['parent']
  85. def del_parent_thread(self):
  86. """Delete the message thread's parent reference."""
  87. thread = self.xml.find('{%s}thread' % self.namespace)
  88. if thread is not None and 'parent' in thread.attrib:
  89. del thread.attrib['parent']
  90. def chat(self):
  91. """Set the message type to 'chat'."""
  92. self['type'] = 'chat'
  93. return self
  94. def normal(self):
  95. """Set the message type to 'normal'."""
  96. self['type'] = 'normal'
  97. return self
  98. def reply(self, body=None, clear=True):
  99. """
  100. Create a message reply.
  101. Overrides StanzaBase.reply.
  102. Sets proper 'to' attribute if the message is from a MUC, and
  103. adds a message body if one is given.
  104. Arguments:
  105. body -- Optional text content for the message.
  106. clear -- Indicates if existing content should be removed
  107. before replying. Defaults to True.
  108. """
  109. thread = self['thread']
  110. parent = self['parent_thread']
  111. StanzaBase.reply(self, clear)
  112. if self['type'] == 'groupchat':
  113. self['to'] = self['to'].bare
  114. self['thread'] = thread
  115. self['parent_thread'] = parent
  116. del self['id']
  117. if body is not None:
  118. self['body'] = body
  119. return self
  120. def get_mucroom(self):
  121. """
  122. Return the name of the MUC room where the message originated.
  123. Read-only stanza interface.
  124. """
  125. if self['type'] == 'groupchat':
  126. return self['from'].bare
  127. else:
  128. return ''
  129. def get_mucnick(self):
  130. """
  131. Return the nickname of the MUC user that sent the message.
  132. Read-only stanza interface.
  133. """
  134. if self['type'] == 'groupchat':
  135. return self['from'].resource
  136. else:
  137. return ''
  138. def set_mucroom(self, value):
  139. """Dummy method to prevent modification."""
  140. pass
  141. def del_mucroom(self):
  142. """Dummy method to prevent deletion."""
  143. pass
  144. def set_mucnick(self, value):
  145. """Dummy method to prevent modification."""
  146. pass
  147. def del_mucnick(self):
  148. """Dummy method to prevent deletion."""
  149. pass
  150. # To comply with PEP8, method names now use underscores.
  151. # Deprecated method names are re-mapped for backwards compatibility.
  152. Message.getType = Message.get_type
  153. Message.getMucroom = Message.get_mucroom
  154. Message.setMucroom = Message.set_mucroom
  155. Message.delMucroom = Message.del_mucroom
  156. Message.getMucnick = Message.get_mucnick
  157. Message.setMucnick = Message.set_mucnick
  158. Message.delMucnick = Message.del_mucnick