Package pyxmpp :: Module presence
[hide private]

Source Code for Module pyxmpp.presence

  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  """Presence XMPP stanza handling 
 19   
 20  Normative reference: 
 21    - `RFC 3920 <http://www.ietf.org/rfc/rfc3920.txt>`__ 
 22  """ 
 23   
 24  __revision__="$Id: presence.py 714 2010-04-05 10:20:10Z jajcus $" 
 25  __docformat__="restructuredtext en" 
 26   
 27  import libxml2 
 28   
 29  from pyxmpp.utils import to_utf8,from_utf8 
 30  from pyxmpp.stanza import Stanza 
 31  from pyxmpp.xmlextra import common_ns 
 32   
 33  presence_types=("available","unavailable","probe","subscribe","unsubscribe","subscribed", 
 34          "unsubscribed","invisible","error") 
 35   
 36  accept_responses={ 
 37          "subscribe": "subscribed", 
 38          "subscribed": "subscribe", 
 39          "unsubscribe": "unsubscribed", 
 40          "unsubscribed": "unsubscribe", 
 41          } 
 42   
 43  deny_responses={ 
 44          "subscribe": "unsubscribed", 
 45          "subscribed": "unsubscribe", 
 46          "unsubscribe": "subscribed", 
 47          "unsubscribed": "subscribe", 
 48          } 
 49   
50 -class Presence(Stanza):
51 """Wraper object for <presence /> stanzas.""" 52 stanza_type="presence"
53 - def __init__(self, xmlnode = None, from_jid = None, to_jid = None, stanza_type = None, 54 stanza_id = None, show = None, status = None, priority = 0, 55 error = None, error_cond = None, stream = None):
56 """Initialize a `Presence` object. 57 58 :Parameters: 59 - `xmlnode`: XML node to_jid be wrapped into the `Presence` object 60 or other Presence object to be copied. If not given then new 61 presence stanza is created using following parameters. 62 - `from_jid`: sender JID. 63 - `to_jid`: recipient JID. 64 - `stanza_type`: staza type: one of: None, "available", "unavailable", 65 "subscribe", "subscribed", "unsubscribe", "unsubscribed" or 66 "error". "available" is automaticaly changed to_jid None. 67 - `stanza_id`: stanza id -- value of stanza's "id" attribute 68 - `show`: "show" field of presence stanza. One of: None, "away", 69 "xa", "dnd", "chat". 70 - `status`: descriptive text for the presence stanza. 71 - `priority`: presence priority. 72 - `error_cond`: error condition name. Ignored if `stanza_type` is not "error" 73 :Types: 74 - `xmlnode`: `unicode` or `libxml2.xmlNode` or `Stanza` 75 - `from_jid`: `JID` 76 - `to_jid`: `JID` 77 - `stanza_type`: `unicode` 78 - `stanza_id`: `unicode` 79 - `show`: `unicode` 80 - `status`: `unicode` 81 - `priority`: `unicode` 82 - `error_cond`: `unicode`""" 83 self.xmlnode=None 84 if isinstance(xmlnode,Presence): 85 pass 86 elif isinstance(xmlnode,Stanza): 87 raise TypeError,"Couldn't make Presence from other Stanza" 88 elif isinstance(xmlnode,libxml2.xmlNode): 89 pass 90 elif xmlnode is not None: 91 raise TypeError,"Couldn't make Presence from %r" % (type(xmlnode),) 92 93 if stanza_type and stanza_type not in presence_types: 94 raise ValueError, "Invalid presence type: %r" % (type,) 95 96 if stanza_type=="available": 97 stanza_type=None 98 99 if xmlnode is None: 100 xmlnode="presence" 101 102 Stanza.__init__(self, xmlnode, from_jid = from_jid, to_jid = to_jid, stanza_type = stanza_type, 103 stanza_id = stanza_id, error = error, error_cond = error_cond, stream = stream) 104 105 if show: 106 self.xmlnode.newTextChild(common_ns,"show",to_utf8(show)) 107 if status: 108 self.xmlnode.newTextChild(common_ns,"status",to_utf8(status)) 109 if priority and priority!=0: 110 self.xmlnode.newTextChild(common_ns,"priority",to_utf8(unicode(priority)))
111
112 - def copy(self):
113 """Create a deep copy of the presence stanza. 114 115 :returntype: `Presence`""" 116 return Presence(self)
117
118 - def set_status(self,status):
119 """Change presence status description. 120 121 :Parameters: 122 - `status`: descriptive text for the presence stanza. 123 :Types: 124 - `status`: `unicode`""" 125 n=self.xpath_eval("ns:status") 126 if not status: 127 if n: 128 n[0].unlinkNode() 129 n[0].freeNode() 130 else: 131 return 132 if n: 133 n[0].setContent(to_utf8(status)) 134 else: 135 self.xmlnode.newTextChild(common_ns,"status",to_utf8(status))
136
137 - def get_status(self):
138 """Get presence status description. 139 140 :return: value of stanza's <status/> field. 141 :returntype: `unicode`""" 142 n=self.xpath_eval("ns:status") 143 if n: 144 return from_utf8(n[0].getContent()) 145 else: 146 return None
147
148 - def get_show(self):
149 """Get presence "show" field. 150 151 :return: value of stanza's <show/> field. 152 :returntype: `unicode`""" 153 n=self.xpath_eval("ns:show") 154 if n: 155 return from_utf8(n[0].getContent()) 156 else: 157 return None
158
159 - def set_show(self,show):
160 """Change presence "show" field. 161 162 :Parameters: 163 - `show`: new value for the "show" field of presence stanza. One 164 of: None, "away", "xa", "dnd", "chat". 165 :Types: 166 - `show`: `unicode`""" 167 n=self.xpath_eval("ns:show") 168 if not show: 169 if n: 170 n[0].unlinkNode() 171 n[0].freeNode() 172 else: 173 return 174 if n: 175 n[0].setContent(to_utf8(show)) 176 else: 177 self.xmlnode.newTextChild(common_ns,"show",to_utf8(show))
178
179 - def get_priority(self):
180 """Get presence priority. 181 182 :return: value of stanza's priority. 0 if the stanza doesn't contain 183 <priority/> element. 184 :returntype: `int`""" 185 n=self.xpath_eval("ns:priority") 186 if not n: 187 return 0 188 try: 189 prio=int(n[0].getContent()) 190 except ValueError: 191 return 0 192 return prio
193
194 - def set_priority(self,priority):
195 """Change presence priority. 196 197 :Parameters: 198 - `priority`: new presence priority. 199 :Types: 200 - `priority`: `int`""" 201 n=self.xpath_eval("ns:priority") 202 if not priority: 203 if n: 204 n[0].unlinkNode() 205 n[0].freeNode() 206 else: 207 return 208 priority=int(priority) 209 if priority<-128 or priority>127: 210 raise ValueError, "Bad priority value" 211 priority=str(priority) 212 if n: 213 n[0].setContent(priority) 214 else: 215 self.xmlnode.newTextChild(common_ns,"priority",priority)
216
217 - def make_accept_response(self):
218 """Create "accept" response for the "subscribe"/"subscribed"/"unsubscribe"/"unsubscribed" 219 presence stanza. 220 221 :return: new stanza. 222 :returntype: `Presence`""" 223 224 if self.get_type() not in ("subscribe","subscribed","unsubscribe","unsubscribed"): 225 raise ValueError, ("Results may only be generated for 'subscribe'," 226 "'subscribed','unsubscribe' or 'unsubscribed' presence") 227 228 pr=Presence(stanza_type=accept_responses[self.get_type()], 229 from_jid=self.get_to(),to_jid=self.get_from(),stanza_id=self.get_id()) 230 return pr
231
232 - def make_deny_response(self):
233 """Create "deny" response for the "subscribe"/"subscribed"/"unsubscribe"/"unsubscribed" 234 presence stanza. 235 236 :return: new presence stanza. 237 :returntype: `Presence`""" 238 if self.get_type() not in ("subscribe","subscribed","unsubscribe","unsubscribed"): 239 raise ValueError, ("Results may only be generated for 'subscribe'," 240 "'subscribed','unsubscribe' or 'unsubscribed' presence") 241 242 pr=Presence(stanza_type=deny_responses[self.get_type()], 243 from_jid=self.get_to(),to_jid=self.get_from(),stanza_id=self.get_id()) 244 return pr
245
246 - def make_error_response(self,cond):
247 """Create error response for the any non-error presence stanza. 248 249 :Parameters: 250 - `cond`: error condition name, as defined in XMPP specification. 251 :Types: 252 - `cond`: `unicode` 253 254 :return: new presence stanza. 255 :returntype: `Presence`""" 256 257 if self.get_type() == "error": 258 raise ValueError, "Errors may not be generated in response to errors" 259 260 p=Presence(stanza_type="error",from_jid=self.get_to(),to_jid=self.get_from(), 261 stanza_id=self.get_id(),error_cond=cond) 262 263 if self.xmlnode.children: 264 n=self.xmlnode.children 265 while n: 266 p.xmlnode.children.addPrevSibling(n.copyNode(1)) 267 n=n.next 268 return p
269 270 # vi: sts=4 et sw=4 271