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  __revision__="$Id: delay.py 714 2010-04-05 10:20:10Z jajcus $" 
 25  __docformat__="restructuredtext en" 
 26   
 27  import libxml2 
 28  import time 
 29  import datetime 
 30   
 31  from pyxmpp.jid import JID 
 32   
 33  from pyxmpp.utils import to_utf8,from_utf8 
 34  from pyxmpp.xmlextra import get_node_ns_uri 
 35  from pyxmpp.utils import datetime_utc_to_local,datetime_local_to_utc 
 36  from pyxmpp.objects import StanzaPayloadObject 
 37  from pyxmpp.exceptions import BadRequestProtocolError, JIDMalformedProtocolError, JIDError 
 38   
 39  DELAY_NS="jabber:x:delay" 
 40   
41 -class Delay(StanzaPayloadObject):
42 """ 43 Delayed delivery tag. 44 45 Represents 'jabber:x:delay' (JEP-0091) element of a Jabber stanza. 46 47 :Ivariables: 48 - `delay_from`: the "from" value of the delay element 49 - `reason`: the "reason" (content) of the delay element 50 - `timestamp`: the UTC timestamp as naive datetime object 51 """ 52 53 xml_element_name = "x" 54 xml_element_namespace = DELAY_NS 55
56 - def __init__(self,node_or_datetime,delay_from=None,reason=None,utc=True):
57 """ 58 Initialize the Delay object. 59 60 :Parameters: 61 - `node_or_datetime`: an XML node to parse or the timestamp. 62 - `delay_from`: JID of the entity which adds the delay mark 63 (when `node_or_datetime` is a timestamp). 64 - `reason`: reason of the delay (when `node_or_datetime` is a 65 timestamp). 66 - `utc`: if `True` then the timestamp is assumed to be UTC, 67 otherwise it is assumed to be local time. 68 :Types: 69 - `node_or_datetime`: `libxml2.xmlNode` or `datetime.datetime` 70 - `delay_from`: `pyxmpp.JID` 71 - `reason`: `unicode` 72 - `utc`: `bool`""" 73 if isinstance(node_or_datetime,libxml2.xmlNode): 74 self.from_xml(node_or_datetime) 75 else: 76 if utc: 77 self.timestamp=node_or_datetime 78 else: 79 self.timestamp=datetime_local_to_utc(node_or_datetime) 80 self.delay_from=JID(delay_from) 81 self.reason=unicode(reason)
82
83 - def from_xml(self,xmlnode):
84 """Initialize Delay object from an XML node. 85 86 :Parameters: 87 - `xmlnode`: the jabber:x:delay XML element. 88 :Types: 89 - `xmlnode`: `libxml2.xmlNode`""" 90 if xmlnode.type!="element": 91 raise ValueError,"XML node is not a jabber:x:delay element (not an element)" 92 ns=get_node_ns_uri(xmlnode) 93 if ns and ns!=DELAY_NS or xmlnode.name!="x": 94 raise ValueError,"XML node is not a jabber:x:delay element" 95 stamp=xmlnode.prop("stamp") 96 if stamp.endswith("Z"): 97 stamp=stamp[:-1] 98 if "-" in stamp: 99 stamp=stamp.split("-",1)[0] 100 try: 101 tm = time.strptime(stamp, "%Y%m%dT%H:%M:%S") 102 except ValueError: 103 raise BadRequestProtocolError, "Bad timestamp" 104 tm=tm[0:8]+(0,) 105 self.timestamp=datetime.datetime.fromtimestamp(time.mktime(tm)) 106 delay_from=from_utf8(xmlnode.prop("from")) 107 if delay_from: 108 try: 109 self.delay_from = JID(delay_from) 110 except JIDError: 111 raise JIDMalformedProtocolError, "Bad JID in the jabber:x:delay 'from' attribute" 112 else: 113 self.delay_from = None 114 self.reason = from_utf8(xmlnode.getContent())
115
116 - def complete_xml_element(self, xmlnode, _unused):
117 """Complete the XML node with `self` content. 118 119 Should be overriden in classes derived from `StanzaPayloadObject`. 120 121 :Parameters: 122 - `xmlnode`: XML node with the element being built. It has already 123 right name and namespace, but no attributes or content. 124 - `_unused`: document to which the element belongs. 125 :Types: 126 - `xmlnode`: `libxml2.xmlNode` 127 - `_unused`: `libxml2.xmlDoc`""" 128 tm=self.timestamp.strftime("%Y%m%dT%H:%M:%S") 129 xmlnode.setProp("stamp",tm) 130 if self.delay_from: 131 xmlnode.setProp("from",self.delay_from.as_utf8()) 132 if self.reason: 133 xmlnode.setContent(to_utf8(self.reason))
134
135 - def get_datetime_local(self):
136 """Get the timestamp as a local time. 137 138 :return: the timestamp of the delay element represented in the local 139 timezone. 140 :returntype: `datetime.datetime`""" 141 r=datetime_utc_to_local(self.timestamp) 142 return r
143
144 - def get_datetime_utc(self):
145 """Get the timestamp as a UTC. 146 147 :return: the timestamp of the delay element represented in UTC. 148 :returntype: `datetime.datetime`""" 149 return self.timestamp
150
151 - def __str__(self):
152 n=self.as_xml() 153 r=n.serialize() 154 n.freeNode() 155 return r
156
157 - def __cmp__(self,other):
158 return cmp(timestamp, other.timestamp)
159
160 -def get_delays(stanza):
161 """Get jabber:x:delay elements from the stanza. 162 163 :Parameters: 164 - `stanza`: a, probably delayed, stanza. 165 :Types: 166 - `stanza`: `pyxmpp.stanza.Stanza` 167 168 :return: list of delay tags sorted by the timestamp. 169 :returntype: `list` of `Delay`""" 170 delays=[] 171 n=stanza.xmlnode.children 172 while n: 173 if n.type=="element" and get_node_ns_uri(n)==DELAY_NS and n.name=="x": 174 delays.append(Delay(n)) 175 n=n.next 176 delays.sort() 177 return delays
178
179 -def get_delay(stanza):
180 """Get the oldest jabber:x:delay elements from the stanza. 181 182 :Parameters: 183 - `stanza`: a, probably delayed, stanza. 184 :Types: 185 - `stanza`: `pyxmpp.stanza.Stanza` 186 187 The return value, if not `None`, contains a quite reliable 188 timestamp of a delayed (e.g. from offline storage) message. 189 190 :return: the oldest delay tag of the stanza or `None`. 191 :returntype: `Delay`""" 192 delays=get_delays(stanza) 193 if not delays: 194 return None 195 return get_delays(stanza)[0]
196 197 # vi: sts=4 et sw=4 198