Package pyxmpp :: Package jabber :: Module delay
[hide private]

Source Code for Module pyxmpp.jabber.delay

  1  # 
  2  # (C) Copyright 2003-2010 Jacek Konieczny <jajcus@jajcus.net> 
  3  # 
  4  # This program is free software; you can redistribute it and/or modify 
  5  # it under the terms of the GNU Lesser General Public License Version 
  6  # 2.1 as published by the Free Software Foundation. 
  7  # 
  8  # This program is distributed in the hope that it will be useful, 
  9  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 10  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 11  # GNU Lesser General Public License for more details. 
 12  # 
 13  # You should have received a copy of the GNU Lesser General Public 
 14  # License along with this program; if not, write to the Free Software 
 15  # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
 16  # 
 17   
 18  """Delayed delivery mark (jabber:x:delay) handling. 
 19   
 20  Normative reference: 
 21    - `JEP 91 <http://www.jabber.org/jeps/jep-0091.html>`__ 
 22  """ 
 23   
 24  __docformat__="restructuredtext en" 
 25   
 26  import libxml2 
 27  import time 
 28  import datetime 
 29   
 30  from pyxmpp.jid import JID 
 31   
 32  from pyxmpp.utils import to_utf8,from_utf8 
 33  from pyxmpp.xmlextra import get_node_ns_uri 
 34  from pyxmpp.utils import datetime_utc_to_local,datetime_local_to_utc 
 35  from pyxmpp.objects import StanzaPayloadObject 
 36  from pyxmpp.exceptions import BadRequestProtocolError, JIDMalformedProtocolError, JIDError 
 37   
 38  DELAY_NS="jabber:x:delay" 
 39   
40 -class Delay(StanzaPayloadObject):
41 """ 42 Delayed delivery tag. 43 44 Represents 'jabber:x:delay' (JEP-0091) element of a Jabber stanza. 45 46 :Ivariables: 47 - `delay_from`: the "from" value of the delay element 48 - `reason`: the "reason" (content) of the delay element 49 - `timestamp`: the UTC timestamp as naive datetime object 50 """ 51 52 xml_element_name = "x" 53 xml_element_namespace = DELAY_NS 54
55 - def __init__(self,node_or_datetime,delay_from=None,reason=None,utc=True):
56 """ 57 Initialize the Delay object. 58 59 :Parameters: 60 - `node_or_datetime`: an XML node to parse or the timestamp. 61 - `delay_from`: JID of the entity which adds the delay mark 62 (when `node_or_datetime` is a timestamp). 63 - `reason`: reason of the delay (when `node_or_datetime` is a 64 timestamp). 65 - `utc`: if `True` then the timestamp is assumed to be UTC, 66 otherwise it is assumed to be local time. 67 :Types: 68 - `node_or_datetime`: `libxml2.xmlNode` or `datetime.datetime` 69 - `delay_from`: `pyxmpp.JID` 70 - `reason`: `unicode` 71 - `utc`: `bool`""" 72 if isinstance(node_or_datetime,libxml2.xmlNode): 73 self.from_xml(node_or_datetime) 74 else: 75 if utc: 76 self.timestamp=node_or_datetime 77 else: 78 self.timestamp=datetime_local_to_utc(node_or_datetime) 79 self.delay_from=JID(delay_from) 80 self.reason=unicode(reason)
81
82 - def from_xml(self,xmlnode):
83 """Initialize Delay object from an XML node. 84 85 :Parameters: 86 - `xmlnode`: the jabber:x:delay XML element. 87 :Types: 88 - `xmlnode`: `libxml2.xmlNode`""" 89 if xmlnode.type!="element": 90 raise ValueError,"XML node is not a jabber:x:delay element (not an element)" 91 ns=get_node_ns_uri(xmlnode) 92 if ns and ns!=DELAY_NS or xmlnode.name!="x": 93 raise ValueError,"XML node is not a jabber:x:delay element" 94 stamp=xmlnode.prop("stamp") 95 if stamp.endswith("Z"): 96 stamp=stamp[:-1] 97 if "-" in stamp: 98 stamp=stamp.split("-",1)[0] 99 try: 100 tm = time.strptime(stamp, "%Y%m%dT%H:%M:%S") 101 except ValueError: 102 raise BadRequestProtocolError, "Bad timestamp" 103 tm=tm[0:8]+(0,) 104 self.timestamp=datetime.datetime.fromtimestamp(time.mktime(tm)) 105 delay_from=from_utf8(xmlnode.prop("from")) 106 if delay_from: 107 try: 108 self.delay_from = JID(delay_from) 109 except JIDError: 110 raise JIDMalformedProtocolError, "Bad JID in the jabber:x:delay 'from' attribute" 111 else: 112 self.delay_from = None 113 self.reason = from_utf8(xmlnode.getContent())
114
115 - def complete_xml_element(self, xmlnode, _unused):
116 """Complete the XML node with `self` content. 117 118 Should be overriden in classes derived from `StanzaPayloadObject`. 119 120 :Parameters: 121 - `xmlnode`: XML node with the element being built. It has already 122 right name and namespace, but no attributes or content. 123 - `_unused`: document to which the element belongs. 124 :Types: 125 - `xmlnode`: `libxml2.xmlNode` 126 - `_unused`: `libxml2.xmlDoc`""" 127 tm=self.timestamp.strftime("%Y%m%dT%H:%M:%S") 128 xmlnode.setProp("stamp",tm) 129 if self.delay_from: 130 xmlnode.setProp("from",self.delay_from.as_utf8()) 131 if self.reason: 132 xmlnode.setContent(to_utf8(self.reason))
133
134 - def get_datetime_local(self):
135 """Get the timestamp as a local time. 136 137 :return: the timestamp of the delay element represented in the local 138 timezone. 139 :returntype: `datetime.datetime`""" 140 r=datetime_utc_to_local(self.timestamp) 141 return r
142
143 - def get_datetime_utc(self):
144 """Get the timestamp as a UTC. 145 146 :return: the timestamp of the delay element represented in UTC. 147 :returntype: `datetime.datetime`""" 148 return self.timestamp
149
150 - def __str__(self):
151 n=self.as_xml() 152 r=n.serialize() 153 n.freeNode() 154 return r
155
156 - def __cmp__(self,other):
157 return cmp(timestamp, other.timestamp)
158
159 -def get_delays(stanza):
160 """Get jabber:x:delay elements from the stanza. 161 162 :Parameters: 163 - `stanza`: a, probably delayed, stanza. 164 :Types: 165 - `stanza`: `pyxmpp.stanza.Stanza` 166 167 :return: list of delay tags sorted by the timestamp. 168 :returntype: `list` of `Delay`""" 169 delays=[] 170 n=stanza.xmlnode.children 171 while n: 172 if n.type=="element" and get_node_ns_uri(n)==DELAY_NS and n.name=="x": 173 delays.append(Delay(n)) 174 n=n.next 175 delays.sort() 176 return delays
177
178 -def get_delay(stanza):
179 """Get the oldest jabber:x:delay elements from the stanza. 180 181 :Parameters: 182 - `stanza`: a, probably delayed, stanza. 183 :Types: 184 - `stanza`: `pyxmpp.stanza.Stanza` 185 186 The return value, if not `None`, contains a quite reliable 187 timestamp of a delayed (e.g. from offline storage) message. 188 189 :return: the oldest delay tag of the stanza or `None`. 190 :returntype: `Delay`""" 191 delays=get_delays(stanza) 192 if not delays: 193 return None 194 return get_delays(stanza)[0]
195 196 # vi: sts=4 et sw=4 197