summaryrefslogtreecommitdiff
path: root/sleekxmpp/plugins/xep_0202
diff options
context:
space:
mode:
authorLance Stout <lancestout@gmail.com>2011-07-27 19:35:42 -0700
committerLance Stout <lancestout@gmail.com>2011-07-27 19:35:42 -0700
commitad978700fc891602c826dea03615c396f39364a0 (patch)
tree76315f3d39cd7209c71a164864f5e815d1a27d07 /sleekxmpp/plugins/xep_0202
parent48fb7006f75dd03caa23f61cb512f9002fe91b90 (diff)
parente022b2a36c342b6a83d7c7f0a39dfb851cdfd2de (diff)
downloadslixmpp-ad978700fc891602c826dea03615c396f39364a0.tar.gz
slixmpp-ad978700fc891602c826dea03615c396f39364a0.tar.bz2
slixmpp-ad978700fc891602c826dea03615c396f39364a0.tar.xz
slixmpp-ad978700fc891602c826dea03615c396f39364a0.zip
Merge branch 'develop' into roster
Diffstat (limited to 'sleekxmpp/plugins/xep_0202')
-rw-r--r--sleekxmpp/plugins/xep_0202/__init__.py11
-rw-r--r--sleekxmpp/plugins/xep_0202/stanza.py126
-rw-r--r--sleekxmpp/plugins/xep_0202/time.py92
3 files changed, 229 insertions, 0 deletions
diff --git a/sleekxmpp/plugins/xep_0202/__init__.py b/sleekxmpp/plugins/xep_0202/__init__.py
new file mode 100644
index 00000000..82338d3a
--- /dev/null
+++ b/sleekxmpp/plugins/xep_0202/__init__.py
@@ -0,0 +1,11 @@
+"""
+ 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 permission.
+"""
+
+from sleekxmpp.plugins.xep_0202 import stanza
+from sleekxmpp.plugins.xep_0202.stanza import EntityTime
+from sleekxmpp.plugins.xep_0202.time import xep_0202
diff --git a/sleekxmpp/plugins/xep_0202/stanza.py b/sleekxmpp/plugins/xep_0202/stanza.py
new file mode 100644
index 00000000..bb27692a
--- /dev/null
+++ b/sleekxmpp/plugins/xep_0202/stanza.py
@@ -0,0 +1,126 @@
+"""
+ SleekXMPP: The Sleek XMPP Library
+ Copyright (C) 2010 Nathanael C. Fritz
+ This file is part of SleekXMPP.
+
+ See the file LICENSE for copying permission.
+"""
+
+import datetime as dt
+from dateutil.tz import tzoffset, tzutc
+
+from sleekxmpp.xmlstream import ElementBase
+from sleekxmpp.plugins import xep_0082
+
+
+class EntityTime(ElementBase):
+
+ """
+ The <time> element represents the local time for an XMPP agent.
+ The time is expressed in UTC to make synchronization easier
+ between entities, but the offset for the local timezone is also
+ included.
+
+ Example <time> stanzas:
+ <iq type="result">
+ <time xmlns="urn:xmpp:time">
+ <utc>2011-07-03T11:37:12.234569</utc>
+ <tzo>-07:00</tzo>
+ </time>
+ </iq>
+
+ Stanza Interface:
+ time -- The local time for the entity (updates utc and tzo).
+ utc -- The UTC equivalent to local time.
+ tzo -- The local timezone offset from UTC.
+
+ Methods:
+ get_time -- Return local time datetime object.
+ set_time -- Set UTC and TZO fields.
+ del_time -- Remove both UTC and TZO fields.
+ get_utc -- Return datetime object of UTC time.
+ set_utc -- Set the UTC time.
+ get_tzo -- Return tzinfo object.
+ set_tzo -- Set the local timezone offset.
+ """
+
+ name = 'time'
+ namespace = 'urn:xmpp:time'
+ plugin_attrib = 'entity_time'
+ interfaces = set(('tzo', 'utc', 'time'))
+ sub_interfaces = interfaces
+
+ def set_time(self, value):
+ """
+ Set both the UTC and TZO fields given a time object.
+
+ Arguments:
+ value -- A datetime object or properly formatted
+ string equivalent.
+ """
+ date = value
+ if not isinstance(value, dt.datetime):
+ date = xep_0082.parse(value)
+ self['utc'] = date
+ self['tzo'] = date.tzinfo
+
+ def get_time(self):
+ """
+ Return the entity's local time based on the UTC and TZO data.
+ """
+ date = self['utc']
+ tz = self['tzo']
+ return date.astimezone(tz)
+
+ def del_time(self):
+ """Remove both the UTC and TZO fields."""
+ del self['utc']
+ del self['tzo']
+
+ def get_tzo(self):
+ """
+ Return the timezone offset from UTC as a tzinfo object.
+ """
+ tzo = self._get_sub_text('tzo')
+ if tzo == '':
+ tzo = 'Z'
+ time = xep_0082.parse('00:00:00%s' % tzo)
+ return time.tzinfo
+
+ def set_tzo(self, value):
+ """
+ Set the timezone offset from UTC.
+
+ Arguments:
+ value -- Either a tzinfo object or the number of
+ seconds (positive or negative) to offset.
+ """
+ time = xep_0082.time(offset=value)
+ if xep_0082.parse(time).tzinfo == tzutc():
+ self._set_sub_text('tzo', 'Z')
+ else:
+ self._set_sub_text('tzo', time[-6:])
+
+ def get_utc(self):
+ """
+ Return the time in UTC as a datetime object.
+ """
+ value = self._get_sub_text('utc')
+ if value == '':
+ return xep_0082.parse(xep_0082.datetime())
+ return xep_0082.parse('%sZ' % value)
+
+ def set_utc(self, value):
+ """
+ Set the time in UTC.
+
+ Arguments:
+ value -- A datetime object or properly formatted
+ string equivalent.
+ """
+ date = value
+ if not isinstance(value, dt.datetime):
+ date = xep_0082.parse(value)
+ date = date.astimezone(tzutc())
+ value = xep_0082.format_datetime(date)[:-1]
+ self._set_sub_text('utc', value)
diff --git a/sleekxmpp/plugins/xep_0202/time.py b/sleekxmpp/plugins/xep_0202/time.py
new file mode 100644
index 00000000..bcad8bc8
--- /dev/null
+++ b/sleekxmpp/plugins/xep_0202/time.py
@@ -0,0 +1,92 @@
+"""
+ SleekXMPP: The Sleek XMPP Library
+ Copyright (C) 2010 Nathanael C. Fritz
+ This file is part of SleekXMPP.
+
+ See the file LICENSE for copying permission.
+"""
+
+import logging
+
+from sleekxmpp.stanza.iq import Iq
+from sleekxmpp.xmlstream import register_stanza_plugin
+from sleekxmpp.xmlstream.handler import Callback
+from sleekxmpp.xmlstream.matcher import StanzaPath
+from sleekxmpp.plugins.base import base_plugin
+from sleekxmpp.plugins import xep_0082
+from sleekxmpp.plugins.xep_0202 import stanza
+
+
+log = logging.getLogger(__name__)
+
+
+class xep_0202(base_plugin):
+
+ """
+ XEP-0202: Entity Time
+ """
+
+ def plugin_init(self):
+ """Start the XEP-0203 plugin."""
+ self.xep = '0202'
+ self.description = 'Entity Time'
+ self.stanza = stanza
+
+ self.tz_offset = self.config.get('tz_offset', 0)
+
+ # As a default, respond to time requests with the
+ # local time returned by XEP-0082. However, a
+ # custom function can be supplied which accepts
+ # the JID of the entity to query for the time.
+ self.local_time = self.config.get('local_time', None)
+ if not self.local_time:
+ self.local_time = lambda x: xep_0082.datetime(offset=self.tz_offset)
+
+ self.xmpp.registerHandler(
+ Callback('Entity Time',
+ StanzaPath('iq/entity_time'),
+ self._handle_time_request))
+ register_stanza_plugin(Iq, stanza.EntityTime)
+
+ def post_init(self):
+ """Handle cross-plugin interactions."""
+ base_plugin.post_init(self)
+ self.xmpp['xep_0030'].add_feature('urn:xmpp:time')
+
+
+ def _handle_time_request(self, iq):
+ """
+ Respond to a request for the local time.
+
+ The time is taken from self.local_time(), which may be replaced
+ during plugin configuration with a function that maps JIDs to
+ times.
+
+ Arguments:
+ iq -- The Iq time request stanza.
+ """
+ iq.reply()
+ iq['entity_time']['time'] = self.local_time(iq['to'])
+ iq.send()
+
+ def get_entity_time(self, to, ifrom=None, **iqargs):
+ """
+ Request the time from another entity.
+
+ Arguments:
+ to -- JID of the entity to query.
+ ifrom -- Specifiy the sender's JID.
+ block -- If true, block and wait for the stanzas' reply.
+ timeout -- The time in seconds to block while waiting for
+ a reply. If None, then wait indefinitely.
+ callback -- Optional callback to execute when a reply is
+ received instead of blocking and waiting for
+ the reply.
+ """
+ iq = self.xmpp.Iq()
+ iq['type'] = 'get'
+ iq['to'] = 'to'
+ if ifrom:
+ iq['from'] = 'ifrom'
+ iq.enable('entity_time')
+ return iq.send(**iqargs)