Add guide for sending a message and then disconnecting.

This commit is contained in:
Lance Stout 2011-08-17 21:21:37 -07:00
parent 01061a0355
commit 961668d420
8 changed files with 146 additions and 162 deletions

8
docs/api/basexmpp.rst Normal file
View file

@ -0,0 +1,8 @@
========
basexmpp
========
.. module:: sleekxmpp.basexmpp
.. autoclass:: BaseXMPP
:members:

8
docs/api/xmlstream.rst Normal file
View file

@ -0,0 +1,8 @@
=========
xmlstream
=========
.. module:: sleekxmpp.xmlstream
.. autoclass:: XMLStream
:members:

2
docs/features.rst Normal file
View file

@ -0,0 +1,2 @@
How to Use Stream Features
==========================

View file

@ -1,3 +1,5 @@
.. _echobot:
===============================
SleekXMPP Quickstart - Echo Bot
===============================
@ -386,127 +388,3 @@ can also be found in the SleekXMPP `examples directory <http://github.com/fritzy
.. include:: ../../examples/echo_client.py
:literal:
..
.. #!/usr/bin/env python
.. # -*- coding: utf-8 -*-
.. import sys
.. import logging
.. import time
.. import getpass
.. from optparse import OptionParser
..
.. import sleekxmpp
..
..
.. class EchoBot(sleekxmpp.ClientXMPP):
..
.. """
.. A simple SleekXMPP bot that will echo messages it
.. receives, along with a short thank you message.
.. """
..
.. def __init__(self, jid, password):
.. sleekxmpp.ClientXMPP.__init__(self, jid, password)
..
.. # The session_start event will be triggered when
.. # the bot establishes its connection with the server
.. # and the XML streams are ready for use. We want to
.. # listen for this event so that we we can intialize
.. # our roster.
.. self.add_event_handler("session_start", self.start)
..
.. # The message event is triggered whenever a message
.. # stanza is received. Be aware that that includes
.. # MUC messages and error messages.
.. self.add_event_handler("message", self.message)
..
.. def start(self, event):
.. """
.. Process the session_start event.
..
.. Typical actions for the session_start event are
.. requesting the roster and broadcasting an intial
.. presence stanza.
..
.. Arguments:
.. event -- An empty dictionary. The session_start
.. event does not provide any additional
.. data.
.. """
.. self.send_presence()
.. self.get_roster()
..
.. def message(self, msg):
.. """
.. Process incoming message stanzas. Be aware that this also
.. includes MUC messages and error messages. It is usually
.. a good idea to check the messages's type before processing
.. or sending replies.
..
.. Arguments:
.. msg -- The received message stanza. See the documentation
.. for stanza objects and the Message stanza to see
.. how it may be used.
.. """
.. if msg['type'] in ('normal', 'chat'):
.. msg.reply("Thanks for sending\n%(body)s" % msg).send()
..
..
.. if __name__ == '__main__':
.. # Setup the command line arguments.
.. optp = OptionParser()
..
.. # Output verbosity options.
.. optp.add_option('-q', '--quiet', help='set logging to ERROR',
.. action='store_const', dest='loglevel',
.. const=logging.ERROR, default=logging.INFO)
.. optp.add_option('-d', '--debug', help='set logging to DEBUG',
.. action='store_const', dest='loglevel',
.. const=logging.DEBUG, default=logging.INFO)
.. optp.add_option('-v', '--verbose', help='set logging to COMM',
.. action='store_const', dest='loglevel',
.. const=5, default=logging.INFO)
..
.. # JID and password options.
.. optp.add_option("-j", "--jid", dest="jid",
.. help="JID to use")
.. optp.add_option("-p", "--password", dest="password",
.. help="password to use")
..
.. opts, args = optp.parse_args()
..
.. # Setup logging.
.. logging.basicConfig(level=opts.loglevel,
.. format='%(levelname)-8s %(message)s')
..
.. if opts.jid is None:
.. opts.jid = raw_input("Username: ")
.. if opts.password is None:
.. opts.password = getpass.getpass("Password: ")
..
.. # Setup the EchoBot and register plugins. Note that while plugins may
.. # have interdependencies, the order in which you register them does
.. # not matter.
.. xmpp = EchoBot(opts.jid, opts.password)
.. xmpp.register_plugin('xep_0030') # Service Discovery
.. xmpp.register_plugin('xep_0199') # XMPP Ping
..
.. # If you are working with an OpenFire server, you may need
.. # to adjust the SSL version used:
.. # xmpp.ssl_version = ssl.PROTOCOL_SSLv3
..
.. # Connect to the XMPP server and start processing XMPP stanzas.
.. if xmpp.connect():
.. # If you do not have the pydns library installed, you will need
.. # to manually specify the name of the server if it does not match
.. # the one in the JID. For example, to use Google Talk you would
.. # need to use:
.. #
.. # if xmpp.connect(('talk.google.com', 5222)):
.. # ...
.. xmpp.process(threaded=False)
.. print("Done")
.. else:
.. print("Unable to connect.")

View file

@ -1,5 +1,94 @@
Login, Send a Message, and Disconnect
=====================================
Sign in, Send a Message, and Disconnect
=======================================
.. 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>`_.
A common use case for SleekXMPP is to send one-off messages from
time to time.
time to time. For example, one use case could be sending out a notice when
a shell script finishes a task.
We will create our one-shot bot based on the pattern explained in :ref:`echobot`. To
start, we create a client class based on :class:`ClientXMPP <sleekxmpp.clientxmpp.ClientXMPP>` and
register a handler for the :term:`session_start` event. We will also accept parameters
for the JID that will receive our message, and the string content of the message.
.. code-block:: python
import sleekxmpp
class SendMsgBot(sleekxmpp.ClientXMPP):
def __init__(self, jid, password, recipient, msg):
super(SendMsgBot, self).__init__(jid, password)
self.recipient = recipient
self.msg = msg
self.add_event_handler('session_start', self.start)
def start(self, event):
self.send_presence()
self.get_roster()
Note that as in :ref:`echobot`, we need to include send an initial presence and request
the roster. Next, we want to send our message, and to do that we will use :meth:`send_message <sleekxmpp.basexmpp.BaseXMPP.send_message>`.
.. code-block:: python
def start(self, event):
self.send_presence()
self.get_roster()
self.send_message(mto=self.recipient, mbody=self.msg)
Finally, we need to disconnect the client using :meth:`disconnect <sleekxmpp.xmlstream.XMLStream.disconnect>`.
Now, sent stanzas are placed in a queue to pass them to the send thread. If we were to call
:meth:`disconnect <sleekxmpp.xmlstream.XMLStream.disconnect>` without any parameters, then it is possible
for the client to disconnect before the send queue is processed and the message is actually
sent on the wire. To ensure that our message is processed, we use
:meth:`disconnect(wait=True) <sleekxmpp.xmlstream.XMLStream.disconnect>`.
.. code-block:: python
def start(self, event):
self.send_presence()
self.get_roster()
self.send_message(mto=self.recipient, mbody=self.msg)
self.disconnect(wait=True)
.. warning::
If you happen to be adding stanzas to the send queue faster than the send thread
can process them, then :meth:`disconnect(wait=True) <sleekxmpp.xmlstream.XMLStream.disconnect>`
will block and not disconnect.
Final Product
-------------
.. compound::
The final step is to create a small runner script for initialising our ``SendMsgBot`` 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 send_client.py -d -j oneshot@example.com -t someone@example.net -m "This is a message"
which will prompt for the password and then log in, send your message, and then disconnect. To test, open
your regular IM client with the account you wish to send messages to. When you run the ``send_client.py``
example and instruct it to send your IM client account a message, you should receive the message you
gave. If the two JIDs you use also have a mutual presence subscription (they're on each other's buddy lists)
then you will also see the ``SendMsgBot`` client come online and then go offline.
.. include:: ../../examples/send_client.py
:literal:

View file

@ -67,7 +67,7 @@ SleekXMPP's design goals and philosphy are:
Getting Started (with Examples)
-------------------------------
.. toctree::
:maxdepth: 2
:maxdepth: 1
getting_started/echobot
getting_started/sendlogout
@ -82,27 +82,29 @@ Getting Started (with Examples)
Tutorials, FAQs, and How To Guides
----------------------------------
.. toctree::
:maxdepth: 2
:maxdepth: 1
xeps
xmpp_tdg
create_plugin
features
sasl
handlersmatchers
Plugin Guides
~~~~~~~~~~~~~
.. toctree::
:maxdepth: 2
:maxdepth: 1
guide_xep_0030
SleekXMPP Architecture and Design
---------------------------------
.. toctree::
:maxdepth: 2
:maxdepth: 3
architecture.rst
architecture
plugin_arch
API Reference
-------------
@ -111,6 +113,8 @@ API Reference
event_index
api/clientxmpp
api/basexmpp
api/xmlstream
Additional Info
---------------

2
docs/plugin_arch.rst Normal file
View file

@ -0,0 +1,2 @@
Plugin Architecture
===================

View file

@ -29,13 +29,18 @@ if sys.version_info < (3, 0):
class SendMsgBot(sleekxmpp.ClientXMPP):
"""
A simple SleekXMPP bot that will echo messages it
receives, along with a short thank you message.
A basic SleekXMPP bot that will log in, send a message,
and then log out.
"""
def __init__(self, jid, password):
def __init__(self, jid, password, recipient, message):
sleekxmpp.ClientXMPP.__init__(self, jid, password)
# The message we wish to send, and the JID that
# will receive it.
self.recipient = recipient
self.msg = message
# The session_start event will be triggered when
# the bot establishes its connection with the server
# and the XML streams are ready for use. We want to
@ -43,11 +48,6 @@ class SendMsgBot(sleekxmpp.ClientXMPP):
# our roster.
self.add_event_handler("session_start", self.start)
# The message event is triggered whenever a message
# stanza is received. Be aware that that includes
# MUC messages and error messages.
self.add_event_handler("message", self.message)
def start(self, event):
"""
Process the session_start event.
@ -63,27 +63,14 @@ class SendMsgBot(sleekxmpp.ClientXMPP):
"""
self.send_presence()
self.get_roster()
msg = self.Message()
msg['to'] = 'user@example.com'
msg['type'] = 'chat'
msg['body'] = "Hello there!"
msg.send()
self.disconnect()
def message(self, msg):
"""
Process incoming message stanzas. Be aware that this also
includes MUC messages and error messages. It is usually
a good idea to check the messages's type before processing
or sending replies.
self.send_message(mto=self.recipient,
mbody=self.msg,
mtype='chat')
Arguments:
msg -- The received message stanza. See the documentation
for stanza objects and the Message stanza to see
how it may be used.
"""
#msg.reply("Thanks for sending\n%(body)s" % msg).send()
print "Msg rceived from %(body)s: %(jid)s" % msg
# Using wait=True ensures that the send queue will be
# emptied before ending the session.
self.disconnect(wait=True)
if __name__ == '__main__':
@ -106,6 +93,10 @@ if __name__ == '__main__':
help="JID to use")
optp.add_option("-p", "--password", dest="password",
help="password to use")
optp.add_option("-t", "--to", dest="to",
help="JID to send the message to")
optp.add_option("-m", "--message", dest="message",
help="message to send")
opts, args = optp.parse_args()
@ -117,14 +108,16 @@ if __name__ == '__main__':
opts.jid = raw_input("Username: ")
if opts.password is None:
opts.password = getpass.getpass("Password: ")
if opts.to is None:
opts.to = raw_input("Send To: ")
if opts.message is None:
opts.message = raw_input("Message: ")
# Setup the EchoBot and register plugins. Note that while plugins may
# have interdependencies, the order in which you register them does
# not matter.
xmpp = SendMsgBot(opts.jid, opts.password)
xmpp = SendMsgBot(opts.jid, opts.password, opts.to, opts.message)
xmpp.register_plugin('xep_0030') # Service Discovery
xmpp.register_plugin('xep_0004') # Data Forms
xmpp.register_plugin('xep_0060') # PubSub
xmpp.register_plugin('xep_0199') # XMPP Ping
# If you are working with an OpenFire server, you may need