带有 ejabberd muc 的 sleekxmpp

sleekxmpp with ejabberd muc

我想使用 sleekxmpp 和 ejabberd 制作一个 muc scrit。 我该怎么办?

我试过这个教程来了解吃 sleekxmpp http://sleekxmpp.com/getting_started/echobot.html 但是,ejabberd 面板上的连接用户数一直超过 0

代码:

#!/usr/bin/env python
# -*- coding: utf-8 -*-


import sys
import logging
import getpass
from optparse import OptionParser

import sleekxmpp

# Python versions before 3.0 do not use UTF-8 encoding
# by default. To ensure that Unicode is handled properly
# throughout SleekXMPP, we will set the default encoding
# ourselves to UTF-8.
if sys.version_info < (3, 0):
    reload(sys)
    sys.setdefaultencoding('utf8')
else:
    raw_input = input


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 initialize
        # 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 initial
        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 ('chat', 'normal'):
            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_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
    # to adjust the SSL version used:
    # xmpp.ssl_version = ssl.PROTOCOL_SSLv3

    # If you want to verify the SSL certificates offered by a server:
    # xmpp.ca_certs = "path/to/ca/cert"

    # Connect to the XMPP server and start processing XMPP stanzas.
    if xmpp.connect():
        # If you do not have the dnspython 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(block=True)
        print("Done")
    else:
        print("Unable to connect.")

控制台输出:

DEBUG    Loaded Plugin: RFC 6120: Stream Feature: STARTTLS
DEBUG    Loaded Plugin: RFC 6120: Stream Feature: Resource Binding
DEBUG    Loaded Plugin: RFC 3920: Stream Feature: Start Session
DEBUG    Loaded Plugin: RFC 6121: Stream Feature: Roster Versioning
DEBUG    Loaded Plugin: RFC 6121: Stream Feature: Subscription Pre-Approval
DEBUG    Loaded Plugin: RFC 6120: Stream Feature: SASL
DEBUG    Loaded Plugin: XEP-0030: Service Discovery
DEBUG    Loaded Plugin: XEP-0004: Data Forms
DEBUG    Loaded Plugin: XEP-0082: XMPP Date and Time Profiles
DEBUG    Loaded Plugin: XEP-0131: Stanza Headers and Internet Metadata
DEBUG    Loaded Plugin: XEP-0060: Publish-Subscribe
DEBUG    Loaded Plugin: XEP-0199: XMPP Ping
DEBUG    Connecting to 192.168.1.103:5222
DEBUG    Event triggered: connected
DEBUG     ==== TRANSITION disconnected -> connected
DEBUG    Starting HANDLER THREAD
DEBUG    Loading event runner
DEBUG    SEND (IMMED): <stream:stream to='192.168.1.103' xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:client' xml:lang='en' version='1.0'>
DEBUG    RECV: <stream:stream from="localhost" id="3423333123714766535" xml:lang="en">
WARNING  Legacy XMPP 0.9 protocol detected.
DEBUG    Event triggered: legacy_protocol
DEBUG    RECV: <stream:error xmlns="http://etherx.jabber.org/streams"><host-unknown xmlns="urn:ietf:params:xml:ns:xmpp-streams" /></stream:error>
DEBUG    Event triggered: stream_error
DEBUG    End of stream recieved
DEBUG    reconnecting...
DEBUG    Event triggered: session_end
DEBUG    SEND (IMMED): </stream:stream>
INFO     Waiting for </stream:stream> from server
DEBUG    Event triggered: socket_error
DEBUG    Event triggered: disconnected
DEBUG     ==== TRANSITION connected -> disconnected
DEBUG    connecting...
DEBUG    Waiting 1.98786049338 seconds before connecting.

这是问题所在:

DEBUG    SEND (IMMED): <stream:stream to='192.168.1.103' xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:client' xml:lang='en' version='1.0'>
DEBUG    RECV: <stream:stream from="localhost" id="3423333123714766535" xml:lang="en">
WARNING  Legacy XMPP 0.9 protocol detected.
DEBUG    Event triggered: legacy_protocol
DEBUG    RECV: <stream:error xmlns="http://etherx.jabber.org/streams"><host-unknown xmlns="urn:ietf:params:xml:ns:xmpp-streams" /></stream:error>
DEBUG    Event triggered: stream_error
DEBUG    End of stream recieved

您的客户端正在打开 192.168.1.103 的流,但您收到的响应表明它来自 localhost,然后您收到 host-unknown 错误。 (我假设您输入的 JID 是 echobot@192.168.1.103?)

您的 ejabberd 配置为使用主机名 localhost。在配置文件中将其更改为 192.168.1.103,您将能够使用 "hostname".

进行连接

或者,您可以将 JID 输入为 echobot@localhost,并强制连接使用不同的主机,方法是执行代码中关于 Google 的注释所说的内容:

if xmpp.connect(('192.168.1.103', 5222)):

这适用于当前的 ejabberd 配置。