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 __revision__="$Id: muccore.py 648 2006-08-26 20:09:37Z 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
101 if self.xmlnode:
102 self.free()
103
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
114 """
115 Detach the XML node borrowed by `self`.
116 """
117 self.xmlnode=None
118
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
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):
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
203 since = None
204 return HistoryParameters(maxchars, maxstanzas, maxseconds, since)
205
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
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
268 """
269 Base class for <status/> and <item/> element wrappers.
270 """
272 if self.__class__ is MucItemBase:
273 raise RuntimeError,"Abstract class called"
274
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
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
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 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