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