Compare commits
20 Commits
disco
...
slix-1.2.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
36824379c3 | ||
|
|
a0a37c19ff | ||
|
|
1b5fe57a5e | ||
|
|
5da31db0c7 | ||
|
|
f8cea760b6 | ||
|
|
5ef01ecdd1 | ||
|
|
62aafe0ee7 | ||
|
|
cf3f36ac52 | ||
|
|
b88d2ecd77 | ||
|
|
e691850a2b | ||
|
|
d4bff8dee6 | ||
|
|
187c350805 | ||
|
|
96d1c26f90 | ||
|
|
46a90749f8 | ||
|
|
0c63a4bbda | ||
|
|
e4696e0471 | ||
|
|
8217dc5239 | ||
|
|
2586abc0d3 | ||
|
|
28f84ab3d9 | ||
|
|
813b45aded |
@@ -12,8 +12,8 @@ Building
|
|||||||
--------
|
--------
|
||||||
|
|
||||||
Slixmpp can make use of cython to improve performance on critical modules.
|
Slixmpp can make use of cython to improve performance on critical modules.
|
||||||
To do that, cython3 is necessary along with libidn headers. Otherwise,
|
To do that, **cython3** is necessary along with **libidn** headers.
|
||||||
no compilation is needed. Building is done by running setup.py::
|
Otherwise, no compilation is needed. Building is done by running setup.py::
|
||||||
|
|
||||||
python3 setup.py build_ext --inplace
|
python3 setup.py build_ext --inplace
|
||||||
|
|
||||||
@@ -108,6 +108,11 @@ Slixmpp Credits
|
|||||||
|
|
||||||
**Contributors:**
|
**Contributors:**
|
||||||
- Emmanuel Gil Peyrot (`Link mauve <xmpp:linkmauve@linkmauve.fr?message>`_)
|
- 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>`_)
|
||||||
|
|
||||||
Credits (SleekXMPP)
|
Credits (SleekXMPP)
|
||||||
-------------------
|
-------------------
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ as well.
|
|||||||
class EchoBot(slixmpp.ClientXMPP):
|
class EchoBot(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
def __init__(self, jid, password):
|
def __init__(self, jid, password):
|
||||||
super(EchoBot, self).__init__(jid, password)
|
super().__init__(jid, password)
|
||||||
|
|
||||||
Handling Session Start
|
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
|
.. code-block:: python
|
||||||
|
|
||||||
def __init__(self, jid, password):
|
def __init__(self, jid, password):
|
||||||
super(EchoBot, self).__init__(jid, password)
|
super().__init__(jid, password)
|
||||||
|
|
||||||
self.add_event_handler('session_start', self.start)
|
self.add_event_handler('session_start', self.start)
|
||||||
|
|
||||||
@@ -153,7 +153,7 @@ whenever a messsage is received.
|
|||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
def __init__(self, jid, password):
|
def __init__(self, jid, password):
|
||||||
super(EchoBot, self).__init__(jid, password)
|
super().__init__(jid, password)
|
||||||
|
|
||||||
self.add_event_handler('session_start', self.start)
|
self.add_event_handler('session_start', self.start)
|
||||||
self.add_event_handler('message', self.message)
|
self.add_event_handler('message', self.message)
|
||||||
|
|||||||
@@ -63,13 +63,13 @@ has been established:
|
|||||||
def start(self, event):
|
def start(self, event):
|
||||||
self.get_roster()
|
self.get_roster()
|
||||||
self.send_presence()
|
self.send_presence()
|
||||||
self.plugin['xep_0045'].joinMUC(self.room,
|
self.plugin['xep_0045'].join_muc(self.room,
|
||||||
self.nick,
|
self.nick,
|
||||||
wait=True)
|
wait=True)
|
||||||
|
|
||||||
Note that as in :ref:`echobot`, we need to include send an initial presence and request
|
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
|
the roster. Next, we want to join the group chat, so we call the
|
||||||
``joinMUC`` method of the MUC plugin.
|
``join_muc`` method of the MUC plugin.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ for the JID that will receive our message, and the string content of the message
|
|||||||
class SendMsgBot(slixmpp.ClientXMPP):
|
class SendMsgBot(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
def __init__(self, jid, password, recipient, msg):
|
def __init__(self, jid, password, recipient, msg):
|
||||||
super(SendMsgBot, self).__init__(jid, password)
|
super().__init__(jid, password)
|
||||||
|
|
||||||
self.recipient = recipient
|
self.recipient = recipient
|
||||||
self.msg = msg
|
self.msg = msg
|
||||||
|
|||||||
@@ -67,11 +67,11 @@ class MUCBot(slixmpp.ClientXMPP):
|
|||||||
"""
|
"""
|
||||||
self.get_roster()
|
self.get_roster()
|
||||||
self.send_presence()
|
self.send_presence()
|
||||||
self.plugin['xep_0045'].joinMUC(self.room,
|
self.plugin['xep_0045'].join_muc(self.room,
|
||||||
self.nick,
|
self.nick,
|
||||||
# If a room password is needed, use:
|
# If a room password is needed, use:
|
||||||
# password=the_room_password,
|
# password=the_room_password,
|
||||||
wait=True)
|
wait=True)
|
||||||
|
|
||||||
def muc_message(self, msg):
|
def muc_message(self, msg):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ class PubsubClient(slixmpp.ClientXMPP):
|
|||||||
|
|
||||||
def __init__(self, jid, password, server,
|
def __init__(self, jid, password, server,
|
||||||
node=None, action='nodes', data=''):
|
node=None, action='nodes', data=''):
|
||||||
super(PubsubClient, self).__init__(jid, password)
|
super().__init__(jid, password)
|
||||||
|
|
||||||
self.register_plugin('xep_0030')
|
self.register_plugin('xep_0030')
|
||||||
self.register_plugin('xep_0059')
|
self.register_plugin('xep_0059')
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ from slixmpp.xmlstream.handler import Callback
|
|||||||
class PubsubEvents(slixmpp.ClientXMPP):
|
class PubsubEvents(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
def __init__(self, jid, password):
|
def __init__(self, jid, password):
|
||||||
super(PubsubEvents, self).__init__(jid, password)
|
super().__init__(jid, password)
|
||||||
|
|
||||||
self.register_plugin('xep_0030')
|
self.register_plugin('xep_0030')
|
||||||
self.register_plugin('xep_0059')
|
self.register_plugin('xep_0059')
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ from slixmpp import ClientXMPP
|
|||||||
class LocationBot(ClientXMPP):
|
class LocationBot(ClientXMPP):
|
||||||
|
|
||||||
def __init__(self, jid, password):
|
def __init__(self, jid, password):
|
||||||
super(LocationBot, self).__init__(jid, password)
|
super().__init__(jid, password)
|
||||||
|
|
||||||
self.add_event_handler('session_start', self.start)
|
self.add_event_handler('session_start', self.start)
|
||||||
self.add_event_handler('user_location_publish',
|
self.add_event_handler('user_location_publish',
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ from slixmpp import ClientXMPP
|
|||||||
class TuneBot(ClientXMPP):
|
class TuneBot(ClientXMPP):
|
||||||
|
|
||||||
def __init__(self, jid, password):
|
def __init__(self, jid, password):
|
||||||
super(TuneBot, self).__init__(jid, password)
|
super().__init__(jid, password)
|
||||||
|
|
||||||
# Check for the current song every 5 seconds.
|
# Check for the current song every 5 seconds.
|
||||||
self.schedule('Check Current Tune', 5, self._update_tune, repeat=True)
|
self.schedule('Check Current Tune', 5, self._update_tune, repeat=True)
|
||||||
|
|||||||
@@ -141,8 +141,11 @@ class ClientXMPP(BaseXMPP):
|
|||||||
will be used.
|
will be used.
|
||||||
|
|
||||||
:param address: A tuple containing the server's host and port.
|
:param address: A tuple containing the server's host and port.
|
||||||
:param use_tls: Indicates if TLS should be used for the
|
:param force_starttls: Indicates that negotiation should be aborted
|
||||||
connection. Defaults to ``True``.
|
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_ssl: Indicates if the older SSL connection method
|
:param use_ssl: Indicates if the older SSL connection method
|
||||||
should be used. Defaults to ``False``.
|
should be used. Defaults to ``False``.
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ class IqTimeout(XMPPError):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, iq):
|
def __init__(self, iq):
|
||||||
super(IqTimeout, self).__init__(
|
super().__init__(
|
||||||
condition='remote-server-timeout',
|
condition='remote-server-timeout',
|
||||||
etype='cancel')
|
etype='cancel')
|
||||||
|
|
||||||
@@ -94,7 +94,7 @@ class IqError(XMPPError):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, iq):
|
def __init__(self, iq):
|
||||||
super(IqError, self).__init__(
|
super().__init__(
|
||||||
condition=iq['error']['condition'],
|
condition=iq['error']['condition'],
|
||||||
text=iq['error']['text'],
|
text=iq['error']['text'],
|
||||||
etype=iq['error']['type'])
|
etype=iq['error']['type'])
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ def _validate_node(node):
|
|||||||
:returns: The local portion of a JID, as validated by nodeprep.
|
:returns: The local portion of a JID, as validated by nodeprep.
|
||||||
"""
|
"""
|
||||||
if node is None:
|
if node is None:
|
||||||
return None
|
return ''
|
||||||
|
|
||||||
try:
|
try:
|
||||||
node = nodeprep(node)
|
node = nodeprep(node)
|
||||||
@@ -160,7 +160,7 @@ def _validate_resource(resource):
|
|||||||
:returns: The local portion of a JID, as validated by resourceprep.
|
:returns: The local portion of a JID, as validated by resourceprep.
|
||||||
"""
|
"""
|
||||||
if resource is None:
|
if resource is None:
|
||||||
return None
|
return ''
|
||||||
|
|
||||||
try:
|
try:
|
||||||
resource = resourceprep(resource)
|
resource = resourceprep(resource)
|
||||||
|
|||||||
@@ -308,7 +308,7 @@ class BasePlugin(object):
|
|||||||
if key in self.default_config:
|
if key in self.default_config:
|
||||||
self.config[key] = value
|
self.config[key] = value
|
||||||
else:
|
else:
|
||||||
super(BasePlugin, self).__setattr__(key, value)
|
super().__setattr__(key, value)
|
||||||
|
|
||||||
def _init(self):
|
def _init(self):
|
||||||
"""Initialize plugin state, such as registering event handlers.
|
"""Initialize plugin state, such as registering event handlers.
|
||||||
|
|||||||
@@ -23,13 +23,13 @@ class GmailQuery(ElementBase):
|
|||||||
plugin_attrib = 'gmail'
|
plugin_attrib = 'gmail'
|
||||||
interfaces = set(('newer-than-time', 'newer-than-tid', 'q', 'search'))
|
interfaces = set(('newer-than-time', 'newer-than-tid', 'q', 'search'))
|
||||||
|
|
||||||
def getSearch(self):
|
def get_search(self):
|
||||||
return self['q']
|
return self['q']
|
||||||
|
|
||||||
def setSearch(self, search):
|
def set_search(self, search):
|
||||||
self['q'] = search
|
self['q'] = search
|
||||||
|
|
||||||
def delSearch(self):
|
def del_search(self):
|
||||||
del self['q']
|
del self['q']
|
||||||
|
|
||||||
|
|
||||||
@@ -40,17 +40,17 @@ class MailBox(ElementBase):
|
|||||||
interfaces = set(('result-time', 'total-matched', 'total-estimate',
|
interfaces = set(('result-time', 'total-matched', 'total-estimate',
|
||||||
'url', 'threads', 'matched', 'estimate'))
|
'url', 'threads', 'matched', 'estimate'))
|
||||||
|
|
||||||
def getThreads(self):
|
def get_threads(self):
|
||||||
threads = []
|
threads = []
|
||||||
for threadXML in self.xml.findall('{%s}%s' % (MailThread.namespace,
|
for threadXML in self.xml.findall('{%s}%s' % (MailThread.namespace,
|
||||||
MailThread.name)):
|
MailThread.name)):
|
||||||
threads.append(MailThread(xml=threadXML, parent=None))
|
threads.append(MailThread(xml=threadXML, parent=None))
|
||||||
return threads
|
return threads
|
||||||
|
|
||||||
def getMatched(self):
|
def get_matched(self):
|
||||||
return self['total-matched']
|
return self['total-matched']
|
||||||
|
|
||||||
def getEstimate(self):
|
def get_estimate(self):
|
||||||
return self['total-estimate'] == '1'
|
return self['total-estimate'] == '1'
|
||||||
|
|
||||||
|
|
||||||
@@ -62,7 +62,7 @@ class MailThread(ElementBase):
|
|||||||
'senders', 'url', 'labels', 'subject', 'snippet'))
|
'senders', 'url', 'labels', 'subject', 'snippet'))
|
||||||
sub_interfaces = set(('labels', 'subject', 'snippet'))
|
sub_interfaces = set(('labels', 'subject', 'snippet'))
|
||||||
|
|
||||||
def getSenders(self):
|
def get_senders(self):
|
||||||
senders = []
|
senders = []
|
||||||
sendersXML = self.xml.find('{%s}senders' % self.namespace)
|
sendersXML = self.xml.find('{%s}senders' % self.namespace)
|
||||||
if sendersXML is not None:
|
if sendersXML is not None:
|
||||||
@@ -77,10 +77,10 @@ class MailSender(ElementBase):
|
|||||||
plugin_attrib = 'sender'
|
plugin_attrib = 'sender'
|
||||||
interfaces = set(('address', 'name', 'originator', 'unread'))
|
interfaces = set(('address', 'name', 'originator', 'unread'))
|
||||||
|
|
||||||
def getOriginator(self):
|
def get_originator(self):
|
||||||
return self.xml.attrib.get('originator', '0') == '1'
|
return self.xml.attrib.get('originator', '0') == '1'
|
||||||
|
|
||||||
def getUnread(self):
|
def get_unread(self):
|
||||||
return self.xml.attrib.get('unread', '0') == '1'
|
return self.xml.attrib.get('unread', '0') == '1'
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -92,13 +92,13 @@ def _py2xml(*args):
|
|||||||
def xml2py(params):
|
def xml2py(params):
|
||||||
namespace = 'jabber:iq:rpc'
|
namespace = 'jabber:iq:rpc'
|
||||||
vals = []
|
vals = []
|
||||||
for param in params.xml.findall('{%s}param' % namespace):
|
for param in params.findall('{%s}param' % namespace):
|
||||||
vals.append(_xml2py(param.find('{%s}value' % namespace)))
|
vals.append(_xml2py(param.find('{%s}value' % namespace)))
|
||||||
return vals
|
return vals
|
||||||
|
|
||||||
def _xml2py(value):
|
def _xml2py(value):
|
||||||
namespace = 'jabber:iq:rpc'
|
namespace = 'jabber:iq:rpc'
|
||||||
find_value = value.xml.find
|
find_value = value.find
|
||||||
if find_value('{%s}nil' % namespace) is not None:
|
if find_value('{%s}nil' % namespace) is not None:
|
||||||
return None
|
return None
|
||||||
if find_value('{%s}i4' % namespace) is not None:
|
if find_value('{%s}i4' % namespace) is not None:
|
||||||
|
|||||||
@@ -117,9 +117,12 @@ for atype in ('all', 'bcc', 'cc', 'noreply', 'replyroom', 'replyto', 'to'):
|
|||||||
setattr(Addresses, "set_%s" % atype, set_multi)
|
setattr(Addresses, "set_%s" % atype, set_multi)
|
||||||
setattr(Addresses, "del_%s" % atype, del_multi)
|
setattr(Addresses, "del_%s" % atype, del_multi)
|
||||||
|
|
||||||
# To retain backwards compatibility:
|
|
||||||
if atype == 'all':
|
if atype == 'all':
|
||||||
Addresses.interfaces.add('addresses')
|
Addresses.interfaces.add('addresses')
|
||||||
|
setattr(Addresses, "get_addresses", get_multi)
|
||||||
|
setattr(Addresses, "set_addresses", set_multi)
|
||||||
|
setattr(Addresses, "del_addresses", del_multi)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
register_stanza_plugin(Addresses, Address, iterable=True)
|
register_stanza_plugin(Addresses, Address, iterable=True)
|
||||||
|
|||||||
@@ -29,82 +29,82 @@ class MUCPresence(ElementBase):
|
|||||||
affiliations = set(('', ))
|
affiliations = set(('', ))
|
||||||
roles = set(('', ))
|
roles = set(('', ))
|
||||||
|
|
||||||
def getXMLItem(self):
|
def get_xml_item(self):
|
||||||
item = self.xml.find('{http://jabber.org/protocol/muc#user}item')
|
item = self.xml.find('{http://jabber.org/protocol/muc#user}item')
|
||||||
if item is None:
|
if item is None:
|
||||||
item = ET.Element('{http://jabber.org/protocol/muc#user}item')
|
item = ET.Element('{http://jabber.org/protocol/muc#user}item')
|
||||||
self.xml.append(item)
|
self.xml.append(item)
|
||||||
return item
|
return item
|
||||||
|
|
||||||
def getAffiliation(self):
|
def get_affiliation(self):
|
||||||
#TODO if no affilation, set it to the default and return default
|
#TODO if no affilation, set it to the default and return default
|
||||||
item = self.getXMLItem()
|
item = self.get_xml_item()
|
||||||
return item.get('affiliation', '')
|
return item.get('affiliation', '')
|
||||||
|
|
||||||
def setAffiliation(self, value):
|
def set_affiliation(self, value):
|
||||||
item = self.getXMLItem()
|
item = self.get_xml_item()
|
||||||
#TODO check for valid affiliation
|
#TODO check for valid affiliation
|
||||||
item.attrib['affiliation'] = value
|
item.attrib['affiliation'] = value
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def delAffiliation(self):
|
def del_affiliation(self):
|
||||||
item = self.getXMLItem()
|
item = self.get_xml_item()
|
||||||
#TODO set default affiliation
|
#TODO set default affiliation
|
||||||
if 'affiliation' in item.attrib: del item.attrib['affiliation']
|
if 'affiliation' in item.attrib: del item.attrib['affiliation']
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def getJid(self):
|
def get_jid(self):
|
||||||
item = self.getXMLItem()
|
item = self.get_xml_item()
|
||||||
return JID(item.get('jid', ''))
|
return JID(item.get('jid', ''))
|
||||||
|
|
||||||
def setJid(self, value):
|
def set_jid(self, value):
|
||||||
item = self.getXMLItem()
|
item = self.get_xml_item()
|
||||||
if not isinstance(value, str):
|
if not isinstance(value, str):
|
||||||
value = str(value)
|
value = str(value)
|
||||||
item.attrib['jid'] = value
|
item.attrib['jid'] = value
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def delJid(self):
|
def del_jid(self):
|
||||||
item = self.getXMLItem()
|
item = self.get_xml_item()
|
||||||
if 'jid' in item.attrib: del item.attrib['jid']
|
if 'jid' in item.attrib: del item.attrib['jid']
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def getRole(self):
|
def get_role(self):
|
||||||
item = self.getXMLItem()
|
item = self.get_xml_item()
|
||||||
#TODO get default role, set default role if none
|
#TODO get default role, set default role if none
|
||||||
return item.get('role', '')
|
return item.get('role', '')
|
||||||
|
|
||||||
def setRole(self, value):
|
def set_role(self, value):
|
||||||
item = self.getXMLItem()
|
item = self.get_xml_item()
|
||||||
#TODO check for valid role
|
#TODO check for valid role
|
||||||
item.attrib['role'] = value
|
item.attrib['role'] = value
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def delRole(self):
|
def del_role(self):
|
||||||
item = self.getXMLItem()
|
item = self.get_xml_item()
|
||||||
#TODO set default role
|
#TODO set default role
|
||||||
if 'role' in item.attrib: del item.attrib['role']
|
if 'role' in item.attrib: del item.attrib['role']
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def getNick(self):
|
def get_nick(self):
|
||||||
return self.parent()['from'].resource
|
return self.parent()['from'].resource
|
||||||
|
|
||||||
def getRoom(self):
|
def get_room(self):
|
||||||
return self.parent()['from'].bare
|
return self.parent()['from'].bare
|
||||||
|
|
||||||
def setNick(self, value):
|
def set_nick(self, value):
|
||||||
log.warning("Cannot set nick through mucpresence plugin.")
|
log.warning("Cannot set nick through mucpresence plugin.")
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def setRoom(self, value):
|
def set_room(self, value):
|
||||||
log.warning("Cannot set room through mucpresence plugin.")
|
log.warning("Cannot set room through mucpresence plugin.")
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def delNick(self):
|
def del_nick(self):
|
||||||
log.warning("Cannot delete nick through mucpresence plugin.")
|
log.warning("Cannot delete nick through mucpresence plugin.")
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def delRoom(self):
|
def del_room(self):
|
||||||
log.warning("Cannot delete room through mucpresence plugin.")
|
log.warning("Cannot delete room through mucpresence plugin.")
|
||||||
return self
|
return self
|
||||||
|
|
||||||
@@ -121,7 +121,7 @@ class XEP_0045(BasePlugin):
|
|||||||
|
|
||||||
def plugin_init(self):
|
def plugin_init(self):
|
||||||
self.rooms = {}
|
self.rooms = {}
|
||||||
self.ourNicks = {}
|
self.our_nicks = {}
|
||||||
self.xep = '0045'
|
self.xep = '0045'
|
||||||
# load MUC support in presence stanzas
|
# load MUC support in presence stanzas
|
||||||
register_stanza_plugin(Presence, MUCPresence)
|
register_stanza_plugin(Presence, MUCPresence)
|
||||||
@@ -201,22 +201,22 @@ class XEP_0045(BasePlugin):
|
|||||||
"""
|
"""
|
||||||
self.xmpp.event('groupchat_subject', msg)
|
self.xmpp.event('groupchat_subject', msg)
|
||||||
|
|
||||||
def jidInRoom(self, room, jid):
|
def jid_in_room(self, room, jid):
|
||||||
for nick in self.rooms[room]:
|
for nick in self.rooms[room]:
|
||||||
entry = self.rooms[room][nick]
|
entry = self.rooms[room][nick]
|
||||||
if entry is not None and entry['jid'].full == jid:
|
if entry is not None and entry['jid'].full == jid:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def getNick(self, room, jid):
|
def get_nick(self, room, jid):
|
||||||
for nick in self.rooms[room]:
|
for nick in self.rooms[room]:
|
||||||
entry = self.rooms[room][nick]
|
entry = self.rooms[room][nick]
|
||||||
if entry is not None and entry['jid'].full == jid:
|
if entry is not None and entry['jid'].full == jid:
|
||||||
return nick
|
return nick
|
||||||
|
|
||||||
def configureRoom(self, room, form=None, ifrom=None):
|
def configure_room(self, room, form=None, ifrom=None):
|
||||||
if form is None:
|
if form is None:
|
||||||
form = self.getRoomConfig(room, ifrom=ifrom)
|
form = self.get_room_config(room, ifrom=ifrom)
|
||||||
iq = self.xmpp.make_iq_set()
|
iq = self.xmpp.make_iq_set()
|
||||||
iq['to'] = room
|
iq['to'] = room
|
||||||
if ifrom is not None:
|
if ifrom is not None:
|
||||||
@@ -234,7 +234,7 @@ class XEP_0045(BasePlugin):
|
|||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def joinMUC(self, room, nick, maxhistory="0", password='', wait=False, pstatus=None, pshow=None, pfrom=None):
|
def join_muc(self, room, nick, maxhistory="0", password='', wait=False, pstatus=None, pshow=None, pfrom=None):
|
||||||
""" Join the specified room, requesting 'maxhistory' lines of history.
|
""" 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)
|
stanza = self.xmpp.make_presence(pto="%s/%s" % (room, nick), pstatus=pstatus, pshow=pshow, pfrom=pfrom)
|
||||||
@@ -258,7 +258,7 @@ class XEP_0045(BasePlugin):
|
|||||||
expect = ET.Element("{%s}presence" % self.xmpp.default_ns, {'from':"%s/%s" % (room, nick)})
|
expect = ET.Element("{%s}presence" % self.xmpp.default_ns, {'from':"%s/%s" % (room, nick)})
|
||||||
self.xmpp.send(stanza, expect)
|
self.xmpp.send(stanza, expect)
|
||||||
self.rooms[room] = {}
|
self.rooms[room] = {}
|
||||||
self.ourNicks[room] = nick
|
self.our_nicks[room] = nick
|
||||||
|
|
||||||
def destroy(self, room, reason='', altroom = '', ifrom=None):
|
def destroy(self, room, reason='', altroom = '', ifrom=None):
|
||||||
iq = self.xmpp.make_iq_set()
|
iq = self.xmpp.make_iq_set()
|
||||||
@@ -283,7 +283,7 @@ class XEP_0045(BasePlugin):
|
|||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def setAffiliation(self, room, jid=None, nick=None, affiliation='member', ifrom=None):
|
def set_affiliation(self, room, jid=None, nick=None, affiliation='member', ifrom=None):
|
||||||
""" Change room affiliation."""
|
""" Change room affiliation."""
|
||||||
if affiliation not in ('outcast', 'member', 'admin', 'owner', 'none'):
|
if affiliation not in ('outcast', 'member', 'admin', 'owner', 'none'):
|
||||||
raise TypeError
|
raise TypeError
|
||||||
@@ -305,7 +305,7 @@ class XEP_0045(BasePlugin):
|
|||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def setRole(self, room, nick, role):
|
def set_role(self, room, nick, role):
|
||||||
""" Change role property of a nick in a room.
|
""" Change role property of a nick in a room.
|
||||||
Typically, roles are temporary (they last only as long as you are in the
|
Typically, roles are temporary (they last only as long as you are in the
|
||||||
room), whereas affiliations are permanent (they last across groupchat
|
room), whereas affiliations are permanent (they last across groupchat
|
||||||
@@ -337,7 +337,7 @@ class XEP_0045(BasePlugin):
|
|||||||
msg.append(x)
|
msg.append(x)
|
||||||
self.xmpp.send(msg)
|
self.xmpp.send(msg)
|
||||||
|
|
||||||
def leaveMUC(self, room, nick, msg='', pfrom=None):
|
def leave_muc(self, room, nick, msg='', pfrom=None):
|
||||||
""" Leave the specified room.
|
""" Leave the specified room.
|
||||||
"""
|
"""
|
||||||
if msg:
|
if msg:
|
||||||
@@ -346,7 +346,7 @@ class XEP_0045(BasePlugin):
|
|||||||
self.xmpp.send_presence(pshow='unavailable', pto="%s/%s" % (room, nick), pfrom=pfrom)
|
self.xmpp.send_presence(pshow='unavailable', pto="%s/%s" % (room, nick), pfrom=pfrom)
|
||||||
del self.rooms[room]
|
del self.rooms[room]
|
||||||
|
|
||||||
def getRoomConfig(self, room, ifrom=''):
|
def get_room_config(self, room, ifrom=''):
|
||||||
iq = self.xmpp.make_iq_get('http://jabber.org/protocol/muc#owner')
|
iq = self.xmpp.make_iq_get('http://jabber.org/protocol/muc#owner')
|
||||||
iq['to'] = room
|
iq['to'] = room
|
||||||
iq['from'] = ifrom
|
iq['from'] = ifrom
|
||||||
@@ -362,7 +362,7 @@ class XEP_0045(BasePlugin):
|
|||||||
raise ValueError
|
raise ValueError
|
||||||
return self.xmpp.plugin['xep_0004'].build_form(form)
|
return self.xmpp.plugin['xep_0004'].build_form(form)
|
||||||
|
|
||||||
def cancelConfig(self, room, ifrom=None):
|
def cancel_config(self, room, ifrom=None):
|
||||||
query = ET.Element('{http://jabber.org/protocol/muc#owner}query')
|
query = ET.Element('{http://jabber.org/protocol/muc#owner}query')
|
||||||
x = ET.Element('{jabber:x:data}x', type='cancel')
|
x = ET.Element('{jabber:x:data}x', type='cancel')
|
||||||
query.append(x)
|
query.append(x)
|
||||||
@@ -371,7 +371,7 @@ class XEP_0045(BasePlugin):
|
|||||||
iq['from'] = ifrom
|
iq['from'] = ifrom
|
||||||
iq.send()
|
iq.send()
|
||||||
|
|
||||||
def setRoomConfig(self, room, config, ifrom=''):
|
def set_room_config(self, room, config, ifrom=''):
|
||||||
query = ET.Element('{http://jabber.org/protocol/muc#owner}query')
|
query = ET.Element('{http://jabber.org/protocol/muc#owner}query')
|
||||||
config['type'] = 'submit'
|
config['type'] = 'submit'
|
||||||
query.append(config)
|
query.append(config)
|
||||||
@@ -380,31 +380,31 @@ class XEP_0045(BasePlugin):
|
|||||||
iq['from'] = ifrom
|
iq['from'] = ifrom
|
||||||
iq.send()
|
iq.send()
|
||||||
|
|
||||||
def getJoinedRooms(self):
|
def get_joined_rooms(self):
|
||||||
return self.rooms.keys()
|
return self.rooms.keys()
|
||||||
|
|
||||||
def getOurJidInRoom(self, roomJid):
|
def get_our_jid_in_room(self, room_jid):
|
||||||
""" Return the jid we're using in a room.
|
""" Return the jid we're using in a room.
|
||||||
"""
|
"""
|
||||||
return "%s/%s" % (roomJid, self.ourNicks[roomJid])
|
return "%s/%s" % (room_jid, self.our_nicks[room_jid])
|
||||||
|
|
||||||
def getJidProperty(self, room, nick, jidProperty):
|
def get_jid_property(self, room, nick, jid_property):
|
||||||
""" Get the property of a nick in a room, such as its 'jid' or 'affiliation'
|
""" Get the property of a nick in a room, such as its 'jid' or 'affiliation'
|
||||||
If not found, return None.
|
If not found, return None.
|
||||||
"""
|
"""
|
||||||
if room in self.rooms and nick in self.rooms[room] and jidProperty in self.rooms[room][nick]:
|
if room in self.rooms and nick in self.rooms[room] and jid_property in self.rooms[room][nick]:
|
||||||
return self.rooms[room][nick][jidProperty]
|
return self.rooms[room][nick][jid_property]
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def getRoster(self, room):
|
def get_roster(self, room):
|
||||||
""" Get the list of nicks in a room.
|
""" Get the list of nicks in a room.
|
||||||
"""
|
"""
|
||||||
if room not in self.rooms.keys():
|
if room not in self.rooms.keys():
|
||||||
return None
|
return None
|
||||||
return self.rooms[room].keys()
|
return self.rooms[room].keys()
|
||||||
|
|
||||||
def getUsersByAffiliation(cls, room, affiliation='member', ifrom=None):
|
def get_users_by_affiliation(cls, room, affiliation='member', ifrom=None):
|
||||||
if affiliation not in ('outcast', 'member', 'admin', 'owner', 'none'):
|
if affiliation not in ('outcast', 'member', 'admin', 'owner', 'none'):
|
||||||
raise TypeError
|
raise TypeError
|
||||||
query = ET.Element('{http://jabber.org/protocol/muc#admin}query')
|
query = ET.Element('{http://jabber.org/protocol/muc#admin}query')
|
||||||
@@ -415,5 +415,4 @@ class XEP_0045(BasePlugin):
|
|||||||
return iq.send()
|
return iq.send()
|
||||||
|
|
||||||
|
|
||||||
xep_0045 = XEP_0045
|
|
||||||
register_plugin(XEP_0045)
|
register_plugin(XEP_0045)
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ class XEP_0048(BasePlugin):
|
|||||||
for conf in bookmarks['conferences']:
|
for conf in bookmarks['conferences']:
|
||||||
if conf['autojoin']:
|
if conf['autojoin']:
|
||||||
log.debug('Auto joining %s as %s', conf['jid'], conf['nick'])
|
log.debug('Auto joining %s as %s', conf['jid'], conf['nick'])
|
||||||
self.xmpp['xep_0045'].joinMUC(conf['jid'], conf['nick'],
|
self.xmpp['xep_0045'].join_muc(conf['jid'], conf['nick'],
|
||||||
password=conf['password'])
|
password=conf['password'])
|
||||||
|
|
||||||
def set_bookmarks(self, bookmarks, method=None, **iqargs):
|
def set_bookmarks(self, bookmarks, method=None, **iqargs):
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ class Command(ElementBase):
|
|||||||
('error', 'The command ran, but had errors')]
|
('error', 'The command ran, but had errors')]
|
||||||
"""
|
"""
|
||||||
notes = []
|
notes = []
|
||||||
notes_xml = self.findall('{%s}note' % self.namespace)
|
notes_xml = self.xml.findall('{%s}note' % self.namespace)
|
||||||
for note in notes_xml:
|
for note in notes_xml:
|
||||||
notes.append((note.attrib.get('type', 'info'),
|
notes.append((note.attrib.get('type', 'info'),
|
||||||
note.text))
|
note.text))
|
||||||
@@ -167,7 +167,7 @@ class Command(ElementBase):
|
|||||||
"""
|
"""
|
||||||
Remove all notes associated with the command result.
|
Remove all notes associated with the command result.
|
||||||
"""
|
"""
|
||||||
notes_xml = self.findall('{%s}note' % self.namespace)
|
notes_xml = self.xml.findall('{%s}note' % self.namespace)
|
||||||
for note in notes_xml:
|
for note in notes_xml:
|
||||||
self.xml.remove(note)
|
self.xml.remove(note)
|
||||||
|
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ class Telephone(ElementBase):
|
|||||||
'ISDN', 'PCS', 'PREF'])
|
'ISDN', 'PCS', 'PREF'])
|
||||||
|
|
||||||
def setup(self, xml=None):
|
def setup(self, xml=None):
|
||||||
super(Telephone, self).setup(xml=xml)
|
super().setup(xml=xml)
|
||||||
## this blanks out numbers received from server
|
## this blanks out numbers received from server
|
||||||
##self._set_sub_text('NUMBER', '', keep=True)
|
##self._set_sub_text('NUMBER', '', keep=True)
|
||||||
|
|
||||||
|
|||||||
@@ -206,7 +206,10 @@ class Options(ElementBase):
|
|||||||
return form
|
return form
|
||||||
|
|
||||||
def set_options(self, value):
|
def set_options(self, value):
|
||||||
self.xml.append(value)
|
if isinstance(value, ElementBase):
|
||||||
|
self.xml.append(value.xml)
|
||||||
|
else:
|
||||||
|
self.xml.append(value)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def del_options(self):
|
def del_options(self):
|
||||||
@@ -238,7 +241,10 @@ class PublishOptions(ElementBase):
|
|||||||
if value is None:
|
if value is None:
|
||||||
self.del_publish_options()
|
self.del_publish_options()
|
||||||
else:
|
else:
|
||||||
self.xml.append(value)
|
if isinstance(value, ElementBase):
|
||||||
|
self.xml.append(value.xml)
|
||||||
|
else:
|
||||||
|
self.xml.append(value)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def del_publish_options(self):
|
def del_publish_options(self):
|
||||||
|
|||||||
@@ -38,9 +38,8 @@ class StaticExtendedDisco(object):
|
|||||||
The data parameter may provide:
|
The data parameter may provide:
|
||||||
data -- Either a single data form, or a list of data forms.
|
data -- Either a single data form, or a list of data forms.
|
||||||
"""
|
"""
|
||||||
with self.static.lock:
|
self.del_extended_info(jid, node, ifrom, data)
|
||||||
self.del_extended_info(jid, node, ifrom, data)
|
self.add_extended_info(jid, node, ifrom, data)
|
||||||
self.add_extended_info(jid, node, ifrom, data)
|
|
||||||
|
|
||||||
def add_extended_info(self, jid, node, ifrom, data):
|
def add_extended_info(self, jid, node, ifrom, data):
|
||||||
"""
|
"""
|
||||||
@@ -49,16 +48,15 @@ class StaticExtendedDisco(object):
|
|||||||
The data parameter may provide:
|
The data parameter may provide:
|
||||||
data -- Either a single data form, or a list of data forms.
|
data -- Either a single data form, or a list of data forms.
|
||||||
"""
|
"""
|
||||||
with self.static.lock:
|
self.static.add_node(jid, node)
|
||||||
self.static.add_node(jid, node)
|
|
||||||
|
|
||||||
forms = data.get('data', [])
|
forms = data.get('data', [])
|
||||||
if not isinstance(forms, list):
|
if not isinstance(forms, list):
|
||||||
forms = [forms]
|
forms = [forms]
|
||||||
|
|
||||||
info = self.static.get_node(jid, node)['info']
|
info = self.static.get_node(jid, node)['info']
|
||||||
for form in forms:
|
for form in forms:
|
||||||
info.append(form)
|
info.append(form)
|
||||||
|
|
||||||
def del_extended_info(self, jid, node, ifrom, data):
|
def del_extended_info(self, jid, node, ifrom, data):
|
||||||
"""
|
"""
|
||||||
@@ -66,8 +64,7 @@ class StaticExtendedDisco(object):
|
|||||||
|
|
||||||
The data parameter is not used.
|
The data parameter is not used.
|
||||||
"""
|
"""
|
||||||
with self.static.lock:
|
if self.static.node_exists(jid, node):
|
||||||
if self.static.node_exists(jid, node):
|
info = self.static.get_node(jid, node)['info']
|
||||||
info = self.static.get_node(jid, node)['info']
|
for form in info['substanza']:
|
||||||
for form in info['substanza']:
|
info.xml.remove(form.xml)
|
||||||
info.xml.remove(form.xml)
|
|
||||||
|
|||||||
@@ -9,5 +9,5 @@
|
|||||||
# We don't want to have to import the entire library
|
# We don't want to have to import the entire library
|
||||||
# just to get the version info for setup.py
|
# just to get the version info for setup.py
|
||||||
|
|
||||||
__version__ = '1.1'
|
__version__ = '1.2.1'
|
||||||
__version_info__ = (1, 1)
|
__version_info__ = (1, 2, 1)
|
||||||
|
|||||||
@@ -1,38 +1,10 @@
|
|||||||
"""
|
"""
|
||||||
A module that monkey patches the standard asyncio module to add an
|
asyncio-related utilities
|
||||||
idle_call() method to the main loop. This method is used to execute a
|
|
||||||
callback whenever the loop is not busy handling anything else. This means
|
|
||||||
that it is a callback with lower priority than IO, timer, or even
|
|
||||||
call_soon() ones. These callback are called only once each.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
from asyncio import events
|
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
|
||||||
import collections
|
|
||||||
|
|
||||||
def idle_call(self, callback):
|
|
||||||
if asyncio.iscoroutinefunction(callback):
|
|
||||||
raise TypeError("coroutines cannot be used with idle_call()")
|
|
||||||
handle = events.Handle(callback, [], self)
|
|
||||||
self._idle.append(handle)
|
|
||||||
|
|
||||||
def my_run_once(self):
|
|
||||||
if self._idle:
|
|
||||||
self._ready.append(events.Handle(lambda: None, (), self))
|
|
||||||
real_run_once(self)
|
|
||||||
if self._idle:
|
|
||||||
handle = self._idle.popleft()
|
|
||||||
handle._run()
|
|
||||||
|
|
||||||
cls = asyncio.get_event_loop().__class__
|
|
||||||
|
|
||||||
cls._idle = collections.deque()
|
|
||||||
cls.idle_call = idle_call
|
|
||||||
real_run_once = cls._run_once
|
|
||||||
cls._run_once = my_run_once
|
|
||||||
|
|
||||||
def future_wrapper(func):
|
def future_wrapper(func):
|
||||||
"""
|
"""
|
||||||
Make sure the result of a function call is an asyncio.Future()
|
Make sure the result of a function call is an asyncio.Future()
|
||||||
|
|||||||
@@ -668,9 +668,6 @@ class ElementBase(object):
|
|||||||
|
|
||||||
if hasattr(self, get_method):
|
if hasattr(self, get_method):
|
||||||
return getattr(self, get_method)(**kwargs)
|
return getattr(self, get_method)(**kwargs)
|
||||||
get_method2 = "get%s" % attrib.title()
|
|
||||||
if hasattr(self, get_method2):
|
|
||||||
return getattr(self, get_method2)(**kwargs)
|
|
||||||
else:
|
else:
|
||||||
if attrib in self.sub_interfaces:
|
if attrib in self.sub_interfaces:
|
||||||
return self._get_sub_text(attrib, lang=lang)
|
return self._get_sub_text(attrib, lang=lang)
|
||||||
@@ -733,7 +730,6 @@ class ElementBase(object):
|
|||||||
if attrib in self.interfaces or attrib == 'lang':
|
if attrib in self.interfaces or attrib == 'lang':
|
||||||
if value is not None:
|
if value is not None:
|
||||||
set_method = "set_%s" % attrib.lower()
|
set_method = "set_%s" % attrib.lower()
|
||||||
set_method2 = "set%s" % attrib.title()
|
|
||||||
|
|
||||||
if self.plugin_overrides:
|
if self.plugin_overrides:
|
||||||
name = self.plugin_overrides.get(set_method, None)
|
name = self.plugin_overrides.get(set_method, None)
|
||||||
@@ -746,8 +742,6 @@ class ElementBase(object):
|
|||||||
|
|
||||||
if hasattr(self, set_method):
|
if hasattr(self, set_method):
|
||||||
getattr(self, set_method)(value, **kwargs)
|
getattr(self, set_method)(value, **kwargs)
|
||||||
elif hasattr(self, set_method2):
|
|
||||||
getattr(self, set_method2)(value, **kwargs)
|
|
||||||
else:
|
else:
|
||||||
if attrib in self.sub_interfaces:
|
if attrib in self.sub_interfaces:
|
||||||
if lang == '*':
|
if lang == '*':
|
||||||
@@ -820,7 +814,6 @@ class ElementBase(object):
|
|||||||
|
|
||||||
if attrib in self.interfaces or attrib == 'lang':
|
if attrib in self.interfaces or attrib == 'lang':
|
||||||
del_method = "del_%s" % attrib.lower()
|
del_method = "del_%s" % attrib.lower()
|
||||||
del_method2 = "del%s" % attrib.title()
|
|
||||||
|
|
||||||
if self.plugin_overrides:
|
if self.plugin_overrides:
|
||||||
name = self.plugin_overrides.get(del_method, None)
|
name = self.plugin_overrides.get(del_method, None)
|
||||||
@@ -833,8 +826,6 @@ class ElementBase(object):
|
|||||||
|
|
||||||
if hasattr(self, del_method):
|
if hasattr(self, del_method):
|
||||||
getattr(self, del_method)(**kwargs)
|
getattr(self, del_method)(**kwargs)
|
||||||
elif hasattr(self, del_method2):
|
|
||||||
getattr(self, del_method2)(**kwargs)
|
|
||||||
else:
|
else:
|
||||||
if attrib in self.sub_interfaces:
|
if attrib in self.sub_interfaces:
|
||||||
return self._del_sub(attrib, lang=lang)
|
return self._del_sub(attrib, lang=lang)
|
||||||
@@ -916,11 +907,17 @@ class ElementBase(object):
|
|||||||
stanzas = self.xml.findall(name)
|
stanzas = self.xml.findall(name)
|
||||||
if not stanzas:
|
if not stanzas:
|
||||||
return default
|
return default
|
||||||
|
result = None
|
||||||
for stanza in stanzas:
|
for stanza in stanzas:
|
||||||
if stanza.attrib.get('{%s}lang' % XML_NS, default_lang) == lang:
|
if stanza.attrib.get('{%s}lang' % XML_NS, default_lang) == lang:
|
||||||
if stanza.text is None:
|
if stanza.text is None:
|
||||||
return default
|
return default
|
||||||
return stanza.text
|
result = stanza.text
|
||||||
|
break
|
||||||
|
if stanza.text:
|
||||||
|
result = stanza.text
|
||||||
|
if result is not None:
|
||||||
|
return result
|
||||||
return default
|
return default
|
||||||
|
|
||||||
def _get_all_sub_text(self, name, default='', lang=None):
|
def _get_all_sub_text(self, name, default='', lang=None):
|
||||||
|
|||||||
@@ -256,9 +256,9 @@ class XMLStream(asyncio.BaseProtocol):
|
|||||||
TODO fix the comment
|
TODO fix the comment
|
||||||
:param force_starttls: If True, the connection will be aborted if
|
:param force_starttls: If True, the connection will be aborted if
|
||||||
the server does not initiate a STARTTLS
|
the server does not initiate a STARTTLS
|
||||||
negociation. If None, the connection will be
|
negotiation. If None, the connection will be
|
||||||
upgraded to TLS only if the server initiate
|
upgraded to TLS only if the server initiate
|
||||||
the STARTTLS negociation, otherwise it will
|
the STARTTLS negotiation, otherwise it will
|
||||||
connect in clear. If False it will never
|
connect in clear. If False it will never
|
||||||
upgrade to TLS, even if the server provides
|
upgrade to TLS, even if the server provides
|
||||||
it. Use this for example if you’re on
|
it. Use this for example if you’re on
|
||||||
@@ -380,7 +380,7 @@ class XMLStream(asyncio.BaseProtocol):
|
|||||||
elif self.xml_depth == 1:
|
elif self.xml_depth == 1:
|
||||||
# A stanza is an XML element that is a direct child of
|
# A stanza is an XML element that is a direct child of
|
||||||
# the root element, hence the check of depth == 1
|
# the root element, hence the check of depth == 1
|
||||||
self.loop.idle_call(functools.partial(self.__spawn_event, xml))
|
self._spawn_event(xml)
|
||||||
if self.xml_root is not None:
|
if self.xml_root is not None:
|
||||||
# Keep the root element empty of children to
|
# Keep the root element empty of children to
|
||||||
# save on memory use.
|
# save on memory use.
|
||||||
@@ -760,6 +760,9 @@ class XMLStream(asyncio.BaseProtocol):
|
|||||||
:param repeat: Flag indicating if the scheduled event should
|
:param repeat: Flag indicating if the scheduled event should
|
||||||
be reset and repeat after executing.
|
be reset and repeat after executing.
|
||||||
"""
|
"""
|
||||||
|
if name in self.scheduled_events:
|
||||||
|
raise ValueError(
|
||||||
|
"There is already a scheduled event of name: %s" % name)
|
||||||
if seconds is None:
|
if seconds is None:
|
||||||
seconds = RESPONSE_TIMEOUT
|
seconds = RESPONSE_TIMEOUT
|
||||||
cb = functools.partial(callback, *args, **kwargs)
|
cb = functools.partial(callback, *args, **kwargs)
|
||||||
@@ -769,7 +772,6 @@ class XMLStream(asyncio.BaseProtocol):
|
|||||||
else:
|
else:
|
||||||
handle = self.loop.call_later(seconds, self._execute_and_unschedule,
|
handle = self.loop.call_later(seconds, self._execute_and_unschedule,
|
||||||
name, cb)
|
name, cb)
|
||||||
|
|
||||||
# Save that handle, so we can just cancel this scheduled event by
|
# Save that handle, so we can just cancel this scheduled event by
|
||||||
# canceling scheduled_events[name]
|
# canceling scheduled_events[name]
|
||||||
self.scheduled_events[name] = handle
|
self.scheduled_events[name] = handle
|
||||||
@@ -891,7 +893,7 @@ class XMLStream(asyncio.BaseProtocol):
|
|||||||
stanza['lang'] = self.peer_default_lang
|
stanza['lang'] = self.peer_default_lang
|
||||||
return stanza
|
return stanza
|
||||||
|
|
||||||
def __spawn_event(self, xml):
|
def _spawn_event(self, xml):
|
||||||
"""
|
"""
|
||||||
Analyze incoming XML stanzas and convert them into stanza
|
Analyze incoming XML stanzas and convert them into stanza
|
||||||
objects if applicable and queue stream events to be processed
|
objects if applicable and queue stream events to be processed
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ class TestElementBase(SlixTest):
|
|||||||
interfaces = set(('bar', 'baz', 'qux'))
|
interfaces = set(('bar', 'baz', 'qux'))
|
||||||
sub_interfaces = set(('baz',))
|
sub_interfaces = set(('baz',))
|
||||||
|
|
||||||
def getQux(self):
|
def get_qux(self):
|
||||||
return 'qux'
|
return 'qux'
|
||||||
|
|
||||||
class TestStanzaPlugin(ElementBase):
|
class TestStanzaPlugin(ElementBase):
|
||||||
@@ -188,7 +188,7 @@ class TestElementBase(SlixTest):
|
|||||||
interfaces = set(('bar', 'baz', 'qux'))
|
interfaces = set(('bar', 'baz', 'qux'))
|
||||||
sub_interfaces = set(('baz',))
|
sub_interfaces = set(('baz',))
|
||||||
|
|
||||||
def setQux(self, value):
|
def set_qux(self, value):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class TestStanzaPlugin(ElementBase):
|
class TestStanzaPlugin(ElementBase):
|
||||||
@@ -222,7 +222,7 @@ class TestElementBase(SlixTest):
|
|||||||
interfaces = set(('bar', 'baz', 'qux'))
|
interfaces = set(('bar', 'baz', 'qux'))
|
||||||
sub_interfaces = set(('bar',))
|
sub_interfaces = set(('bar',))
|
||||||
|
|
||||||
def delQux(self):
|
def del_qux(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class TestStanzaPlugin(ElementBase):
|
class TestStanzaPlugin(ElementBase):
|
||||||
@@ -300,14 +300,14 @@ class TestElementBase(SlixTest):
|
|||||||
namespace = "foo"
|
namespace = "foo"
|
||||||
interfaces = set(('bar',))
|
interfaces = set(('bar',))
|
||||||
|
|
||||||
def setBar(self, value):
|
def set_bar(self, value):
|
||||||
wrapper = ET.Element("{foo}wrapper")
|
wrapper = ET.Element("{foo}wrapper")
|
||||||
bar = ET.Element("{foo}bar")
|
bar = ET.Element("{foo}bar")
|
||||||
bar.text = value
|
bar.text = value
|
||||||
wrapper.append(bar)
|
wrapper.append(bar)
|
||||||
self.xml.append(wrapper)
|
self.xml.append(wrapper)
|
||||||
|
|
||||||
def getBar(self):
|
def get_bar(self):
|
||||||
return self._get_sub_text("wrapper/bar", default="not found")
|
return self._get_sub_text("wrapper/bar", default="not found")
|
||||||
|
|
||||||
stanza = TestStanza()
|
stanza = TestStanza()
|
||||||
@@ -333,16 +333,16 @@ class TestElementBase(SlixTest):
|
|||||||
namespace = "foo"
|
namespace = "foo"
|
||||||
interfaces = set(('bar', 'baz'))
|
interfaces = set(('bar', 'baz'))
|
||||||
|
|
||||||
def setBaz(self, value):
|
def set_baz(self, value):
|
||||||
self._set_sub_text("wrapper/baz", text=value)
|
self._set_sub_text("wrapper/baz", text=value)
|
||||||
|
|
||||||
def getBaz(self):
|
def get_baz(self):
|
||||||
return self._get_sub_text("wrapper/baz")
|
return self._get_sub_text("wrapper/baz")
|
||||||
|
|
||||||
def setBar(self, value):
|
def set_bar(self, value):
|
||||||
self._set_sub_text("wrapper/bar", text=value)
|
self._set_sub_text("wrapper/bar", text=value)
|
||||||
|
|
||||||
def getBar(self):
|
def get_bar(self):
|
||||||
return self._get_sub_text("wrapper/bar")
|
return self._get_sub_text("wrapper/bar")
|
||||||
|
|
||||||
stanza = TestStanza()
|
stanza = TestStanza()
|
||||||
@@ -384,22 +384,22 @@ class TestElementBase(SlixTest):
|
|||||||
namespace = "foo"
|
namespace = "foo"
|
||||||
interfaces = set(('bar', 'baz'))
|
interfaces = set(('bar', 'baz'))
|
||||||
|
|
||||||
def setBar(self, value):
|
def set_bar(self, value):
|
||||||
self._set_sub_text("path/to/only/bar", value)
|
self._set_sub_text("path/to/only/bar", value)
|
||||||
|
|
||||||
def getBar(self):
|
def get_bar(self):
|
||||||
return self._get_sub_text("path/to/only/bar")
|
return self._get_sub_text("path/to/only/bar")
|
||||||
|
|
||||||
def delBar(self):
|
def del_bar(self):
|
||||||
self._del_sub("path/to/only/bar")
|
self._del_sub("path/to/only/bar")
|
||||||
|
|
||||||
def setBaz(self, value):
|
def set_baz(self, value):
|
||||||
self._set_sub_text("path/to/just/baz", value)
|
self._set_sub_text("path/to/just/baz", value)
|
||||||
|
|
||||||
def getBaz(self):
|
def get_baz(self):
|
||||||
return self._get_sub_text("path/to/just/baz")
|
return self._get_sub_text("path/to/just/baz")
|
||||||
|
|
||||||
def delBaz(self):
|
def del_baz(self):
|
||||||
self._del_sub("path/to/just/baz")
|
self._del_sub("path/to/just/baz")
|
||||||
|
|
||||||
stanza = TestStanza()
|
stanza = TestStanza()
|
||||||
@@ -466,10 +466,10 @@ class TestElementBase(SlixTest):
|
|||||||
interfaces = set(('bar','baz', 'qux'))
|
interfaces = set(('bar','baz', 'qux'))
|
||||||
sub_interfaces = set(('qux',))
|
sub_interfaces = set(('qux',))
|
||||||
|
|
||||||
def setQux(self, value):
|
def set_qux(self, value):
|
||||||
self._set_sub_text('qux', text=value)
|
self._set_sub_text('qux', text=value)
|
||||||
|
|
||||||
def getQux(self):
|
def get_qux(self):
|
||||||
return self._get_sub_text('qux')
|
return self._get_sub_text('qux')
|
||||||
|
|
||||||
class TestStanzaPlugin(ElementBase):
|
class TestStanzaPlugin(ElementBase):
|
||||||
|
|||||||
@@ -20,12 +20,6 @@ class TestMessageStanzas(SlixTest):
|
|||||||
msg = msg.reply()
|
msg = msg.reply()
|
||||||
self.failUnless(str(msg['to']) == 'room@someservice.someserver.tld')
|
self.failUnless(str(msg['to']) == 'room@someservice.someserver.tld')
|
||||||
|
|
||||||
def testAttribProperty(self):
|
|
||||||
"Test attrib property returning self"
|
|
||||||
msg = self.Message()
|
|
||||||
msg.attrib.attrib.attrib['to'] = 'usr@server.tld'
|
|
||||||
self.failUnless(str(msg['to']) == 'usr@server.tld')
|
|
||||||
|
|
||||||
def testHTMLPlugin(self):
|
def testHTMLPlugin(self):
|
||||||
"Test message/html/body stanza"
|
"Test message/html/body stanza"
|
||||||
msg = self.Message()
|
msg = self.Message()
|
||||||
|
|||||||
@@ -136,11 +136,11 @@ class TestPubsubStanzas(SlixTest):
|
|||||||
iq = self.Iq()
|
iq = self.Iq()
|
||||||
iq['pubsub_owner']['default']
|
iq['pubsub_owner']['default']
|
||||||
iq['pubsub_owner']['default']['node'] = 'mynode'
|
iq['pubsub_owner']['default']['node'] = 'mynode'
|
||||||
iq['pubsub_owner']['default']['form'].addField('pubsub#title',
|
iq['pubsub_owner']['default']['form'].add_field('pubsub#title',
|
||||||
ftype='text-single',
|
ftype='text-single',
|
||||||
value='This thing is awesome')
|
value='This thing is awesome')
|
||||||
self.check(iq, """
|
self.check(iq, """
|
||||||
<iq id="0">
|
<iq id="0">
|
||||||
<pubsub xmlns="http://jabber.org/protocol/pubsub#owner">
|
<pubsub xmlns="http://jabber.org/protocol/pubsub#owner">
|
||||||
<default node="mynode">
|
<default node="mynode">
|
||||||
<x xmlns="jabber:x:data" type="form">
|
<x xmlns="jabber:x:data" type="form">
|
||||||
@@ -161,7 +161,8 @@ class TestPubsubStanzas(SlixTest):
|
|||||||
iq['pubsub']['subscribe']['options']['node'] = 'cheese'
|
iq['pubsub']['subscribe']['options']['node'] = 'cheese'
|
||||||
iq['pubsub']['subscribe']['options']['jid'] = 'fritzy@netflint.net/slixmpp'
|
iq['pubsub']['subscribe']['options']['jid'] = 'fritzy@netflint.net/slixmpp'
|
||||||
form = xep_0004.Form()
|
form = xep_0004.Form()
|
||||||
form.addField('pubsub#title', ftype='text-single', value='this thing is awesome')
|
form['type'] = 'submit'
|
||||||
|
form.add_field('pubsub#title', ftype='text-single', value='this thing is awesome')
|
||||||
iq['pubsub']['subscribe']['options']['options'] = form
|
iq['pubsub']['subscribe']['options']['options'] = form
|
||||||
self.check(iq, """
|
self.check(iq, """
|
||||||
<iq id="0">
|
<iq id="0">
|
||||||
@@ -201,6 +202,7 @@ class TestPubsubStanzas(SlixTest):
|
|||||||
iq['pubsub']['publish'].append(item)
|
iq['pubsub']['publish'].append(item)
|
||||||
iq['pubsub']['publish'].append(item2)
|
iq['pubsub']['publish'].append(item2)
|
||||||
form = xep_0004.Form()
|
form = xep_0004.Form()
|
||||||
|
form['type'] = 'submit'
|
||||||
form.addField('pubsub#description', ftype='text-single', value='this thing is awesome')
|
form.addField('pubsub#description', ftype='text-single', value='this thing is awesome')
|
||||||
iq['pubsub']['publish_options'] = form
|
iq['pubsub']['publish_options'] = form
|
||||||
|
|
||||||
@@ -253,7 +255,7 @@ class TestPubsubStanzas(SlixTest):
|
|||||||
pub = iq['pubsub']
|
pub = iq['pubsub']
|
||||||
pub['create']['node'] = 'testnode2'
|
pub['create']['node'] = 'testnode2'
|
||||||
pub['configure']['form']['type'] = 'submit'
|
pub['configure']['form']['type'] = 'submit'
|
||||||
pub['configure']['form'].setFields([
|
pub['configure']['form'].set_fields([
|
||||||
('FORM_TYPE', {'type': 'hidden',
|
('FORM_TYPE', {'type': 'hidden',
|
||||||
'value': 'http://jabber.org/protocol/pubsub#node_config'}),
|
'value': 'http://jabber.org/protocol/pubsub#node_config'}),
|
||||||
('pubsub#node_type', {'type': 'list-single',
|
('pubsub#node_type', {'type': 'list-single',
|
||||||
|
|||||||
Reference in New Issue
Block a user