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 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
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 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
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 """
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
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
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
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
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
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
509 n=n.next
510 return ret
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
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
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
550 pass
551
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
564 """
565 Base class for MUC specific stanza extensions. Used together
566 with one of stanza classes (Iq, Message or Presence).
567 """
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
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
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
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
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
657 """
658 Free MUC specific data.
659 """
660 if self.muc_child:
661 self.muc_child.free_borrowed()
662
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
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
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
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
790 """ Return a copy of `self`. """
791 return MucIq(self)
792
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
814 """Free the data associated with this `MucIq` object."""
815 self.muc_free()
816 Iq.free(self)
817
818
819