diff --git a/setup.py b/setup.py
index ae8cf682..4575a078 100644
--- a/setup.py
+++ b/setup.py
@@ -50,6 +50,7 @@ packages = [ 'sleekxmpp',
'sleekxmpp/plugins/xep_0030',
'sleekxmpp/plugins/xep_0030/stanza',
'sleekxmpp/plugins/xep_0059',
+ 'sleekxmpp/plugins/xep_0085',
'sleekxmpp/plugins/xep_0092',
'sleekxmpp/plugins/xep_0199',
]
diff --git a/sleekxmpp/plugins/xep_0085.py b/sleekxmpp/plugins/xep_0085.py
deleted file mode 100644
index 3627e718..00000000
--- a/sleekxmpp/plugins/xep_0085.py
+++ /dev/null
@@ -1,104 +0,0 @@
-"""
- SleekXMPP: The Sleek XMPP Library
- Copyright (C) 2010 Nathanael C. Fritz, Lance J.T. Stout
- This file is part of SleekXMPP.
-
- See the file LICENSE for copying permissio
-"""
-
-import logging
-from . import base
-from .. xmlstream.handler.callback import Callback
-from .. xmlstream.matcher.xpath import MatchXPath
-from .. xmlstream.stanzabase import registerStanzaPlugin, ElementBase, ET, JID
-from .. stanza.message import Message
-
-
-log = logging.getLogger(__name__)
-
-
-class ChatState(ElementBase):
- namespace = 'http://jabber.org/protocol/chatstates'
- plugin_attrib = 'chat_state'
- interface = set(('state',))
- states = set(('active', 'composing', 'gone', 'inactive', 'paused'))
-
- def active(self):
- self.setState('active')
-
- def composing(self):
- self.setState('composing')
-
- def gone(self):
- self.setState('gone')
-
- def inactive(self):
- self.setState('inactive')
-
- def paused(self):
- self.setState('paused')
-
- def setState(self, state):
- if state in self.states:
- self.name = state
- self.xml.tag = '{%s}%s' % (self.namespace, state)
- else:
- raise ValueError('Invalid chat state')
-
- def getState(self):
- return self.name
-
-# In order to match the various chat state elements,
-# we need one stanza object per state, even though
-# they are all the same except for the initial name
-# value. Do not depend on the type of the chat state
-# stanza object for the actual state.
-
-class Active(ChatState):
- name = 'active'
-class Composing(ChatState):
- name = 'composing'
-class Gone(ChatState):
- name = 'gone'
-class Inactive(ChatState):
- name = 'inactive'
-class Paused(ChatState):
- name = 'paused'
-
-
-class xep_0085(base.base_plugin):
- """
- XEP-0085 Chat State Notifications
- """
-
- def plugin_init(self):
- self.xep = '0085'
- self.description = 'Chat State Notifications'
-
- handlers = [('Active Chat State', 'active'),
- ('Composing Chat State', 'composing'),
- ('Gone Chat State', 'gone'),
- ('Inactive Chat State', 'inactive'),
- ('Paused Chat State', 'paused')]
- for handler in handlers:
- self.xmpp.registerHandler(
- Callback(handler[0],
- MatchXPath("{%s}message/{%s}%s" % (self.xmpp.default_ns,
- ChatState.namespace,
- handler[1])),
- self._handleChatState))
-
- registerStanzaPlugin(Message, Active)
- registerStanzaPlugin(Message, Composing)
- registerStanzaPlugin(Message, Gone)
- registerStanzaPlugin(Message, Inactive)
- registerStanzaPlugin(Message, Paused)
-
- def post_init(self):
- base.base_plugin.post_init(self)
- self.xmpp.plugin['xep_0030'].add_feature('http://jabber.org/protocol/chatstates')
-
- def _handleChatState(self, msg):
- state = msg['chat_state'].name
- log.debug("Chat State: %s, %s" % (state, msg['from'].jid))
- self.xmpp.event('chatstate_%s' % state, msg)
diff --git a/sleekxmpp/plugins/xep_0085/__init__.py b/sleekxmpp/plugins/xep_0085/__init__.py
new file mode 100644
index 00000000..ff882f05
--- /dev/null
+++ b/sleekxmpp/plugins/xep_0085/__init__.py
@@ -0,0 +1,10 @@
+"""
+ SleekXMPP: The Sleek XMPP Library
+ Copyright (C) 2011 Nathanael C. Fritz, Lance J.T. Stout
+ This file is part of SleekXMPP.
+
+ See the file LICENSE for copying permissio
+"""
+
+from sleekxmpp.plugins.xep_0085.stanza import ChatState
+from sleekxmpp.plugins.xep_0085.chat_states import xep_0085
diff --git a/sleekxmpp/plugins/xep_0085/chat_states.py b/sleekxmpp/plugins/xep_0085/chat_states.py
new file mode 100644
index 00000000..a2feb531
--- /dev/null
+++ b/sleekxmpp/plugins/xep_0085/chat_states.py
@@ -0,0 +1,48 @@
+"""
+ SleekXMPP: The Sleek XMPP Library
+ Copyright (C) 2011 Nathanael C. Fritz, Lance J.T. Stout
+ This file is part of SleekXMPP.
+
+ See the file LICENSE for copying permissio
+"""
+
+import logging
+
+import sleekxmpp
+from sleekxmpp.stanza import Message
+from sleekxmpp.xmlstream.handler import Callback
+from sleekxmpp.xmlstream.matcher import StanzaPath
+from sleekxmpp.xmlstream import register_stanza_plugin, ElementBase, ET
+from sleekxmpp.plugins.base import base_plugin
+from sleekxmpp.plugins.xep_0085 import stanza
+
+
+log = logging.getLogger(__name__)
+
+
+class xep_0085(base_plugin):
+
+ """
+ XEP-0085 Chat State Notifications
+ """
+
+ def plugin_init(self):
+ self.xep = '0085'
+ self.description = 'Chat State Notifications'
+ self.stanza = stanza
+
+ self.xmpp.registerHandler(
+ Callback('Chat States',
+ StanzaPath('message/chat_state'),
+ self._handle_chat_state))
+
+ register_stanza_plugin(Message, stanza.ChatState)
+
+ def post_init(self):
+ base_plugin.post_init(self)
+ self.xmpp.plugin['xep_0030'].add_feature(stanza.ChatState.namepsace)
+
+ def _handle_chat_state(self, msg):
+ state = msg['chat_state']
+ log.debug("Chat State: %s, %s" % (state, msg['from'].jid))
+ self.xmpp.event('chatstate_%s' % state, msg)
diff --git a/sleekxmpp/plugins/xep_0085/stanza.py b/sleekxmpp/plugins/xep_0085/stanza.py
new file mode 100644
index 00000000..8c46758c
--- /dev/null
+++ b/sleekxmpp/plugins/xep_0085/stanza.py
@@ -0,0 +1,73 @@
+"""
+ SleekXMPP: The Sleek XMPP Library
+ Copyright (C) 2011 Nathanael C. Fritz, Lance J.T. Stout
+ This file is part of SleekXMPP.
+
+ See the file LICENSE for copying permissio
+"""
+
+import sleekxmpp
+from sleekxmpp.xmlstream import ElementBase, ET
+
+
+class ChatState(ElementBase):
+
+ """
+ Example chat state stanzas:
+
+
+
+
+
+
+
+
+ Stanza Interfaces:
+ chat_state
+
+ Attributes:
+ states
+
+ Methods:
+ get_chat_state
+ set_chat_state
+ del_chat_state
+ """
+
+ name = ''
+ namespace = 'http://jabber.org/protocol/chatstates'
+ plugin_attrib = 'chat_state'
+ interfaces = set(('chat_state',))
+ is_extension = True
+
+ states = set(('active', 'composing', 'gone', 'inactive', 'paused'))
+
+ def setup(self, xml=None):
+ self.xml = ET.Element('')
+ return True
+
+ def get_chat_state(self):
+ parent = self.parent()
+ for state in self.states:
+ state_xml = parent.find('{%s}%s' % (self.namespace, state))
+ if state_xml is not None:
+ self.xml = state_xml
+ return state
+ return ''
+
+ def set_chat_state(self, state):
+ self.del_chat_state()
+ parent = self.parent()
+ if state in self.states:
+ self.xml = ET.Element('{%s}%s' % (self.namespace, state))
+ parent.append(self.xml)
+ elif state not in [None, '']:
+ raise ValueError('Invalid chat state')
+
+ def del_chat_state(self):
+ parent = self.parent()
+ for state in self.states:
+ state_xml = parent.find('{%s}%s' % (self.namespace, state))
+ if state_xml is not None:
+ self.xml = ET.Element('')
+ parent.xml.remove(state_xml)
diff --git a/tests/test_stanza_xep_0085.py b/tests/test_stanza_xep_0085.py
index 5db7139a..b08404e2 100644
--- a/tests/test_stanza_xep_0085.py
+++ b/tests/test_stanza_xep_0085.py
@@ -4,11 +4,7 @@ import sleekxmpp.plugins.xep_0085 as xep_0085
class TestChatStates(SleekTest):
def setUp(self):
- register_stanza_plugin(Message, xep_0085.Active)
- register_stanza_plugin(Message, xep_0085.Composing)
- register_stanza_plugin(Message, xep_0085.Gone)
- register_stanza_plugin(Message, xep_0085.Inactive)
- register_stanza_plugin(Message, xep_0085.Paused)
+ register_stanza_plugin(Message, xep_0085.ChatState)
def testCreateChatState(self):
"""Testing creating chat states."""
@@ -20,25 +16,26 @@ class TestChatStates(SleekTest):
"""
msg = self.Message()
- msg['chat_state'].active()
- self.check(msg, xmlstring % 'active',
- use_values=False)
- msg['chat_state'].composing()
- self.check(msg, xmlstring % 'composing',
- use_values=False)
+ self.assertEqual(msg['chat_state'], '')
+ self.check(msg, "", use_values=False)
+ msg['chat_state'] = 'active'
+ self.check(msg, xmlstring % 'active', use_values=False)
- msg['chat_state'].gone()
- self.check(msg, xmlstring % 'gone',
- use_values=False)
+ msg['chat_state'] = 'composing'
+ self.check(msg, xmlstring % 'composing', use_values=False)
- msg['chat_state'].inactive()
- self.check(msg, xmlstring % 'inactive',
- use_values=False)
+ msg['chat_state'] = 'gone'
+ self.check(msg, xmlstring % 'gone', use_values=False)
- msg['chat_state'].paused()
- self.check(msg, xmlstring % 'paused',
- use_values=False)
+ msg['chat_state'] = 'inactive'
+ self.check(msg, xmlstring % 'inactive', use_values=False)
+
+ msg['chat_state'] = 'paused'
+ self.check(msg, xmlstring % 'paused', use_values=False)
+
+ del msg['chat_state']
+ self.check(msg, "")
suite = unittest.TestLoader().loadTestsFromTestCase(TestChatStates)