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

Source Code for Module pyxmpp.jabber.muccore

  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  """Jabber Multi-User Chat implementation. 
 18   
 19  Normative reference: 
 20    - `JEP 45 <http://www.jabber.org/jeps/jep-0045.html>`__ 
 21  """ 
 22   
 23  __revision__="$Id: muccore.py 714 2010-04-05 10:20:10Z jajcus $" 
 24  __docformat__="restructuredtext en" 
 25   
 26  import libxml2 
 27   
 28  from pyxmpp.utils import to_utf8,from_utf8 
 29  from pyxmpp.xmlextra import common_doc, common_root, common_ns, get_node_ns_uri 
 30  from pyxmpp.presence import Presence 
 31  from pyxmpp.iq import Iq 
 32  from pyxmpp.jid import JID 
 33  from pyxmpp import xmlextra 
 34  from pyxmpp.objects import StanzaPayloadWrapperObject 
 35  from pyxmpp.xmlextra import xml_element_iter 
 36   
 37  MUC_NS="http://jabber.org/protocol/muc" 
 38  MUC_USER_NS=MUC_NS+"#user" 
 39  MUC_ADMIN_NS=MUC_NS+"#admin" 
 40  MUC_OWNER_NS=MUC_NS+"#owner" 
 41   
 42  affiliations=("admin","member","none","outcast","owner") 
 43  roles=("moderator","none","participant","visitor") 
 44   
45 -class MucXBase(StanzaPayloadWrapperObject):
46 """ 47 Base class for MUC-specific stanza payload - wrapper around 48 an XML element. 49 50 :Ivariables: 51 - `xmlnode`: the wrapped XML node 52 """ 53 element="x" 54 ns=None
55 - def __init__(self, xmlnode=None, copy=True, parent=None):
56 """ 57 Copy MucXBase object or create a new one, possibly 58 based on or wrapping an XML node. 59 60 :Parameters: 61 - `xmlnode`: is the object to copy or an XML node to wrap. 62 - `copy`: when `True` a copy of the XML node provided will be included 63 in `self`, the node will be copied otherwise. 64 - `parent`: parent node for the created/copied XML element. 65 :Types: 66 - `xmlnode`: `MucXBase` or `libxml2.xmlNode` 67 - `copy`: `bool` 68 - `parent`: `libxml2.xmlNode` 69 """ 70 if self.ns==None: 71 raise RuntimeError,"Pure virtual class called" 72 self.xmlnode=None 73 self.borrowed=False 74 if isinstance(xmlnode,libxml2.xmlNode): 75 if copy: 76 self.xmlnode=xmlnode.docCopyNode(common_doc,1) 77 common_root.addChild(self.xmlnode) 78 else: 79 self.xmlnode=xmlnode 80 self.borrowed=True 81 if copy: 82 ns=xmlnode.ns() 83 xmlextra.replace_ns(self.xmlnode, ns, common_ns) 84 elif isinstance(xmlnode,MucXBase): 85 if not copy: 86 raise TypeError, "MucXBase may only be copied" 87 self.xmlnode=xmlnode.xmlnode.docCopyNode(common_doc,1) 88 common_root.addChild(self.xmlnode) 89 elif xmlnode is not None: 90 raise TypeError, "Bad MucX constructor argument" 91 else: 92 if parent: 93 self.xmlnode=parent.newChild(None,self.element,None) 94 self.borrowed=True 95 else: 96 self.xmlnode=common_root.newChild(None,self.element,None) 97 ns=self.xmlnode.newNs(self.ns,None) 98 self.xmlnode.setNs(ns)
99
100 - def __del__(self):
101 if self.xmlnode: 102 self.free()
103
104 - def free(self):
105 """ 106 Unlink and free the XML node owned by `self`. 107 """ 108 if not self.borrowed: 109 self.xmlnode.unlinkNode() 110 self.xmlnode.freeNode() 111 self.xmlnode=None
112
113 - def free_borrowed(self):
114 """ 115 Detach the XML node borrowed by `self`. 116 """ 117 self.xmlnode=None
118
119 - def xpath_eval(self,expr):
120 """ 121 Evaluate XPath expression in context of `self.xmlnode`. 122 123 :Parameters: 124 - `expr`: the XPath expression 125 :Types: 126 - `expr`: `unicode` 127 128 :return: the result of the expression evaluation. 129 :returntype: list of `libxml2.xmlNode` 130 """ 131 ctxt = common_doc.xpathNewContext() 132 ctxt.setContextNode(self.xmlnode) 133 ctxt.xpathRegisterNs("muc",self.ns.getContent()) 134 ret=ctxt.xpathEval(to_utf8(expr)) 135 ctxt.xpathFreeContext() 136 return ret
137
138 - def serialize(self):
139 """ 140 Serialize `self` as XML. 141 142 :return: serialized `self.xmlnode`. 143 :returntype: `str` 144 """ 145 return self.xmlnode.serialize()
146
147 -class MucX(MucXBase):
148 """ 149 Wrapper for http://www.jabber.org/protocol/muc namespaced 150 stanza payload "x" elements. 151 """ 152 ns=MUC_NS
153 - def __init__(self, xmlnode=None, copy=True, parent=None):
154 MucXBase.__init__(self,xmlnode=xmlnode, copy=copy, parent=parent)
155
156 - def set_history(self, parameters):
157 """ 158 Set history parameters. 159 160 Types: 161 - `parameters`: `HistoryParameters` 162 """ 163 for child in xml_element_iter(self.xmlnode.children): 164 if get_node_ns_uri(child) == MUC_NS and child.name == "history": 165 child.unlinkNode() 166 child.freeNode() 167 break 168 169 if parameters.maxchars and parameters.maxchars < 0: 170 raise ValueError, "History parameter maxchars must be positive" 171 if parameters.maxstanzas and parameters.maxstanzas < 0: 172 raise ValueError, "History parameter maxstanzas must be positive" 173 if parameters.maxseconds and parameters.maxseconds < 0: 174 raise ValueError, "History parameter maxseconds must be positive" 175 176 hnode=self.xmlnode.newChild(self.xmlnode.ns(), "history", None) 177 178 if parameters.maxchars is not None: 179 hnode.setProp("maxchars", str(parameters.maxchars)) 180 if parameters.maxstanzas is not None: 181 hnode.setProp("maxstanzas", str(parameters.maxstanzas)) 182 if parameters.maxseconds is not None: 183 hnode.setProp("maxseconds", str(parameters.maxseconds)) 184 if parameters.since is not None: 185 hnode.setProp("since", parameters.since.strftime("%Y-%m-%dT%H:%M:%SZ"))
186
187 - def get_history(self):
188 """Return history parameters carried by the stanza. 189 190 :returntype: `HistoryParameters`""" 191 for child in xml_element_iter(self.xmlnode.children): 192 if get_node_ns_uri(child) == MUC_NS and child.name == "history": 193 maxchars = from_utf8(child.prop("maxchars")) 194 if maxchars is not None: 195 maxchars = int(maxchars) 196 maxstanzas = from_utf8(child.prop("maxstanzas")) 197 if maxstanzas is not None: 198 maxstanzas = int(maxstanzas) 199 maxseconds = from_utf8(child.prop("maxseconds")) 200 if maxseconds is not None: 201 maxseconds = int(maxseconds) 202 # TODO: since -- requires parsing of Jabber dateTime profile 203 since = None 204 return HistoryParameters(maxchars, maxstanzas, maxseconds, since)
205
206 - def set_password(self, password):
207 """Set password for the MUC request. 208 209 :Parameters: 210 - `password`: password 211 :Types: 212 - `password`: `unicode`""" 213 for child in xml_element_iter(self.xmlnode.children): 214 if get_node_ns_uri(child) == MUC_NS and child.name == "password": 215 child.unlinkNode() 216 child.freeNode() 217 break 218 219 if password is not None: 220 self.xmlnode.newTextChild(self.xmlnode.ns(), "password", to_utf8(password))
221
222 - def get_password(self):
223 """Get password from the MUC request. 224 225 :returntype: `unicode` 226 """ 227 for child in xml_element_iter(self.xmlnode.children): 228 if get_node_ns_uri(child) == MUC_NS and child.name == "password": 229 return from_utf8(child.getContent()) 230 return None
231
232 -class HistoryParameters(object):
233 """Provides parameters for MUC history management 234 235 :Ivariables: 236 - `maxchars`: limit of the total number of characters in history. 237 - `maxstanzas`: limit of the total number of messages in history. 238 - `seconds`: send only messages received in the last `seconds` seconds. 239 - `since`: Send only the messages received since the dateTime (UTC) 240 specified. 241 :Types: 242 - `maxchars`: `int` 243 - `maxstanzas`: `int` 244 - `seconds`: `int` 245 - `since`: `datetime.datetime` 246 """
247 - def __init__(self, maxchars = None, maxstanzas = None, maxseconds = None, since = None):
248 """Initializes a `HistoryParameters` object. 249 250 :Parameters: 251 - `maxchars`: limit of the total number of characters in history. 252 - `maxstanzas`: limit of the total number of messages in history. 253 - `maxseconds`: send only messages received in the last `seconds` seconds. 254 - `since`: Send only the messages received since the dateTime specified. 255 :Types: 256 - `maxchars`: `int` 257 - `maxstanzas`: `int` 258 - `maxseconds`: `int` 259 - `since`: `datetime.datetime` 260 """ 261 self.maxchars = maxchars 262 self.maxstanzas = maxstanzas 263 self.maxseconds = maxseconds 264 self.since = since
265 266
267 -class MucItemBase(object):
268 """ 269 Base class for <status/> and <item/> element wrappers. 270 """
271 - def __init__(self):
272 if self.__class__ is MucItemBase: 273 raise RuntimeError,"Abstract class called"
274
275 -class MucItem(MucItemBase):
276 """ 277 MUC <item/> element -- describes a room occupant. 278 279 :Ivariables: 280 - `affiliation`: affiliation of the user. 281 - `role`: role of the user. 282 - `jid`: JID of the user. 283 - `nick`: nickname of the user. 284 - `actor`: actor modyfying the user data. 285 - `reason`: reason of change of the user data. 286 :Types: 287 - `affiliation`: `str` 288 - `role`: `str` 289 - `jid`: `JID` 290 - `nick`: `unicode` 291 - `actor`: `JID` 292 - `reason`: `unicode` 293 """
294 - def __init__(self,xmlnode_or_affiliation,role=None,jid=None,nick=None,actor=None,reason=None):
295 """ 296 Initialize a `MucItem` object. 297 298 :Parameters: 299 - `xmlnode_or_affiliation`: XML node to be pased or the affiliation of 300 the user being described. 301 - `role`: role of the user. 302 - `jid`: JID of the user. 303 - `nick`: nickname of the user. 304 - `actor`: actor modyfying the user data. 305 - `reason`: reason of change of the user data. 306 :Types: 307 - `xmlnode_or_affiliation`: `libxml2.xmlNode` or `str` 308 - `role`: `str` 309 - `jid`: `JID` 310 - `nick`: `unicode` 311 - `actor`: `JID` 312 - `reason`: `unicode` 313 """ 314 self.jid,self.nick,self.actor,self.affiliation,self.reason,self.role=(None,)*6 315 MucItemBase.__init__(self) 316 if isinstance(xmlnode_or_affiliation,libxml2.xmlNode): 317 self.__from_xmlnode(xmlnode_or_affiliation) 318 else: 319 self.__init(xmlnode_or_affiliation,role,jid,nick,actor,reason)
320
321 - def __init(self,affiliation,role,jid=None,nick=None,actor=None,reason=None):
322 """Initialize a `MucItem` object from a set of attributes. 323 324 :Parameters: 325 - `affiliation`: affiliation of the user. 326 - `role`: role of the user. 327 - `jid`: JID of the user. 328 - `nick`: nickname of the user. 329 - `actor`: actor modyfying the user data. 330 - `reason`: reason of change of the user data. 331 :Types: 332 - `affiliation`: `str` 333 - `role`: `str` 334 - `jid`: `JID` 335 - `nick`: `unicode` 336 - `actor`: `JID` 337 - `reason`: `unicode` 338 """ 339 if not affiliation: 340 affiliation=None 341 elif affiliation not in affiliations: 342 raise ValueError,"Bad affiliation" 343 self.affiliation=affiliation 344 if not role: 345 role=None 346 elif role not in roles: 347 raise ValueError,"Bad role" 348 self.role=role 349 if jid: 350 self.jid=JID(jid) 351 else: 352 self.jid=None 353 if actor: 354 self.actor=JID(actor) 355 else: 356 self.actor=None 357 self.nick=nick 358 self.reason=reason
359
360 - def __from_xmlnode(self, xmlnode):
361 """Initialize a `MucItem` object from an XML node. 362 363 :Parameters: 364 - `xmlnode`: the XML node. 365 :Types: 366 - `xmlnode`: `libxml2.xmlNode` 367 """ 368 actor=None 369 reason=None 370 n=xmlnode.children 371 while n: 372 ns=n.ns() 373 if ns and ns.getContent()!=MUC_USER_NS: 374 continue 375 if n.name=="actor": 376 actor=n.getContent() 377 if n.name=="reason": 378 reason=n.getContent() 379 n=n.next 380 self.__init( 381 from_utf8(xmlnode.prop("affiliation")), 382 from_utf8(xmlnode.prop("role")), 383 from_utf8(xmlnode.prop("jid")), 384 from_utf8(xmlnode.prop("nick")), 385 from_utf8(actor), 386 from_utf8(reason), 387 );
388
389 - def as_xml(self,parent):
390 """ 391 Create XML representation of `self`. 392 393 :Parameters: 394 - `parent`: the element to which the created node should be linked to. 395 :Types: 396 - `parent`: `libxml2.xmlNode` 397 398 :return: an XML node. 399 :returntype: `libxml2.xmlNode` 400 """ 401 n=parent.newChild(None,"item",None) 402 if self.actor: 403 n.newTextChild(None,"actor",to_utf8(self.actor)) 404 if self.reason: 405 n.newTextChild(None,"reason",to_utf8(self.reason)) 406 n.setProp("affiliation",to_utf8(self.affiliation)) 407 if self.role: 408 n.setProp("role",to_utf8(self.role)) 409 if self.jid: 410 n.setProp("jid",to_utf8(self.jid.as_unicode())) 411 if self.nick: 412 n.setProp("nick",to_utf8(self.nick)) 413 return n
414
415 -class MucStatus(MucItemBase):
416 """ 417 MUC <item/> element - describes special meaning of a stanza 418 419 :Ivariables: 420 - `code`: staus code, as defined in JEP 45 421 :Types: 422 - `code`: `int` 423 """
424 - def __init__(self,xmlnode_or_code):
425 """Initialize a `MucStatus` element. 426 427 :Parameters: 428 - `xmlnode_or_code`: XML node to parse or a status code. 429 :Types: 430 - `xmlnode_or_code`: `libxml2.xmlNode` or `int` 431 """ 432 self.code=None 433 MucItemBase.__init__(self) 434 if isinstance(xmlnode_or_code,libxml2.xmlNode): 435 self.__from_xmlnode(xmlnode_or_code) 436 else: 437 self.__init(xmlnode_or_code)
438
439 - def __init(self,code):
440 """Initialize a `MucStatus` element from a status code. 441 442 :Parameters: 443 - `code`: the status code. 444 :Types: 445 - `code`: `int` 446 """ 447 code=int(code) 448 if code<0 or code>999: 449 raise ValueError,"Bad status code" 450 self.code=code
451
452 - def __from_xmlnode(self, xmlnode):
453 """Initialize a `MucStatus` element from an XML node. 454 455 :Parameters: 456 - `xmlnode`: XML node to parse. 457 :Types: 458 - `xmlnode`: `libxml2.xmlNode` 459 """ 460 self.code=int(xmlnode.prop("code"))
461
462 - def as_xml(self,parent):
463 """ 464 Create XML representation of `self`. 465 466 :Parameters: 467 - `parent`: the element to which the created node should be linked to. 468 :Types: 469 - `parent`: `libxml2.xmlNode` 470 471 :return: an XML node. 472 :returntype: `libxml2.xmlNode` 473 """ 474 n=parent.newChild(None,"status",None) 475 n.setProp("code","%03i" % (self.code,)) 476 return n
477
478 -class MucUserX(MucXBase):
479 """ 480 Wrapper for http://www.jabber.org/protocol/muc#user namespaced 481 stanza payload "x" elements and usually containing information 482 about a room user. 483 484 :Ivariables: 485 - `xmlnode`: wrapped XML node 486 :Types: 487 - `xmlnode`: `libxml2.xmlNode` 488 """ 489 ns=MUC_USER_NS
490 - def get_items(self):
491 """Get a list of objects describing the content of `self`. 492 493 :return: the list of objects. 494 :returntype: `list` of `MucItemBase` (`MucItem` and/or `MucStatus`) 495 """ 496 if not self.xmlnode.children: 497 return [] 498 ret=[] 499 n=self.xmlnode.children 500 while n: 501 ns=n.ns() 502 if ns and ns.getContent()!=self.ns: 503 pass 504 elif n.name=="item": 505 ret.append(MucItem(n)) 506 elif n.name=="status": 507 ret.append(MucStatus(n)) 508 # FIXME: alt,decline,invite,password 509 n=n.next 510 return ret
511 - def clear(self):
512 """ 513 Clear the content of `self.xmlnode` removing all <item/>, <status/>, etc. 514 """ 515 if not self.xmlnode.children: 516 return 517 n=self.xmlnode.children 518 while n: 519 ns=n.ns() 520 if ns and ns.getContent()!=MUC_USER_NS: 521 pass 522 else: 523 n.unlinkNode() 524 n.freeNode() 525 n=n.next
526 - def add_item(self,item):
527 """Add an item to `self`. 528 529 :Parameters: 530 - `item`: the item to add. 531 :Types: 532 - `item`: `MucItemBase` 533 """ 534 if not isinstance(item,MucItemBase): 535 raise TypeError,"Bad item type for muc#user" 536 item.as_xml(self.xmlnode)
537
538 -class MucOwnerX(MucXBase):
539 """ 540 Wrapper for http://www.jabber.org/protocol/muc#owner namespaced 541 stanza payload "x" elements and usually containing information 542 about a room user. 543 544 :Ivariables: 545 - `xmlnode`: wrapped XML node. 546 :Types: 547 - `xmlnode`: `libxml2.xmlNode` 548 """ 549 # FIXME: implement 550 pass
551
552 -class MucAdminQuery(MucUserX):
553 """ 554 Wrapper for http://www.jabber.org/protocol/muc#admin namespaced 555 IQ stanza payload "query" elements and usually describing 556 administrative actions or their results. 557 558 Not implemented yet. 559 """ 560 ns=MUC_ADMIN_NS 561 element="query"
562
563 -class MucStanzaExt:
564 """ 565 Base class for MUC specific stanza extensions. Used together 566 with one of stanza classes (Iq, Message or Presence). 567 """
568 - def __init__(self):
569 """Initialize a `MucStanzaExt` derived object.""" 570 if self.__class__ is MucStanzaExt: 571 raise RuntimeError,"Abstract class called" 572 self.xmlnode=None 573 self.muc_child=None
574
575 - def get_muc_child(self):
576 """ 577 Get the MUC specific payload element. 578 579 :return: the object describing the stanza payload in MUC namespace. 580 :returntype: `MucX` or `MucUserX` or `MucAdminQuery` or `MucOwnerX` 581 """ 582 if self.muc_child: 583 return self.muc_child 584 if not self.xmlnode.children: 585 return None 586 n=self.xmlnode.children 587 while n: 588 if n.name not in ("x","query"): 589 n=n.next 590 continue 591 ns=n.ns() 592 if not ns: 593 n=n.next 594 continue 595 ns_uri=ns.getContent() 596 if (n.name,ns_uri)==("x",MUC_NS): 597 self.muc_child=MucX(n) 598 return self.muc_child 599 if (n.name,ns_uri)==("x",MUC_USER_NS): 600 self.muc_child=MucUserX(n) 601 return self.muc_child 602 if (n.name,ns_uri)==("query",MUC_ADMIN_NS): 603 self.muc_child=MucAdminQuery(n) 604 return self.muc_child 605 if (n.name,ns_uri)==("query",MUC_OWNER_NS): 606 self.muc_child=MucOwnerX(n) 607 return self.muc_child 608 n=n.next
609
610 - def clear_muc_child(self):
611 """ 612 Remove the MUC specific stanza payload element. 613 """ 614 if self.muc_child: 615 self.muc_child.free_borrowed() 616 self.muc_child=None 617 if not self.xmlnode.children: 618 return 619 n=self.xmlnode.children 620 while n: 621 if n.name not in ("x","query"): 622 n=n.next 623 continue 624 ns=n.ns() 625 if not ns: 626 n=n.next 627 continue 628 ns_uri=ns.getContent() 629 if ns_uri in (MUC_NS,MUC_USER_NS,MUC_ADMIN_NS,MUC_OWNER_NS): 630 n.unlinkNode() 631 n.freeNode() 632 n=n.next
633
634 - def make_muc_userinfo(self):
635 """ 636 Create <x xmlns="...muc#user"/> element in the stanza. 637 638 :return: the element created. 639 :returntype: `MucUserX` 640 """ 641 self.clear_muc_child() 642 self.muc_child=MucUserX(parent=self.xmlnode) 643 return self.muc_child
644
645 - def make_muc_admin_quey(self):
646 """ 647 Create <query xmlns="...muc#admin"/> element in the stanza. 648 649 :return: the element created. 650 :returntype: `MucAdminQuery` 651 """ 652 self.clear_muc_child() 653 self.muc_child=MucAdminQuery(parent=self.xmlnode) 654 return self.muc_child
655
656 - def muc_free(self):
657 """ 658 Free MUC specific data. 659 """ 660 if self.muc_child: 661 self.muc_child.free_borrowed()
662
663 -class MucPresence(Presence,MucStanzaExt):
664 """ 665 Extend `Presence` with MUC related interface. 666 """
667 - def __init__(self, xmlnode=None,from_jid=None,to_jid=None,stanza_type=None,stanza_id=None, 668 show=None,status=None,priority=0,error=None,error_cond=None):
669 """Initialize a `MucPresence` object. 670 671 :Parameters: 672 - `xmlnode`: XML node to_jid be wrapped into the `MucPresence` object 673 or other Presence object to be copied. If not given then new 674 presence stanza is created using following parameters. 675 - `from_jid`: sender JID. 676 - `to_jid`: recipient JID. 677 - `stanza_type`: staza type: one of: None, "available", "unavailable", 678 "subscribe", "subscribed", "unsubscribe", "unsubscribed" or 679 "error". "available" is automaticaly changed to_jid None. 680 - `stanza_id`: stanza id -- value of stanza's "id" attribute 681 - `show`: "show" field of presence stanza. One of: None, "away", 682 "xa", "dnd", "chat". 683 - `status`: descriptive text for the presence stanza. 684 - `priority`: presence priority. 685 - `error_cond`: error condition name. Ignored if `stanza_type` is not "error" 686 :Types: 687 - `xmlnode`: `unicode` or `libxml2.xmlNode` or `pyxmpp.stanza.Stanza` 688 - `from_jid`: `JID` 689 - `to_jid`: `JID` 690 - `stanza_type`: `unicode` 691 - `stanza_id`: `unicode` 692 - `show`: `unicode` 693 - `status`: `unicode` 694 - `priority`: `unicode` 695 - `error_cond`: `unicode`""" 696 MucStanzaExt.__init__(self) 697 Presence.__init__(self,xmlnode,from_jid=from_jid,to_jid=to_jid, 698 stanza_type=stanza_type,stanza_id=stanza_id, 699 show=show,status=status,priority=priority, 700 error=error,error_cond=error_cond)
701
702 - def copy(self):
703 """ 704 Return a copy of `self`. 705 """ 706 return MucPresence(self)
707
708 - def make_join_request(self, password = None, history_maxchars = None, 709 history_maxstanzas = None, history_seconds = None, 710 history_since = None):
711 """ 712 Make the presence stanza a MUC room join request. 713 714 :Parameters: 715 - `password`: password to the room. 716 - `history_maxchars`: limit of the total number of characters in 717 history. 718 - `history_maxstanzas`: limit of the total number of messages in 719 history. 720 - `history_seconds`: send only messages received in the last 721 `seconds` seconds. 722 - `history_since`: Send only the messages received since the 723 dateTime specified (UTC). 724 :Types: 725 - `password`: `unicode` 726 - `history_maxchars`: `int` 727 - `history_maxstanzas`: `int` 728 - `history_seconds`: `int` 729 - `history_since`: `datetime.datetime` 730 """ 731 self.clear_muc_child() 732 self.muc_child=MucX(parent=self.xmlnode) 733 if (history_maxchars is not None or history_maxstanzas is not None 734 or history_seconds is not None or history_since is not None): 735 history = HistoryParameters(history_maxchars, history_maxstanzas, 736 history_seconds, history_since) 737 self.muc_child.set_history(history) 738 if password is not None: 739 self.muc_child.set_password(password)
740
741 - def get_join_info(self):
742 """If `self` is a MUC room join request return the information contained. 743 744 :return: the join request details or `None`. 745 :returntype: `MucX` 746 """ 747 x=self.get_muc_child() 748 if not x: 749 return None 750 if not isinstance(x,MucX): 751 return None 752 return x
753
754 - def free(self):
755 """Free the data associated with this `MucPresence` object.""" 756 self.muc_free() 757 Presence.free(self)
758
759 -class MucIq(Iq,MucStanzaExt):
760 """ 761 Extend `Iq` with MUC related interface. 762 """
763 - def __init__(self,xmlnode=None,from_jid=None,to_jid=None,stanza_type=None,stanza_id=None, 764 error=None,error_cond=None):
765 """Initialize an `Iq` object. 766 767 :Parameters: 768 - `xmlnode`: XML node to_jid be wrapped into the `Iq` object 769 or other Iq object to be copied. If not given then new 770 presence stanza is created using following parameters. 771 - `from_jid`: sender JID. 772 - `to_jid`: recipient JID. 773 - `stanza_type`: staza type: one of: "get", "set", "result" or "error". 774 - `stanza_id`: stanza id -- value of stanza's "id" attribute. If not 775 given, then unique for the session value is generated. 776 - `error_cond`: error condition name. Ignored if `stanza_type` is not "error". 777 :Types: 778 - `xmlnode`: `unicode` or `libxml2.xmlNode` or `Iq` 779 - `from_jid`: `JID` 780 - `to_jid`: `JID` 781 - `stanza_type`: `unicode` 782 - `stanza_id`: `unicode` 783 - `error_cond`: `unicode`""" 784 MucStanzaExt.__init__(self) 785 Iq.__init__(self,xmlnode,from_jid=from_jid,to_jid=to_jid, 786 stanza_type=stanza_type,stanza_id=stanza_id, 787 error=error,error_cond=error_cond)
788
789 - def copy(self):
790 """ Return a copy of `self`. """ 791 return MucIq(self)
792
793 - def make_kick_request(self,nick,reason):
794 """ 795 Make the iq stanza a MUC room participant kick request. 796 797 :Parameters: 798 - `nick`: nickname of user to kick. 799 - `reason`: reason of the kick. 800 :Types: 801 - `nick`: `unicode` 802 - `reason`: `unicode` 803 804 :return: object describing the kick request details. 805 :returntype: `MucItem` 806 """ 807 self.clear_muc_child() 808 self.muc_child=MucAdminQuery(parent=self.xmlnode) 809 item=MucItem("none","none",nick=nick,reason=reason) 810 self.muc_child.add_item(item) 811 return self.muc_child
812
813 - def free(self):
814 """Free the data associated with this `MucIq` object.""" 815 self.muc_free() 816 Iq.free(self)
817 818 # vi: sts=4 et sw=4 819