summaryrefslogtreecommitdiff
path: root/sleekxmpp
diff options
context:
space:
mode:
authorLance Stout <lancestout@gmail.com>2010-10-25 20:37:02 -0400
committerLance Stout <lancestout@gmail.com>2010-10-25 20:37:02 -0400
commit6d68706326e3248e167b92289fd695ed8b11cec7 (patch)
tree81c7153b4ccab3352d5c4d7c91a48ef4c3b495f9 /sleekxmpp
parent5bdcd9ef9d74d7921f5579086e6c6d94c0ac7deb (diff)
downloadslixmpp-6d68706326e3248e167b92289fd695ed8b11cec7.tar.gz
slixmpp-6d68706326e3248e167b92289fd695ed8b11cec7.tar.bz2
slixmpp-6d68706326e3248e167b92289fd695ed8b11cec7.tar.xz
slixmpp-6d68706326e3248e167b92289fd695ed8b11cec7.zip
Added XEP-0012 Last Activity plugin.
Contributed by Cesar Alcalde.
Diffstat (limited to 'sleekxmpp')
-rw-r--r--sleekxmpp/plugins/__init__.py5
-rw-r--r--sleekxmpp/plugins/xep_0012.py115
2 files changed, 118 insertions, 2 deletions
diff --git a/sleekxmpp/plugins/__init__.py b/sleekxmpp/plugins/__init__.py
index 36fa1771..7d4d9815 100644
--- a/sleekxmpp/plugins/__init__.py
+++ b/sleekxmpp/plugins/__init__.py
@@ -5,5 +5,6 @@
See the file LICENSE for copying permission.
"""
-__all__ = ['xep_0004', 'xep_0030', 'xep_0033', 'xep_0045', 'xep_0050',
-'xep_0078', 'xep_0085', 'xep_0092', 'xep_0199', 'gmail_notify', 'xep_0060']
+__all__ = ['xep_0004', 'xep_0012', 'xep_0030', 'xep_0033', 'xep_0045',
+ 'xep_0050', 'xep_0078', 'xep_0085', 'xep_0092', 'xep_0199',
+ 'gmail_notify', 'xep_0060']
diff --git a/sleekxmpp/plugins/xep_0012.py b/sleekxmpp/plugins/xep_0012.py
new file mode 100644
index 00000000..45ca8a00
--- /dev/null
+++ b/sleekxmpp/plugins/xep_0012.py
@@ -0,0 +1,115 @@
+"""
+ SleekXMPP: The Sleek XMPP Library
+ Copyright (C) 2010 Nathanael C. Fritz
+ This file is part of SleekXMPP.
+
+ See the file LICENSE for copying permission.
+"""
+
+from datetime import datetime
+import logging
+
+from . import base
+from .. stanza.iq import Iq
+from .. xmlstream.handler.callback import Callback
+from .. xmlstream.matcher.xpath import MatchXPath
+from .. xmlstream import ElementBase, ET, JID, register_stanza_plugin
+
+
+class LastActivity(ElementBase):
+ name = 'query'
+ namespace = 'jabber:iq:last'
+ plugin_attrib = 'last_activity'
+ interfaces = set(('seconds', 'status'))
+
+ def get_seconds(self):
+ return int(self._get_attr('seconds'))
+
+ def set_seconds(self, value):
+ self._set_attr('seconds', str(value))
+
+ def get_status(self):
+ return self.xml.text
+
+ def set_status(self, value):
+ self.xml.text = str(value)
+
+ def del_status(self):
+ self.xml.text = ''
+
+class xep_0012(base.base_plugin):
+ """
+ XEP-0012 Last Activity
+ """
+ def plugin_init(self):
+ self.description = "Last Activity"
+ self.xep = "0012"
+
+ self.xmpp.registerHandler(
+ Callback('Last Activity',
+ MatchXPath('{%s}iq/{%s}query' % (self.xmpp.default_ns,
+ LastActivity.namespace)),
+ self.handle_last_activity_query))
+ register_stanza_plugin(Iq, LastActivity)
+
+ self.xmpp.add_event_handler('last_activity_request', self.handle_last_activity)
+
+
+ def post_init(self):
+ base.base_plugin.post_init(self)
+ if self.xmpp.is_component:
+ # We are a component, so we track the uptime
+ self.xmpp.add_event_handler("session_start", self._reset_uptime)
+ self._start_datetime = datetime.now()
+ self.xmpp.plugin['xep_0030'].add_feature('jabber:iq:last')
+
+ def _reset_uptime(self, event):
+ self._start_datetime = datetime.now()
+
+ def handle_last_activity_query(self, iq):
+ if iq['type'] == 'get':
+ logging.debug("Last activity requested by %s" % iq['from'])
+ self.xmpp.event('last_activity_request', iq)
+ elif iq['type'] == 'result':
+ logging.debug("Last activity result from %s" % iq['from'])
+ self.xmpp.event('last_activity', iq)
+
+ def handle_last_activity(self, iq):
+ jid = iq['from']
+
+ if self.xmpp.is_component:
+ # Send the uptime
+ result = LastActivity()
+ td = (datetime.now() - self._start_datetime)
+ result['seconds'] = td.seconds + td.days * 24 * 3600
+ reply = iq.reply().setPayload(result.xml).send()
+ else:
+ barejid = JID(jid).bare
+ if barejid in self.xmpp.roster and ( self.xmpp.roster[barejid]['subscription'] in ('from', 'both') or
+ barejid == self.xmpp.boundjid.bare ):
+ # We don't know how to calculate it
+ iq.reply().error().setPayload(iq['last_activity'].xml)
+ iq['error']['code'] = '503'
+ iq['error']['type'] = 'cancel'
+ iq['error']['condition'] = 'service-unavailable'
+ iq.send()
+ else:
+ iq.reply().error().setPayload(iq['last_activity'].xml)
+ iq['error']['code'] = '403'
+ iq['error']['type'] = 'auth'
+ iq['error']['condition'] = 'forbidden'
+ iq.send()
+
+ def get_last_activity(self, jid):
+ """Query the LastActivity of jid and return it in seconds"""
+ iq = self.xmpp.makeIqGet()
+ query = LastActivity()
+ iq.append(query.xml)
+ iq.attrib['to'] = jid
+ iq.attrib['from'] = self.xmpp.boundjid.full
+ id = iq.get('id')
+ result = iq.send()
+ if result and result is not None and result.get('type', 'error') != 'error':
+ return result['last_activity']['seconds']
+ else:
+ return False