mirror of
https://github.com/correl/SleekXMPP.git
synced 2024-11-27 19:19:54 +00:00
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:
commit
72e1ab47fc
9 changed files with 450 additions and 7 deletions
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:
|
||||
|
|
Loading…
Reference in a new issue