Compare commits
1 Commits
slix-1.2.2
...
sleek-merg
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4512248901 |
@@ -1,14 +0,0 @@
|
||||
Contributing to the Slixmpp project
|
||||
===================================
|
||||
|
||||
To contribute, the preferred way is to commit your changes on some
|
||||
publicly-available git repository (on a fork `on github
|
||||
<https://github.com/poezio/slixmpp>`_ or on your own repository) and to
|
||||
notify the developers with either:
|
||||
- a ticket `on the bug tracker <https://dev.poez.io/new>`_
|
||||
- a pull request on github
|
||||
- a simple message on `the XMPP MUC <xmpp:slixmpp@muc.poez.io>`_
|
||||
|
||||
Even though Slixmpp’s github repository is just a read-only mirror, we can
|
||||
still be notified of the pull requests and fetch your mirror manually to
|
||||
integrate your changes.
|
||||
22
README.rst
22
README.rst
@@ -8,15 +8,6 @@ Slixmpp's goals is to only rewrite the core of the library (the low level
|
||||
socket handling, the timers, the events dispatching) in order to remove all
|
||||
threads.
|
||||
|
||||
Building
|
||||
--------
|
||||
|
||||
Slixmpp can make use of cython to improve performance on critical modules.
|
||||
To do that, **cython3** is necessary along with **libidn** headers.
|
||||
Otherwise, no compilation is needed. Building is done by running setup.py::
|
||||
|
||||
python3 setup.py build_ext --inplace
|
||||
|
||||
Documentation and Testing
|
||||
-------------------------
|
||||
Documentation can be found both inline in the code, and as a Sphinx project in ``/docs``.
|
||||
@@ -102,17 +93,8 @@ Slixmpp projects::
|
||||
Slixmpp Credits
|
||||
---------------
|
||||
|
||||
**Maintainers:**
|
||||
- Florent Le Coz (`louiz@louiz.org <xmpp:louiz@louiz.org?message>`_),
|
||||
- Mathieu Pasquet (`mathieui@mathieui.net <xmpp:mathieui@mathieui.net?message>`_),
|
||||
|
||||
**Contributors:**
|
||||
- Emmanuel Gil Peyrot (`Link mauve <xmpp:linkmauve@linkmauve.fr?message>`_)
|
||||
- Sam Whited (`Sam Whited <mailto:sam@samwhited.com>`_)
|
||||
- Dan Sully (`Dan Sully <mailto:daniel@electricalrain.com>`_)
|
||||
- Gasper Zejn (`Gasper Zejn <mailto:zejn@kiberpipa.org>`_)
|
||||
- Krzysztof Kotlenga (`Krzysztof Kotlenga <mailto:pocek@users.sf.net>`_)
|
||||
- Tsukasa Hiiragi (`Tsukasa Hiiragi <mailto:bakalolka@gmail.com>`_)
|
||||
**Maintainer of the slixmpp fork:** Florent Le Coz
|
||||
`louiz@louiz.org <xmpp:louiz@louiz.org?message>`_,
|
||||
|
||||
Credits (SleekXMPP)
|
||||
-------------------
|
||||
|
||||
@@ -48,9 +48,9 @@ copyright = u'2011, Nathan Fritz, Lance Stout'
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '1.1'
|
||||
version = '1.0'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '1.1'
|
||||
release = '1.0'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
||||
@@ -163,7 +163,7 @@ behaviour:
|
||||
namespace = 'jabber:iq:register'
|
||||
name = 'query'
|
||||
plugin_attrib = 'register'
|
||||
interfaces = {'username', 'password', 'registered', 'remove'}
|
||||
interfaces = set(('username', 'password', 'registered', 'remove'))
|
||||
sub_interfaces = interfaces
|
||||
|
||||
def getRegistered(self):
|
||||
@@ -535,10 +535,10 @@ with some additional registration fields implemented.
|
||||
namespace = 'jabber:iq:register'
|
||||
name = 'query'
|
||||
plugin_attrib = 'register'
|
||||
interfaces = {'username', 'password', 'email', 'nick', 'name',
|
||||
'first', 'last', 'address', 'city', 'state', 'zip',
|
||||
'phone', 'url', 'date', 'misc', 'text', 'key',
|
||||
'registered', 'remove', 'instructions'}
|
||||
interfaces = set(('username', 'password', 'email', 'nick', 'name',
|
||||
'first', 'last', 'address', 'city', 'state', 'zip',
|
||||
'phone', 'url', 'date', 'misc', 'text', 'key',
|
||||
'registered', 'remove', 'instructions'))
|
||||
sub_interfaces = interfaces
|
||||
|
||||
def getRegistered(self):
|
||||
|
||||
@@ -259,8 +259,8 @@ Event Index
|
||||
|
||||
Signal that a connection to the XMPP server has been lost and the current
|
||||
stream session has ended. Currently equivalent to :term:`disconnected`, but
|
||||
implementations of `XEP-0198: Stream Management <http://xmpp.org/extensions/xep-0198.html>`_
|
||||
distinguish between the two events.
|
||||
future implementation of `XEP-0198: Stream Management <http://xmpp.org/extensions/xep-0198.html>`_
|
||||
will distinguish the two events.
|
||||
|
||||
Plugins that maintain session-based state should clear themselves when
|
||||
this event is fired.
|
||||
|
||||
@@ -70,7 +70,7 @@ as well.
|
||||
class EchoBot(slixmpp.ClientXMPP):
|
||||
|
||||
def __init__(self, jid, password):
|
||||
super().__init__(jid, password)
|
||||
super(EchoBot, self).__init__(jid, password)
|
||||
|
||||
Handling Session Start
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
@@ -83,7 +83,7 @@ started. To do that, we will register an event handler for the :term:`session_st
|
||||
.. code-block:: python
|
||||
|
||||
def __init__(self, jid, password):
|
||||
super().__init__(jid, password)
|
||||
super(EchoBot, self).__init__(jid, password)
|
||||
|
||||
self.add_event_handler('session_start', self.start)
|
||||
|
||||
@@ -153,7 +153,7 @@ whenever a messsage is received.
|
||||
.. code-block:: python
|
||||
|
||||
def __init__(self, jid, password):
|
||||
super().__init__(jid, password)
|
||||
super(EchoBot, self).__init__(jid, password)
|
||||
|
||||
self.add_event_handler('session_start', self.start)
|
||||
self.add_event_handler('message', self.message)
|
||||
@@ -329,7 +329,7 @@ The Final Product
|
||||
-----------------
|
||||
|
||||
Here then is what the final result should look like after working through the guide above. The code
|
||||
can also be found in the Slixmpp `examples directory <http://git.poez.io/slixmpp/tree/examples>`_.
|
||||
can also be found in the Slixmpp `examples directory <http://github.com/fritzy/Slixmpp/tree/master/examples>`_.
|
||||
|
||||
.. compound::
|
||||
|
||||
|
||||
@@ -63,13 +63,13 @@ has been established:
|
||||
def start(self, event):
|
||||
self.get_roster()
|
||||
self.send_presence()
|
||||
self.plugin['xep_0045'].join_muc(self.room,
|
||||
self.nick,
|
||||
wait=True)
|
||||
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
|
||||
``join_muc`` method of the MUC plugin.
|
||||
``joinMUC`` method of the MUC plugin.
|
||||
|
||||
.. note::
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ for the JID that will receive our message, and the string content of the message
|
||||
class SendMsgBot(slixmpp.ClientXMPP):
|
||||
|
||||
def __init__(self, jid, password, recipient, msg):
|
||||
super().__init__(jid, password)
|
||||
super(SendMsgBot, self).__init__(jid, password)
|
||||
|
||||
self.recipient = recipient
|
||||
self.msg = msg
|
||||
|
||||
@@ -61,7 +61,7 @@ operation using these stanzas without doing any complex operations such as
|
||||
checking an ACL, etc.
|
||||
|
||||
You may find it necessary at some point to revert a particular node or JID to
|
||||
using the default, static handlers. To do so, use the method ``restore_defaults()``.
|
||||
using the default, static handlers. To do so, use the method ``make_static()``.
|
||||
You may also elect to only convert a given set of actions instead.
|
||||
|
||||
Creating a Node Handler
|
||||
@@ -162,7 +162,7 @@ item itself, and the JID and node that will own the item.
|
||||
parameters ``ijid`` and ``node``.
|
||||
|
||||
Performing Disco Queries
|
||||
------------------------
|
||||
-----------------------
|
||||
The methods ``get_info()`` and ``get_items()`` are used to query remote JIDs
|
||||
and their nodes for disco information. Since these methods are wrappers for
|
||||
sending Iq stanzas, they also accept all of the parameters of the ``Iq.send()``
|
||||
|
||||
@@ -68,7 +68,7 @@ class CommandBot(slixmpp.ClientXMPP):
|
||||
session. Additional, custom data may be saved
|
||||
here to persist across handler callbacks.
|
||||
"""
|
||||
form = self['xep_0004'].make_form('form', 'Greeting')
|
||||
form = self['xep_0004'].makeForm('form', 'Greeting')
|
||||
form['instructions'] = 'Send a custom greeting to a JID'
|
||||
form.addField(var='greeting',
|
||||
ftype='text-single',
|
||||
|
||||
@@ -94,7 +94,7 @@ class CommandUserBot(slixmpp.ClientXMPP):
|
||||
# label="Your greeting" />
|
||||
# </x>
|
||||
|
||||
form = self['xep_0004'].make_form(ftype='submit')
|
||||
form = self['xep_0004'].makeForm(ftype='submit')
|
||||
form.addField(var='greeting',
|
||||
value=session['greeting'])
|
||||
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Slixmpp: The Slick XMPP Library
|
||||
Copyright (C) 2015 Emmanuel Gil Peyrot
|
||||
This file is part of Slixmpp.
|
||||
|
||||
See the file LICENSE for copying permission.
|
||||
"""
|
||||
|
||||
import logging
|
||||
from getpass import getpass
|
||||
from argparse import ArgumentParser
|
||||
|
||||
import slixmpp
|
||||
from slixmpp.exceptions import XMPPError
|
||||
from slixmpp import asyncio
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AnswerConfirm(slixmpp.ClientXMPP):
|
||||
|
||||
"""
|
||||
A basic client demonstrating how to confirm or deny an HTTP request.
|
||||
"""
|
||||
|
||||
def __init__(self, jid, password, trusted):
|
||||
slixmpp.ClientXMPP.__init__(self, jid, password)
|
||||
|
||||
self.add_event_handler("http_confirm", self.confirm)
|
||||
self.add_event_handler("session_start", self.start)
|
||||
|
||||
def start(self, *args):
|
||||
self.make_presence().send()
|
||||
|
||||
def prompt(self, stanza):
|
||||
confirm = stanza['confirm']
|
||||
print('Received confirm request %s from %s to access %s using '
|
||||
'method %s' % (
|
||||
confirm['id'], stanza['from'], confirm['url'],
|
||||
confirm['method'])
|
||||
)
|
||||
result = input("Do you accept (y/N)? ")
|
||||
return 'y' == result.lower()
|
||||
|
||||
def confirm(self, stanza):
|
||||
if self.prompt(stanza):
|
||||
reply = stanza.reply()
|
||||
else:
|
||||
reply = stanza.reply()
|
||||
reply.enable('error')
|
||||
reply['error']['type'] = 'auth'
|
||||
reply['error']['code'] = '401'
|
||||
reply['error']['condition'] = 'not-authorized'
|
||||
reply.append(stanza['confirm'])
|
||||
reply.send()
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Setup the command line arguments.
|
||||
parser = ArgumentParser()
|
||||
parser.add_argument("-q","--quiet", help="set logging to ERROR",
|
||||
action="store_const",
|
||||
dest="loglevel",
|
||||
const=logging.ERROR,
|
||||
default=logging.INFO)
|
||||
parser.add_argument("-d","--debug", help="set logging to DEBUG",
|
||||
action="store_const",
|
||||
dest="loglevel",
|
||||
const=logging.DEBUG,
|
||||
default=logging.INFO)
|
||||
|
||||
# JID and password options.
|
||||
parser.add_argument("-j", "--jid", dest="jid",
|
||||
help="JID to use")
|
||||
parser.add_argument("-p", "--password", dest="password",
|
||||
help="password to use")
|
||||
|
||||
# Other options.
|
||||
parser.add_argument("-t", "--trusted", nargs='*',
|
||||
help="List of trusted JIDs")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Setup logging.
|
||||
logging.basicConfig(level=args.loglevel,
|
||||
format='%(levelname)-8s %(message)s')
|
||||
|
||||
if args.jid is None:
|
||||
args.jid = input("Username: ")
|
||||
if args.password is None:
|
||||
args.password = getpass("Password: ")
|
||||
|
||||
xmpp = AnswerConfirm(args.jid, args.password, args.trusted)
|
||||
xmpp.register_plugin('xep_0070')
|
||||
|
||||
# Connect to the XMPP server and start processing XMPP stanzas.
|
||||
xmpp.connect()
|
||||
xmpp.process()
|
||||
@@ -1,125 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Slixmpp: The Slick XMPP Library
|
||||
Copyright (C) 2015 Emmanuel Gil Peyrot
|
||||
This file is part of Slixmpp.
|
||||
|
||||
See the file LICENSE for copying permission.
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
import logging
|
||||
from getpass import getpass
|
||||
from argparse import ArgumentParser
|
||||
|
||||
import slixmpp
|
||||
from slixmpp.exceptions import XMPPError, IqError
|
||||
from slixmpp import asyncio
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AskConfirm(slixmpp.ClientXMPP):
|
||||
|
||||
"""
|
||||
A basic client asking an entity if they confirm the access to an HTTP URL.
|
||||
"""
|
||||
|
||||
def __init__(self, jid, password, recipient, id, url, method):
|
||||
slixmpp.ClientXMPP.__init__(self, jid, password)
|
||||
|
||||
self.recipient = recipient
|
||||
self.id = id
|
||||
self.url = url
|
||||
self.method = method
|
||||
|
||||
# Will be used to set the proper exit code.
|
||||
self.confirmed = asyncio.Future()
|
||||
|
||||
self.add_event_handler("session_start", self.start)
|
||||
self.add_event_handler("message", self.start)
|
||||
self.add_event_handler("http_confirm_message", self.confirm)
|
||||
|
||||
def confirm(self, message):
|
||||
print(message)
|
||||
if message['confirm']['id'] == self.id:
|
||||
if message['type'] == 'error':
|
||||
self.confirmed.set_result(False)
|
||||
else:
|
||||
self.confirmed.set_result(True)
|
||||
|
||||
@asyncio.coroutine
|
||||
def start(self, event):
|
||||
log.info('Sending confirm request %s to %s who wants to access %s using '
|
||||
'method %s...' % (self.id, self.recipient, self.url, self.method))
|
||||
try:
|
||||
confirmed = yield from self['xep_0070'].ask_confirm(self.recipient,
|
||||
id=self.id,
|
||||
url=self.url,
|
||||
method=self.method,
|
||||
message='Plz say yes or no for {method} {url} ({id}).')
|
||||
if isinstance(confirmed, slixmpp.Message):
|
||||
confirmed = yield from self.confirmed
|
||||
else:
|
||||
confirmed = True
|
||||
except IqError:
|
||||
confirmed = False
|
||||
if confirmed:
|
||||
print('Confirmed')
|
||||
else:
|
||||
print('Denied')
|
||||
self.disconnect()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Setup the command line arguments.
|
||||
parser = ArgumentParser()
|
||||
parser.add_argument("-q","--quiet", help="set logging to ERROR",
|
||||
action="store_const",
|
||||
dest="loglevel",
|
||||
const=logging.ERROR,
|
||||
default=logging.INFO)
|
||||
parser.add_argument("-d","--debug", help="set logging to DEBUG",
|
||||
action="store_const",
|
||||
dest="loglevel",
|
||||
const=logging.DEBUG,
|
||||
default=logging.INFO)
|
||||
|
||||
# JID and password options.
|
||||
parser.add_argument("-j", "--jid", dest="jid",
|
||||
help="JID to use")
|
||||
parser.add_argument("-p", "--password", dest="password",
|
||||
help="password to use")
|
||||
|
||||
# Other options.
|
||||
parser.add_argument("-r", "--recipient", required=True,
|
||||
help="Recipient JID")
|
||||
parser.add_argument("-i", "--id", required=True,
|
||||
help="id TODO")
|
||||
parser.add_argument("-u", "--url", required=True,
|
||||
help="URL the user tried to access")
|
||||
parser.add_argument("-m", "--method", required=True,
|
||||
help="HTTP method used")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Setup logging.
|
||||
logging.basicConfig(level=args.loglevel,
|
||||
format='%(levelname)-8s %(message)s')
|
||||
|
||||
if args.jid is None:
|
||||
args.jid = input("Username: ")
|
||||
if args.password is None:
|
||||
args.password = getpass("Password: ")
|
||||
|
||||
xmpp = AskConfirm(args.jid, args.password, args.recipient, args.id,
|
||||
args.url, args.method)
|
||||
xmpp.register_plugin('xep_0070')
|
||||
|
||||
# Connect to the XMPP server and start processing XMPP stanzas.
|
||||
xmpp.connect()
|
||||
xmpp.process(forever=False)
|
||||
sys.exit(0 if xmpp.confirmed else 1)
|
||||
@@ -41,7 +41,7 @@ class Action(ElementBase):
|
||||
#: del action['status']
|
||||
#:
|
||||
#: to set, get, or remove its values.
|
||||
interfaces = {'method', 'param', 'status'}
|
||||
interfaces = set(('method', 'param', 'status'))
|
||||
|
||||
#: By default, values in the `interfaces` set are mapped to
|
||||
#: attribute values. This can be changed such that an interface
|
||||
|
||||
@@ -67,11 +67,11 @@ class MUCBot(slixmpp.ClientXMPP):
|
||||
"""
|
||||
self.get_roster()
|
||||
self.send_presence()
|
||||
self.plugin['xep_0045'].join_muc(self.room,
|
||||
self.nick,
|
||||
# If a room password is needed, use:
|
||||
# password=the_room_password,
|
||||
wait=True)
|
||||
self.plugin['xep_0045'].joinMUC(self.room,
|
||||
self.nick,
|
||||
# If a room password is needed, use:
|
||||
# password=the_room_password,
|
||||
wait=True)
|
||||
|
||||
def muc_message(self, msg):
|
||||
"""
|
||||
|
||||
@@ -15,7 +15,7 @@ class PubsubClient(slixmpp.ClientXMPP):
|
||||
|
||||
def __init__(self, jid, password, server,
|
||||
node=None, action='nodes', data=''):
|
||||
super().__init__(jid, password)
|
||||
super(PubsubClient, self).__init__(jid, password)
|
||||
|
||||
self.register_plugin('xep_0030')
|
||||
self.register_plugin('xep_0059')
|
||||
|
||||
@@ -14,7 +14,7 @@ from slixmpp.xmlstream.handler import Callback
|
||||
class PubsubEvents(slixmpp.ClientXMPP):
|
||||
|
||||
def __init__(self, jid, password):
|
||||
super().__init__(jid, password)
|
||||
super(PubsubEvents, self).__init__(jid, password)
|
||||
|
||||
self.register_plugin('xep_0030')
|
||||
self.register_plugin('xep_0059')
|
||||
|
||||
@@ -22,7 +22,7 @@ from slixmpp import ClientXMPP
|
||||
class LocationBot(ClientXMPP):
|
||||
|
||||
def __init__(self, jid, password):
|
||||
super().__init__(jid, password)
|
||||
super(LocationBot, self).__init__(jid, password)
|
||||
|
||||
self.add_event_handler('session_start', self.start)
|
||||
self.add_event_handler('user_location_publish',
|
||||
|
||||
@@ -17,7 +17,7 @@ from slixmpp import ClientXMPP
|
||||
class TuneBot(ClientXMPP):
|
||||
|
||||
def __init__(self, jid, password):
|
||||
super().__init__(jid, password)
|
||||
super(TuneBot, self).__init__(jid, password)
|
||||
|
||||
# Check for the current song every 5 seconds.
|
||||
self.schedule('Check Current Tune', 5, self._update_tune, repeat=True)
|
||||
|
||||
32
setup.py
32
setup.py
@@ -7,15 +7,20 @@
|
||||
# This software is licensed as described in the README.rst and LICENSE
|
||||
# file, which you should have received as part of this distribution.
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
from subprocess import call, DEVNULL
|
||||
from tempfile import TemporaryFile
|
||||
try:
|
||||
from setuptools import setup
|
||||
except ImportError:
|
||||
from distutils.core import setup
|
||||
|
||||
try:
|
||||
from Cython.Build import cythonize
|
||||
except ImportError:
|
||||
print('Cython not found, falling back to the slow stringprep module.')
|
||||
ext_modules = None
|
||||
else:
|
||||
ext_modules = cythonize('slixmpp/stringprep.pyx')
|
||||
|
||||
from run_tests import TestCommand
|
||||
from slixmpp.version import __version__
|
||||
|
||||
@@ -35,27 +40,6 @@ CLASSIFIERS = [
|
||||
|
||||
packages = [str(mod.parent) for mod in Path('slixmpp').rglob('__init__.py')]
|
||||
|
||||
def check_include(header):
|
||||
command = [os.environ.get('CC', 'cc'), '-E', '-']
|
||||
with TemporaryFile('w+') as c_file:
|
||||
c_file.write('#include <%s>' % header)
|
||||
c_file.seek(0)
|
||||
try:
|
||||
return call(command, stdin=c_file, stdout=DEVNULL, stderr=DEVNULL) == 0
|
||||
except FileNotFoundError:
|
||||
return False
|
||||
|
||||
ext_modules = None
|
||||
if check_include('stringprep.h'):
|
||||
try:
|
||||
from Cython.Build import cythonize
|
||||
except ImportError:
|
||||
print('Cython not found, falling back to the slow stringprep module.')
|
||||
else:
|
||||
ext_modules = cythonize('slixmpp/stringprep.pyx')
|
||||
else:
|
||||
print('libidn-dev not found, falling back to the slow stringprep module.')
|
||||
|
||||
setup(
|
||||
name="slixmpp",
|
||||
version=VERSION,
|
||||
|
||||
@@ -7,8 +7,7 @@
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
if hasattr(asyncio, 'sslproto'): # no ssl proto: very old asyncio = no need for this
|
||||
asyncio.sslproto._is_sslproto_available=lambda: False
|
||||
asyncio.sslproto._is_sslproto_available=lambda: False
|
||||
import logging
|
||||
logging.getLogger(__name__).addHandler(logging.NullHandler())
|
||||
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
:license: MIT, see LICENSE for more details
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
import threading
|
||||
|
||||
from slixmpp import plugins, roster, stanza
|
||||
from slixmpp.api import APIRegistry
|
||||
@@ -21,6 +21,7 @@ from slixmpp.exceptions import IqError, IqTimeout
|
||||
|
||||
from slixmpp.stanza import Message, Presence, Iq, StreamError
|
||||
from slixmpp.stanza.roster import Roster
|
||||
from slixmpp.stanza.nick import Nick
|
||||
|
||||
from slixmpp.xmlstream import XMLStream, JID
|
||||
from slixmpp.xmlstream import ET, register_stanza_plugin
|
||||
@@ -69,7 +70,7 @@ class BaseXMPP(XMLStream):
|
||||
#: redirections that will be followed before quitting.
|
||||
self.max_redirects = 5
|
||||
|
||||
self.session_bind_event = asyncio.Event()
|
||||
self.session_bind_event = threading.Event()
|
||||
|
||||
#: A dictionary mapping plugin names to plugins.
|
||||
self.plugin = PluginManager(self)
|
||||
@@ -193,6 +194,7 @@ class BaseXMPP(XMLStream):
|
||||
|
||||
# Initialize a few default stanza plugins.
|
||||
register_stanza_plugin(Iq, Roster)
|
||||
register_stanza_plugin(Message, Nick)
|
||||
|
||||
def start_stream_handler(self, xml):
|
||||
"""Save the stream ID once the streams have been established.
|
||||
@@ -685,6 +687,7 @@ class BaseXMPP(XMLStream):
|
||||
self.address = (host, port)
|
||||
self.default_domain = host
|
||||
self.dns_records = None
|
||||
self.reconnect_delay = None
|
||||
self.reconnect()
|
||||
|
||||
def _handle_message(self, msg):
|
||||
@@ -750,9 +753,6 @@ class BaseXMPP(XMLStream):
|
||||
|
||||
Update the roster with presence information.
|
||||
"""
|
||||
if self.roster[presence['from']].ignore_updates:
|
||||
return
|
||||
|
||||
if not self.is_component and not presence['to'].bare:
|
||||
presence['to'] = self.boundjid
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
:license: MIT, see LICENSE for more details
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
from slixmpp.stanza import StreamFeatures
|
||||
@@ -20,7 +19,7 @@ from slixmpp.basexmpp import BaseXMPP
|
||||
from slixmpp.exceptions import XMPPError
|
||||
from slixmpp.xmlstream import XMLStream
|
||||
from slixmpp.xmlstream.matcher import StanzaPath, MatchXPath
|
||||
from slixmpp.xmlstream.handler import Callback, CoroutineCallback
|
||||
from slixmpp.xmlstream.handler import Callback
|
||||
|
||||
# Flag indicating if DNS SRV records are available for use.
|
||||
try:
|
||||
@@ -105,18 +104,13 @@ class ClientXMPP(BaseXMPP):
|
||||
self.register_stanza(StreamFeatures)
|
||||
|
||||
self.register_handler(
|
||||
CoroutineCallback('Stream Features',
|
||||
MatchXPath('{%s}features' % self.stream_ns),
|
||||
self._handle_stream_features))
|
||||
def roster_push_filter(iq):
|
||||
from_ = iq['from']
|
||||
if from_ and from_ != self.boundjid.bare:
|
||||
return
|
||||
self.event('roster_update', iq)
|
||||
Callback('Stream Features',
|
||||
MatchXPath('{%s}features' % self.stream_ns),
|
||||
self._handle_stream_features))
|
||||
self.register_handler(
|
||||
Callback('Roster Update',
|
||||
StanzaPath('iq@type=set/roster'),
|
||||
roster_push_filter))
|
||||
lambda iq: self.event('roster_update', iq)))
|
||||
|
||||
# Setup default stream features
|
||||
self.register_plugin('feature_starttls')
|
||||
@@ -146,11 +140,8 @@ class ClientXMPP(BaseXMPP):
|
||||
will be used.
|
||||
|
||||
:param address: A tuple containing the server's host and port.
|
||||
:param force_starttls: Indicates that negotiation should be aborted
|
||||
if the server does not advertise support for
|
||||
STARTTLS. Defaults to ``True``.
|
||||
:param disable_starttls: Disables TLS for the connection.
|
||||
Defaults to ``False``.
|
||||
:param use_tls: Indicates if TLS should be used for the
|
||||
connection. Defaults to ``True``.
|
||||
:param use_ssl: Indicates if the older SSL connection method
|
||||
should be used. Defaults to ``False``.
|
||||
"""
|
||||
@@ -258,7 +249,6 @@ class ClientXMPP(BaseXMPP):
|
||||
self.bindfail = False
|
||||
self.features = set()
|
||||
|
||||
@asyncio.coroutine
|
||||
def _handle_stream_features(self, features):
|
||||
"""Process the received stream features.
|
||||
|
||||
@@ -267,11 +257,7 @@ class ClientXMPP(BaseXMPP):
|
||||
for order, name in self._stream_feature_order:
|
||||
if name in features['features']:
|
||||
handler, restart = self._stream_feature_handlers[name]
|
||||
if asyncio.iscoroutinefunction(handler):
|
||||
result = yield from handler(features)
|
||||
else:
|
||||
result = handler(features)
|
||||
if result and restart:
|
||||
if handler(features) and restart:
|
||||
# Don't continue if the feature requires
|
||||
# restarting the XML stream.
|
||||
return True
|
||||
|
||||
@@ -77,7 +77,7 @@ class IqTimeout(XMPPError):
|
||||
"""
|
||||
|
||||
def __init__(self, iq):
|
||||
super().__init__(
|
||||
super(IqTimeout, self).__init__(
|
||||
condition='remote-server-timeout',
|
||||
etype='cancel')
|
||||
|
||||
@@ -94,7 +94,7 @@ class IqError(XMPPError):
|
||||
"""
|
||||
|
||||
def __init__(self, iq):
|
||||
super().__init__(
|
||||
super(IqError, self).__init__(
|
||||
condition=iq['error']['condition'],
|
||||
text=iq['error']['text'],
|
||||
etype=iq['error']['type'])
|
||||
|
||||
@@ -13,3 +13,7 @@ from slixmpp.features.feature_bind.stanza import Bind
|
||||
|
||||
|
||||
register_plugin(FeatureBind)
|
||||
|
||||
|
||||
# Retain some backwards compatibility
|
||||
feature_bind = FeatureBind
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
See the file LICENSE for copying permission.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
from slixmpp.jid import JID
|
||||
@@ -35,7 +34,6 @@ class FeatureBind(BasePlugin):
|
||||
register_stanza_plugin(Iq, stanza.Bind)
|
||||
register_stanza_plugin(StreamFeatures, stanza.Bind)
|
||||
|
||||
@asyncio.coroutine
|
||||
def _handle_bind_resource(self, features):
|
||||
"""
|
||||
Handle requesting a specific resource.
|
||||
@@ -51,7 +49,7 @@ class FeatureBind(BasePlugin):
|
||||
if self.xmpp.requested_jid.resource:
|
||||
iq['bind']['resource'] = self.xmpp.requested_jid.resource
|
||||
|
||||
yield from iq.send(callback=self._on_bind_response)
|
||||
iq.send(callback=self._on_bind_response)
|
||||
|
||||
def _on_bind_response(self, response):
|
||||
self.xmpp.boundjid = JID(response['bind']['jid'])
|
||||
|
||||
@@ -16,6 +16,6 @@ class Bind(ElementBase):
|
||||
|
||||
name = 'bind'
|
||||
namespace = 'urn:ietf:params:xml:ns:xmpp-bind'
|
||||
interfaces = {'resource', 'jid'}
|
||||
interfaces = set(('resource', 'jid'))
|
||||
sub_interfaces = interfaces
|
||||
plugin_attrib = 'bind'
|
||||
|
||||
@@ -16,3 +16,7 @@ from slixmpp.features.feature_mechanisms.stanza import Failure
|
||||
|
||||
|
||||
register_plugin(FeatureMechanisms)
|
||||
|
||||
|
||||
# Retain some backwards compatibility
|
||||
feature_mechanisms = FeatureMechanisms
|
||||
|
||||
@@ -49,7 +49,7 @@ class FeatureMechanisms(BasePlugin):
|
||||
if self.security_callback is None:
|
||||
self.security_callback = self._default_security
|
||||
|
||||
creds = self.sasl_callback({'username'}, set())
|
||||
creds = self.sasl_callback(set(['username']), set())
|
||||
if not self.use_mech and not creds['username']:
|
||||
self.use_mech = 'ANONYMOUS'
|
||||
|
||||
|
||||
@@ -19,12 +19,12 @@ class Auth(StanzaBase):
|
||||
|
||||
name = 'auth'
|
||||
namespace = 'urn:ietf:params:xml:ns:xmpp-sasl'
|
||||
interfaces = {'mechanism', 'value'}
|
||||
interfaces = set(('mechanism', 'value'))
|
||||
plugin_attrib = name
|
||||
|
||||
#: Some SASL mechs require sending values as is,
|
||||
#: without converting base64.
|
||||
plain_mechs = {'X-MESSENGER-OAUTH2'}
|
||||
plain_mechs = set(['X-MESSENGER-OAUTH2'])
|
||||
|
||||
def setup(self, xml):
|
||||
StanzaBase.setup(self, xml)
|
||||
|
||||
@@ -19,7 +19,7 @@ class Challenge(StanzaBase):
|
||||
|
||||
name = 'challenge'
|
||||
namespace = 'urn:ietf:params:xml:ns:xmpp-sasl'
|
||||
interfaces = {'value'}
|
||||
interfaces = set(('value',))
|
||||
plugin_attrib = name
|
||||
|
||||
def setup(self, xml):
|
||||
|
||||
@@ -16,14 +16,13 @@ class Failure(StanzaBase):
|
||||
|
||||
name = 'failure'
|
||||
namespace = 'urn:ietf:params:xml:ns:xmpp-sasl'
|
||||
interfaces = {'condition', 'text'}
|
||||
interfaces = set(('condition', 'text'))
|
||||
plugin_attrib = name
|
||||
sub_interfaces = {'text'}
|
||||
conditions = {'aborted', 'account-disabled', 'credentials-expired',
|
||||
'encryption-required', 'incorrect-encoding',
|
||||
'invalid-authzid', 'invalid-mechanism', 'malformed-request',
|
||||
'mechansism-too-weak', 'not-authorized',
|
||||
'temporary-auth-failure'}
|
||||
sub_interfaces = set(('text',))
|
||||
conditions = set(('aborted', 'account-disabled', 'credentials-expired',
|
||||
'encryption-required', 'incorrect-encoding', 'invalid-authzid',
|
||||
'invalid-mechanism', 'malformed-request', 'mechansism-too-weak',
|
||||
'not-authorized', 'temporary-auth-failure'))
|
||||
|
||||
def setup(self, xml=None):
|
||||
"""
|
||||
|
||||
@@ -16,7 +16,7 @@ class Mechanisms(ElementBase):
|
||||
|
||||
name = 'mechanisms'
|
||||
namespace = 'urn:ietf:params:xml:ns:xmpp-sasl'
|
||||
interfaces = {'mechanisms', 'required'}
|
||||
interfaces = set(('mechanisms', 'required'))
|
||||
plugin_attrib = name
|
||||
is_extension = True
|
||||
|
||||
@@ -29,7 +29,7 @@ class Mechanisms(ElementBase):
|
||||
"""
|
||||
"""
|
||||
results = []
|
||||
mechs = self.xml.findall('{%s}mechanism' % self.namespace)
|
||||
mechs = self.findall('{%s}mechanism' % self.namespace)
|
||||
if mechs:
|
||||
for mech in mechs:
|
||||
results.append(mech.text)
|
||||
@@ -47,7 +47,7 @@ class Mechanisms(ElementBase):
|
||||
def del_mechanisms(self):
|
||||
"""
|
||||
"""
|
||||
mechs = self.xml.findall('{%s}mechanism' % self.namespace)
|
||||
mechs = self.findall('{%s}mechanism' % self.namespace)
|
||||
if mechs:
|
||||
for mech in mechs:
|
||||
self.xml.remove(mech)
|
||||
|
||||
@@ -19,7 +19,7 @@ class Response(StanzaBase):
|
||||
|
||||
name = 'response'
|
||||
namespace = 'urn:ietf:params:xml:ns:xmpp-sasl'
|
||||
interfaces = {'value'}
|
||||
interfaces = set(('value',))
|
||||
plugin_attrib = name
|
||||
|
||||
def setup(self, xml):
|
||||
|
||||
@@ -18,7 +18,7 @@ class Success(StanzaBase):
|
||||
|
||||
name = 'success'
|
||||
namespace = 'urn:ietf:params:xml:ns:xmpp-sasl'
|
||||
interfaces = {'value'}
|
||||
interfaces = set(['value'])
|
||||
plugin_attrib = name
|
||||
|
||||
def setup(self, xml):
|
||||
|
||||
@@ -13,3 +13,7 @@ from slixmpp.features.feature_rosterver.stanza import RosterVer
|
||||
|
||||
|
||||
register_plugin(FeatureRosterVer)
|
||||
|
||||
|
||||
# Retain some backwards compatibility
|
||||
feature_rosterver = FeatureRosterVer
|
||||
|
||||
@@ -13,3 +13,7 @@ from slixmpp.features.feature_session.stanza import Session
|
||||
|
||||
|
||||
register_plugin(FeatureSession)
|
||||
|
||||
|
||||
# Retain some backwards compatibility
|
||||
feature_session = FeatureSession
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
See the file LICENSE for copying permission.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
from slixmpp.stanza import Iq, StreamFeatures
|
||||
@@ -35,7 +34,6 @@ class FeatureSession(BasePlugin):
|
||||
register_stanza_plugin(Iq, stanza.Session)
|
||||
register_stanza_plugin(StreamFeatures, stanza.Session)
|
||||
|
||||
@asyncio.coroutine
|
||||
def _handle_start_session(self, features):
|
||||
"""
|
||||
Handle the start of the session.
|
||||
@@ -46,7 +44,7 @@ class FeatureSession(BasePlugin):
|
||||
iq = self.xmpp.Iq()
|
||||
iq['type'] = 'set'
|
||||
iq.enable('session')
|
||||
yield from iq.send(callback=self._on_start_session_response)
|
||||
iq.send(callback=self._on_start_session_response)
|
||||
|
||||
def _on_start_session_response(self, response):
|
||||
self.xmpp.features.add('session')
|
||||
|
||||
@@ -13,3 +13,7 @@ from slixmpp.features.feature_starttls.stanza import *
|
||||
|
||||
|
||||
register_plugin(FeatureSTARTTLS)
|
||||
|
||||
|
||||
# Retain some backwards compatibility
|
||||
feature_starttls = FeatureSTARTTLS
|
||||
|
||||
@@ -16,7 +16,7 @@ class STARTTLS(ElementBase):
|
||||
|
||||
name = 'starttls'
|
||||
namespace = 'urn:ietf:params:xml:ns:xmpp-tls'
|
||||
interfaces = {'required'}
|
||||
interfaces = set(('required',))
|
||||
plugin_attrib = name
|
||||
|
||||
def get_required(self):
|
||||
|
||||
@@ -79,7 +79,7 @@ def _validate_node(node):
|
||||
:returns: The local portion of a JID, as validated by nodeprep.
|
||||
"""
|
||||
if node is None:
|
||||
return ''
|
||||
return None
|
||||
|
||||
try:
|
||||
node = nodeprep(node)
|
||||
@@ -160,7 +160,7 @@ def _validate_resource(resource):
|
||||
:returns: The local portion of a JID, as validated by resourceprep.
|
||||
"""
|
||||
if resource is None:
|
||||
return ''
|
||||
return None
|
||||
|
||||
try:
|
||||
resource = resourceprep(resource)
|
||||
@@ -208,15 +208,16 @@ def _format_jid(local=None, domain=None, resource=None):
|
||||
|
||||
:return: A full or bare JID string.
|
||||
"""
|
||||
if domain is None:
|
||||
return ''
|
||||
result = []
|
||||
if local is not None:
|
||||
result = local + '@' + domain
|
||||
else:
|
||||
result = domain
|
||||
result.append(local)
|
||||
result.append('@')
|
||||
if domain is not None:
|
||||
result.append(domain)
|
||||
if resource is not None:
|
||||
result += '/' + resource
|
||||
return result
|
||||
result.append('/')
|
||||
result.append(resource)
|
||||
return ''.join(result)
|
||||
|
||||
|
||||
class InvalidJID(ValueError):
|
||||
@@ -299,23 +300,19 @@ class JID:
|
||||
:raises InvalidJID:
|
||||
"""
|
||||
|
||||
__slots__ = ('_node', '_domain', '_resource', '_bare', '_full')
|
||||
__slots__ = ('_node', '_domain', '_resource')
|
||||
|
||||
def __init__(self, jid=None):
|
||||
if not jid:
|
||||
self._node = ''
|
||||
self._domain = ''
|
||||
self._resource = ''
|
||||
self._bare = ''
|
||||
self._full = ''
|
||||
return
|
||||
self._node = None
|
||||
self._domain = None
|
||||
self._resource = None
|
||||
elif not isinstance(jid, JID):
|
||||
self._node, self._domain, self._resource = _parse_jid(jid)
|
||||
else:
|
||||
self._node = jid._node
|
||||
self._domain = jid._domain
|
||||
self._resource = jid._resource
|
||||
self._update_bare_full()
|
||||
|
||||
def unescape(self):
|
||||
"""Return an unescaped JID object.
|
||||
@@ -332,94 +329,77 @@ class JID:
|
||||
self._domain,
|
||||
self._resource)
|
||||
|
||||
def _update_bare_full(self):
|
||||
"""Format the given JID into a bare and a full JID.
|
||||
"""
|
||||
self._bare = (self._node + '@' + self._domain
|
||||
if self._node
|
||||
else self._domain)
|
||||
self._full = (self._bare + '/' + self._resource
|
||||
if self._resource
|
||||
else self._bare)
|
||||
|
||||
@property
|
||||
def node(self):
|
||||
return self._node
|
||||
return self._node or ''
|
||||
|
||||
@property
|
||||
def user(self):
|
||||
return self._node
|
||||
return self._node or ''
|
||||
|
||||
@property
|
||||
def local(self):
|
||||
return self._node
|
||||
return self._node or ''
|
||||
|
||||
@property
|
||||
def username(self):
|
||||
return self._node
|
||||
return self._node or ''
|
||||
|
||||
@property
|
||||
def domain(self):
|
||||
return self._domain
|
||||
return self._domain or ''
|
||||
|
||||
@property
|
||||
def server(self):
|
||||
return self._domain
|
||||
return self._domain or ''
|
||||
|
||||
@property
|
||||
def host(self):
|
||||
return self._domain
|
||||
return self._domain or ''
|
||||
|
||||
@property
|
||||
def resource(self):
|
||||
return self._resource
|
||||
return self._resource or ''
|
||||
|
||||
@property
|
||||
def bare(self):
|
||||
return self._bare
|
||||
return _format_jid(self._node, self._domain)
|
||||
|
||||
@property
|
||||
def full(self):
|
||||
return self._full
|
||||
return _format_jid(self._node, self._domain, self._resource)
|
||||
|
||||
@property
|
||||
def jid(self):
|
||||
return self._full
|
||||
return _format_jid(self._node, self._domain, self._resource)
|
||||
|
||||
@node.setter
|
||||
def node(self, value):
|
||||
self._node = _validate_node(value)
|
||||
self._update_bare_full()
|
||||
|
||||
@user.setter
|
||||
def user(self, value):
|
||||
self._node = _validate_node(value)
|
||||
self._update_bare_full()
|
||||
|
||||
@local.setter
|
||||
def local(self, value):
|
||||
self._node = _validate_node(value)
|
||||
self._update_bare_full()
|
||||
|
||||
@username.setter
|
||||
def username(self, value):
|
||||
self._node = _validate_node(value)
|
||||
self._update_bare_full()
|
||||
|
||||
@domain.setter
|
||||
def domain(self, value):
|
||||
self._domain = _validate_domain(value)
|
||||
self._update_bare_full()
|
||||
|
||||
@server.setter
|
||||
def server(self, value):
|
||||
self._domain = _validate_domain(value)
|
||||
self._update_bare_full()
|
||||
|
||||
@host.setter
|
||||
def host(self, value):
|
||||
self._domain = _validate_domain(value)
|
||||
self._update_bare_full()
|
||||
|
||||
@bare.setter
|
||||
def bare(self, value):
|
||||
@@ -427,30 +407,26 @@ class JID:
|
||||
assert not resource
|
||||
self._node = node
|
||||
self._domain = domain
|
||||
self._update_bare_full()
|
||||
|
||||
@resource.setter
|
||||
def resource(self, value):
|
||||
self._resource = _validate_resource(value)
|
||||
self._update_bare_full()
|
||||
|
||||
@full.setter
|
||||
def full(self, value):
|
||||
self._node, self._domain, self._resource = _parse_jid(value)
|
||||
self._update_bare_full()
|
||||
|
||||
@jid.setter
|
||||
def jid(self, value):
|
||||
self._node, self._domain, self._resource = _parse_jid(value)
|
||||
self._update_bare_full()
|
||||
|
||||
def __str__(self):
|
||||
"""Use the full JID as the string value."""
|
||||
return self._full
|
||||
return _format_jid(self._node, self._domain, self._resource)
|
||||
|
||||
def __repr__(self):
|
||||
"""Use the full JID as the representation."""
|
||||
return self._full
|
||||
return _format_jid(self._node, self._domain, self._resource)
|
||||
|
||||
# pylint: disable=W0212
|
||||
def __eq__(self, other):
|
||||
@@ -470,4 +446,4 @@ class JID:
|
||||
|
||||
def __hash__(self):
|
||||
"""Hash a JID based on the string version of its full JID."""
|
||||
return hash(self._full)
|
||||
return hash(_format_jid(self._node, self._domain, self._resource))
|
||||
|
||||
@@ -308,7 +308,7 @@ class BasePlugin(object):
|
||||
if key in self.default_config:
|
||||
self.config[key] = value
|
||||
else:
|
||||
super().__setattr__(key, value)
|
||||
super(BasePlugin, self).__setattr__(key, value)
|
||||
|
||||
def _init(self):
|
||||
"""Initialize plugin state, such as registering event handlers.
|
||||
|
||||
@@ -21,15 +21,15 @@ class GmailQuery(ElementBase):
|
||||
namespace = 'google:mail:notify'
|
||||
name = 'query'
|
||||
plugin_attrib = 'gmail'
|
||||
interfaces = {'newer-than-time', 'newer-than-tid', 'q', 'search'}
|
||||
interfaces = set(('newer-than-time', 'newer-than-tid', 'q', 'search'))
|
||||
|
||||
def get_search(self):
|
||||
def getSearch(self):
|
||||
return self['q']
|
||||
|
||||
def set_search(self, search):
|
||||
def setSearch(self, search):
|
||||
self['q'] = search
|
||||
|
||||
def del_search(self):
|
||||
def delSearch(self):
|
||||
del self['q']
|
||||
|
||||
|
||||
@@ -37,20 +37,20 @@ class MailBox(ElementBase):
|
||||
namespace = 'google:mail:notify'
|
||||
name = 'mailbox'
|
||||
plugin_attrib = 'mailbox'
|
||||
interfaces = {'result-time', 'total-matched', 'total-estimate',
|
||||
'url', 'threads', 'matched', 'estimate'}
|
||||
interfaces = set(('result-time', 'total-matched', 'total-estimate',
|
||||
'url', 'threads', 'matched', 'estimate'))
|
||||
|
||||
def get_threads(self):
|
||||
def getThreads(self):
|
||||
threads = []
|
||||
for threadXML in self.xml.findall('{%s}%s' % (MailThread.namespace,
|
||||
MailThread.name)):
|
||||
threads.append(MailThread(xml=threadXML, parent=None))
|
||||
return threads
|
||||
|
||||
def get_matched(self):
|
||||
def getMatched(self):
|
||||
return self['total-matched']
|
||||
|
||||
def get_estimate(self):
|
||||
def getEstimate(self):
|
||||
return self['total-estimate'] == '1'
|
||||
|
||||
|
||||
@@ -58,11 +58,11 @@ class MailThread(ElementBase):
|
||||
namespace = 'google:mail:notify'
|
||||
name = 'mail-thread-info'
|
||||
plugin_attrib = 'thread'
|
||||
interfaces = {'tid', 'participation', 'messages', 'date',
|
||||
'senders', 'url', 'labels', 'subject', 'snippet'}
|
||||
sub_interfaces = {'labels', 'subject', 'snippet'}
|
||||
interfaces = set(('tid', 'participation', 'messages', 'date',
|
||||
'senders', 'url', 'labels', 'subject', 'snippet'))
|
||||
sub_interfaces = set(('labels', 'subject', 'snippet'))
|
||||
|
||||
def get_senders(self):
|
||||
def getSenders(self):
|
||||
senders = []
|
||||
sendersXML = self.xml.find('{%s}senders' % self.namespace)
|
||||
if sendersXML is not None:
|
||||
@@ -75,12 +75,12 @@ class MailSender(ElementBase):
|
||||
namespace = 'google:mail:notify'
|
||||
name = 'sender'
|
||||
plugin_attrib = 'sender'
|
||||
interfaces = {'address', 'name', 'originator', 'unread'}
|
||||
interfaces = set(('address', 'name', 'originator', 'unread'))
|
||||
|
||||
def get_originator(self):
|
||||
def getOriginator(self):
|
||||
return self.xml.attrib.get('originator', '0') == '1'
|
||||
|
||||
def get_unread(self):
|
||||
def getUnread(self):
|
||||
return self.xml.attrib.get('unread', '0') == '1'
|
||||
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ class GoogleAuth(ElementBase):
|
||||
name = 'auth'
|
||||
namespace = 'http://www.google.com/talk/protocol/auth'
|
||||
plugin_attrib = 'google'
|
||||
interfaces = {'client_uses_full_bind_result', 'service'}
|
||||
interfaces = set(['client_uses_full_bind_result', 'service'])
|
||||
|
||||
discovery_attr= '{%s}client-uses-full-bind-result' % namespace
|
||||
service_attr= '{%s}service' % namespace
|
||||
|
||||
@@ -14,7 +14,7 @@ class NoSave(ElementBase):
|
||||
name = 'x'
|
||||
namespace = 'google:nosave'
|
||||
plugin_attrib = 'google_nosave'
|
||||
interfaces = {'value'}
|
||||
interfaces = set(['value'])
|
||||
|
||||
def get_value(self):
|
||||
return self._get_attr('value', '') == 'enabled'
|
||||
@@ -35,7 +35,7 @@ class Item(ElementBase):
|
||||
namespace = 'google:nosave'
|
||||
plugin_attrib = 'item'
|
||||
plugin_multi_attrib = 'items'
|
||||
interfaces = {'jid', 'source', 'value'}
|
||||
interfaces = set(['jid', 'source', 'value'])
|
||||
|
||||
def get_value(self):
|
||||
return self._get_attr('value', '') == 'enabled'
|
||||
|
||||
@@ -14,3 +14,9 @@ from slixmpp.plugins.xep_0004.dataforms import XEP_0004
|
||||
|
||||
|
||||
register_plugin(XEP_0004)
|
||||
|
||||
|
||||
# Retain some backwards compatibility
|
||||
xep_0004 = XEP_0004
|
||||
xep_0004.makeForm = xep_0004.make_form
|
||||
xep_0004.buildForm = xep_0004.build_form
|
||||
|
||||
@@ -23,7 +23,7 @@ class XEP_0004(BasePlugin):
|
||||
|
||||
name = 'xep_0004'
|
||||
description = 'XEP-0004: Data Forms'
|
||||
dependencies = {'xep_0030'}
|
||||
dependencies = set(['xep_0030'])
|
||||
stanza = stanza
|
||||
|
||||
def plugin_init(self):
|
||||
|
||||
@@ -14,21 +14,21 @@ class FormField(ElementBase):
|
||||
name = 'field'
|
||||
plugin_attrib = 'field'
|
||||
plugin_multi_attrib = 'fields'
|
||||
interfaces = {'answer', 'desc', 'required', 'value',
|
||||
'label', 'type', 'var'}
|
||||
sub_interfaces = {'desc'}
|
||||
interfaces = set(('answer', 'desc', 'required', 'value',
|
||||
'label', 'type', 'var'))
|
||||
sub_interfaces = set(('desc',))
|
||||
plugin_tag_map = {}
|
||||
plugin_attrib_map = {}
|
||||
|
||||
field_types = {'boolean', 'fixed', 'hidden', 'jid-multi',
|
||||
'jid-single', 'list-multi', 'list-single',
|
||||
'text-multi', 'text-private', 'text-single'}
|
||||
field_types = set(('boolean', 'fixed', 'hidden', 'jid-multi',
|
||||
'jid-single', 'list-multi', 'list-single',
|
||||
'text-multi', 'text-private', 'text-single'))
|
||||
|
||||
true_values = {True, '1', 'true'}
|
||||
option_types = {'list-multi', 'list-single'}
|
||||
multi_line_types = {'hidden', 'text-multi'}
|
||||
multi_value_types = {'hidden', 'jid-multi',
|
||||
'list-multi', 'text-multi'}
|
||||
true_values = set((True, '1', 'true'))
|
||||
option_types = set(('list-multi', 'list-single'))
|
||||
multi_line_types = set(('hidden', 'text-multi'))
|
||||
multi_value_types = set(('hidden', 'jid-multi',
|
||||
'list-multi', 'text-multi'))
|
||||
|
||||
def setup(self, xml=None):
|
||||
if ElementBase.setup(self, xml):
|
||||
@@ -164,8 +164,8 @@ class FieldOption(ElementBase):
|
||||
namespace = 'jabber:x:data'
|
||||
name = 'option'
|
||||
plugin_attrib = 'option'
|
||||
interfaces = {'label', 'value'}
|
||||
sub_interfaces = {'value'}
|
||||
interfaces = set(('label', 'value'))
|
||||
sub_interfaces = set(('value',))
|
||||
plugin_multi_attrib = 'options'
|
||||
|
||||
|
||||
|
||||
@@ -24,8 +24,8 @@ class Form(ElementBase):
|
||||
name = 'x'
|
||||
plugin_attrib = 'form'
|
||||
interfaces = OrderedSet(('instructions', 'reported', 'title', 'type', 'items', ))
|
||||
sub_interfaces = {'title'}
|
||||
form_types = {'cancel', 'form', 'result', 'submit'}
|
||||
sub_interfaces = set(('title',))
|
||||
form_types = set(('cancel', 'form', 'result', 'submit'))
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
title = None
|
||||
@@ -81,6 +81,18 @@ class Form(ElementBase):
|
||||
self.append(field)
|
||||
return field
|
||||
|
||||
def getXML(self, type='submit'):
|
||||
self['type'] = type
|
||||
log.warning("Form.getXML() is deprecated API compatibility " + \
|
||||
"with plugins/old_0004.py")
|
||||
return self.xml
|
||||
|
||||
def fromXML(self, xml):
|
||||
log.warning("Form.fromXML() is deprecated API compatibility " + \
|
||||
"with plugins/old_0004.py")
|
||||
n = Form(xml=xml)
|
||||
return n
|
||||
|
||||
def add_item(self, values):
|
||||
itemXML = ET.Element('{%s}item' % self.namespace)
|
||||
self.xml.append(itemXML)
|
||||
@@ -184,13 +196,13 @@ class Form(ElementBase):
|
||||
for var, field in fields:
|
||||
field['var'] = var
|
||||
self.add_field(
|
||||
var=field.get('var'),
|
||||
label=field.get('label'),
|
||||
desc=field.get('desc'),
|
||||
required=field.get('required'),
|
||||
value=field.get('value'),
|
||||
options=field.get('options'),
|
||||
type=field.get('type'))
|
||||
var = field.get('var'),
|
||||
label = field.get('label'),
|
||||
desc = field.get('desc'),
|
||||
required = field.get('required'),
|
||||
value = field.get('value'),
|
||||
options = field.get('options'),
|
||||
type = field.get('type'))
|
||||
|
||||
def set_instructions(self, instructions):
|
||||
del self['instructions']
|
||||
@@ -209,7 +221,7 @@ class Form(ElementBase):
|
||||
|
||||
def set_reported(self, reported):
|
||||
"""
|
||||
This either needs a dictionary of dictionaries or a dictionary of form fields.
|
||||
This either needs a dictionary or dictionaries or a dictionary of form fields.
|
||||
:param reported:
|
||||
:return:
|
||||
"""
|
||||
|
||||
@@ -14,3 +14,7 @@ from slixmpp.plugins.xep_0009.stanza import RPCQuery, MethodCall, MethodResponse
|
||||
|
||||
|
||||
register_plugin(XEP_0009)
|
||||
|
||||
|
||||
# Retain some backwards compatibility
|
||||
xep_0009 = XEP_0009
|
||||
|
||||
@@ -25,7 +25,7 @@ def fault2xml(fault):
|
||||
|
||||
def xml2fault(params):
|
||||
vals = []
|
||||
for value in params.xml.findall('{%s}value' % _namespace):
|
||||
for value in params.findall('{%s}value' % _namespace):
|
||||
vals.append(_xml2py(value))
|
||||
fault = dict()
|
||||
fault['code'] = vals[0]['faultCode']
|
||||
@@ -98,34 +98,33 @@ def xml2py(params):
|
||||
|
||||
def _xml2py(value):
|
||||
namespace = 'jabber:iq:rpc'
|
||||
find_value = value.find
|
||||
if find_value('{%s}nil' % namespace) is not None:
|
||||
if value.find('{%s}nil' % namespace) is not None:
|
||||
return None
|
||||
if find_value('{%s}i4' % namespace) is not None:
|
||||
return int(find_value('{%s}i4' % namespace).text)
|
||||
if find_value('{%s}int' % namespace) is not None:
|
||||
return int(find_value('{%s}int' % namespace).text)
|
||||
if find_value('{%s}boolean' % namespace) is not None:
|
||||
return bool(int(find_value('{%s}boolean' % namespace).text))
|
||||
if find_value('{%s}string' % namespace) is not None:
|
||||
return find_value('{%s}string' % namespace).text
|
||||
if find_value('{%s}double' % namespace) is not None:
|
||||
return float(find_value('{%s}double' % namespace).text)
|
||||
if find_value('{%s}base64' % namespace) is not None:
|
||||
return rpcbase64(find_value('{%s}base64' % namespace).text.encode())
|
||||
if find_value('{%s}Base64' % namespace) is not None:
|
||||
if value.find('{%s}i4' % namespace) is not None:
|
||||
return int(value.find('{%s}i4' % namespace).text)
|
||||
if value.find('{%s}int' % namespace) is not None:
|
||||
return int(value.find('{%s}int' % namespace).text)
|
||||
if value.find('{%s}boolean' % namespace) is not None:
|
||||
return bool(int(value.find('{%s}boolean' % namespace).text))
|
||||
if value.find('{%s}string' % namespace) is not None:
|
||||
return value.find('{%s}string' % namespace).text
|
||||
if value.find('{%s}double' % namespace) is not None:
|
||||
return float(value.find('{%s}double' % namespace).text)
|
||||
if value.find('{%s}base64' % namespace) is not None:
|
||||
return rpcbase64(value.find('{%s}base64' % namespace).text.encode())
|
||||
if value.find('{%s}Base64' % namespace) is not None:
|
||||
# Older versions of XEP-0009 used Base64
|
||||
return rpcbase64(find_value('{%s}Base64' % namespace).text.encode())
|
||||
if find_value('{%s}dateTime.iso8601' % namespace) is not None:
|
||||
return rpctime(find_value('{%s}dateTime.iso8601' % namespace).text)
|
||||
if find_value('{%s}struct' % namespace) is not None:
|
||||
return rpcbase64(value.find('{%s}Base64' % namespace).text.encode())
|
||||
if value.find('{%s}dateTime.iso8601' % namespace) is not None:
|
||||
return rpctime(value.find('{%s}dateTime.iso8601' % namespace).text)
|
||||
if value.find('{%s}struct' % namespace) is not None:
|
||||
struct = {}
|
||||
for member in find_value('{%s}struct' % namespace).findall('{%s}member' % namespace):
|
||||
for member in value.find('{%s}struct' % namespace).findall('{%s}member' % namespace):
|
||||
struct[member.find('{%s}name' % namespace).text] = _xml2py(member.find('{%s}value' % namespace))
|
||||
return struct
|
||||
if find_value('{%s}array' % namespace) is not None:
|
||||
if value.find('{%s}array' % namespace) is not None:
|
||||
array = []
|
||||
for val in find_value('{%s}array' % namespace).find('{%s}data' % namespace).findall('{%s}value' % namespace):
|
||||
for val in value.find('{%s}array' % namespace).find('{%s}data' % namespace).findall('{%s}value' % namespace):
|
||||
array.append(_xml2py(val))
|
||||
return array
|
||||
raise ValueError()
|
||||
|
||||
@@ -163,7 +163,7 @@ class ACL:
|
||||
|
||||
@classmethod
|
||||
def _next_token(cls, expression, index):
|
||||
new_index = expression.xml.find('*', index)
|
||||
new_index = expression.find('*', index)
|
||||
if new_index == 0:
|
||||
return ''
|
||||
else:
|
||||
@@ -182,7 +182,7 @@ class ACL:
|
||||
#! print "[TOKEN] '%s'" % token
|
||||
size = len(token)
|
||||
if size > 0:
|
||||
token_index = value.xml.find(token, position)
|
||||
token_index = value.find(token, position)
|
||||
if token_index == -1:
|
||||
return False
|
||||
else:
|
||||
|
||||
@@ -24,7 +24,7 @@ class XEP_0009(BasePlugin):
|
||||
|
||||
name = 'xep_0009'
|
||||
description = 'XEP-0009: Jabber-RPC'
|
||||
dependencies = {'xep_0030'}
|
||||
dependencies = set(['xep_0030'])
|
||||
stanza = stanza
|
||||
|
||||
def plugin_init(self):
|
||||
@@ -121,7 +121,7 @@ class XEP_0009(BasePlugin):
|
||||
def _recipient_unvailable(self, iq):
|
||||
payload = iq.get_payload()
|
||||
iq = iq.reply()
|
||||
iq.error().set_payload(payload)
|
||||
error().set_payload(payload)
|
||||
iq['error']['code'] = '404'
|
||||
iq['error']['type'] = 'wait'
|
||||
iq['error']['condition'] = 'recipient-unavailable'
|
||||
|
||||
@@ -14,8 +14,8 @@ class RPCQuery(ElementBase):
|
||||
name = 'query'
|
||||
namespace = 'jabber:iq:rpc'
|
||||
plugin_attrib = 'rpc_query'
|
||||
interfaces = {}
|
||||
subinterfaces = {}
|
||||
interfaces = set(())
|
||||
subinterfaces = set(())
|
||||
plugin_attrib_map = {}
|
||||
plugin_tag_map = {}
|
||||
|
||||
@@ -24,8 +24,8 @@ class MethodCall(ElementBase):
|
||||
name = 'methodCall'
|
||||
namespace = 'jabber:iq:rpc'
|
||||
plugin_attrib = 'method_call'
|
||||
interfaces = {'method_name', 'params'}
|
||||
subinterfaces = {}
|
||||
interfaces = set(('method_name', 'params'))
|
||||
subinterfaces = set(())
|
||||
plugin_attrib_map = {}
|
||||
plugin_tag_map = {}
|
||||
|
||||
@@ -46,8 +46,8 @@ class MethodResponse(ElementBase):
|
||||
name = 'methodResponse'
|
||||
namespace = 'jabber:iq:rpc'
|
||||
plugin_attrib = 'method_response'
|
||||
interfaces = {'params', 'fault'}
|
||||
subinterfaces = {}
|
||||
interfaces = set(('params', 'fault'))
|
||||
subinterfaces = set(())
|
||||
plugin_attrib_map = {}
|
||||
plugin_tag_map = {}
|
||||
|
||||
|
||||
@@ -13,3 +13,7 @@ from slixmpp.plugins.xep_0012.last_activity import XEP_0012
|
||||
|
||||
|
||||
register_plugin(XEP_0012)
|
||||
|
||||
|
||||
# Retain some backwards compatibility
|
||||
xep_0004 = XEP_0012
|
||||
|
||||
@@ -29,7 +29,7 @@ class XEP_0012(BasePlugin):
|
||||
|
||||
name = 'xep_0012'
|
||||
description = 'XEP-0012: Last Activity'
|
||||
dependencies = {'xep_0030'}
|
||||
dependencies = set(['xep_0030'])
|
||||
stanza = stanza
|
||||
|
||||
def plugin_init(self):
|
||||
@@ -66,7 +66,7 @@ class XEP_0012(BasePlugin):
|
||||
self.del_last_activity(jid)
|
||||
|
||||
def start_uptime(self, status=None):
|
||||
self.set_last_activity(None, 0, status)
|
||||
self.set_last_activity(jid, 0, status)
|
||||
|
||||
def set_last_activity(self, jid=None, seconds=None, status=None):
|
||||
self.api['set_last_activity'](jid, args={
|
||||
|
||||
@@ -14,7 +14,7 @@ class LastActivity(ElementBase):
|
||||
name = 'query'
|
||||
namespace = 'jabber:iq:last'
|
||||
plugin_attrib = 'last_activity'
|
||||
interfaces = {'seconds', 'status'}
|
||||
interfaces = set(('seconds', 'status'))
|
||||
|
||||
def get_seconds(self):
|
||||
return int(self._get_attr('seconds'))
|
||||
|
||||
@@ -29,7 +29,7 @@ class XEP_0013(BasePlugin):
|
||||
|
||||
name = 'xep_0013'
|
||||
description = 'XEP-0013: Flexible Offline Message Retrieval'
|
||||
dependencies = {'xep_0030'}
|
||||
dependencies = set(['xep_0030'])
|
||||
stanza = stanza
|
||||
|
||||
def plugin_init(self):
|
||||
|
||||
@@ -14,7 +14,7 @@ class Offline(ElementBase):
|
||||
name = 'offline'
|
||||
namespace = 'http://jabber.org/protocol/offline'
|
||||
plugin_attrib = 'offline'
|
||||
interfaces = {'fetch', 'purge', 'results'}
|
||||
interfaces = set(['fetch', 'purge', 'results'])
|
||||
bool_interfaces = interfaces
|
||||
|
||||
def setup(self, xml=None):
|
||||
@@ -39,9 +39,9 @@ class Item(ElementBase):
|
||||
name = 'item'
|
||||
namespace = 'http://jabber.org/protocol/offline'
|
||||
plugin_attrib = 'item'
|
||||
interfaces = {'action', 'node', 'jid'}
|
||||
interfaces = set(['action', 'node', 'jid'])
|
||||
|
||||
actions = {'view', 'remove'}
|
||||
actions = set(['view', 'remove'])
|
||||
|
||||
def get_jid(self):
|
||||
return JID(self._get_attr('jid'))
|
||||
|
||||
@@ -17,7 +17,7 @@ class XEP_0016(BasePlugin):
|
||||
|
||||
name = 'xep_0016'
|
||||
description = 'XEP-0016: Privacy Lists'
|
||||
dependencies = {'xep_0030'}
|
||||
dependencies = set(['xep_0030'])
|
||||
stanza = stanza
|
||||
|
||||
def plugin_init(self):
|
||||
|
||||
@@ -18,14 +18,14 @@ class Active(ElementBase):
|
||||
name = 'active'
|
||||
namespace = 'jabber:iq:privacy'
|
||||
plugin_attrib = name
|
||||
interfaces = {'name'}
|
||||
interfaces = set(['name'])
|
||||
|
||||
|
||||
class Default(ElementBase):
|
||||
name = 'default'
|
||||
namespace = 'jabber:iq:privacy'
|
||||
plugin_attrib = name
|
||||
interfaces = {'name'}
|
||||
interfaces = set(['name'])
|
||||
|
||||
|
||||
class List(ElementBase):
|
||||
@@ -33,7 +33,7 @@ class List(ElementBase):
|
||||
namespace = 'jabber:iq:privacy'
|
||||
plugin_attrib = name
|
||||
plugin_multi_attrib = 'lists'
|
||||
interfaces = {'name'}
|
||||
interfaces = set(['name'])
|
||||
|
||||
def add_item(self, value, action, order, itype=None, iq=False,
|
||||
message=False, presence_in=False, presence_out=False):
|
||||
@@ -55,9 +55,9 @@ class Item(ElementBase):
|
||||
namespace = 'jabber:iq:privacy'
|
||||
plugin_attrib = name
|
||||
plugin_multi_attrib = 'items'
|
||||
interfaces = {'type', 'value', 'action', 'order', 'iq',
|
||||
'message', 'presence_in', 'presence_out'}
|
||||
bool_interfaces = {'message', 'iq', 'presence_in', 'presence_out'}
|
||||
interfaces = set(['type', 'value', 'action', 'order', 'iq',
|
||||
'message', 'presence_in', 'presence_out'])
|
||||
bool_interfaces = set(['message', 'iq', 'presence_in', 'presence_out'])
|
||||
|
||||
type_values = ('', 'jid', 'group', 'subscription')
|
||||
action_values = ('allow', 'deny')
|
||||
|
||||
@@ -24,7 +24,7 @@ class XEP_0020(BasePlugin):
|
||||
|
||||
name = 'xep_0020'
|
||||
description = 'XEP-0020: Feature Negotiation'
|
||||
dependencies = {'xep_0004', 'xep_0030'}
|
||||
dependencies = set(['xep_0004', 'xep_0030'])
|
||||
stanza = stanza
|
||||
|
||||
def plugin_init(self):
|
||||
|
||||
@@ -13,7 +13,7 @@ class Signed(ElementBase):
|
||||
name = 'x'
|
||||
namespace = 'jabber:x:signed'
|
||||
plugin_attrib = 'signed'
|
||||
interfaces = {'signed'}
|
||||
interfaces = set(['signed'])
|
||||
is_extension = True
|
||||
|
||||
def set_signed(self, value):
|
||||
@@ -33,7 +33,7 @@ class Encrypted(ElementBase):
|
||||
name = 'x'
|
||||
namespace = 'jabber:x:encrypted'
|
||||
plugin_attrib = 'encrypted'
|
||||
interfaces = {'encrypted'}
|
||||
interfaces = set(['encrypted'])
|
||||
is_extension = True
|
||||
|
||||
def set_encrypted(self, value):
|
||||
|
||||
@@ -15,3 +15,8 @@ from slixmpp.plugins.xep_0030.disco import XEP_0030
|
||||
|
||||
|
||||
register_plugin(XEP_0030)
|
||||
|
||||
# Retain some backwards compatibility
|
||||
xep_0030 = XEP_0030
|
||||
XEP_0030.getInfo = XEP_0030.get_info
|
||||
XEP_0030.make_static = XEP_0030.restore_defaults
|
||||
|
||||
@@ -71,8 +71,8 @@ class DiscoInfo(ElementBase):
|
||||
name = 'query'
|
||||
namespace = 'http://jabber.org/protocol/disco#info'
|
||||
plugin_attrib = 'disco_info'
|
||||
interfaces = {'node', 'features', 'identities'}
|
||||
lang_interfaces = {'identities'}
|
||||
interfaces = set(('node', 'features', 'identities'))
|
||||
lang_interfaces = set(('identities',))
|
||||
|
||||
# Cache identities and features
|
||||
_identities = set()
|
||||
@@ -91,7 +91,7 @@ class DiscoInfo(ElementBase):
|
||||
"""
|
||||
ElementBase.setup(self, xml)
|
||||
|
||||
self._identities = {id[0:3] for id in self['identities']}
|
||||
self._identities = set([id[0:3] for id in self['identities']])
|
||||
self._features = self['features']
|
||||
|
||||
def add_identity(self, category, itype, name=None, lang=None):
|
||||
@@ -137,7 +137,7 @@ class DiscoInfo(ElementBase):
|
||||
identity = (category, itype, lang)
|
||||
if identity in self._identities:
|
||||
self._identities.remove(identity)
|
||||
for id_xml in self.xml.findall('{%s}identity' % self.namespace):
|
||||
for id_xml in self.findall('{%s}identity' % self.namespace):
|
||||
id = (id_xml.attrib['category'],
|
||||
id_xml.attrib['type'],
|
||||
id_xml.attrib.get('{%s}lang' % self.xml_ns, None))
|
||||
@@ -163,7 +163,7 @@ class DiscoInfo(ElementBase):
|
||||
identities = set()
|
||||
else:
|
||||
identities = []
|
||||
for id_xml in self.xml.findall('{%s}identity' % self.namespace):
|
||||
for id_xml in self.findall('{%s}identity' % self.namespace):
|
||||
xml_lang = id_xml.attrib.get('{%s}lang' % self.xml_ns, None)
|
||||
if lang is None or xml_lang == lang:
|
||||
id = (id_xml.attrib['category'],
|
||||
@@ -205,7 +205,7 @@ class DiscoInfo(ElementBase):
|
||||
Arguments:
|
||||
lang -- Optional, standard xml:lang value.
|
||||
"""
|
||||
for id_xml in self.xml.findall('{%s}identity' % self.namespace):
|
||||
for id_xml in self.findall('{%s}identity' % self.namespace):
|
||||
if lang is None:
|
||||
self.xml.remove(id_xml)
|
||||
elif id_xml.attrib.get('{%s}lang' % self.xml_ns, None) == lang:
|
||||
@@ -239,7 +239,7 @@ class DiscoInfo(ElementBase):
|
||||
"""
|
||||
if feature in self._features:
|
||||
self._features.remove(feature)
|
||||
for feature_xml in self.xml.findall('{%s}feature' % self.namespace):
|
||||
for feature_xml in self.findall('{%s}feature' % self.namespace):
|
||||
if feature_xml.attrib['var'] == feature:
|
||||
self.xml.remove(feature_xml)
|
||||
return True
|
||||
@@ -251,7 +251,7 @@ class DiscoInfo(ElementBase):
|
||||
features = set()
|
||||
else:
|
||||
features = []
|
||||
for feature_xml in self.xml.findall('{%s}feature' % self.namespace):
|
||||
for feature_xml in self.findall('{%s}feature' % self.namespace):
|
||||
if dedupe:
|
||||
features.add(feature_xml.attrib['var'])
|
||||
else:
|
||||
@@ -272,5 +272,5 @@ class DiscoInfo(ElementBase):
|
||||
def del_features(self):
|
||||
"""Remove all features."""
|
||||
self._features = set()
|
||||
for feature_xml in self.xml.findall('{%s}feature' % self.namespace):
|
||||
for feature_xml in self.findall('{%s}feature' % self.namespace):
|
||||
self.xml.remove(feature_xml)
|
||||
|
||||
@@ -45,7 +45,7 @@ class DiscoItems(ElementBase):
|
||||
name = 'query'
|
||||
namespace = 'http://jabber.org/protocol/disco#items'
|
||||
plugin_attrib = 'disco_items'
|
||||
interfaces = {'node', 'items'}
|
||||
interfaces = set(('node', 'items'))
|
||||
|
||||
# Cache items
|
||||
_items = set()
|
||||
@@ -62,7 +62,7 @@ class DiscoItems(ElementBase):
|
||||
xml -- Use an existing XML object for the stanza's values.
|
||||
"""
|
||||
ElementBase.setup(self, xml)
|
||||
self._items = {item[0:2] for item in self['items']}
|
||||
self._items = set([item[0:2] for item in self['items']])
|
||||
|
||||
def add_item(self, jid, node=None, name=None):
|
||||
"""
|
||||
@@ -95,7 +95,7 @@ class DiscoItems(ElementBase):
|
||||
node -- Optional extra identifying information.
|
||||
"""
|
||||
if (jid, node) in self._items:
|
||||
for item_xml in self.xml.findall('{%s}item' % self.namespace):
|
||||
for item_xml in self.findall('{%s}item' % self.namespace):
|
||||
item = (item_xml.attrib['jid'],
|
||||
item_xml.attrib.get('node', None))
|
||||
if item == (jid, node):
|
||||
@@ -138,7 +138,7 @@ class DiscoItem(ElementBase):
|
||||
name = 'item'
|
||||
namespace = 'http://jabber.org/protocol/disco#items'
|
||||
plugin_attrib = name
|
||||
interfaces = {'jid', 'node', 'name'}
|
||||
interfaces = set(('jid', 'node', 'name'))
|
||||
|
||||
def get_node(self):
|
||||
"""Return the item's node name or ``None``."""
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"""
|
||||
|
||||
import logging
|
||||
import threading
|
||||
|
||||
from slixmpp import Iq
|
||||
from slixmpp.exceptions import XMPPError, IqError, IqTimeout
|
||||
@@ -47,6 +48,7 @@ class StaticDisco(object):
|
||||
self.nodes = {}
|
||||
self.xmpp = xmpp
|
||||
self.disco = disco
|
||||
self.lock = threading.RLock()
|
||||
|
||||
def add_node(self, jid=None, node=None, ifrom=None):
|
||||
"""
|
||||
@@ -57,45 +59,48 @@ class StaticDisco(object):
|
||||
jid -- The JID that will own the new stanzas.
|
||||
node -- The node that will own the new stanzas.
|
||||
"""
|
||||
if jid is None:
|
||||
jid = self.xmpp.boundjid.full
|
||||
if node is None:
|
||||
node = ''
|
||||
if ifrom is None:
|
||||
ifrom = ''
|
||||
if isinstance(ifrom, JID):
|
||||
ifrom = ifrom.full
|
||||
if (jid, node, ifrom) not in self.nodes:
|
||||
self.nodes[(jid, node, ifrom)] = {'info': DiscoInfo(),
|
||||
'items': DiscoItems()}
|
||||
self.nodes[(jid, node, ifrom)]['info']['node'] = node
|
||||
self.nodes[(jid, node, ifrom)]['items']['node'] = node
|
||||
with self.lock:
|
||||
if jid is None:
|
||||
jid = self.xmpp.boundjid.full
|
||||
if node is None:
|
||||
node = ''
|
||||
if ifrom is None:
|
||||
ifrom = ''
|
||||
if isinstance(ifrom, JID):
|
||||
ifrom = ifrom.full
|
||||
if (jid, node, ifrom) not in self.nodes:
|
||||
self.nodes[(jid, node, ifrom)] = {'info': DiscoInfo(),
|
||||
'items': DiscoItems()}
|
||||
self.nodes[(jid, node, ifrom)]['info']['node'] = node
|
||||
self.nodes[(jid, node, ifrom)]['items']['node'] = node
|
||||
|
||||
def get_node(self, jid=None, node=None, ifrom=None):
|
||||
if jid is None:
|
||||
jid = self.xmpp.boundjid.full
|
||||
if node is None:
|
||||
node = ''
|
||||
if ifrom is None:
|
||||
ifrom = ''
|
||||
if isinstance(ifrom, JID):
|
||||
ifrom = ifrom.full
|
||||
if (jid, node, ifrom) not in self.nodes:
|
||||
self.add_node(jid, node, ifrom)
|
||||
return self.nodes[(jid, node, ifrom)]
|
||||
with self.lock:
|
||||
if jid is None:
|
||||
jid = self.xmpp.boundjid.full
|
||||
if node is None:
|
||||
node = ''
|
||||
if ifrom is None:
|
||||
ifrom = ''
|
||||
if isinstance(ifrom, JID):
|
||||
ifrom = ifrom.full
|
||||
if (jid, node, ifrom) not in self.nodes:
|
||||
self.add_node(jid, node, ifrom)
|
||||
return self.nodes[(jid, node, ifrom)]
|
||||
|
||||
def node_exists(self, jid=None, node=None, ifrom=None):
|
||||
if jid is None:
|
||||
jid = self.xmpp.boundjid.full
|
||||
if node is None:
|
||||
node = ''
|
||||
if ifrom is None:
|
||||
ifrom = ''
|
||||
if isinstance(ifrom, JID):
|
||||
ifrom = ifrom.full
|
||||
if (jid, node, ifrom) not in self.nodes:
|
||||
return False
|
||||
return True
|
||||
with self.lock:
|
||||
if jid is None:
|
||||
jid = self.xmpp.boundjid.full
|
||||
if node is None:
|
||||
node = ''
|
||||
if ifrom is None:
|
||||
ifrom = ''
|
||||
if isinstance(ifrom, JID):
|
||||
ifrom = ifrom.full
|
||||
if (jid, node, ifrom) not in self.nodes:
|
||||
return False
|
||||
return True
|
||||
|
||||
# =================================================================
|
||||
# Node Handlers
|
||||
@@ -194,13 +199,14 @@ class StaticDisco(object):
|
||||
|
||||
The data parameter is not used.
|
||||
"""
|
||||
if not self.node_exists(jid, node):
|
||||
if not node:
|
||||
return DiscoInfo()
|
||||
with self.lock:
|
||||
if not self.node_exists(jid, node):
|
||||
if not node:
|
||||
return DiscoInfo()
|
||||
else:
|
||||
raise XMPPError(condition='item-not-found')
|
||||
else:
|
||||
raise XMPPError(condition='item-not-found')
|
||||
else:
|
||||
return self.get_node(jid, node)['info']
|
||||
return self.get_node(jid, node)['info']
|
||||
|
||||
def set_info(self, jid, node, ifrom, data):
|
||||
"""
|
||||
@@ -208,8 +214,9 @@ class StaticDisco(object):
|
||||
|
||||
The data parameter is a disco#info substanza.
|
||||
"""
|
||||
self.add_node(jid, node)
|
||||
self.get_node(jid, node)['info'] = data
|
||||
with self.lock:
|
||||
self.add_node(jid, node)
|
||||
self.get_node(jid, node)['info'] = data
|
||||
|
||||
def del_info(self, jid, node, ifrom, data):
|
||||
"""
|
||||
@@ -217,8 +224,9 @@ class StaticDisco(object):
|
||||
|
||||
The data parameter is not used.
|
||||
"""
|
||||
if self.node_exists(jid, node):
|
||||
self.get_node(jid, node)['info'] = DiscoInfo()
|
||||
with self.lock:
|
||||
if self.node_exists(jid, node):
|
||||
self.get_node(jid, node)['info'] = DiscoInfo()
|
||||
|
||||
def get_items(self, jid, node, ifrom, data):
|
||||
"""
|
||||
@@ -226,13 +234,14 @@ class StaticDisco(object):
|
||||
|
||||
The data parameter is not used.
|
||||
"""
|
||||
if not self.node_exists(jid, node):
|
||||
if not node:
|
||||
return DiscoItems()
|
||||
with self.lock:
|
||||
if not self.node_exists(jid, node):
|
||||
if not node:
|
||||
return DiscoItems()
|
||||
else:
|
||||
raise XMPPError(condition='item-not-found')
|
||||
else:
|
||||
raise XMPPError(condition='item-not-found')
|
||||
else:
|
||||
return self.get_node(jid, node)['items']
|
||||
return self.get_node(jid, node)['items']
|
||||
|
||||
def set_items(self, jid, node, ifrom, data):
|
||||
"""
|
||||
@@ -241,9 +250,10 @@ class StaticDisco(object):
|
||||
The data parameter may provide:
|
||||
items -- A set of items in tuple format.
|
||||
"""
|
||||
items = data.get('items', set())
|
||||
self.add_node(jid, node)
|
||||
self.get_node(jid, node)['items']['items'] = items
|
||||
with self.lock:
|
||||
items = data.get('items', set())
|
||||
self.add_node(jid, node)
|
||||
self.get_node(jid, node)['items']['items'] = items
|
||||
|
||||
def del_items(self, jid, node, ifrom, data):
|
||||
"""
|
||||
@@ -251,8 +261,9 @@ class StaticDisco(object):
|
||||
|
||||
The data parameter is not used.
|
||||
"""
|
||||
if self.node_exists(jid, node):
|
||||
self.get_node(jid, node)['items'] = DiscoItems()
|
||||
with self.lock:
|
||||
if self.node_exists(jid, node):
|
||||
self.get_node(jid, node)['items'] = DiscoItems()
|
||||
|
||||
def add_identity(self, jid, node, ifrom, data):
|
||||
"""
|
||||
@@ -264,12 +275,13 @@ class StaticDisco(object):
|
||||
name -- Optional human readable name for this identity.
|
||||
lang -- Optional standard xml:lang value.
|
||||
"""
|
||||
self.add_node(jid, node)
|
||||
self.get_node(jid, node)['info'].add_identity(
|
||||
data.get('category', ''),
|
||||
data.get('itype', ''),
|
||||
data.get('name', None),
|
||||
data.get('lang', None))
|
||||
with self.lock:
|
||||
self.add_node(jid, node)
|
||||
self.get_node(jid, node)['info'].add_identity(
|
||||
data.get('category', ''),
|
||||
data.get('itype', ''),
|
||||
data.get('name', None),
|
||||
data.get('lang', None))
|
||||
|
||||
def set_identities(self, jid, node, ifrom, data):
|
||||
"""
|
||||
@@ -279,9 +291,10 @@ class StaticDisco(object):
|
||||
identities -- A list of identities in tuple form:
|
||||
(category, type, name, lang)
|
||||
"""
|
||||
identities = data.get('identities', set())
|
||||
self.add_node(jid, node)
|
||||
self.get_node(jid, node)['info']['identities'] = identities
|
||||
with self.lock:
|
||||
identities = data.get('identities', set())
|
||||
self.add_node(jid, node)
|
||||
self.get_node(jid, node)['info']['identities'] = identities
|
||||
|
||||
def del_identity(self, jid, node, ifrom, data):
|
||||
"""
|
||||
@@ -293,12 +306,13 @@ class StaticDisco(object):
|
||||
name -- Optional human readable name for this identity.
|
||||
lang -- Optional, standard xml:lang value.
|
||||
"""
|
||||
if self.node_exists(jid, node):
|
||||
self.get_node(jid, node)['info'].del_identity(
|
||||
data.get('category', ''),
|
||||
data.get('itype', ''),
|
||||
data.get('name', None),
|
||||
data.get('lang', None))
|
||||
with self.lock:
|
||||
if self.node_exists(jid, node):
|
||||
self.get_node(jid, node)['info'].del_identity(
|
||||
data.get('category', ''),
|
||||
data.get('itype', ''),
|
||||
data.get('name', None),
|
||||
data.get('lang', None))
|
||||
|
||||
def del_identities(self, jid, node, ifrom, data):
|
||||
"""
|
||||
@@ -306,8 +320,9 @@ class StaticDisco(object):
|
||||
|
||||
The data parameter is not used.
|
||||
"""
|
||||
if self.node_exists(jid, node):
|
||||
del self.get_node(jid, node)['info']['identities']
|
||||
with self.lock:
|
||||
if self.node_exists(jid, node):
|
||||
del self.get_node(jid, node)['info']['identities']
|
||||
|
||||
def add_feature(self, jid, node, ifrom, data):
|
||||
"""
|
||||
@@ -316,9 +331,10 @@ class StaticDisco(object):
|
||||
The data parameter should include:
|
||||
feature -- The namespace of the supported feature.
|
||||
"""
|
||||
self.add_node(jid, node)
|
||||
self.get_node(jid, node)['info'].add_feature(
|
||||
data.get('feature', ''))
|
||||
with self.lock:
|
||||
self.add_node(jid, node)
|
||||
self.get_node(jid, node)['info'].add_feature(
|
||||
data.get('feature', ''))
|
||||
|
||||
def set_features(self, jid, node, ifrom, data):
|
||||
"""
|
||||
@@ -327,9 +343,10 @@ class StaticDisco(object):
|
||||
The data parameter should include:
|
||||
features -- The new set of supported features.
|
||||
"""
|
||||
features = data.get('features', set())
|
||||
self.add_node(jid, node)
|
||||
self.get_node(jid, node)['info']['features'] = features
|
||||
with self.lock:
|
||||
features = data.get('features', set())
|
||||
self.add_node(jid, node)
|
||||
self.get_node(jid, node)['info']['features'] = features
|
||||
|
||||
def del_feature(self, jid, node, ifrom, data):
|
||||
"""
|
||||
@@ -338,9 +355,10 @@ class StaticDisco(object):
|
||||
The data parameter should include:
|
||||
feature -- The namespace of the removed feature.
|
||||
"""
|
||||
if self.node_exists(jid, node):
|
||||
self.get_node(jid, node)['info'].del_feature(
|
||||
data.get('feature', ''))
|
||||
with self.lock:
|
||||
if self.node_exists(jid, node):
|
||||
self.get_node(jid, node)['info'].del_feature(
|
||||
data.get('feature', ''))
|
||||
|
||||
def del_features(self, jid, node, ifrom, data):
|
||||
"""
|
||||
@@ -348,9 +366,10 @@ class StaticDisco(object):
|
||||
|
||||
The data parameter is not used.
|
||||
"""
|
||||
if not self.node_exists(jid, node):
|
||||
return
|
||||
del self.get_node(jid, node)['info']['features']
|
||||
with self.lock:
|
||||
if not self.node_exists(jid, node):
|
||||
return
|
||||
del self.get_node(jid, node)['info']['features']
|
||||
|
||||
def add_item(self, jid, node, ifrom, data):
|
||||
"""
|
||||
@@ -362,11 +381,12 @@ class StaticDisco(object):
|
||||
non-addressable items.
|
||||
name -- Optional human readable name for the item.
|
||||
"""
|
||||
self.add_node(jid, node)
|
||||
self.get_node(jid, node)['items'].add_item(
|
||||
data.get('ijid', ''),
|
||||
node=data.get('inode', ''),
|
||||
name=data.get('name', ''))
|
||||
with self.lock:
|
||||
self.add_node(jid, node)
|
||||
self.get_node(jid, node)['items'].add_item(
|
||||
data.get('ijid', ''),
|
||||
node=data.get('inode', ''),
|
||||
name=data.get('name', ''))
|
||||
|
||||
def del_item(self, jid, node, ifrom, data):
|
||||
"""
|
||||
@@ -376,10 +396,11 @@ class StaticDisco(object):
|
||||
ijid -- JID of the item to remove.
|
||||
inode -- Optional extra identifying information.
|
||||
"""
|
||||
if self.node_exists(jid, node):
|
||||
self.get_node(jid, node)['items'].del_item(
|
||||
data.get('ijid', ''),
|
||||
node=data.get('inode', None))
|
||||
with self.lock:
|
||||
if self.node_exists(jid, node):
|
||||
self.get_node(jid, node)['items'].del_item(
|
||||
data.get('ijid', ''),
|
||||
node=data.get('inode', None))
|
||||
|
||||
def cache_info(self, jid, node, ifrom, data):
|
||||
"""
|
||||
@@ -389,11 +410,12 @@ class StaticDisco(object):
|
||||
containing the disco info to cache, or
|
||||
the disco#info substanza itself.
|
||||
"""
|
||||
if isinstance(data, Iq):
|
||||
data = data['disco_info']
|
||||
with self.lock:
|
||||
if isinstance(data, Iq):
|
||||
data = data['disco_info']
|
||||
|
||||
self.add_node(jid, node, ifrom)
|
||||
self.get_node(jid, node, ifrom)['info'] = data
|
||||
self.add_node(jid, node, ifrom)
|
||||
self.get_node(jid, node, ifrom)['info'] = data
|
||||
|
||||
def get_cached_info(self, jid, node, ifrom, data):
|
||||
"""
|
||||
@@ -401,7 +423,8 @@ class StaticDisco(object):
|
||||
|
||||
The data parameter is not used.
|
||||
"""
|
||||
if not self.node_exists(jid, node, ifrom):
|
||||
return None
|
||||
else:
|
||||
return self.get_node(jid, node, ifrom)['info']
|
||||
with self.lock:
|
||||
if not self.node_exists(jid, node, ifrom):
|
||||
return None
|
||||
else:
|
||||
return self.get_node(jid, node, ifrom)['info']
|
||||
|
||||
@@ -14,3 +14,7 @@ from slixmpp.plugins.xep_0033.addresses import XEP_0033
|
||||
|
||||
|
||||
register_plugin(XEP_0033)
|
||||
|
||||
# Retain some backwards compatibility
|
||||
xep_0033 = XEP_0033
|
||||
Addresses.addAddress = Addresses.add_address
|
||||
|
||||
@@ -22,7 +22,7 @@ class XEP_0033(BasePlugin):
|
||||
|
||||
name = 'xep_0033'
|
||||
description = 'XEP-0033: Extended Stanza Addressing'
|
||||
dependencies = {'xep_0030'}
|
||||
dependencies = set(['xep_0030'])
|
||||
stanza = stanza
|
||||
|
||||
def plugin_init(self):
|
||||
|
||||
@@ -37,9 +37,9 @@ class Address(ElementBase):
|
||||
name = 'address'
|
||||
namespace = 'http://jabber.org/protocol/address'
|
||||
plugin_attrib = 'address'
|
||||
interfaces = {'type', 'jid', 'node', 'uri', 'desc', 'delivered'}
|
||||
interfaces = set(['type', 'jid', 'node', 'uri', 'desc', 'delivered'])
|
||||
|
||||
address_types = {'bcc', 'cc', 'noreply', 'replyroom', 'replyto', 'to'}
|
||||
address_types = set(('bcc', 'cc', 'noreply', 'replyroom', 'replyto', 'to'))
|
||||
|
||||
def get_jid(self):
|
||||
return JID(self._get_attr('jid'))
|
||||
@@ -117,12 +117,15 @@ for atype in ('all', 'bcc', 'cc', 'noreply', 'replyroom', 'replyto', 'to'):
|
||||
setattr(Addresses, "set_%s" % atype, set_multi)
|
||||
setattr(Addresses, "del_%s" % atype, del_multi)
|
||||
|
||||
# To retain backwards compatibility:
|
||||
setattr(Addresses, "get%s" % atype.title(), get_multi)
|
||||
setattr(Addresses, "set%s" % atype.title(), set_multi)
|
||||
setattr(Addresses, "del%s" % atype.title(), del_multi)
|
||||
if atype == 'all':
|
||||
Addresses.interfaces.add('addresses')
|
||||
setattr(Addresses, "get_addresses", get_multi)
|
||||
setattr(Addresses, "set_addresses", set_multi)
|
||||
setattr(Addresses, "del_addresses", del_multi)
|
||||
|
||||
setattr(Addresses, "getAddresses", get_multi)
|
||||
setattr(Addresses, "setAddresses", set_multi)
|
||||
setattr(Addresses, "delAddresses", del_multi)
|
||||
|
||||
|
||||
register_stanza_plugin(Addresses, Address, iterable=True)
|
||||
|
||||
@@ -25,86 +25,86 @@ class MUCPresence(ElementBase):
|
||||
name = 'x'
|
||||
namespace = 'http://jabber.org/protocol/muc#user'
|
||||
plugin_attrib = 'muc'
|
||||
interfaces = {'affiliation', 'role', 'jid', 'nick', 'room'}
|
||||
affiliations = {'', }
|
||||
roles = {'', }
|
||||
interfaces = set(('affiliation', 'role', 'jid', 'nick', 'room'))
|
||||
affiliations = set(('', ))
|
||||
roles = set(('', ))
|
||||
|
||||
def get_xml_item(self):
|
||||
def getXMLItem(self):
|
||||
item = self.xml.find('{http://jabber.org/protocol/muc#user}item')
|
||||
if item is None:
|
||||
item = ET.Element('{http://jabber.org/protocol/muc#user}item')
|
||||
self.xml.append(item)
|
||||
return item
|
||||
|
||||
def get_affiliation(self):
|
||||
def getAffiliation(self):
|
||||
#TODO if no affilation, set it to the default and return default
|
||||
item = self.get_xml_item()
|
||||
item = self.getXMLItem()
|
||||
return item.get('affiliation', '')
|
||||
|
||||
def set_affiliation(self, value):
|
||||
item = self.get_xml_item()
|
||||
def setAffiliation(self, value):
|
||||
item = self.getXMLItem()
|
||||
#TODO check for valid affiliation
|
||||
item.attrib['affiliation'] = value
|
||||
return self
|
||||
|
||||
def del_affiliation(self):
|
||||
item = self.get_xml_item()
|
||||
def delAffiliation(self):
|
||||
item = self.getXMLItem()
|
||||
#TODO set default affiliation
|
||||
if 'affiliation' in item.attrib: del item.attrib['affiliation']
|
||||
return self
|
||||
|
||||
def get_jid(self):
|
||||
item = self.get_xml_item()
|
||||
def getJid(self):
|
||||
item = self.getXMLItem()
|
||||
return JID(item.get('jid', ''))
|
||||
|
||||
def set_jid(self, value):
|
||||
item = self.get_xml_item()
|
||||
def setJid(self, value):
|
||||
item = self.getXMLItem()
|
||||
if not isinstance(value, str):
|
||||
value = str(value)
|
||||
item.attrib['jid'] = value
|
||||
return self
|
||||
|
||||
def del_jid(self):
|
||||
item = self.get_xml_item()
|
||||
def delJid(self):
|
||||
item = self.getXMLItem()
|
||||
if 'jid' in item.attrib: del item.attrib['jid']
|
||||
return self
|
||||
|
||||
def get_role(self):
|
||||
item = self.get_xml_item()
|
||||
def getRole(self):
|
||||
item = self.getXMLItem()
|
||||
#TODO get default role, set default role if none
|
||||
return item.get('role', '')
|
||||
|
||||
def set_role(self, value):
|
||||
item = self.get_xml_item()
|
||||
def setRole(self, value):
|
||||
item = self.getXMLItem()
|
||||
#TODO check for valid role
|
||||
item.attrib['role'] = value
|
||||
return self
|
||||
|
||||
def del_role(self):
|
||||
item = self.get_xml_item()
|
||||
def delRole(self):
|
||||
item = self.getXMLItem()
|
||||
#TODO set default role
|
||||
if 'role' in item.attrib: del item.attrib['role']
|
||||
return self
|
||||
|
||||
def get_nick(self):
|
||||
def getNick(self):
|
||||
return self.parent()['from'].resource
|
||||
|
||||
def get_room(self):
|
||||
def getRoom(self):
|
||||
return self.parent()['from'].bare
|
||||
|
||||
def set_nick(self, value):
|
||||
def setNick(self, value):
|
||||
log.warning("Cannot set nick through mucpresence plugin.")
|
||||
return self
|
||||
|
||||
def set_room(self, value):
|
||||
def setRoom(self, value):
|
||||
log.warning("Cannot set room through mucpresence plugin.")
|
||||
return self
|
||||
|
||||
def del_nick(self):
|
||||
def delNick(self):
|
||||
log.warning("Cannot delete nick through mucpresence plugin.")
|
||||
return self
|
||||
|
||||
def del_room(self):
|
||||
def delRoom(self):
|
||||
log.warning("Cannot delete room through mucpresence plugin.")
|
||||
return self
|
||||
|
||||
@@ -117,11 +117,11 @@ class XEP_0045(BasePlugin):
|
||||
|
||||
name = 'xep_0045'
|
||||
description = 'XEP-0045: Multi-User Chat'
|
||||
dependencies = {'xep_0030', 'xep_0004'}
|
||||
dependencies = set(['xep_0030', 'xep_0004'])
|
||||
|
||||
def plugin_init(self):
|
||||
self.rooms = {}
|
||||
self.our_nicks = {}
|
||||
self.ourNicks = {}
|
||||
self.xep = '0045'
|
||||
# load MUC support in presence stanzas
|
||||
register_stanza_plugin(Presence, MUCPresence)
|
||||
@@ -160,7 +160,6 @@ class XEP_0045(BasePlugin):
|
||||
got_online = False
|
||||
if pr['muc']['room'] not in self.rooms.keys():
|
||||
return
|
||||
self.xmpp.roster[pr['from']].ignore_updates = True
|
||||
entry = pr['muc'].get_stanza_values()
|
||||
entry['show'] = pr['show']
|
||||
entry['status'] = pr['status']
|
||||
@@ -201,28 +200,28 @@ class XEP_0045(BasePlugin):
|
||||
"""
|
||||
self.xmpp.event('groupchat_subject', msg)
|
||||
|
||||
def jid_in_room(self, room, jid):
|
||||
def jidInRoom(self, room, jid):
|
||||
for nick in self.rooms[room]:
|
||||
entry = self.rooms[room][nick]
|
||||
if entry is not None and entry['jid'].full == jid:
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_nick(self, room, jid):
|
||||
def getNick(self, room, jid):
|
||||
for nick in self.rooms[room]:
|
||||
entry = self.rooms[room][nick]
|
||||
if entry is not None and entry['jid'].full == jid:
|
||||
return nick
|
||||
|
||||
def configure_room(self, room, form=None, ifrom=None):
|
||||
def configureRoom(self, room, form=None, ifrom=None):
|
||||
if form is None:
|
||||
form = self.get_room_config(room, ifrom=ifrom)
|
||||
form = self.getRoomConfig(room, ifrom=ifrom)
|
||||
iq = self.xmpp.make_iq_set()
|
||||
iq['to'] = room
|
||||
if ifrom is not None:
|
||||
iq['from'] = ifrom
|
||||
query = ET.Element('{http://jabber.org/protocol/muc#owner}query')
|
||||
form['type'] = 'submit'
|
||||
form = form.getXML('submit')
|
||||
query.append(form)
|
||||
iq.append(query)
|
||||
# For now, swallow errors to preserve existing API
|
||||
@@ -234,7 +233,7 @@ class XEP_0045(BasePlugin):
|
||||
return False
|
||||
return True
|
||||
|
||||
def join_muc(self, room, nick, maxhistory="0", password='', wait=False, pstatus=None, pshow=None, pfrom=None):
|
||||
def joinMUC(self, room, nick, maxhistory="0", password='', wait=False, pstatus=None, pshow=None, pfrom=None):
|
||||
""" Join the specified room, requesting 'maxhistory' lines of history.
|
||||
"""
|
||||
stanza = self.xmpp.make_presence(pto="%s/%s" % (room, nick), pstatus=pstatus, pshow=pshow, pfrom=pfrom)
|
||||
@@ -258,7 +257,7 @@ class XEP_0045(BasePlugin):
|
||||
expect = ET.Element("{%s}presence" % self.xmpp.default_ns, {'from':"%s/%s" % (room, nick)})
|
||||
self.xmpp.send(stanza, expect)
|
||||
self.rooms[room] = {}
|
||||
self.our_nicks[room] = nick
|
||||
self.ourNicks[room] = nick
|
||||
|
||||
def destroy(self, room, reason='', altroom = '', ifrom=None):
|
||||
iq = self.xmpp.make_iq_set()
|
||||
@@ -283,7 +282,7 @@ class XEP_0045(BasePlugin):
|
||||
return False
|
||||
return True
|
||||
|
||||
def set_affiliation(self, room, jid=None, nick=None, affiliation='member', ifrom=None):
|
||||
def setAffiliation(self, room, jid=None, nick=None, affiliation='member', ifrom=None):
|
||||
""" Change room affiliation."""
|
||||
if affiliation not in ('outcast', 'member', 'admin', 'owner', 'none'):
|
||||
raise TypeError
|
||||
@@ -305,7 +304,7 @@ class XEP_0045(BasePlugin):
|
||||
return False
|
||||
return True
|
||||
|
||||
def set_role(self, room, nick, role):
|
||||
def setRole(self, room, nick, role):
|
||||
""" Change role property of a nick in a room.
|
||||
Typically, roles are temporary (they last only as long as you are in the
|
||||
room), whereas affiliations are permanent (they last across groupchat
|
||||
@@ -337,7 +336,7 @@ class XEP_0045(BasePlugin):
|
||||
msg.append(x)
|
||||
self.xmpp.send(msg)
|
||||
|
||||
def leave_muc(self, room, nick, msg='', pfrom=None):
|
||||
def leaveMUC(self, room, nick, msg='', pfrom=None):
|
||||
""" Leave the specified room.
|
||||
"""
|
||||
if msg:
|
||||
@@ -346,7 +345,7 @@ class XEP_0045(BasePlugin):
|
||||
self.xmpp.send_presence(pshow='unavailable', pto="%s/%s" % (room, nick), pfrom=pfrom)
|
||||
del self.rooms[room]
|
||||
|
||||
def get_room_config(self, room, ifrom=''):
|
||||
def getRoomConfig(self, room, ifrom=''):
|
||||
iq = self.xmpp.make_iq_get('http://jabber.org/protocol/muc#owner')
|
||||
iq['to'] = room
|
||||
iq['from'] = ifrom
|
||||
@@ -360,9 +359,9 @@ class XEP_0045(BasePlugin):
|
||||
form = result.xml.find('{http://jabber.org/protocol/muc#owner}query/{jabber:x:data}x')
|
||||
if form is None:
|
||||
raise ValueError
|
||||
return self.xmpp.plugin['xep_0004'].build_form(form)
|
||||
return self.xmpp.plugin['xep_0004'].buildForm(form)
|
||||
|
||||
def cancel_config(self, room, ifrom=None):
|
||||
def cancelConfig(self, room, ifrom=None):
|
||||
query = ET.Element('{http://jabber.org/protocol/muc#owner}query')
|
||||
x = ET.Element('{jabber:x:data}x', type='cancel')
|
||||
query.append(x)
|
||||
@@ -371,40 +370,40 @@ class XEP_0045(BasePlugin):
|
||||
iq['from'] = ifrom
|
||||
iq.send()
|
||||
|
||||
def set_room_config(self, room, config, ifrom=''):
|
||||
def setRoomConfig(self, room, config, ifrom=''):
|
||||
query = ET.Element('{http://jabber.org/protocol/muc#owner}query')
|
||||
config['type'] = 'submit'
|
||||
query.append(config)
|
||||
x = config.getXML('submit')
|
||||
query.append(x)
|
||||
iq = self.xmpp.make_iq_set(query)
|
||||
iq['to'] = room
|
||||
iq['from'] = ifrom
|
||||
iq.send()
|
||||
|
||||
def get_joined_rooms(self):
|
||||
def getJoinedRooms(self):
|
||||
return self.rooms.keys()
|
||||
|
||||
def get_our_jid_in_room(self, room_jid):
|
||||
def getOurJidInRoom(self, roomJid):
|
||||
""" Return the jid we're using in a room.
|
||||
"""
|
||||
return "%s/%s" % (room_jid, self.our_nicks[room_jid])
|
||||
return "%s/%s" % (roomJid, self.ourNicks[roomJid])
|
||||
|
||||
def get_jid_property(self, room, nick, jid_property):
|
||||
def getJidProperty(self, room, nick, jidProperty):
|
||||
""" Get the property of a nick in a room, such as its 'jid' or 'affiliation'
|
||||
If not found, return None.
|
||||
"""
|
||||
if room in self.rooms and nick in self.rooms[room] and jid_property in self.rooms[room][nick]:
|
||||
return self.rooms[room][nick][jid_property]
|
||||
if room in self.rooms and nick in self.rooms[room] and jidProperty in self.rooms[room][nick]:
|
||||
return self.rooms[room][nick][jidProperty]
|
||||
else:
|
||||
return None
|
||||
|
||||
def get_roster(self, room):
|
||||
def getRoster(self, room):
|
||||
""" Get the list of nicks in a room.
|
||||
"""
|
||||
if room not in self.rooms.keys():
|
||||
return None
|
||||
return self.rooms[room].keys()
|
||||
|
||||
def get_users_by_affiliation(cls, room, affiliation='member', ifrom=None):
|
||||
def getUsersByAffiliation(cls, room, affiliation='member', ifrom=None):
|
||||
if affiliation not in ('outcast', 'member', 'admin', 'owner', 'none'):
|
||||
raise TypeError
|
||||
query = ET.Element('{http://jabber.org/protocol/muc#admin}query')
|
||||
@@ -415,4 +414,5 @@ class XEP_0045(BasePlugin):
|
||||
return iq.send()
|
||||
|
||||
|
||||
xep_0045 = XEP_0045
|
||||
register_plugin(XEP_0045)
|
||||
|
||||
@@ -15,3 +15,7 @@ from slixmpp.plugins.xep_0047.ibb import XEP_0047
|
||||
|
||||
|
||||
register_plugin(XEP_0047)
|
||||
|
||||
|
||||
# Retain some backwards compatibility
|
||||
xep_0047 = XEP_0047
|
||||
|
||||
@@ -18,7 +18,7 @@ class XEP_0047(BasePlugin):
|
||||
|
||||
name = 'xep_0047'
|
||||
description = 'XEP-0047: In-band Bytestreams'
|
||||
dependencies = {'xep_0030'}
|
||||
dependencies = set(['xep_0030'])
|
||||
stanza = stanza
|
||||
default_config = {
|
||||
'block_size': 4096,
|
||||
|
||||
@@ -21,7 +21,7 @@ class Open(ElementBase):
|
||||
name = 'open'
|
||||
namespace = 'http://jabber.org/protocol/ibb'
|
||||
plugin_attrib = 'ibb_open'
|
||||
interfaces = {'block_size', 'sid', 'stanza'}
|
||||
interfaces = set(('block_size', 'sid', 'stanza'))
|
||||
|
||||
def get_block_size(self):
|
||||
return int(self._get_attr('block-size', '0'))
|
||||
@@ -37,8 +37,8 @@ class Data(ElementBase):
|
||||
name = 'data'
|
||||
namespace = 'http://jabber.org/protocol/ibb'
|
||||
plugin_attrib = 'ibb_data'
|
||||
interfaces = {'seq', 'sid', 'data'}
|
||||
sub_interfaces = {'data'}
|
||||
interfaces = set(('seq', 'sid', 'data'))
|
||||
sub_interfaces = set(['data'])
|
||||
|
||||
def get_seq(self):
|
||||
return int(self._get_attr('seq', '0'))
|
||||
@@ -67,4 +67,4 @@ class Close(ElementBase):
|
||||
name = 'close'
|
||||
namespace = 'http://jabber.org/protocol/ibb'
|
||||
plugin_attrib = 'ibb_close'
|
||||
interfaces = {'sid'}
|
||||
interfaces = set(['sid'])
|
||||
|
||||
@@ -24,7 +24,7 @@ class XEP_0048(BasePlugin):
|
||||
|
||||
name = 'xep_0048'
|
||||
description = 'XEP-0048: Bookmarks'
|
||||
dependencies = {'xep_0045', 'xep_0049', 'xep_0060', 'xep_0163', 'xep_0223'}
|
||||
dependencies = set(['xep_0045', 'xep_0049', 'xep_0060', 'xep_0163', 'xep_0223'])
|
||||
stanza = stanza
|
||||
default_config = {
|
||||
'auto_join': False,
|
||||
@@ -59,7 +59,7 @@ class XEP_0048(BasePlugin):
|
||||
for conf in bookmarks['conferences']:
|
||||
if conf['autojoin']:
|
||||
log.debug('Auto joining %s as %s', conf['jid'], conf['nick'])
|
||||
self.xmpp['xep_0045'].join_muc(conf['jid'], conf['nick'],
|
||||
self.xmpp['xep_0045'].joinMUC(conf['jid'], conf['nick'],
|
||||
password=conf['password'])
|
||||
|
||||
def set_bookmarks(self, bookmarks, method=None, **iqargs):
|
||||
|
||||
@@ -40,8 +40,8 @@ class Conference(ElementBase):
|
||||
namespace = 'storage:bookmarks'
|
||||
plugin_attrib = 'conference'
|
||||
plugin_multi_attrib = 'conferences'
|
||||
interfaces = {'nick', 'password', 'autojoin', 'jid', 'name'}
|
||||
sub_interfaces = {'nick', 'password'}
|
||||
interfaces = set(['nick', 'password', 'autojoin', 'jid', 'name'])
|
||||
sub_interfaces = set(['nick', 'password'])
|
||||
|
||||
def get_autojoin(self):
|
||||
value = self._get_attr('autojoin')
|
||||
@@ -58,7 +58,7 @@ class URL(ElementBase):
|
||||
namespace = 'storage:bookmarks'
|
||||
plugin_attrib = 'url'
|
||||
plugin_multi_attrib = 'urls'
|
||||
interfaces = {'url', 'name'}
|
||||
interfaces = set(['url', 'name'])
|
||||
|
||||
|
||||
register_stanza_plugin(Bookmarks, Conference, iterable=True)
|
||||
|
||||
@@ -23,7 +23,7 @@ class XEP_0049(BasePlugin):
|
||||
|
||||
name = 'xep_0049'
|
||||
description = 'XEP-0049: Private XML Storage'
|
||||
dependencies = {}
|
||||
dependencies = set([])
|
||||
stanza = stanza
|
||||
|
||||
def plugin_init(self):
|
||||
|
||||
@@ -13,3 +13,7 @@ from slixmpp.plugins.xep_0050.adhoc import XEP_0050
|
||||
|
||||
|
||||
register_plugin(XEP_0050)
|
||||
|
||||
|
||||
# Retain some backwards compatibility
|
||||
xep_0050 = XEP_0050
|
||||
|
||||
@@ -74,7 +74,7 @@ class XEP_0050(BasePlugin):
|
||||
|
||||
name = 'xep_0050'
|
||||
description = 'XEP-0050: Ad-Hoc Commands'
|
||||
dependencies = {'xep_0030', 'xep_0004'}
|
||||
dependencies = set(['xep_0030', 'xep_0004'])
|
||||
stanza = stanza
|
||||
default_config = {
|
||||
'session_db': None
|
||||
@@ -225,8 +225,8 @@ class XEP_0050(BasePlugin):
|
||||
if len(payload) == 1:
|
||||
payload = payload[0]
|
||||
|
||||
interfaces = {item.plugin_attrib for item in payload}
|
||||
payload_classes = {item.__class__ for item in payload}
|
||||
interfaces = set([item.plugin_attrib for item in payload])
|
||||
payload_classes = set([item.__class__ for item in payload])
|
||||
|
||||
initial_session = {'id': sessionid,
|
||||
'from': iq['from'],
|
||||
@@ -322,8 +322,8 @@ class XEP_0050(BasePlugin):
|
||||
interfaces = session.get('interfaces', set())
|
||||
payload_classes = session.get('payload_classes', set())
|
||||
|
||||
interfaces.update({item.plugin_attrib for item in payload})
|
||||
payload_classes.update({item.__class__ for item in payload})
|
||||
interfaces.update(set([item.plugin_attrib for item in payload]))
|
||||
payload_classes.update(set([item.__class__ for item in payload]))
|
||||
|
||||
session['interfaces'] = interfaces
|
||||
session['payload_classes'] = payload_classes
|
||||
|
||||
@@ -72,11 +72,11 @@ class Command(ElementBase):
|
||||
name = 'command'
|
||||
namespace = 'http://jabber.org/protocol/commands'
|
||||
plugin_attrib = 'command'
|
||||
interfaces = {'action', 'sessionid', 'node',
|
||||
'status', 'actions', 'notes'}
|
||||
actions = {'cancel', 'complete', 'execute', 'next', 'prev'}
|
||||
statuses = {'canceled', 'completed', 'executing'}
|
||||
next_actions = {'prev', 'next', 'complete'}
|
||||
interfaces = set(('action', 'sessionid', 'node',
|
||||
'status', 'actions', 'notes'))
|
||||
actions = set(('cancel', 'complete', 'execute', 'next', 'prev'))
|
||||
statuses = set(('canceled', 'completed', 'executing'))
|
||||
next_actions = set(('prev', 'next', 'complete'))
|
||||
|
||||
def get_action(self):
|
||||
"""
|
||||
@@ -100,7 +100,7 @@ class Command(ElementBase):
|
||||
self.del_actions()
|
||||
if values:
|
||||
self._set_sub_text('{%s}actions' % self.namespace, '', True)
|
||||
actions = self.xml.find('{%s}actions' % self.namespace)
|
||||
actions = self.find('{%s}actions' % self.namespace)
|
||||
for val in values:
|
||||
if val in self.next_actions:
|
||||
action = ET.Element('{%s}%s' % (self.namespace, val))
|
||||
@@ -111,7 +111,7 @@ class Command(ElementBase):
|
||||
Return the set of allowable next actions.
|
||||
"""
|
||||
actions = set()
|
||||
actions_xml = self.xml.find('{%s}actions' % self.namespace)
|
||||
actions_xml = self.find('{%s}actions' % self.namespace)
|
||||
if actions_xml is not None:
|
||||
for action in self.next_actions:
|
||||
action_xml = actions_xml.find('{%s}%s' % (self.namespace,
|
||||
@@ -136,7 +136,7 @@ class Command(ElementBase):
|
||||
('error', 'The command ran, but had errors')]
|
||||
"""
|
||||
notes = []
|
||||
notes_xml = self.xml.findall('{%s}note' % self.namespace)
|
||||
notes_xml = self.findall('{%s}note' % self.namespace)
|
||||
for note in notes_xml:
|
||||
notes.append((note.attrib.get('type', 'info'),
|
||||
note.text))
|
||||
@@ -167,7 +167,7 @@ class Command(ElementBase):
|
||||
"""
|
||||
Remove all notes associated with the command result.
|
||||
"""
|
||||
notes_xml = self.xml.findall('{%s}note' % self.namespace)
|
||||
notes_xml = self.findall('{%s}note' % self.namespace)
|
||||
for note in notes_xml:
|
||||
self.xml.remove(note)
|
||||
|
||||
|
||||
@@ -10,15 +10,15 @@ class VCardTemp(ElementBase):
|
||||
name = 'vCard'
|
||||
namespace = 'vcard-temp'
|
||||
plugin_attrib = 'vcard_temp'
|
||||
interfaces = {'FN', 'VERSION'}
|
||||
sub_interfaces = {'FN', 'VERSION'}
|
||||
interfaces = set(['FN', 'VERSION'])
|
||||
sub_interfaces = set(['FN', 'VERSION'])
|
||||
|
||||
|
||||
class Name(ElementBase):
|
||||
name = 'N'
|
||||
namespace = 'vcard-temp'
|
||||
plugin_attrib = name
|
||||
interfaces = {'FAMILY', 'GIVEN', 'MIDDLE', 'PREFIX', 'SUFFIX'}
|
||||
interfaces = set(['FAMILY', 'GIVEN', 'MIDDLE', 'PREFIX', 'SUFFIX'])
|
||||
sub_interfaces = interfaces
|
||||
|
||||
def _set_component(self, name, value):
|
||||
@@ -72,7 +72,7 @@ class Nickname(ElementBase):
|
||||
namespace = 'vcard-temp'
|
||||
plugin_attrib = name
|
||||
plugin_multi_attrib = 'nicknames'
|
||||
interfaces = {name}
|
||||
interfaces = set([name])
|
||||
is_extension = True
|
||||
|
||||
def set_nickname(self, value):
|
||||
@@ -95,9 +95,9 @@ class Email(ElementBase):
|
||||
namespace = 'vcard-temp'
|
||||
plugin_attrib = name
|
||||
plugin_multi_attrib = 'emails'
|
||||
interfaces = {'HOME', 'WORK', 'INTERNET', 'PREF', 'X400', 'USERID'}
|
||||
sub_interfaces = {'USERID'}
|
||||
bool_interfaces = {'HOME', 'WORK', 'INTERNET', 'PREF', 'X400'}
|
||||
interfaces = set(['HOME', 'WORK', 'INTERNET', 'PREF', 'X400', 'USERID'])
|
||||
sub_interfaces = set(['USERID'])
|
||||
bool_interfaces = set(['HOME', 'WORK', 'INTERNET', 'PREF', 'X400'])
|
||||
|
||||
|
||||
class Address(ElementBase):
|
||||
@@ -105,12 +105,12 @@ class Address(ElementBase):
|
||||
namespace = 'vcard-temp'
|
||||
plugin_attrib = name
|
||||
plugin_multi_attrib = 'addresses'
|
||||
interfaces = {'HOME', 'WORK', 'POSTAL', 'PARCEL', 'DOM', 'INTL',
|
||||
'PREF', 'POBOX', 'EXTADD', 'STREET', 'LOCALITY',
|
||||
'REGION', 'PCODE', 'CTRY'}
|
||||
sub_interfaces = {'POBOX', 'EXTADD', 'STREET', 'LOCALITY',
|
||||
'REGION', 'PCODE', 'CTRY'}
|
||||
bool_interfaces = {'HOME', 'WORK', 'DOM', 'INTL', 'PREF'}
|
||||
interfaces = set(['HOME', 'WORK', 'POSTAL', 'PARCEL', 'DOM', 'INTL',
|
||||
'PREF', 'POBOX', 'EXTADD', 'STREET', 'LOCALITY',
|
||||
'REGION', 'PCODE', 'CTRY'])
|
||||
sub_interfaces = set(['POBOX', 'EXTADD', 'STREET', 'LOCALITY',
|
||||
'REGION', 'PCODE', 'CTRY'])
|
||||
bool_interfaces = set(['HOME', 'WORK', 'DOM', 'INTL', 'PREF'])
|
||||
|
||||
|
||||
class Telephone(ElementBase):
|
||||
@@ -118,16 +118,16 @@ class Telephone(ElementBase):
|
||||
namespace = 'vcard-temp'
|
||||
plugin_attrib = name
|
||||
plugin_multi_attrib = 'telephone_numbers'
|
||||
interfaces = {'HOME', 'WORK', 'VOICE', 'FAX', 'PAGER', 'MSG',
|
||||
'CELL', 'VIDEO', 'BBS', 'MODEM', 'ISDN', 'PCS',
|
||||
'PREF', 'NUMBER'}
|
||||
sub_interfaces = {'NUMBER'}
|
||||
bool_interfaces = {'HOME', 'WORK', 'VOICE', 'FAX', 'PAGER',
|
||||
'MSG', 'CELL', 'VIDEO', 'BBS', 'MODEM',
|
||||
'ISDN', 'PCS', 'PREF'}
|
||||
interfaces = set(['HOME', 'WORK', 'VOICE', 'FAX', 'PAGER', 'MSG',
|
||||
'CELL', 'VIDEO', 'BBS', 'MODEM', 'ISDN', 'PCS',
|
||||
'PREF', 'NUMBER'])
|
||||
sub_interfaces = set(['NUMBER'])
|
||||
bool_interfaces = set(['HOME', 'WORK', 'VOICE', 'FAX', 'PAGER',
|
||||
'MSG', 'CELL', 'VIDEO', 'BBS', 'MODEM',
|
||||
'ISDN', 'PCS', 'PREF'])
|
||||
|
||||
def setup(self, xml=None):
|
||||
super().setup(xml=xml)
|
||||
super(Telephone, self).setup(xml=xml)
|
||||
## this blanks out numbers received from server
|
||||
##self._set_sub_text('NUMBER', '', keep=True)
|
||||
|
||||
@@ -143,10 +143,10 @@ class Label(ElementBase):
|
||||
namespace = 'vcard-temp'
|
||||
plugin_attrib = name
|
||||
plugin_multi_attrib = 'labels'
|
||||
interfaces = {'HOME', 'WORK', 'POSTAL', 'PARCEL', 'DOM', 'INT',
|
||||
'PREF', 'lines'}
|
||||
bool_interfaces = {'HOME', 'WORK', 'POSTAL', 'PARCEL', 'DOM',
|
||||
'INT', 'PREF'}
|
||||
interfaces = set(['HOME', 'WORK', 'POSTAL', 'PARCEL', 'DOM', 'INT',
|
||||
'PREF', 'lines'])
|
||||
bool_interfaces = set(['HOME', 'WORK', 'POSTAL', 'PARCEL', 'DOM',
|
||||
'INT', 'PREF'])
|
||||
|
||||
def add_line(self, value):
|
||||
line = ET.Element('{%s}LINE' % self.namespace)
|
||||
@@ -177,7 +177,7 @@ class Geo(ElementBase):
|
||||
namespace = 'vcard-temp'
|
||||
plugin_attrib = name
|
||||
plugin_multi_attrib = 'geolocations'
|
||||
interfaces = {'LAT', 'LON'}
|
||||
interfaces = set(['LAT', 'LON'])
|
||||
sub_interfaces = interfaces
|
||||
|
||||
|
||||
@@ -186,8 +186,8 @@ class Org(ElementBase):
|
||||
namespace = 'vcard-temp'
|
||||
plugin_attrib = name
|
||||
plugin_multi_attrib = 'organizations'
|
||||
interfaces = {'ORGNAME', 'ORGUNIT', 'orgunits'}
|
||||
sub_interfaces = {'ORGNAME', 'ORGUNIT'}
|
||||
interfaces = set(['ORGNAME', 'ORGUNIT', 'orgunits'])
|
||||
sub_interfaces = set(['ORGNAME', 'ORGUNIT'])
|
||||
|
||||
def add_orgunit(self, value):
|
||||
orgunit = ET.Element('{%s}ORGUNIT' % self.namespace)
|
||||
@@ -218,7 +218,7 @@ class Photo(ElementBase):
|
||||
namespace = 'vcard-temp'
|
||||
plugin_attrib = name
|
||||
plugin_multi_attrib = 'photos'
|
||||
interfaces = {'TYPE', 'EXTVAL'}
|
||||
interfaces = set(['TYPE', 'EXTVAL'])
|
||||
sub_interfaces = interfaces
|
||||
|
||||
|
||||
@@ -227,7 +227,7 @@ class Logo(ElementBase):
|
||||
namespace = 'vcard-temp'
|
||||
plugin_attrib = name
|
||||
plugin_multi_attrib = 'logos'
|
||||
interfaces = {'TYPE', 'EXTVAL'}
|
||||
interfaces = set(['TYPE', 'EXTVAL'])
|
||||
sub_interfaces = interfaces
|
||||
|
||||
|
||||
@@ -236,7 +236,7 @@ class Sound(ElementBase):
|
||||
namespace = 'vcard-temp'
|
||||
plugin_attrib = name
|
||||
plugin_multi_attrib = 'sounds'
|
||||
interfaces = {'PHONETC', 'EXTVAL'}
|
||||
interfaces = set(['PHONETC', 'EXTVAL'])
|
||||
sub_interfaces = interfaces
|
||||
|
||||
|
||||
@@ -244,7 +244,7 @@ class BinVal(ElementBase):
|
||||
name = 'BINVAL'
|
||||
namespace = 'vcard-temp'
|
||||
plugin_attrib = name
|
||||
interfaces = {'BINVAL'}
|
||||
interfaces = set(['BINVAL'])
|
||||
is_extension = True
|
||||
|
||||
def setup(self, xml=None):
|
||||
@@ -275,7 +275,7 @@ class Classification(ElementBase):
|
||||
namespace = 'vcard-temp'
|
||||
plugin_attrib = name
|
||||
plugin_multi_attrib = 'classifications'
|
||||
interfaces = {'PUBLIC', 'PRIVATE', 'CONFIDENTIAL'}
|
||||
interfaces = set(['PUBLIC', 'PRIVATE', 'CONFIDENTIAL'])
|
||||
bool_interfaces = interfaces
|
||||
|
||||
|
||||
@@ -284,7 +284,7 @@ class Categories(ElementBase):
|
||||
namespace = 'vcard-temp'
|
||||
plugin_attrib = name
|
||||
plugin_multi_attrib = 'categories'
|
||||
interfaces = {name}
|
||||
interfaces = set([name])
|
||||
is_extension = True
|
||||
|
||||
def set_categories(self, values):
|
||||
@@ -314,7 +314,7 @@ class Birthday(ElementBase):
|
||||
namespace = 'vcard-temp'
|
||||
plugin_attrib = name
|
||||
plugin_multi_attrib = 'birthdays'
|
||||
interfaces = {name}
|
||||
interfaces = set([name])
|
||||
is_extension = True
|
||||
|
||||
def set_bday(self, value):
|
||||
@@ -336,7 +336,7 @@ class Rev(ElementBase):
|
||||
namespace = 'vcard-temp'
|
||||
plugin_attrib = name
|
||||
plugin_multi_attrib = 'revision_dates'
|
||||
interfaces = {name}
|
||||
interfaces = set([name])
|
||||
is_extension = True
|
||||
|
||||
def set_rev(self, value):
|
||||
@@ -358,7 +358,7 @@ class Title(ElementBase):
|
||||
namespace = 'vcard-temp'
|
||||
plugin_attrib = name
|
||||
plugin_multi_attrib = 'titles'
|
||||
interfaces = {name}
|
||||
interfaces = set([name])
|
||||
is_extension = True
|
||||
|
||||
def set_title(self, value):
|
||||
@@ -373,7 +373,7 @@ class Role(ElementBase):
|
||||
namespace = 'vcard-temp'
|
||||
plugin_attrib = name
|
||||
plugin_multi_attrib = 'roles'
|
||||
interfaces = {name}
|
||||
interfaces = set([name])
|
||||
is_extension = True
|
||||
|
||||
def set_role(self, value):
|
||||
@@ -388,7 +388,7 @@ class Note(ElementBase):
|
||||
namespace = 'vcard-temp'
|
||||
plugin_attrib = name
|
||||
plugin_multi_attrib = 'notes'
|
||||
interfaces = {name}
|
||||
interfaces = set([name])
|
||||
is_extension = True
|
||||
|
||||
def set_note(self, value):
|
||||
@@ -403,7 +403,7 @@ class Desc(ElementBase):
|
||||
namespace = 'vcard-temp'
|
||||
plugin_attrib = name
|
||||
plugin_multi_attrib = 'descriptions'
|
||||
interfaces = {name}
|
||||
interfaces = set([name])
|
||||
is_extension = True
|
||||
|
||||
def set_desc(self, value):
|
||||
@@ -418,7 +418,7 @@ class URL(ElementBase):
|
||||
namespace = 'vcard-temp'
|
||||
plugin_attrib = name
|
||||
plugin_multi_attrib = 'urls'
|
||||
interfaces = {name}
|
||||
interfaces = set([name])
|
||||
is_extension = True
|
||||
|
||||
def set_url(self, value):
|
||||
@@ -433,7 +433,7 @@ class UID(ElementBase):
|
||||
namespace = 'vcard-temp'
|
||||
plugin_attrib = name
|
||||
plugin_multi_attrib = 'uids'
|
||||
interfaces = {name}
|
||||
interfaces = set([name])
|
||||
is_extension = True
|
||||
|
||||
def set_uid(self, value):
|
||||
@@ -448,7 +448,7 @@ class ProdID(ElementBase):
|
||||
namespace = 'vcard-temp'
|
||||
plugin_attrib = name
|
||||
plugin_multi_attrib = 'product_ids'
|
||||
interfaces = {name}
|
||||
interfaces = set([name])
|
||||
is_extension = True
|
||||
|
||||
def set_prodid(self, value):
|
||||
@@ -463,7 +463,7 @@ class Mailer(ElementBase):
|
||||
namespace = 'vcard-temp'
|
||||
plugin_attrib = name
|
||||
plugin_multi_attrib = 'mailers'
|
||||
interfaces = {name}
|
||||
interfaces = set([name])
|
||||
is_extension = True
|
||||
|
||||
def set_mailer(self, value):
|
||||
@@ -478,7 +478,7 @@ class SortString(ElementBase):
|
||||
namespace = 'vcard-temp'
|
||||
plugin_attrib = 'SORT_STRING'
|
||||
plugin_multi_attrib = 'sort_strings'
|
||||
interfaces = {name}
|
||||
interfaces = set([name])
|
||||
is_extension = True
|
||||
|
||||
def set_sort_string(self, value):
|
||||
@@ -493,7 +493,7 @@ class Agent(ElementBase):
|
||||
namespace = 'vcard-temp'
|
||||
plugin_attrib = name
|
||||
plugin_multi_attrib = 'agents'
|
||||
interfaces = {'EXTVAL'}
|
||||
interfaces = set(['EXTVAL'])
|
||||
sub_interfaces = interfaces
|
||||
|
||||
|
||||
@@ -502,7 +502,7 @@ class JabberID(ElementBase):
|
||||
namespace = 'vcard-temp'
|
||||
plugin_attrib = name
|
||||
plugin_multi_attrib = 'jids'
|
||||
interfaces = {name}
|
||||
interfaces = set([name])
|
||||
is_extension = True
|
||||
|
||||
def set_jabberid(self, value):
|
||||
@@ -517,7 +517,7 @@ class TimeZone(ElementBase):
|
||||
namespace = 'vcard-temp'
|
||||
plugin_attrib = name
|
||||
plugin_multi_attrib = 'timezones'
|
||||
interfaces = {name}
|
||||
interfaces = set([name])
|
||||
is_extension = True
|
||||
|
||||
def set_tz(self, value):
|
||||
|
||||
@@ -29,7 +29,7 @@ class XEP_0054(BasePlugin):
|
||||
|
||||
name = 'xep_0054'
|
||||
description = 'XEP-0054: vcard-temp'
|
||||
dependencies = {'xep_0030', 'xep_0082'}
|
||||
dependencies = set(['xep_0030', 'xep_0082'])
|
||||
stanza = stanza
|
||||
|
||||
def plugin_init(self):
|
||||
|
||||
@@ -13,3 +13,6 @@ from slixmpp.plugins.xep_0059.rsm import ResultIterator, XEP_0059
|
||||
|
||||
|
||||
register_plugin(XEP_0059)
|
||||
|
||||
# Retain some backwards compatibility
|
||||
xep_0059 = XEP_0059
|
||||
|
||||
@@ -111,7 +111,7 @@ class XEP_0059(BasePlugin):
|
||||
|
||||
name = 'xep_0059'
|
||||
description = 'XEP-0059: Result Set Management'
|
||||
dependencies = {'xep_0030'}
|
||||
dependencies = set(['xep_0030'])
|
||||
stanza = stanza
|
||||
|
||||
def plugin_init(self):
|
||||
|
||||
@@ -64,13 +64,13 @@ class Set(ElementBase):
|
||||
namespace = 'http://jabber.org/protocol/rsm'
|
||||
name = 'set'
|
||||
plugin_attrib = 'rsm'
|
||||
sub_interfaces = {'first', 'after', 'before', 'count',
|
||||
'index', 'last', 'max'}
|
||||
interfaces = {'first_index', 'first', 'after', 'before',
|
||||
'count', 'index', 'last', 'max'}
|
||||
sub_interfaces = set(('first', 'after', 'before', 'count',
|
||||
'index', 'last', 'max'))
|
||||
interfaces = set(('first_index', 'first', 'after', 'before',
|
||||
'count', 'index', 'last', 'max'))
|
||||
|
||||
def set_first_index(self, val):
|
||||
fi = self.xml.find("{%s}first" % (self.namespace))
|
||||
fi = self.find("{%s}first" % (self.namespace))
|
||||
if fi is not None:
|
||||
if val:
|
||||
fi.attrib['index'] = val
|
||||
@@ -82,7 +82,7 @@ class Set(ElementBase):
|
||||
self.xml.append(fi)
|
||||
|
||||
def get_first_index(self):
|
||||
fi = self.xml.find("{%s}first" % (self.namespace))
|
||||
fi = self.find("{%s}first" % (self.namespace))
|
||||
if fi is not None:
|
||||
return fi.attrib.get('index', '')
|
||||
|
||||
|
||||
@@ -13,3 +13,7 @@ from slixmpp.plugins.xep_0060 import stanza
|
||||
|
||||
|
||||
register_plugin(XEP_0060)
|
||||
|
||||
|
||||
# Retain some backwards compatibility
|
||||
xep_0060 = XEP_0060
|
||||
|
||||
@@ -26,7 +26,7 @@ class XEP_0060(BasePlugin):
|
||||
|
||||
name = 'xep_0060'
|
||||
description = 'XEP-0060: Publish-Subscribe'
|
||||
dependencies = {'xep_0030', 'xep_0004', 'xep_0082', 'xep_0131'}
|
||||
dependencies = set(['xep_0030', 'xep_0004', 'xep_0082', 'xep_0131'])
|
||||
stanza = stanza
|
||||
|
||||
def plugin_init(self):
|
||||
|
||||
@@ -11,7 +11,7 @@ from slixmpp.xmlstream import ET
|
||||
|
||||
class OptionalSetting(object):
|
||||
|
||||
interfaces = {'required'}
|
||||
interfaces = set(('required',))
|
||||
|
||||
def set_required(self, value):
|
||||
if value in (True, 'true', 'True', '1'):
|
||||
|
||||
@@ -23,14 +23,14 @@ class Affiliations(ElementBase):
|
||||
namespace = 'http://jabber.org/protocol/pubsub'
|
||||
name = 'affiliations'
|
||||
plugin_attrib = name
|
||||
interfaces = {'node'}
|
||||
interfaces = set(('node',))
|
||||
|
||||
|
||||
class Affiliation(ElementBase):
|
||||
namespace = 'http://jabber.org/protocol/pubsub'
|
||||
name = 'affiliation'
|
||||
plugin_attrib = name
|
||||
interfaces = {'node', 'affiliation', 'jid'}
|
||||
interfaces = set(('node', 'affiliation', 'jid'))
|
||||
|
||||
def set_jid(self, value):
|
||||
self._set_attr('jid', str(value))
|
||||
@@ -43,7 +43,7 @@ class Subscription(ElementBase):
|
||||
namespace = 'http://jabber.org/protocol/pubsub'
|
||||
name = 'subscription'
|
||||
plugin_attrib = name
|
||||
interfaces = {'jid', 'node', 'subscription', 'subid'}
|
||||
interfaces = set(('jid', 'node', 'subscription', 'subid'))
|
||||
|
||||
def set_jid(self, value):
|
||||
self._set_attr('jid', str(value))
|
||||
@@ -56,21 +56,21 @@ class Subscriptions(ElementBase):
|
||||
namespace = 'http://jabber.org/protocol/pubsub'
|
||||
name = 'subscriptions'
|
||||
plugin_attrib = name
|
||||
interfaces = {'node'}
|
||||
interfaces = set(('node',))
|
||||
|
||||
|
||||
class SubscribeOptions(ElementBase, OptionalSetting):
|
||||
namespace = 'http://jabber.org/protocol/pubsub'
|
||||
name = 'subscribe-options'
|
||||
plugin_attrib = 'suboptions'
|
||||
interfaces = {'required'}
|
||||
interfaces = set(('required',))
|
||||
|
||||
|
||||
class Item(ElementBase):
|
||||
namespace = 'http://jabber.org/protocol/pubsub'
|
||||
name = 'item'
|
||||
plugin_attrib = name
|
||||
interfaces = {'id', 'payload'}
|
||||
interfaces = set(('id', 'payload'))
|
||||
|
||||
def set_payload(self, value):
|
||||
del self['payload']
|
||||
@@ -95,7 +95,7 @@ class Items(ElementBase):
|
||||
namespace = 'http://jabber.org/protocol/pubsub'
|
||||
name = 'items'
|
||||
plugin_attrib = name
|
||||
interfaces = {'node', 'max_items'}
|
||||
interfaces = set(('node', 'max_items'))
|
||||
|
||||
def set_max_items(self, value):
|
||||
self._set_attr('max_items', str(value))
|
||||
@@ -105,14 +105,14 @@ class Create(ElementBase):
|
||||
namespace = 'http://jabber.org/protocol/pubsub'
|
||||
name = 'create'
|
||||
plugin_attrib = name
|
||||
interfaces = {'node'}
|
||||
interfaces = set(('node',))
|
||||
|
||||
|
||||
class Default(ElementBase):
|
||||
namespace = 'http://jabber.org/protocol/pubsub'
|
||||
name = 'default'
|
||||
plugin_attrib = name
|
||||
interfaces = {'node', 'type'}
|
||||
interfaces = set(('node', 'type'))
|
||||
|
||||
def get_type(self):
|
||||
t = self._get_attr('type')
|
||||
@@ -125,14 +125,14 @@ class Publish(ElementBase):
|
||||
namespace = 'http://jabber.org/protocol/pubsub'
|
||||
name = 'publish'
|
||||
plugin_attrib = name
|
||||
interfaces = {'node'}
|
||||
interfaces = set(('node',))
|
||||
|
||||
|
||||
class Retract(ElementBase):
|
||||
namespace = 'http://jabber.org/protocol/pubsub'
|
||||
name = 'retract'
|
||||
plugin_attrib = name
|
||||
interfaces = {'node', 'notify'}
|
||||
interfaces = set(('node', 'notify'))
|
||||
|
||||
def get_notify(self):
|
||||
notify = self._get_attr('notify')
|
||||
@@ -156,7 +156,7 @@ class Unsubscribe(ElementBase):
|
||||
namespace = 'http://jabber.org/protocol/pubsub'
|
||||
name = 'unsubscribe'
|
||||
plugin_attrib = name
|
||||
interfaces = {'node', 'jid', 'subid'}
|
||||
interfaces = set(('node', 'jid', 'subid'))
|
||||
|
||||
def set_jid(self, value):
|
||||
self._set_attr('jid', str(value))
|
||||
@@ -169,7 +169,7 @@ class Subscribe(ElementBase):
|
||||
namespace = 'http://jabber.org/protocol/pubsub'
|
||||
name = 'subscribe'
|
||||
plugin_attrib = name
|
||||
interfaces = {'node', 'jid'}
|
||||
interfaces = set(('node', 'jid'))
|
||||
|
||||
def set_jid(self, value):
|
||||
self._set_attr('jid', str(value))
|
||||
@@ -182,7 +182,7 @@ class Configure(ElementBase):
|
||||
namespace = 'http://jabber.org/protocol/pubsub'
|
||||
name = 'configure'
|
||||
plugin_attrib = name
|
||||
interfaces = {'node', 'type'}
|
||||
interfaces = set(('node', 'type'))
|
||||
|
||||
def getType(self):
|
||||
t = self._get_attr('type')
|
||||
@@ -195,7 +195,7 @@ class Options(ElementBase):
|
||||
namespace = 'http://jabber.org/protocol/pubsub'
|
||||
name = 'options'
|
||||
plugin_attrib = name
|
||||
interfaces = {'jid', 'node', 'options'}
|
||||
interfaces = set(('jid', 'node', 'options'))
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
ElementBase.__init__(self, *args, **kwargs)
|
||||
@@ -206,10 +206,7 @@ class Options(ElementBase):
|
||||
return form
|
||||
|
||||
def set_options(self, value):
|
||||
if isinstance(value, ElementBase):
|
||||
self.xml.append(value.xml)
|
||||
else:
|
||||
self.xml.append(value)
|
||||
self.xml.append(value.getXML())
|
||||
return self
|
||||
|
||||
def del_options(self):
|
||||
@@ -227,7 +224,7 @@ class PublishOptions(ElementBase):
|
||||
namespace = 'http://jabber.org/protocol/pubsub'
|
||||
name = 'publish-options'
|
||||
plugin_attrib = 'publish_options'
|
||||
interfaces = {'publish_options'}
|
||||
interfaces = set(('publish_options',))
|
||||
is_extension = True
|
||||
|
||||
def get_publish_options(self):
|
||||
@@ -241,10 +238,7 @@ class PublishOptions(ElementBase):
|
||||
if value is None:
|
||||
self.del_publish_options()
|
||||
else:
|
||||
if isinstance(value, ElementBase):
|
||||
self.xml.append(value.xml)
|
||||
else:
|
||||
self.xml.append(value)
|
||||
self.xml.append(value.getXML())
|
||||
return self
|
||||
|
||||
def del_publish_options(self):
|
||||
|
||||
@@ -13,18 +13,18 @@ from slixmpp.xmlstream import ElementBase, ET, register_stanza_plugin
|
||||
class PubsubErrorCondition(ElementBase):
|
||||
|
||||
plugin_attrib = 'pubsub'
|
||||
interfaces = {'condition', 'unsupported'}
|
||||
interfaces = set(('condition', 'unsupported'))
|
||||
plugin_attrib_map = {}
|
||||
plugin_tag_map = {}
|
||||
conditions = {'closed-node', 'configuration-required', 'invalid-jid',
|
||||
'invalid-options', 'invalid-payload', 'invalid-subid',
|
||||
'item-forbidden', 'item-required', 'jid-required',
|
||||
'max-items-exceeded', 'max-nodes-exceeded',
|
||||
'nodeid-required', 'not-in-roster-group',
|
||||
'not-subscribed', 'payload-too-big',
|
||||
'payload-required', 'pending-subscription',
|
||||
'presence-subscription-required', 'subid-required',
|
||||
'too-many-subscriptions', 'unsupported'}
|
||||
conditions = set(('closed-node', 'configuration-required', 'invalid-jid',
|
||||
'invalid-options', 'invalid-payload', 'invalid-subid',
|
||||
'item-forbidden', 'item-required', 'jid-required',
|
||||
'max-items-exceeded', 'max-nodes-exceeded',
|
||||
'nodeid-required', 'not-in-roster-group',
|
||||
'not-subscribed', 'payload-too-big',
|
||||
'payload-required', 'pending-subscription',
|
||||
'presence-subscription-required', 'subid-required',
|
||||
'too-many-subscriptions', 'unsupported'))
|
||||
condition_ns = 'http://jabber.org/protocol/pubsub#errors'
|
||||
|
||||
def setup(self, xml):
|
||||
|
||||
@@ -25,7 +25,7 @@ class EventItem(ElementBase):
|
||||
namespace = 'http://jabber.org/protocol/pubsub#event'
|
||||
name = 'item'
|
||||
plugin_attrib = name
|
||||
interfaces = {'id', 'payload', 'node', 'publisher'}
|
||||
interfaces = set(('id', 'payload', 'node', 'publisher'))
|
||||
|
||||
def set_payload(self, value):
|
||||
self.xml.append(value)
|
||||
@@ -44,56 +44,56 @@ class EventRetract(ElementBase):
|
||||
namespace = 'http://jabber.org/protocol/pubsub#event'
|
||||
name = 'retract'
|
||||
plugin_attrib = name
|
||||
interfaces = {'id'}
|
||||
interfaces = set(('id',))
|
||||
|
||||
|
||||
class EventItems(ElementBase):
|
||||
namespace = 'http://jabber.org/protocol/pubsub#event'
|
||||
name = 'items'
|
||||
plugin_attrib = name
|
||||
interfaces = {'node'}
|
||||
interfaces = set(('node',))
|
||||
|
||||
|
||||
class EventCollection(ElementBase):
|
||||
namespace = 'http://jabber.org/protocol/pubsub#event'
|
||||
name = 'collection'
|
||||
plugin_attrib = name
|
||||
interfaces = {'node'}
|
||||
interfaces = set(('node',))
|
||||
|
||||
|
||||
class EventAssociate(ElementBase):
|
||||
namespace = 'http://jabber.org/protocol/pubsub#event'
|
||||
name = 'associate'
|
||||
plugin_attrib = name
|
||||
interfaces = {'node'}
|
||||
interfaces = set(('node',))
|
||||
|
||||
|
||||
class EventDisassociate(ElementBase):
|
||||
namespace = 'http://jabber.org/protocol/pubsub#event'
|
||||
name = 'disassociate'
|
||||
plugin_attrib = name
|
||||
interfaces = {'node'}
|
||||
interfaces = set(('node',))
|
||||
|
||||
|
||||
class EventConfiguration(ElementBase):
|
||||
namespace = 'http://jabber.org/protocol/pubsub#event'
|
||||
name = 'configuration'
|
||||
plugin_attrib = name
|
||||
interfaces = {'node'}
|
||||
interfaces = set(('node',))
|
||||
|
||||
|
||||
class EventPurge(ElementBase):
|
||||
namespace = 'http://jabber.org/protocol/pubsub#event'
|
||||
name = 'purge'
|
||||
plugin_attrib = name
|
||||
interfaces = {'node'}
|
||||
interfaces = set(('node',))
|
||||
|
||||
|
||||
class EventDelete(ElementBase):
|
||||
namespace = 'http://jabber.org/protocol/pubsub#event'
|
||||
name = 'delete'
|
||||
plugin_attrib = name
|
||||
interfaces = {'node', 'redirect'}
|
||||
interfaces = set(('node', 'redirect'))
|
||||
|
||||
def set_redirect(self, uri):
|
||||
del self['redirect']
|
||||
@@ -117,7 +117,7 @@ class EventSubscription(ElementBase):
|
||||
namespace = 'http://jabber.org/protocol/pubsub#event'
|
||||
name = 'subscription'
|
||||
plugin_attrib = name
|
||||
interfaces = {'node', 'expiry', 'jid', 'subid', 'subscription'}
|
||||
interfaces = set(('node', 'expiry', 'jid', 'subid', 'subscription'))
|
||||
|
||||
def get_expiry(self):
|
||||
expiry = self._get_attr('expiry')
|
||||
|
||||
@@ -25,7 +25,7 @@ class DefaultConfig(ElementBase):
|
||||
namespace = 'http://jabber.org/protocol/pubsub#owner'
|
||||
name = 'default'
|
||||
plugin_attrib = name
|
||||
interfaces = {'node', 'config'}
|
||||
interfaces = set(('node', 'config'))
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
ElementBase.__init__(self, *args, **kwargs)
|
||||
@@ -41,7 +41,7 @@ class DefaultConfig(ElementBase):
|
||||
|
||||
class OwnerAffiliations(Affiliations):
|
||||
namespace = 'http://jabber.org/protocol/pubsub#owner'
|
||||
interfaces = {'node'}
|
||||
interfaces = set(('node',))
|
||||
|
||||
def append(self, affiliation):
|
||||
if not isinstance(affiliation, OwnerAffiliation):
|
||||
@@ -51,40 +51,40 @@ class OwnerAffiliations(Affiliations):
|
||||
|
||||
class OwnerAffiliation(Affiliation):
|
||||
namespace = 'http://jabber.org/protocol/pubsub#owner'
|
||||
interfaces = {'affiliation', 'jid'}
|
||||
interfaces = set(('affiliation', 'jid'))
|
||||
|
||||
|
||||
class OwnerConfigure(Configure):
|
||||
namespace = 'http://jabber.org/protocol/pubsub#owner'
|
||||
name = 'configure'
|
||||
plugin_attrib = name
|
||||
interfaces = {'node'}
|
||||
interfaces = set(('node',))
|
||||
|
||||
|
||||
class OwnerDefault(OwnerConfigure):
|
||||
namespace = 'http://jabber.org/protocol/pubsub#owner'
|
||||
interfaces = {'node'}
|
||||
interfaces = set(('node',))
|
||||
|
||||
|
||||
class OwnerDelete(ElementBase, OptionalSetting):
|
||||
namespace = 'http://jabber.org/protocol/pubsub#owner'
|
||||
name = 'delete'
|
||||
plugin_attrib = name
|
||||
interfaces = {'node'}
|
||||
interfaces = set(('node',))
|
||||
|
||||
|
||||
class OwnerPurge(ElementBase, OptionalSetting):
|
||||
namespace = 'http://jabber.org/protocol/pubsub#owner'
|
||||
name = 'purge'
|
||||
plugin_attrib = name
|
||||
interfaces = {'node'}
|
||||
interfaces = set(('node',))
|
||||
|
||||
|
||||
class OwnerRedirect(ElementBase):
|
||||
namespace = 'http://jabber.org/protocol/pubsub#owner'
|
||||
name = 'redirect'
|
||||
plugin_attrib = name
|
||||
interfaces = {'node', 'jid'}
|
||||
interfaces = set(('node', 'jid'))
|
||||
|
||||
def set_jid(self, value):
|
||||
self._set_attr('jid', str(value))
|
||||
@@ -97,7 +97,7 @@ class OwnerSubscriptions(Subscriptions):
|
||||
name = 'subscriptions'
|
||||
namespace = 'http://jabber.org/protocol/pubsub#owner'
|
||||
plugin_attrib = name
|
||||
interfaces = {'node'}
|
||||
interfaces = set(('node',))
|
||||
|
||||
def append(self, subscription):
|
||||
if not isinstance(subscription, OwnerSubscription):
|
||||
@@ -109,7 +109,7 @@ class OwnerSubscription(ElementBase):
|
||||
namespace = 'http://jabber.org/protocol/pubsub#owner'
|
||||
name = 'subscription'
|
||||
plugin_attrib = name
|
||||
interfaces = {'jid', 'subscription'}
|
||||
interfaces = set(('jid', 'subscription'))
|
||||
|
||||
def set_jid(self, value):
|
||||
self._set_attr('jid', str(value))
|
||||
|
||||
@@ -22,7 +22,7 @@ class XEP_0065(BasePlugin):
|
||||
|
||||
name = 'xep_0065'
|
||||
description = "XEP-0065: SOCKS5 Bytestreams"
|
||||
dependencies = {'xep_0030'}
|
||||
dependencies = set(['xep_0030'])
|
||||
default_config = {
|
||||
'auto_accept': False
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@ class Socks5(ElementBase):
|
||||
name = 'query'
|
||||
namespace = 'http://jabber.org/protocol/bytestreams'
|
||||
plugin_attrib = 'socks'
|
||||
interfaces = {'sid', 'activate'}
|
||||
sub_interfaces = {'activate'}
|
||||
interfaces = set(['sid', 'activate'])
|
||||
sub_interfaces = set(['activate'])
|
||||
|
||||
def add_streamhost(self, jid, host, port):
|
||||
sh = StreamHost(parent=self)
|
||||
@@ -21,7 +21,7 @@ class StreamHost(ElementBase):
|
||||
namespace = 'http://jabber.org/protocol/bytestreams'
|
||||
plugin_attrib = 'streamhost'
|
||||
plugin_multi_attrib = 'streamhosts'
|
||||
interfaces = {'host', 'jid', 'port'}
|
||||
interfaces = set(['host', 'jid', 'port'])
|
||||
|
||||
def set_jid(self, value):
|
||||
return self._set_attr('jid', str(value))
|
||||
@@ -34,7 +34,7 @@ class StreamHostUsed(ElementBase):
|
||||
name = 'streamhost-used'
|
||||
namespace = 'http://jabber.org/protocol/bytestreams'
|
||||
plugin_attrib = 'streamhost_used'
|
||||
interfaces = {'jid'}
|
||||
interfaces = set(['jid'])
|
||||
|
||||
def set_jid(self, value):
|
||||
return self._set_attr('jid', str(value))
|
||||
|
||||
@@ -14,3 +14,7 @@ from slixmpp.plugins.xep_0066.oob import XEP_0066
|
||||
|
||||
|
||||
register_plugin(XEP_0066)
|
||||
|
||||
|
||||
# Retain some backwards compatibility
|
||||
xep_0066 = XEP_0066
|
||||
|
||||
@@ -44,7 +44,7 @@ class XEP_0066(BasePlugin):
|
||||
|
||||
name = 'xep_0066'
|
||||
description = 'XEP-0066: Out of Band Data'
|
||||
dependencies = {'xep_0030'}
|
||||
dependencies = set(['xep_0030'])
|
||||
stanza = stanza
|
||||
|
||||
def plugin_init(self):
|
||||
|
||||
@@ -17,8 +17,8 @@ class OOBTransfer(ElementBase):
|
||||
name = 'query'
|
||||
namespace = 'jabber:iq:oob'
|
||||
plugin_attrib = 'oob_transfer'
|
||||
interfaces = {'url', 'desc', 'sid'}
|
||||
sub_interfaces = {'url', 'desc'}
|
||||
interfaces = set(('url', 'desc', 'sid'))
|
||||
sub_interfaces = set(('url', 'desc'))
|
||||
|
||||
|
||||
class OOB(ElementBase):
|
||||
@@ -29,5 +29,5 @@ class OOB(ElementBase):
|
||||
name = 'x'
|
||||
namespace = 'jabber:x:oob'
|
||||
plugin_attrib = 'oob'
|
||||
interfaces = {'url', 'desc'}
|
||||
interfaces = set(('url', 'desc'))
|
||||
sub_interfaces = interfaces
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
"""
|
||||
Slixmpp: The Slick XMPP Library
|
||||
Copyright (C) 2015 Emmanuel Gil Peyrot
|
||||
This file is part of Slixmpp.
|
||||
|
||||
See the file LICENSE for copying permission.
|
||||
"""
|
||||
|
||||
from slixmpp.plugins.base import register_plugin
|
||||
|
||||
from slixmpp.plugins.xep_0070.stanza import Confirm
|
||||
from slixmpp.plugins.xep_0070.confirm import XEP_0070
|
||||
|
||||
|
||||
register_plugin(XEP_0070)
|
||||
@@ -1,86 +0,0 @@
|
||||
"""
|
||||
Slixmpp: The Slick XMPP Library
|
||||
Copyright (C) 2015 Emmanuel Gil Peyrot
|
||||
This file is part of Slixmpp.
|
||||
|
||||
See the file LICENSE for copying permission.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
from uuid import uuid4
|
||||
|
||||
from slixmpp.plugins import BasePlugin, register_plugin
|
||||
from slixmpp import future_wrapper, Iq, Message
|
||||
from slixmpp.exceptions import XMPPError, IqError, IqTimeout
|
||||
from slixmpp.jid import JID
|
||||
from slixmpp.xmlstream import JID, register_stanza_plugin
|
||||
from slixmpp.xmlstream.handler import Callback
|
||||
from slixmpp.xmlstream.matcher import StanzaPath
|
||||
from slixmpp.plugins.xep_0070 import stanza, Confirm
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class XEP_0070(BasePlugin):
|
||||
|
||||
"""
|
||||
XEP-0070 Verifying HTTP Requests via XMPP
|
||||
"""
|
||||
|
||||
name = 'xep_0070'
|
||||
description = 'XEP-0070: Verifying HTTP Requests via XMPP'
|
||||
dependencies = {'xep_0030'}
|
||||
stanza = stanza
|
||||
|
||||
def plugin_init(self):
|
||||
register_stanza_plugin(Iq, Confirm)
|
||||
register_stanza_plugin(Message, Confirm)
|
||||
|
||||
self.xmpp.register_handler(
|
||||
Callback('Confirm',
|
||||
StanzaPath('iq@type=get/confirm'),
|
||||
self._handle_iq_confirm))
|
||||
|
||||
self.xmpp.register_handler(
|
||||
Callback('Confirm',
|
||||
StanzaPath('message/confirm'),
|
||||
self._handle_message_confirm))
|
||||
|
||||
def plugin_end(self):
|
||||
self.xmpp.remove_handler('Confirm')
|
||||
self.xmpp['xep_0030'].del_feature(feature='http://jabber.org/protocol/http-auth')
|
||||
|
||||
def session_bind(self, jid):
|
||||
self.xmpp['xep_0030'].add_feature('http://jabber.org/protocol/http-auth')
|
||||
|
||||
@future_wrapper
|
||||
def ask_confirm(self, jid, id, url, method, *, ifrom=None, message=None):
|
||||
jid = JID(jid)
|
||||
if jid.resource:
|
||||
stanza = self.xmpp.Iq()
|
||||
stanza['type'] = 'get'
|
||||
else:
|
||||
stanza = self.xmpp.Message()
|
||||
stanza['thread'] = uuid4().hex
|
||||
stanza['from'] = ifrom
|
||||
stanza['to'] = jid
|
||||
stanza['confirm']['id'] = id
|
||||
stanza['confirm']['url'] = url
|
||||
stanza['confirm']['method'] = method
|
||||
if not jid.resource:
|
||||
if message is not None:
|
||||
stanza['body'] = message.format(id=id, url=url, method=method)
|
||||
stanza.send()
|
||||
return stanza
|
||||
else:
|
||||
return stanza.send()
|
||||
|
||||
def _handle_iq_confirm(self, iq):
|
||||
self.xmpp.event('http_confirm_iq', iq)
|
||||
self.xmpp.event('http_confirm', iq)
|
||||
|
||||
def _handle_message_confirm(self, message):
|
||||
self.xmpp.event('http_confirm_message', message)
|
||||
self.xmpp.event('http_confirm', message)
|
||||
@@ -1,17 +0,0 @@
|
||||
"""
|
||||
Slixmpp: The Slick XMPP Library
|
||||
Copyright (C) 2015 Emmanuel Gil Peyrot
|
||||
This file is part of Slixmpp.
|
||||
|
||||
See the file LICENSE for copying permission.
|
||||
"""
|
||||
|
||||
from slixmpp.xmlstream import ElementBase
|
||||
|
||||
|
||||
class Confirm(ElementBase):
|
||||
|
||||
name = 'confirm'
|
||||
namespace = 'http://jabber.org/protocol/http-auth'
|
||||
plugin_attrib = 'confirm'
|
||||
interfaces = {'id', 'url', 'method'}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user