Skip to content
This repository has been archived by the owner on Dec 15, 2021. It is now read-only.

Commit

Permalink
XEP 0203 support
Browse files Browse the repository at this point in the history
Old jabber:x:delay has already disappeared from servers.
  • Loading branch information
Jajcus committed Aug 12, 2016
1 parent 43e0048 commit ef3cf7e
Showing 1 changed file with 53 additions and 20 deletions.
73 changes: 53 additions & 20 deletions pyxmpp/jabber/delay.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# #


"""Delayed delivery mark (jabber:x:delay) handling. """Delayed delivery mark (urn:xmpp:delay and jabber:x:delay) handling.
Normative reference: Normative reference:
- `JEP 91 <http://www.jabber.org/jeps/jep-0091.html>`__ - `JEP 91 <http://www.jabber.org/jeps/jep-0091.html>`__
- `XEP 0203 <http://xmpp.org/extensions/xep-0203.html>`__
""" """


__docformat__="restructuredtext en" __docformat__="restructuredtext en"
Expand All @@ -35,23 +36,39 @@
from pyxmpp.objects import StanzaPayloadObject from pyxmpp.objects import StanzaPayloadObject
from pyxmpp.exceptions import BadRequestProtocolError, JIDMalformedProtocolError, JIDError from pyxmpp.exceptions import BadRequestProtocolError, JIDMalformedProtocolError, JIDError


DELAY_NS="jabber:x:delay" DELAY_NS = "urn:xmpp:delay"
LEGACY_DELAY_NS = "jabber:x:delay"

def _parse_ts(timestamp):
if "." in timestamp and timestamp.endswith("Z"):
# strip miliseconds
timestamp = timestamp.split(".", 1)[0] + "Z"
for fmt in ("%Y-%m-%dT%H:%M:%SZ", "%Y%m%dT%H:%M:%S"):
try:
result = time.strptime(timestamp, fmt)
return result
except ValueError:
continue
raise BadRequestProtocolError, "Bad timestamp: " + repr(timestamp)


class Delay(StanzaPayloadObject): class Delay(StanzaPayloadObject):
""" """
Delayed delivery tag. Delayed delivery tag.
Represents 'jabber:x:delay' (JEP-0091) element of a Jabber stanza. Represents 'urn:xmpp:delay' (XEP-0203) element of a Jabber stanza.
:Ivariables: :Ivariables:
- `delay_from`: the "from" value of the delay element - `delay_from`: the "from" value of the delay element
- `reason`: the "reason" (content) of the delay element - `reason`: the "reason" (content) of the delay element
- `timestamp`: the UTC timestamp as naive datetime object - `timestamp`: the UTC timestamp as naive datetime object
""" """


xml_element_name = "x" xml_element_name = "delay"
xml_element_namespace = DELAY_NS xml_element_namespace = DELAY_NS


_sort_order = 1
_time_format = "%Y-%m-%dT%H:%M:%SZ"

def __init__(self,node_or_datetime,delay_from=None,reason=None,utc=True): def __init__(self,node_or_datetime,delay_from=None,reason=None,utc=True):
""" """
Initialize the Delay object. Initialize the Delay object.
Expand Down Expand Up @@ -89,25 +106,19 @@ def from_xml(self,xmlnode):
if xmlnode.type!="element": if xmlnode.type!="element":
raise ValueError,"XML node is not a jabber:x:delay element (not an element)" raise ValueError,"XML node is not a jabber:x:delay element (not an element)"
ns=get_node_ns_uri(xmlnode) ns=get_node_ns_uri(xmlnode)
if ns and ns!=DELAY_NS or xmlnode.name!="x": if ns and (ns != self.xml_element_namespace
raise ValueError,"XML node is not a jabber:x:delay element" or xmlnode.name != self.xml_element_name):
raise ValueError,"XML node is not a " + self.xml_element_namespace + " element"
stamp=xmlnode.prop("stamp") stamp=xmlnode.prop("stamp")
if stamp.endswith("Z"): tm = _parse_ts(stamp)
stamp=stamp[:-1]
if "-" in stamp:
stamp=stamp.split("-",1)[0]
try:
tm = time.strptime(stamp, "%Y%m%dT%H:%M:%S")
except ValueError:
raise BadRequestProtocolError, "Bad timestamp"
tm=tm[0:8]+(0,) tm=tm[0:8]+(0,)
self.timestamp=datetime.datetime.fromtimestamp(time.mktime(tm)) self.timestamp=datetime.datetime.fromtimestamp(time.mktime(tm))
delay_from=from_utf8(xmlnode.prop("from")) delay_from=from_utf8(xmlnode.prop("from"))
if delay_from: if delay_from:
try: try:
self.delay_from = JID(delay_from) self.delay_from = JID(delay_from)
except JIDError: except JIDError:
raise JIDMalformedProtocolError, "Bad JID in the jabber:x:delay 'from' attribute" raise JIDMalformedProtocolError, "Bad JID in the " + self.xml_element_namespace + " 'from' attribute"
else: else:
self.delay_from = None self.delay_from = None
self.reason = from_utf8(xmlnode.getContent()) self.reason = from_utf8(xmlnode.getContent())
Expand All @@ -124,7 +135,7 @@ def complete_xml_element(self, xmlnode, _unused):
:Types: :Types:
- `xmlnode`: `libxml2.xmlNode` - `xmlnode`: `libxml2.xmlNode`
- `_unused`: `libxml2.xmlDoc`""" - `_unused`: `libxml2.xmlDoc`"""
tm=self.timestamp.strftime("%Y%m%dT%H:%M:%S") tm=self.timestamp.strftime(self._time_format)
xmlnode.setProp("stamp",tm) xmlnode.setProp("stamp",tm)
if self.delay_from: if self.delay_from:
xmlnode.setProp("from",self.delay_from.as_utf8()) xmlnode.setProp("from",self.delay_from.as_utf8())
Expand Down Expand Up @@ -153,8 +164,27 @@ def __str__(self):
n.freeNode() n.freeNode()
return r return r


def __cmp__(self,other): def __cmp__(self, other):
return cmp(timestamp, other.timestamp) return cmp((self._sort_order, self.timestamp),
(other._sort_order, other.timestamp))

class LegacyDelay(Delay):
"""
Delayed delivery tag.
Represents 'jabber:x:delay' (JEP-0091) element of a Jabber stanza.
:Ivariables:
- `delay_from`: the "from" value of the delay element
- `reason`: the "reason" (content) of the delay element
- `timestamp`: the UTC timestamp as naive datetime object
"""

xml_element_name = "x"
xml_element_namespace = LEGACY_DELAY_NS

_sort_order = 2
_time_format = "%Y%m%dT%H:%M:%S"


def get_delays(stanza): def get_delays(stanza):
"""Get jabber:x:delay elements from the stanza. """Get jabber:x:delay elements from the stanza.
Expand All @@ -169,8 +199,11 @@ def get_delays(stanza):
delays=[] delays=[]
n=stanza.xmlnode.children n=stanza.xmlnode.children
while n: while n:
if n.type=="element" and get_node_ns_uri(n)==DELAY_NS and n.name=="x": if n.type=="element":
delays.append(Delay(n)) if get_node_ns_uri(n) == DELAY_NS and n.name == "delay":
delays.append(Delay(n))
elif get_node_ns_uri(n) == LEGACY_DELAY_NS and n.name == "x":
delays.append(LegacyDelay(n))
n=n.next n=n.next
delays.sort() delays.sort()
return delays return delays
Expand Down

0 comments on commit ef3cf7e

Please sign in to comment.