Merge branch 'docs' into develop
Conflicts: docs/_static/haiku.css docs/_static/header.png docs/conf.py docs/getting_started/muc.rst docs/index.rst examples/muc.py
This commit is contained in:
		
							
								
								
									
										1
									
								
								docs/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								docs/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
_build/*
 | 
			
		||||
							
								
								
									
										35
									
								
								docs/_static/haiku.css
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										35
									
								
								docs/_static/haiku.css
									
									
									
									
										vendored
									
									
								
							@@ -59,9 +59,10 @@ body {
 | 
			
		||||
    margin: auto;
 | 
			
		||||
    padding: 0px;
 | 
			
		||||
    font-family: "Helvetica Neueu", Helvetica, sans-serif;
 | 
			
		||||
    min-width: 59em;
 | 
			
		||||
    min-width: 30em;
 | 
			
		||||
    max-width: 70em;
 | 
			
		||||
    color: #444;
 | 
			
		||||
    text-align: center;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
div.footer {
 | 
			
		||||
@@ -124,21 +125,25 @@ a.headerlink:hover {
 | 
			
		||||
/* basic text elements */
 | 
			
		||||
 | 
			
		||||
div.content {
 | 
			
		||||
    margin: auto;
 | 
			
		||||
    margin-top: 20px;
 | 
			
		||||
    margin-left: 40px;
 | 
			
		||||
    margin-right: 40px;
 | 
			
		||||
    margin-bottom: 50px;
 | 
			
		||||
    font-size: 0.9em;
 | 
			
		||||
    width: 700px;
 | 
			
		||||
    text-align: left;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* heading and navigation */
 | 
			
		||||
 | 
			
		||||
div.header {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    margin: auto;
 | 
			
		||||
    margin-top: 125px;
 | 
			
		||||
    height: 85px;
 | 
			
		||||
    padding: 0 40px;
 | 
			
		||||
    font-family: "Yanone Kaffeesatz";
 | 
			
		||||
    text-align: left;
 | 
			
		||||
    width: 750px;
 | 
			
		||||
}
 | 
			
		||||
div.header h1 {
 | 
			
		||||
    font-size: 2.6em;
 | 
			
		||||
@@ -185,12 +190,12 @@ div.topnav {
 | 
			
		||||
    z-index: 0;
 | 
			
		||||
}
 | 
			
		||||
div.topnav p {
 | 
			
		||||
    margin: auto;
 | 
			
		||||
    margin-top: 0;
 | 
			
		||||
    margin-left: 40px;
 | 
			
		||||
    margin-right: 40px;
 | 
			
		||||
    margin-bottom: 0px;
 | 
			
		||||
    text-align: right;
 | 
			
		||||
    font-size: 0.8em;
 | 
			
		||||
    width: 750px;
 | 
			
		||||
}
 | 
			
		||||
div.bottomnav {
 | 
			
		||||
    background: #eeeeee;
 | 
			
		||||
@@ -404,3 +409,23 @@ div.viewcode-block:target {
 | 
			
		||||
    padding: 0 12px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#from_andyet {
 | 
			
		||||
    -webkit-box-shadow: #CCC 0px 0px 3px;
 | 
			
		||||
    background: rgba(255, 255, 255, 1);
 | 
			
		||||
    bottom: 0px;
 | 
			
		||||
    right: 17px;
 | 
			
		||||
    padding: 3px 10px;
 | 
			
		||||
    position: fixed;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#from_andyet h2 {
 | 
			
		||||
    background-image: url("images/from_&yet.png");
 | 
			
		||||
    background-repeat: no-repeat;
 | 
			
		||||
    height: 29px;
 | 
			
		||||
    line-height: 0;
 | 
			
		||||
    text-indent: -9999em;
 | 
			
		||||
    width: 79px;
 | 
			
		||||
    margin-top: 0;
 | 
			
		||||
    margin: 0px;
 | 
			
		||||
    padding: 0px;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								docs/_static/images/from_&yet.png
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								docs/_static/images/from_&yet.png
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 2.7 KiB  | 
							
								
								
									
										70
									
								
								docs/_static/pygments.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								docs/_static/pygments.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,70 @@
 | 
			
		||||
.highlight .hll { background-color: #ffffcc }
 | 
			
		||||
.highlight  { background: #000000; color: #f6f3e8; }
 | 
			
		||||
.highlight .c { color: #7C7C7C; } /* Comment */
 | 
			
		||||
.highlight .err { color: #f6f3e8; } /* Error */
 | 
			
		||||
.highlight .g { color: #f6f3e8; } /* Generic */
 | 
			
		||||
.highlight .k { color: #00ADEE; } /* Keyword */
 | 
			
		||||
.highlight .l { color: #f6f3e8; } /* Literal */
 | 
			
		||||
.highlight .n { color: #f6f3e8; } /* Name */
 | 
			
		||||
.highlight .o { color: #f6f3e8; } /* Operator */
 | 
			
		||||
.highlight .x { color: #f6f3e8; } /* Other */
 | 
			
		||||
.highlight .p { color: #f6f3e8; } /* Punctuation */
 | 
			
		||||
.highlight .cm { color: #7C7C7C; } /* Comment.Multiline */
 | 
			
		||||
.highlight .cp { color: #96CBFE; } /* Comment.Preproc */
 | 
			
		||||
.highlight .c1 { color: #7C7C7C; } /* Comment.Single */
 | 
			
		||||
.highlight .cs { color: #7C7C7C; } /* Comment.Special */
 | 
			
		||||
.highlight .gd { color: #f6f3e8; } /* Generic.Deleted */
 | 
			
		||||
.highlight .ge { color: #f6f3e8; } /* Generic.Emph */
 | 
			
		||||
.highlight .gr { color: #ffffff; background-color: #ff0000 } /* Generic.Error */
 | 
			
		||||
.highlight .gh { color: #f6f3e8; font-weight: bold; } /* Generic.Heading */
 | 
			
		||||
.highlight .gi { color: #f6f3e8; } /* Generic.Inserted */
 | 
			
		||||
.highlight .go { color: #070707; } /* Generic.Output */
 | 
			
		||||
.highlight .gp { color: #f6f3e8; } /* Generic.Prompt */
 | 
			
		||||
.highlight .gs { color: #f6f3e8; } /* Generic.Strong */
 | 
			
		||||
.highlight .gu { color: #f6f3e8; font-weight: bold; } /* Generic.Subheading */
 | 
			
		||||
.highlight .gt { color: #ffffff; font-weight: bold; background-color: #FF6C60 } /* Generic.Traceback */
 | 
			
		||||
.highlight .kc { color: #6699CC; } /* Keyword.Constant */
 | 
			
		||||
.highlight .kd { color: #6699CC; } /* Keyword.Declaration */
 | 
			
		||||
.highlight .kn { color: #6699CC; } /* Keyword.Namespace */
 | 
			
		||||
.highlight .kp { color: #6699CC; } /* Keyword.Pseudo */
 | 
			
		||||
.highlight .kr { color: #6699CC; } /* Keyword.Reserved */
 | 
			
		||||
.highlight .kt { color: #FFFFB6; } /* Keyword.Type */
 | 
			
		||||
.highlight .ld { color: #f6f3e8; } /* Literal.Date */
 | 
			
		||||
.highlight .m { color: #FF73FD; } /* Literal.Number */
 | 
			
		||||
.highlight .s { color: #F46DBA;/*#A8FF60;*/ } /* Literal.String */
 | 
			
		||||
.highlight .na { color: #f6f3e8; } /* Name.Attribute */
 | 
			
		||||
.highlight .nb { color: #f6f3e8; } /* Name.Builtin */
 | 
			
		||||
.highlight .nc { color: #f6f3e8; } /* Name.Class */
 | 
			
		||||
.highlight .no { color: #99CC99; } /* Name.Constant */
 | 
			
		||||
.highlight .nd { color: #f6f3e8; } /* Name.Decorator */
 | 
			
		||||
.highlight .ni { color: #E18964; } /* Name.Entity */
 | 
			
		||||
.highlight .ne { color: #f6f3e8; } /* Name.Exception */
 | 
			
		||||
.highlight .nf { color: #F64DBA; } /* Name.Function */
 | 
			
		||||
.highlight .nl { color: #f6f3e8; } /* Name.Label */
 | 
			
		||||
.highlight .nn { color: #f6f3e8; } /* Name.Namespace */
 | 
			
		||||
.highlight .nx { color: #f6f3e8; } /* Name.Other */
 | 
			
		||||
.highlight .py { color: #f6f3e8; } /* Name.Property */
 | 
			
		||||
.highlight .nt { color: #00ADEE; } /* Name.Tag */
 | 
			
		||||
.highlight .nv { color: #C6C5FE; } /* Name.Variable */
 | 
			
		||||
.highlight .ow { color: #ffffff; } /* Operator.Word */
 | 
			
		||||
.highlight .w { color: #f6f3e8; } /* Text.Whitespace */
 | 
			
		||||
.highlight .mf { color: #FF73FD; } /* Literal.Number.Float */
 | 
			
		||||
.highlight .mh { color: #FF73FD; } /* Literal.Number.Hex */
 | 
			
		||||
.highlight .mi { color: #FF73FD; } /* Literal.Number.Integer */
 | 
			
		||||
.highlight .mo { color: #FF73FD; } /* Literal.Number.Oct */
 | 
			
		||||
.highlight .sb { color: #A8FF60; } /* Literal.String.Backtick */
 | 
			
		||||
.highlight .sc { color: #A8FF60; } /* Literal.String.Char */
 | 
			
		||||
.highlight .sd { color: #A8FF60; } /* Literal.String.Doc */
 | 
			
		||||
.highlight .s2 { color: #A8FF60; } /* Literal.String.Double */
 | 
			
		||||
.highlight .se { color: #A8FF60; } /* Literal.String.Escape */
 | 
			
		||||
.highlight .sh { color: #A8FF60; } /* Literal.String.Heredoc */
 | 
			
		||||
.highlight .si { color: #A8FF60; } /* Literal.String.Interpol */
 | 
			
		||||
.highlight .sx { color: #A8FF60; } /* Literal.String.Other */
 | 
			
		||||
.highlight .sr { color: #A8FF60; } /* Literal.String.Regex */
 | 
			
		||||
.highlight .s1 { color: #A8FF60; } /* Literal.String.Single */
 | 
			
		||||
.highlight .ss { color: #A8FF60; } /* Literal.String.Symbol */
 | 
			
		||||
.highlight .bp { color: #f6f3e8; } /* Name.Builtin.Pseudo */
 | 
			
		||||
.highlight .vc { color: #C6C5FE; } /* Name.Variable.Class */
 | 
			
		||||
.highlight .vg { color: #C6C5FE; } /* Name.Variable.Global */
 | 
			
		||||
.highlight .vi { color: #C6C5FE; } /* Name.Variable.Instance */
 | 
			
		||||
.highlight .il { color: #FF73FD; } /* Literal.Number.Integer.Long */
 | 
			
		||||
							
								
								
									
										70
									
								
								docs/_templates/layout.html
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								docs/_templates/layout.html
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,70 @@
 | 
			
		||||
{#
 | 
			
		||||
    haiku/layout.html
 | 
			
		||||
    ~~~~~~~~~~~~~~~~~
 | 
			
		||||
 | 
			
		||||
    Sphinx layout template for the haiku theme.
 | 
			
		||||
 | 
			
		||||
    :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
 | 
			
		||||
    :license: BSD, see LICENSE for details.
 | 
			
		||||
#}
 | 
			
		||||
{% extends "basic/layout.html" %}
 | 
			
		||||
{% set script_files = script_files + ['_static/theme_extras.js'] %}
 | 
			
		||||
{% set css_files = css_files + ['_static/print.css'] %}
 | 
			
		||||
 | 
			
		||||
{# do not display relbars #}
 | 
			
		||||
{% block relbar1 %}{% endblock %}
 | 
			
		||||
{% block relbar2 %}{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% macro nav() %}
 | 
			
		||||
        <p>
 | 
			
		||||
        {%- block haikurel1 %}
 | 
			
		||||
        {%- endblock %}
 | 
			
		||||
        {%- if prev %}
 | 
			
		||||
        «  <a href="{{ prev.link|e }}">{{ prev.title }}</a>
 | 
			
		||||
          ::  
 | 
			
		||||
        {%- endif %}
 | 
			
		||||
        <a class="uplink" href="{{ pathto(master_doc) }}">{{ _('Contents') }}</a>
 | 
			
		||||
        {%- if next %}
 | 
			
		||||
          ::  
 | 
			
		||||
        <a href="{{ next.link|e }}">{{ next.title }}</a>  »
 | 
			
		||||
        {%- endif %}
 | 
			
		||||
        {%- block haikurel2 %}
 | 
			
		||||
        {%- endblock %}
 | 
			
		||||
        </p>
 | 
			
		||||
{% endmacro %}
 | 
			
		||||
 | 
			
		||||
{% block content %}
 | 
			
		||||
      <div class="header">
 | 
			
		||||
        {%- block haikuheader %}
 | 
			
		||||
        {%- if theme_full_logo != "false" %}
 | 
			
		||||
        <a href="{{ pathto('index') }}">
 | 
			
		||||
          <img class="logo" src="{{ pathto('_static/' + logo, 1) }}" alt="Logo"/>
 | 
			
		||||
        </a>
 | 
			
		||||
        {%- else %}
 | 
			
		||||
        {%- if logo -%}
 | 
			
		||||
          <img class="rightlogo" src="{{ pathto('_static/' + logo, 1) }}" alt="Logo"/>
 | 
			
		||||
        {%- endif -%}
 | 
			
		||||
        <h1 class="heading"><a href="{{ pathto('index') }}">
 | 
			
		||||
          <span>{{ title|striptags }}</span></a></h1>
 | 
			
		||||
        <h2 class="heading"><span>{{ shorttitle|e }}</span></h2>
 | 
			
		||||
        {%- endif %}
 | 
			
		||||
        {%- endblock %}
 | 
			
		||||
      </div>
 | 
			
		||||
      <div class="topnav">
 | 
			
		||||
      {{ nav() }}
 | 
			
		||||
      </div>
 | 
			
		||||
      <div class="content">
 | 
			
		||||
        {#{%- if display_toc %}
 | 
			
		||||
        <div id="toc">
 | 
			
		||||
          <h3>Table Of Contents</h3>
 | 
			
		||||
          {{ toc }}
 | 
			
		||||
        </div>
 | 
			
		||||
        {%- endif %}#}
 | 
			
		||||
        {% block body %}{% endblock %}
 | 
			
		||||
      </div>
 | 
			
		||||
      <div class="bottomnav">
 | 
			
		||||
      {{ nav() }}
 | 
			
		||||
      </div>
 | 
			
		||||
      <a id="from_andyet" href="http://andyet.net"><h2>From &yet</h2></a>
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
@@ -50,7 +50,7 @@ copyright = u'2011, Nathan Fritz, Lance Stout'
 | 
			
		||||
# The short X.Y version.
 | 
			
		||||
version = '1.0'
 | 
			
		||||
# The full version, including alpha/beta/rc tags.
 | 
			
		||||
release = '1.0RC3'
 | 
			
		||||
release = '1.0'
 | 
			
		||||
 | 
			
		||||
# The language for content autogenerated by Sphinx. Refer to documentation
 | 
			
		||||
# for a list of supported languages.
 | 
			
		||||
@@ -91,7 +91,7 @@ pygments_style = 'tango'
 | 
			
		||||
 | 
			
		||||
# The theme to use for HTML and HTML Help pages.  See the documentation for
 | 
			
		||||
# a list of builtin themes.
 | 
			
		||||
html_theme = 'nature'
 | 
			
		||||
html_theme = 'haiku'
 | 
			
		||||
 | 
			
		||||
# Theme options are theme-specific and customize the look and feel of a theme
 | 
			
		||||
# further.  For a list of options available for each theme, see the
 | 
			
		||||
 
 | 
			
		||||
@@ -1,2 +1,208 @@
 | 
			
		||||
.. _mucbot:
 | 
			
		||||
 | 
			
		||||
=========================
 | 
			
		||||
Mulit-User Chat (MUC) Bot
 | 
			
		||||
=========================
 | 
			
		||||
 | 
			
		||||
.. note::
 | 
			
		||||
 | 
			
		||||
    If you have any issues working through this quickstart guide
 | 
			
		||||
    or the other tutorials here, please either send a message to the
 | 
			
		||||
    `mailing list <http://groups.google.com/group/sleekxmpp-discussion>`_
 | 
			
		||||
    or join the chat room at `sleek@conference.jabber.org
 | 
			
		||||
    <xmpp:sleek@conference.jabber.org?join>`_.
 | 
			
		||||
 | 
			
		||||
If you have not yet installed SleekXMPP, do so now by either checking out a version
 | 
			
		||||
from `Github <http://github.com/fritzy/SleekXMPP>`_, or installing it using ``pip``
 | 
			
		||||
or ``easy_install``.
 | 
			
		||||
 | 
			
		||||
.. code-block:: sh
 | 
			
		||||
 | 
			
		||||
    pip install sleekxmpp  # Or: easy_install sleekxmpp
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Now that you've got the basic gist of using SleekXMPP by following the
 | 
			
		||||
echobot example (:ref:`echobot`), we can use one of the bundled plugins
 | 
			
		||||
to create a very popular XMPP starter project: a `Multi-User Chat`_
 | 
			
		||||
(MUC) bot. Our bot will login to an XMPP server, join an MUC chat room
 | 
			
		||||
and "lurk" indefinitely, responding with a generic message to anyone
 | 
			
		||||
that mentions its nickname. It will also greet members as they join the
 | 
			
		||||
chat room.
 | 
			
		||||
 | 
			
		||||
.. _`multi-user chat`: http://xmpp.org/extensions/xep-0045.html
 | 
			
		||||
 | 
			
		||||
Joining The Room
 | 
			
		||||
----------------
 | 
			
		||||
 | 
			
		||||
As usual, our code will be based on the pattern explained in :ref:`echobot`.
 | 
			
		||||
To start, we create an ``MUCBot`` class based on
 | 
			
		||||
:class:`ClientXMPP <sleekxmpp.clientxmpp.ClientXMPP>` and which accepts
 | 
			
		||||
parameters for the JID of the MUC room to join, and the nick that the
 | 
			
		||||
bot will use inside the chat room.  We also register an
 | 
			
		||||
:term:`event handler` for the :term:`session_start` event.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
 | 
			
		||||
    import sleekxmpp
 | 
			
		||||
 | 
			
		||||
    class MUCBot(sleekxmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
        def __init__(self, jid, password, room, nick):
 | 
			
		||||
            sleekxmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
 | 
			
		||||
            self.room = room
 | 
			
		||||
            self.nick = nick
 | 
			
		||||
 | 
			
		||||
            self.add_event_handler("session_start", self.start)
 | 
			
		||||
 | 
			
		||||
After initialization, we also need to register the MUC (XEP-0045) plugin
 | 
			
		||||
so that we can make use of the group chat plugin's methods and events.
 | 
			
		||||
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
 | 
			
		||||
    xmpp.register_plugin('xep_0045')
 | 
			
		||||
 | 
			
		||||
Finally, we can make our bot join the chat room once an XMPP session
 | 
			
		||||
has been established:
 | 
			
		||||
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
 | 
			
		||||
    def start(self, event):
 | 
			
		||||
        self.get_roster()
 | 
			
		||||
        self.send_presence()
 | 
			
		||||
        self.plugin['xep_0045'].joinMUC(self.room,
 | 
			
		||||
                                        self.nick,
 | 
			
		||||
                                        wait=True)
 | 
			
		||||
 | 
			
		||||
Note that as in :ref:`echobot`, we need to include send an initial presence and request
 | 
			
		||||
the roster. Next, we want to join the group chat, so we call the
 | 
			
		||||
``joinMUC`` method of the MUC plugin.
 | 
			
		||||
 | 
			
		||||
.. note::
 | 
			
		||||
 | 
			
		||||
    The :attr:`plugin <sleekxmpp.basexmpp.BaseXMPP.plugin>` attribute is
 | 
			
		||||
    dictionary that maps to instances of plugins that we have previously
 | 
			
		||||
    registered, by their names.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Adding Functionality
 | 
			
		||||
--------------------
 | 
			
		||||
 | 
			
		||||
Currently, our bot just sits dormantly inside the chat room, but we
 | 
			
		||||
would like it to respond to two distinct events by issuing a generic
 | 
			
		||||
message in each case to the chat room. In particular, when a member
 | 
			
		||||
mentions the bot's nickname inside the chat room, and when a member
 | 
			
		||||
joins the chat room.
 | 
			
		||||
 | 
			
		||||
Responding to Mentions
 | 
			
		||||
~~~~~~~~~~~~~~~~~~~~~~
 | 
			
		||||
 | 
			
		||||
Whenever a user mentions our bot's nickname in chat, our bot will
 | 
			
		||||
respond with a generic message resembling *"I heard that, user."* We do
 | 
			
		||||
this by examining all of the messages sent inside the chat and looking
 | 
			
		||||
for the ones which contain the nickname string.
 | 
			
		||||
 | 
			
		||||
First, we register an event handler for the :term:`groupchat_message`
 | 
			
		||||
event inside the bot's ``__init__`` function.
 | 
			
		||||
 | 
			
		||||
.. note::
 | 
			
		||||
 | 
			
		||||
    We do not register a handler for the :term:`message` event in this
 | 
			
		||||
    bot, but if we did, the group chat message would have been sent to
 | 
			
		||||
    both handlers.
 | 
			
		||||
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
 | 
			
		||||
    def __init__(self, jid, password, room, nick):
 | 
			
		||||
        sleekxmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
 | 
			
		||||
        self.room = room
 | 
			
		||||
        self.nick = nick
 | 
			
		||||
 | 
			
		||||
        self.add_event_handler("session_start", self.start)
 | 
			
		||||
        self.add_event_handler("groupchat_message", self.muc_message)
 | 
			
		||||
 | 
			
		||||
Then, we can send our generic message whenever the bot's nickname gets
 | 
			
		||||
mentioned.
 | 
			
		||||
 | 
			
		||||
.. warning::
 | 
			
		||||
 | 
			
		||||
    Always check that a message is not from yourself,
 | 
			
		||||
    otherwise you will create an infinite loop responding
 | 
			
		||||
    to your own messages.
 | 
			
		||||
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
 | 
			
		||||
    def muc_message(self, msg):
 | 
			
		||||
        if msg['mucnick'] != self.nick and self.nick in msg['body']:
 | 
			
		||||
            self.send_message(mto=msg['from'].bare,
 | 
			
		||||
                              mbody="I heard that, %s." % msg['mucnick'],
 | 
			
		||||
                              mtype='groupchat')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Greeting Members
 | 
			
		||||
~~~~~~~~~~~~~~~~
 | 
			
		||||
 | 
			
		||||
Now we want to greet member whenever they join the group chat. To
 | 
			
		||||
do this we will use the dynamic ``muc::room@server::got_online`` [1]_
 | 
			
		||||
event so it's a good idea to register an event handler for it.
 | 
			
		||||
 | 
			
		||||
.. note::
 | 
			
		||||
 | 
			
		||||
    The groupchat_presence event is triggered whenever a
 | 
			
		||||
    presence stanza is received from any chat room, including
 | 
			
		||||
    any presences you send yourself. To limit event handling
 | 
			
		||||
    to a single room, use the events ``muc::room@server::presence``,
 | 
			
		||||
    ``muc::room@server::got_online``, or ``muc::room@server::got_offline``.
 | 
			
		||||
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
 | 
			
		||||
    def __init__(self, jid, password, room, nick):
 | 
			
		||||
        sleekxmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
 | 
			
		||||
        self.room = room
 | 
			
		||||
        self.nick = nick
 | 
			
		||||
 | 
			
		||||
        self.add_event_handler("session_start", self.start)
 | 
			
		||||
        self.add_event_handler("groupchat_message", self.muc_message)
 | 
			
		||||
        self.add_event_handler("muc::%s::got_online" % self.room,
 | 
			
		||||
                               self.muc_online)
 | 
			
		||||
 | 
			
		||||
Now all that's left to do is to greet them:
 | 
			
		||||
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
 | 
			
		||||
    def muc_online(self, presence):
 | 
			
		||||
        if presence['muc']['nick'] != self.nick:
 | 
			
		||||
            self.send_message(mto=presence['from'].bare,
 | 
			
		||||
                              mbody="Hello, %s %s" % (presence['muc']['role'],
 | 
			
		||||
                                                      presence['muc']['nick']),
 | 
			
		||||
                              mtype='groupchat')
 | 
			
		||||
 | 
			
		||||
.. [1] this is similar to the :term:`got_online` event and is sent by
 | 
			
		||||
       the xep_0045 plugin whenever a member joins the referenced
 | 
			
		||||
       MUC chat room.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Final Product
 | 
			
		||||
-------------
 | 
			
		||||
 | 
			
		||||
.. compound::
 | 
			
		||||
 | 
			
		||||
    The final step is to create a small runner script for initialising our ``MUCBot`` class and adding some
 | 
			
		||||
    basic configuration options. By following the basic boilerplate pattern in :ref:`echobot`, we arrive
 | 
			
		||||
    at the code below. To experiment with this example, you can use:
 | 
			
		||||
 | 
			
		||||
    .. code-block:: sh
 | 
			
		||||
 | 
			
		||||
            python muc.py -d -j jid@example.com -r room@muc.example.net -n lurkbot
 | 
			
		||||
 | 
			
		||||
    which will prompt for the password, log in, and join the group chat. To test, open
 | 
			
		||||
    your regular IM client and join the same group chat that you sent the bot to. You
 | 
			
		||||
    will see ``lurkbot`` as one of the members in the group chat, and that it greeted
 | 
			
		||||
    you upon entry. Send a message with the string "lurkbot" inside the body text, and you
 | 
			
		||||
    will also see that it responds with our pre-programmed customized message.
 | 
			
		||||
 | 
			
		||||
.. include:: ../../examples/muc.py
 | 
			
		||||
    :literal:
 | 
			
		||||
 
 | 
			
		||||
@@ -59,6 +59,72 @@ SleekXMPP's design goals and philosphy are:
 | 
			
		||||
    sensible defaults and appropriate abstractions. XML can be ugly to work
 | 
			
		||||
    with, but it doesn't have to be that way.
 | 
			
		||||
 | 
			
		||||
Here's your first SleekXMPP Bot:
 | 
			
		||||
--------------------------------
 | 
			
		||||
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
 | 
			
		||||
    import logging
 | 
			
		||||
 | 
			
		||||
    from sleekxmpp import ClientXMPP
 | 
			
		||||
    from sleekxmpp.exceptions import IqError, IqTimeout
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    class EchoBot(ClientXMPP):
 | 
			
		||||
 | 
			
		||||
        def __init__(self, jid, password):
 | 
			
		||||
            ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
 | 
			
		||||
            self.add_event_handler("session_start", self.session_start)
 | 
			
		||||
            self.add_event_handler("message", self.message)
 | 
			
		||||
 | 
			
		||||
            self.register_plugin('xep_0030') # Service Discovery
 | 
			
		||||
            self.register_plugin('xep_0199') # XMPP Ping
 | 
			
		||||
 | 
			
		||||
            # Here's how to access plugins once you've registered them:
 | 
			
		||||
            # self['xep_0030'].add_feature('echodemo')
 | 
			
		||||
            # You can also use self.plugin['xep_0030']
 | 
			
		||||
 | 
			
		||||
            # If you are working with an OpenFire server, you will
 | 
			
		||||
            # need to use a different SSL version:
 | 
			
		||||
            # import ssl
 | 
			
		||||
            # self.ssl_version = ssl.PROTOCOL_SSLv3
 | 
			
		||||
 | 
			
		||||
        def session_start(self, event):
 | 
			
		||||
            self.send_presence()
 | 
			
		||||
            self.get_roster()
 | 
			
		||||
 | 
			
		||||
            # Most get_*/set_* methods from plugins use Iq stanzas, which
 | 
			
		||||
            # can generate IqError and IqTimeout exceptions
 | 
			
		||||
            #
 | 
			
		||||
            # try:
 | 
			
		||||
            #     self.get_roster()
 | 
			
		||||
            # except IqError as err:
 | 
			
		||||
            #     logging.error('There was an error getting the roster')
 | 
			
		||||
            #     logging.error(err.iq['error']['condition'])
 | 
			
		||||
            #     self.disconnect()
 | 
			
		||||
            # except IqTimeout:
 | 
			
		||||
            #     logging.error('Server is taking too long to respond')
 | 
			
		||||
            #     self.disconnect()
 | 
			
		||||
 | 
			
		||||
        def message(self, msg):
 | 
			
		||||
            if msg['type'] in ('chat', 'normal'):
 | 
			
		||||
                msg.reply("Thanks for sending\n%(body)s" % msg).send()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    if __name__ == '__main__':
 | 
			
		||||
        # Ideally use optparse or argparse to get JID, 
 | 
			
		||||
        # password, and log level.
 | 
			
		||||
 | 
			
		||||
        logging.basicConfig(level=logging.DEBUG,
 | 
			
		||||
                            format='%(levelname)-8s %(message)s')
 | 
			
		||||
 | 
			
		||||
        xmpp = EchoBot('somejid@example.com', 'use_getpass')
 | 
			
		||||
        xmpp.connect()
 | 
			
		||||
        xmpp.process(block=True)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Getting Started (with Examples)
 | 
			
		||||
-------------------------------
 | 
			
		||||
.. toctree::
 | 
			
		||||
 
 | 
			
		||||
@@ -76,8 +76,13 @@ class MUCBot(sleekxmpp.ClientXMPP):
 | 
			
		||||
                     event does not provide any additional
 | 
			
		||||
                     data.
 | 
			
		||||
        """
 | 
			
		||||
<<<<<<< HEAD
 | 
			
		||||
        self.getRoster()
 | 
			
		||||
        self.sendPresence()
 | 
			
		||||
=======
 | 
			
		||||
        self.get_roster()
 | 
			
		||||
        self.send_presence()
 | 
			
		||||
>>>>>>> docs
 | 
			
		||||
        self.plugin['xep_0045'].joinMUC(self.room,
 | 
			
		||||
                                        self.nick,
 | 
			
		||||
                                        # If a room password is needed, use:
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user