1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
100 if self.xmlnode:
101 self.free()
102
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
113 """
114 Detach the XML node borrowed by `self`.
115 """
116 self.xmlnode=None
117
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
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):
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
202 since = None
203 return HistoryParameters(maxchars, maxstanzas, maxseconds, since)
204
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
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
267 """
268 Base class for <status/> and <item/> element wrappers.
269 """
271 if self.__class__ is MucItemBase:
272 raise RuntimeError,"Abstract class called"
273
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
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
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
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 """
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
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
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
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
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
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
508 n=n.next
509 return ret
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
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
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
549 pass
550
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
563 """
564 Base class for MUC specific stanza extensions. Used together
565 with one of stanza classes (Iq, Message or Presence).
566 """
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
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
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
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
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
656 """
657 Free MUC specific data.
658 """
659 if self.muc_child:
660 self.muc_child.free_borrowed()
661
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
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
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
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
789 """ Return a copy of `self`. """
790 return MucIq(self)
791
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
813 """Free the data associated with this `MucIq` object."""
814 self.muc_free()
815 Iq.free(self)
816
817
818