summaryrefslogtreecommitdiff
path: root/sleekxmpp/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'sleekxmpp/plugins')
-rw-r--r--sleekxmpp/plugins/__init__.py6
-rw-r--r--sleekxmpp/plugins/gmail_notify.py2
-rw-r--r--sleekxmpp/plugins/jobs.py3
-rw-r--r--sleekxmpp/plugins/xep_0004.py3
-rw-r--r--sleekxmpp/plugins/xep_0030/disco.py366
-rw-r--r--sleekxmpp/plugins/xep_0030/stanza/disco.py0
-rw-r--r--sleekxmpp/plugins/xep_0030/stanza/items.py4
-rw-r--r--sleekxmpp/plugins/xep_0030/static.py49
-rw-r--r--sleekxmpp/plugins/xep_0045.py648
-rw-r--r--sleekxmpp/plugins/xep_0050.py2
-rw-r--r--sleekxmpp/plugins/xep_0060.py30
-rw-r--r--sleekxmpp/plugins/xep_0092.py2
12 files changed, 686 insertions, 429 deletions
diff --git a/sleekxmpp/plugins/__init__.py b/sleekxmpp/plugins/__init__.py
index 427ab04e..d27937ae 100644
--- a/sleekxmpp/plugins/__init__.py
+++ b/sleekxmpp/plugins/__init__.py
@@ -5,6 +5,6 @@
See the file LICENSE for copying permission.
"""
-__all__ = ['xep_0004', 'xep_0012', 'xep_0030', 'xep_0033', 'xep_0045',
- 'xep_0050', 'xep_0085', 'xep_0092', 'xep_0199', 'gmail_notify',
- 'xep_0060', 'xep_0202']
+__all__ = ['xep_0004', 'xep_0009', 'xep_0012', 'xep_0030', 'xep_0033',
+ 'xep_0045', 'xep_0050', 'xep_0060', 'xep_0085', 'xep_0086',
+ 'xep_0092', 'xep_0128', 'xep_0199', 'xep_0202', 'gmail_notify']
diff --git a/sleekxmpp/plugins/gmail_notify.py b/sleekxmpp/plugins/gmail_notify.py
index 7e888b90..9a94a413 100644
--- a/sleekxmpp/plugins/gmail_notify.py
+++ b/sleekxmpp/plugins/gmail_notify.py
@@ -143,7 +143,7 @@ class gmail_notify(base.base_plugin):
log.info('Gmail: Searching for emails matching: "%s"' % query)
iq = self.xmpp.Iq()
iq['type'] = 'get'
- iq['to'] = self.xmpp.jid
+ iq['to'] = self.xmpp.boundjid.bare
iq['gmail']['q'] = query
iq['gmail']['newer-than-time'] = newer
return iq.send()
diff --git a/sleekxmpp/plugins/jobs.py b/sleekxmpp/plugins/jobs.py
index 0b93d62e..0f1f7fb1 100644
--- a/sleekxmpp/plugins/jobs.py
+++ b/sleekxmpp/plugins/jobs.py
@@ -1,7 +1,6 @@
from . import base
import logging
from xml.etree import cElementTree as ET
-import types
log = logging.getLogger(__name__)
@@ -43,7 +42,7 @@ class jobs(base.base_plugin):
iq['psstate']['item'] = jobid
iq['psstate']['payload'] = state
result = iq.send()
- if result is None or type(result) == types.BooleanType or result['type'] != 'result':
+ if result is None or type(result) == bool or result['type'] != 'result':
log.error("Unable to change %s:%s to %s" % (node, jobid, state))
return False
return True
diff --git a/sleekxmpp/plugins/xep_0004.py b/sleekxmpp/plugins/xep_0004.py
index b8b7ebfa..5d41d269 100644
--- a/sleekxmpp/plugins/xep_0004.py
+++ b/sleekxmpp/plugins/xep_0004.py
@@ -13,7 +13,6 @@ from .. xmlstream.handler.callback import Callback
from .. xmlstream.matcher.xpath import MatchXPath
from .. xmlstream.stanzabase import registerStanzaPlugin, ElementBase, ET, JID
from .. stanza.message import Message
-import types
log = logging.getLogger(__name__)
@@ -203,7 +202,7 @@ class Form(ElementBase):
def merge(self, other):
new = copy.copy(self)
- if type(other) == types.DictType:
+ if type(other) == dict:
new.setValues(other)
return new
nfields = new.getFields(use_dict=True)
diff --git a/sleekxmpp/plugins/xep_0030/disco.py b/sleekxmpp/plugins/xep_0030/disco.py
index c323ba7c..ad3d0ae2 100644
--- a/sleekxmpp/plugins/xep_0030/disco.py
+++ b/sleekxmpp/plugins/xep_0030/disco.py
@@ -26,30 +26,66 @@ class xep_0030(base_plugin):
"""
XEP-0030: Service Discovery
+ Service discovery in XMPP allows entities to discover information about
+ other agents in the network, such as the feature sets supported by a
+ client, or signposts to other, related entities.
+
+ Also see <http://www.xmpp.org/extensions/xep-0030.html>.
+
+ The XEP-0030 plugin works using a hierarchy of dynamic
+ node handlers, ranging from global handlers to specific
+ JID+node handlers. The default set of handlers operate
+ in a static manner, storing disco information in memory.
+ However, custom handlers may use any available backend
+ storage mechanism desired, such as SQLite or Redis.
+
+ Node handler hierarchy:
+ JID | Node | Level
+ ---------------------
+ None | None | Global
+ Given | None | All nodes for the JID
+ None | Given | Node on self.xmpp.boundjid
+ Given | Given | A single node
+
Stream Handlers:
- Disco Info --
- Disco Items --
+ Disco Info -- Any Iq stanze that includes a query with the
+ namespace http://jabber.org/protocol/disco#info.
+ Disco Items -- Any Iq stanze that includes a query with the
+ namespace http://jabber.org/protocol/disco#items.
Events:
- disco_info --
- disco_items --
- disco_info_query --
- disco_items_query --
+ disco_info -- Received a disco#info Iq query result.
+ disco_items -- Received a disco#items Iq query result.
+ disco_info_query -- Received a disco#info Iq query request.
+ disco_items_query -- Received a disco#items Iq query request.
+
+ Attributes:
+ stanza -- A reference to the module containing the stanza classes
+ provided by this plugin.
+ static -- Object containing the default set of static node handlers.
+ xmpp -- The main SleekXMPP object.
Methods:
- set_node_handler --
- del_node_handler --
- add_identity --
+ set_node_handler -- Assign a handler to a JID/node combination.
+ del_node_handler -- Remove a handler from a JID/node combination.
+ get_info -- Retrieve disco#info data, locally or remote.
+ get_items -- Retrieve disco#items data, locally or remote.
+ set_identities --
+ set_features --
+ set_items --
+ del_items --
del_identity --
- add_feature --
del_feature --
- add_item --
del_item --
- get_info --
- get_items --
+ add_identity --
+ add_feature --
+ add_item --
"""
def plugin_init(self):
+ """
+ Start the XEP-0030 plugin.
+ """
self.xep = '0030'
self.description = 'Service Discovery'
self.stanza = sleekxmpp.plugins.xep_0030.stanza
@@ -70,42 +106,89 @@ class xep_0030(base_plugin):
self.static = StaticDisco(self.xmpp)
self._disco_ops = ['get_info', 'set_identities', 'set_features',
- 'del_info', 'get_items', 'set_items', 'del_items',
+ 'get_items', 'set_items', 'del_items',
'add_identity', 'del_identity', 'add_feature',
'del_feature', 'add_item', 'del_item']
- self.handlers = {}
+ self._handlers = {}
for op in self._disco_ops:
- self.handlers[op] = {'global': getattr(self.static, op),
- 'jid': {},
- 'node': {}}
-
+ self._handlers[op] = {'global': getattr(self.static, op),
+ 'jid': {},
+ 'node': {}}
def set_node_handler(self, htype, jid=None, node=None, handler=None):
"""
+ Add a node handler for the given hierarchy level and
+ handler type.
+
+ Node handlers are ordered in a hierarchy where the
+ most specific handler is executed. Thus, a fallback,
+ global handler can be used for the majority of cases
+ with a few node specific handler that override the
+ global behavior.
+
+ Node handler hierarchy:
+ JID | Node | Level
+ ---------------------
+ None | None | Global
+ Given | None | All nodes for the JID
+ None | Given | Node on self.xmpp.boundjid
+ Given | Given | A single node
+
+ Handler types:
+ get_info
+ get_items
+ set_identities
+ set_features
+ set_items
+ del_items
+ del_identity
+ del_feature
+ del_item
+ add_identity
+ add_feature
+ add_item
+
Arguments:
- htype
- jid
- node
- handler
+ htype -- The operation provided by the handler.
+ jid -- The JID the handler applies to. May be narrowed
+ further if a node is given.
+ node -- The particular node the handler is for. If no JID
+ is given, then the self.xmpp.boundjid.full is
+ assumed.
+ handler -- The handler function to use.
"""
if htype not in self._disco_ops:
return
if jid is None and node is None:
- self.handlers[htype]['global'] = handler
+ self._handlers[htype]['global'] = handler
elif node is None:
- self.handlers[htype]['jid'][jid] = handler
+ self._handlers[htype]['jid'][jid] = handler
elif jid is None:
jid = self.xmpp.boundjid.full
- self.handlers[htype]['node'][(jid, node)] = handler
+ self._handlers[htype]['node'][(jid, node)] = handler
else:
- self.handlers[htype]['node'][(jid, node)] = handler
+ self._handlers[htype]['node'][(jid, node)] = handler
def del_node_handler(self, htype, jid, node):
"""
+ Remove a handler type for a JID and node combination.
+
+ The next handler in the hierarchy will be used if one
+ exists. If removing the global handler, make sure that
+ other handlers exist to process existing nodes.
+
+ Node handler hierarchy:
+ JID | Node | Level
+ ---------------------
+ None | None | Global
+ Given | None | All nodes for the JID
+ None | Given | Node on self.xmpp.boundjid
+ Given | Given | A single node
+
Arguments:
- htype
- jid
- node
+ htype -- The type of handler to remove.
+ jid -- The JID from which to remove the handler.
+ node -- The node from which to remove the handler.
"""
self.set_node_handler(htype, jid, node, None)
@@ -132,14 +215,28 @@ class xep_0030(base_plugin):
def get_info(self, jid=None, node=None, local=False, **kwargs):
"""
+ Retrieve the disco#info results from a given JID/node combination.
+
+ Info may be retrieved from both local resources and remote agents;
+ the local parameter indicates if the information should be gathered
+ by executing the local node handlers, or if a disco#info stanza
+ must be generated and sent.
+
Arguments:
- jid --
- node --
- local --
- dfrom --
- block --
- timeout --
- callback --
+ jid -- Request info from this JID.
+ node -- The particular node to query.
+ local -- If true, then the query is for a JID/node
+ combination handled by this Sleek instance and
+ no stanzas need to be sent.
+ Otherwise, a disco stanza must be sent to the
+ remove JID to retrieve the info.
+ dfrom -- Specifiy the sender's JID.
+ block -- If true, block and wait for the stanzas' reply.
+ timeout -- The time in seconds to block while waiting for
+ a reply. If None, then wait indefinitely.
+ callback -- Optional callback to execute when a reply is
+ received instead of blocking and waiting for
+ the reply.
"""
if local or jid is None:
log.debug("Looking up local disco#info data " + \
@@ -158,14 +255,28 @@ class xep_0030(base_plugin):
def get_items(self, jid=None, node=None, local=False, **kwargs):
"""
+ Retrieve the disco#items results from a given JID/node combination.
+
+ Items may be retrieved from both local resources and remote agents;
+ the local parameter indicates if the items should be gathered by
+ executing the local node handlers, or if a disco#items stanza must
+ be generated and sent.
+
Arguments:
- jid --
- node --
- local --
- dfrom --
- block --
- timeout --
- callback --
+ jid -- Request info from this JID.
+ node -- The particular node to query.
+ local -- If true, then the query is for a JID/node
+ combination handled by this Sleek instance and
+ no stanzas need to be sent.
+ Otherwise, a disco stanza must be sent to the
+ remove JID to retrieve the items.
+ dfrom -- Specifiy the sender's JID.
+ block -- If true, block and wait for the stanzas' reply.
+ timeout -- The time in seconds to block while waiting for
+ a reply. If None, then wait indefinitely.
+ callback -- Optional callback to execute when a reply is
+ received instead of blocking and waiting for
+ the reply.
"""
if local or jid is None:
return self._run_node_handler('get_items', jid, node, kwargs)
@@ -179,37 +290,169 @@ class xep_0030(base_plugin):
block=kwargs.get('block', None),
callback=kwargs.get('callback', None))
- def set_info(self, jid=None, node=None, **kwargs):
- self._run_node_handler('set_info', jid, node, kwargs)
+ def set_items(self, jid=None, node=None, **kwargs):
+ """
+ Set or replace all items for the specified JID/node combination.
- def del_info(self, jid=None, node=None, **kwargs):
- self._run_node_handler('del_info', jid, node, kwargs)
+ The given items must be in a list or set where each item is a
+ tuple of the form: (jid, node, name).
- def set_items(self, jid=None, node=None, **kwargs):
+ Arguments:
+ jid -- The JID to modify.
+ node -- Optional node to modify.
+ items -- A series of items in tuple format.
+ """
self._run_node_handler('set_items', jid, node, kwargs)
def del_items(self, jid=None, node=None, **kwargs):
+ """
+ Remove all items from the given JID/node combination.
+
+ Arguments:
+ jid -- The JID to modify.
+ node -- Optional node to modify.
+ """
self._run_node_handler('del_items', jid, node, kwargs)
+ def add_item(self, jid=None, node=None, **kwargs):
+ """
+ Add a new item element to the given JID/node combination.
+
+ Each item is required to have a JID, but may also specify
+ a node value to reference non-addressable entities.
+
+ Arguments:
+ jid -- The JID to modify.
+ node -- The node to modify.
+ ijid -- The JID for the item.
+ inode -- Optional node for the item.
+ name -- Optional name for the item.
+ """
+ self._run_node_handler('add_item', jid, node, kwargs)
+
+ def del_item(self, jid=None, node=None, **kwargs):
+ """
+ Remove a single item from the given JID/node combination.
+
+ Arguments:
+ jid -- The JID to modify.
+ node -- The node to modify.
+ ijid -- The item's JID.
+ inode -- The item's node.
+ """
+ self._run_node_handler('del_item', jid, node, kwargs)
+
def add_identity(self, jid=None, node=None, **kwargs):
+ """
+ Add a new identity to the given JID/node combination.
+
+ Each identity must be unique in terms of all four identity
+ components: category, type, name, and language.
+
+ Multiple, identical category/type pairs are allowed only
+ if the xml:lang values are different. Likewise, multiple
+ category/type/xml:lang pairs are allowed so long as the
+ names are different. A category and type is always required.
+
+ Arguments:
+ jid -- The JID to modify.
+ node -- The node to modify.
+ category -- The identity's category.
+ itype -- The identity's type.
+ name -- Optional name for the identity.
+ lang -- Optional two-letter language code.
+ """
self._run_node_handler('add_identity', jid, node, kwargs)
def add_feature(self, jid=None, node=None, **kwargs):
+ """
+ Add a feature to a JID/node combination.
+
+ Arguments:
+ jid -- The JID to modify.
+ node -- The node to modify.
+ feature -- The namespace of the supported feature.
+ """
self._run_node_handler('add_feature', jid, node, kwargs)
def del_identity(self, jid=None, node=None, **kwargs):
+ """
+ Remove an identity from the given JID/node combination.
+
+ Arguments:
+ jid -- The JID to modify.
+ node -- The node to modify.
+ category -- The identity's category.
+ itype -- The identity's type value.
+ name -- Optional, human readable name for the identity.
+ lang -- Optional, the identity's xml:lang value.
+ """
self._run_node_handler('del_identity', jid, node, kwargs)
def del_feature(self, jid=None, node=None, **kwargs):
+ """
+ Remove a feature from a given JID/node combination.
+
+ Arguments:
+ jid -- The JID to modify.
+ node -- The node to modify.
+ feature -- The feature's namespace.
+ """
self._run_node_handler('del_feature', jid, node, kwargs)
- def add_item(self, jid=None, node=None, **kwargs):
- self._run_node_handler('add_item', jid, node, kwargs)
+ def set_identities(self, jid=None, node=None, **kwargs):
+ """
+ Add or replace all identities for the given JID/node combination.
- def del_item(self, jid=None, node=None, **kwargs):
- self._run_node_handler('del_item', jid, node, kwargs)
+ The identities must be in a set where each identity is a tuple
+ of the form: (category, type, lang, name)
+
+ Arguments:
+ jid -- The JID to modify.
+ node -- The node to modify.
+ identities -- A set of identities in tuple form.
+ lang -- Optional, xml:lang value.
+ """
+ self._run_node_handler('set_identities', jid, node, kwargs)
- def _run_node_handler(self, htype, jid, node, data=None):
+ def del_identities(self, jid=None, node=None, **kwargs):
+ """
+ Remove all identities for a JID/node combination.
+
+ If a language is specified, only identities using that
+ language will be removed.
+
+ Arguments:
+ jid -- The JID to modify.
+ node -- The node to modify.
+ lang -- Optional. If given, only remove identities
+ using this xml:lang value.
+ """
+ self._run_node_handler('del_identities', jid, node, kwargs)
+
+ def set_features(self, jid=None, node=None, **kwargs):
+ """
+ Add or replace the set of supported features
+ for a JID/node combination.
+
+ Arguments:
+ jid -- The JID to modify.
+ node -- The node to modify.
+ features -- The new set of supported features.
+ """
+ self._run_node_handler('set_features', jid, node, kwargs)
+
+ def del_features(self, jid=None, node=None, **kwargs):
+ """
+ Remove all features from a JID/node combination.
+
+ Arguments:
+ jid -- The JID to modify.
+ node -- The node to modify.
+ """
+ self._run_node_handler('del_features', jid, node, kwargs)
+
+ def _run_node_handler(self, htype, jid, node, data={}):
"""
Execute the most specific node handler for the given
JID/node combination.
@@ -218,19 +461,19 @@ class xep_0030(base_plugin):
htype -- The handler type to execute.
jid -- The JID requested.
node -- The node requested.
- dat -- Optional, custom data to pass to the handler.
+ data -- Optional, custom data to pass to the handler.
"""
if jid is None:
jid = self.xmpp.boundjid.full
if node is None:
node = ''
- if self.handlers[htype]['node'].get((jid, node), False):
- return self.handlers[htype]['node'][(jid, node)](jid, node, data)
- elif self.handlers[htype]['jid'].get(jid, False):
- return self.handlers[htype]['jid'][jid](jid, node, data)
- elif self.handlers[htype]['global']:
- return self.handlers[htype]['global'](jid, node, data)
+ if self._handlers[htype]['node'].get((jid, node), False):
+ return self._handlers[htype]['node'][(jid, node)](jid, node, data)
+ elif self._handlers[htype]['jid'].get(jid, False):
+ return self._handlers[htype]['jid'][jid](jid, node, data)
+ elif self._handlers[htype]['global']:
+ return self._handlers[htype]['global'](jid, node, data)
else:
return None
@@ -311,4 +554,3 @@ class xep_0030(base_plugin):
"Using default disco#info feature.")
info.add_feature(info.namespace)
return info
-
diff --git a/sleekxmpp/plugins/xep_0030/stanza/disco.py b/sleekxmpp/plugins/xep_0030/stanza/disco.py
deleted file mode 100644
index e69de29b..00000000
--- a/sleekxmpp/plugins/xep_0030/stanza/disco.py
+++ /dev/null
diff --git a/sleekxmpp/plugins/xep_0030/stanza/items.py b/sleekxmpp/plugins/xep_0030/stanza/items.py
index 319e666f..a1fb819c 100644
--- a/sleekxmpp/plugins/xep_0030/stanza/items.py
+++ b/sleekxmpp/plugins/xep_0030/stanza/items.py
@@ -12,8 +12,6 @@ from sleekxmpp.xmlstream import ElementBase, ET
class DiscoItems(ElementBase):
"""
-
-
Example disco#items stanzas:
<iq type="get">
<query xmlns="http://jabber.org/protocol/disco#items" />
@@ -74,7 +72,7 @@ class DiscoItems(ElementBase):
Arguments:
jid -- The JID for the item.
- node -- Optional additional information to reference
+ node -- Optional additional information to reference
non-addressable items.
name -- Optional human readable name for the item.
"""
diff --git a/sleekxmpp/plugins/xep_0030/static.py b/sleekxmpp/plugins/xep_0030/static.py
index f3693228..b0e931b4 100644
--- a/sleekxmpp/plugins/xep_0030/static.py
+++ b/sleekxmpp/plugins/xep_0030/static.py
@@ -35,6 +35,11 @@ class StaticDisco(object):
def __init__(self, xmpp):
"""
+ Create a static disco interface. Sets of disco#info and
+ disco#items are maintained for every given JID and node
+ combination. These stanzas are used to store disco
+ information in memory without any additional processing.
+
Arguments:
xmpp -- The main SleekXMPP object.
"""
@@ -52,7 +57,7 @@ class StaticDisco(object):
self.nodes[(jid, node)]['info']['node'] = node
self.nodes[(jid, node)]['items']['node'] = node
- def get_info(self, jid, node, data=None):
+ def get_info(self, jid, node, data):
if (jid, node) not in self.nodes:
if not node:
return DiscoInfo()
@@ -61,11 +66,11 @@ class StaticDisco(object):
else:
return self.nodes[(jid, node)]['info']
- def del_info(self, jid, node, data=None):
+ def del_info(self, jid, node, data):
if (jid, node) in self.nodes:
self.nodes[(jid, node)]['info'] = DiscoInfo()
- def get_items(self, jid, node, data=None):
+ def get_items(self, jid, node, data):
if (jid, node) not in self.nodes:
if not node:
return DiscoInfo()
@@ -74,14 +79,16 @@ class StaticDisco(object):
else:
return self.nodes[(jid, node)]['items']
- def set_items(self, jid, node, data=None):
- pass
+ def set_items(self, jid, node, data):
+ items = data.get('items', set())
+ self.add_node(jid, node)
+ self.nodes[(jid, node)]['items']['items'] = items
- def del_items(self, jid, node, data=None):
+ def del_items(self, jid, node, data):
if (jid, node) in self.nodes:
self.nodes[(jid, node)]['items'] = DiscoItems()
- def add_identity(self, jid, node, data={}):
+ def add_identity(self, jid, node, data):
self.add_node(jid, node)
self.nodes[(jid, node)]['info'].add_identity(
data.get('category', ''),
@@ -89,10 +96,12 @@ class StaticDisco(object):
data.get('name', None),
data.get('lang', None))
- def set_identities(self, jid, node, data=None):
- pass
+ def set_identities(self, jid, node, data):
+ identities = data.get('identities', set())
+ self.add_node(jid, node)
+ self.nodes[(jid, node)]['info']['identities'] = identities
- def del_identity(self, jid, node, data=None):
+ def del_identity(self, jid, node, data):
if (jid, node) not in self.nodes:
return
self.nodes[(jid, node)]['info'].del_identity(
@@ -101,27 +110,29 @@ class StaticDisco(object):
data.get('name', None),
data.get('lang', None))
-
- def add_feature(self, jid, node, data=None):
+ def add_feature(self, jid, node, data):
self.add_node(jid, node)
self.nodes[(jid, node)]['info'].add_feature(data.get('feature', ''))
- def set_features(self, jid, node, data=None):
- pass
+ def set_features(self, jid, node, data):
+ features = data.get('features', set())
+ self.add_node(jid, node)
+ self.nodes[(jid, node)]['info']['features'] = features
- def del_feature(self, jid, node, data=None):
+ def del_feature(self, jid, node, data):
if (jid, node) not in self.nodes:
return
self.nodes[(jid, node)]['info'].del_feature(data.get('feature', ''))
- def add_item(self, jid, node, data=None):
+ def add_item(self, jid, node, data):
self.add_node(jid, node)
self.nodes[(jid, node)]['items'].add_item(
data.get('ijid', ''),
node=data.get('inode', None),
name=data.get('name', None))
- def del_item(self, jid, node, data=None):
+ def del_item(self, jid, node, data):
if (jid, node) in self.nodes:
- self.nodes[(jid, node)]['items'].del_item(**data)
-
+ self.nodes[(jid, node)]['items'].del_item(
+ data.get('ijid', ''),
+ node=data.get('inode', None))
diff --git a/sleekxmpp/plugins/xep_0045.py b/sleekxmpp/plugins/xep_0045.py
index db41cdb3..feec70db 100644
--- a/sleekxmpp/plugins/xep_0045.py
+++ b/sleekxmpp/plugins/xep_0045.py
@@ -20,325 +20,333 @@ log = logging.getLogger(__name__)
class MUCPresence(ElementBase):
- name = 'x'
- namespace = 'http://jabber.org/protocol/muc#user'
- plugin_attrib = 'muc'
- interfaces = set(('affiliation', 'role', 'jid', 'nick', 'room'))
- affiliations = set(('', ))
- roles = set(('', ))
-
- 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 getAffiliation(self):
- #TODO if no affilation, set it to the default and return default
- item = self.getXMLItem()
- return item.get('affiliation', '')
-
- def setAffiliation(self, value):
- item = self.getXMLItem()
- #TODO check for valid affiliation
- item.attrib['affiliation'] = value
- return self
-
- def delAffiliation(self):
- item = self.getXMLItem()
- #TODO set default affiliation
- if 'affiliation' in item.attrib: del item.attrib['affiliation']
- return self
-
- def getJid(self):
- item = self.getXMLItem()
- return JID(item.get('jid', ''))
-
- def setJid(self, value):
- item = self.getXMLItem()
- if not isinstance(value, str):
- value = str(value)
- item.attrib['jid'] = value
- return self
-
- def delJid(self):
- item = self.getXMLItem()
- if 'jid' in item.attrib: del item.attrib['jid']
- return self
-
- def getRole(self):
- item = self.getXMLItem()
- #TODO get default role, set default role if none
- return item.get('role', '')
-
- def setRole(self, value):
- item = self.getXMLItem()
- #TODO check for valid role
- item.attrib['role'] = value
- return self
-
- def delRole(self):
- item = self.getXMLItem()
- #TODO set default role
- if 'role' in item.attrib: del item.attrib['role']
- return self
-
- def getNick(self):
- return self.parent()['from'].resource
-
- def getRoom(self):
- return self.parent()['from'].bare
-
- def setNick(self, value):
- log.warning("Cannot set nick through mucpresence plugin.")
- return self
-
- def setRoom(self, value):
- log.warning("Cannot set room through mucpresence plugin.")
- return self
-
- def delNick(self):
- log.warning("Cannot delete nick through mucpresence plugin.")
- return self
-
- def delRoom(self):
- log.warning("Cannot delete room through mucpresence plugin.")
- return self
+ name = 'x'
+ namespace = 'http://jabber.org/protocol/muc#user'
+ plugin_attrib = 'muc'
+ interfaces = set(('affiliation', 'role', 'jid', 'nick', 'room'))
+ affiliations = set(('', ))
+ roles = set(('', ))
+
+ 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 getAffiliation(self):
+ #TODO if no affilation, set it to the default and return default
+ item = self.getXMLItem()
+ return item.get('affiliation', '')
+
+ def setAffiliation(self, value):
+ item = self.getXMLItem()
+ #TODO check for valid affiliation
+ item.attrib['affiliation'] = value
+ return self
+
+ def delAffiliation(self):
+ item = self.getXMLItem()
+ #TODO set default affiliation
+ if 'affiliation' in item.attrib: del item.attrib['affiliation']
+ return self
+
+ def getJid(self):
+ item = self.getXMLItem()
+ return JID(item.get('jid', ''))
+
+ def setJid(self, value):
+ item = self.getXMLItem()
+ if not isinstance(value, str):
+ value = str(value)
+ item.attrib['jid'] = value
+ return self
+
+ def delJid(self):
+ item = self.getXMLItem()
+ if 'jid' in item.attrib: del item.attrib['jid']
+ return self
+
+ def getRole(self):
+ item = self.getXMLItem()
+ #TODO get default role, set default role if none
+ return item.get('role', '')
+
+ def setRole(self, value):
+ item = self.getXMLItem()
+ #TODO check for valid role
+ item.attrib['role'] = value
+ return self
+
+ def delRole(self):
+ item = self.getXMLItem()
+ #TODO set default role
+ if 'role' in item.attrib: del item.attrib['role']
+ return self
+
+ def getNick(self):
+ return self.parent()['from'].resource
+
+ def getRoom(self):
+ return self.parent()['from'].bare
+
+ def setNick(self, value):
+ log.warning("Cannot set nick through mucpresence plugin.")
+ return self
+
+ def setRoom(self, value):
+ log.warning("Cannot set room through mucpresence plugin.")
+ return self
+
+ def delNick(self):
+ log.warning("Cannot delete nick through mucpresence plugin.")
+ return self
+
+ def delRoom(self):
+ log.warning("Cannot delete room through mucpresence plugin.")
+ return self
class xep_0045(base.base_plugin):
- """
- Impliments XEP-0045 Multi User Chat
- """
-
- def plugin_init(self):
- self.rooms = {}
- self.ourNicks = {}
- self.xep = '0045'
- self.description = 'Multi User Chat'
- # load MUC support in presence stanzas
- registerStanzaPlugin(Presence, MUCPresence)
- self.xmpp.registerHandler(Callback('MUCPresence', MatchXMLMask("<presence xmlns='%s' />" % self.xmpp.default_ns), self.handle_groupchat_presence))
- self.xmpp.registerHandler(Callback('MUCMessage', MatchXMLMask("<message xmlns='%s' type='groupchat'><body/></message>" % self.xmpp.default_ns), self.handle_groupchat_message))
- self.xmpp.registerHandler(Callback('MUCSubject', MatchXMLMask("<message xmlns='%s' type='groupchat'><subject/></message>" % self.xmpp.default_ns), self.handle_groupchat_subject))
-
- def handle_groupchat_presence(self, pr):
- """ Handle a presence in a muc.
- """
- got_offline = False
- got_online = False
- if pr['muc']['room'] not in self.rooms.keys():
- return
- entry = pr['muc'].getStanzaValues()
- entry['show'] = pr['show']
- entry['status'] = pr['status']
- if pr['type'] == 'unavailable':
- if entry['nick'] in self.rooms[entry['room']]:
- del self.rooms[entry['room']][entry['nick']]
- got_offline = True
- else:
- if entry['nick'] not in self.rooms[entry['room']]:
- got_online = True
- self.rooms[entry['room']][entry['nick']] = entry
- log.debug("MUC presence from %s/%s : %s" % (entry['room'],entry['nick'], entry))
- self.xmpp.event("groupchat_presence", pr)
- self.xmpp.event("muc::%s::presence" % entry['room'], pr)
- if got_offline:
- self.xmpp.event("muc::%s::got_offline" % entry['room'], pr)
- if got_online:
- self.xmpp.event("muc::%s::got_online" % entry['room'], pr)
-
- def handle_groupchat_message(self, msg):
- """ Handle a message event in a muc.
- """
- self.xmpp.event('groupchat_message', msg)
- self.xmpp.event("muc::%s::message" % msg['from'].bare, msg)
-
- def handle_groupchat_subject(self, msg):
- """ Handle a message coming from a muc indicating
- a change of subject (or announcing it when joining the room)
- """
- self.xmpp.event('groupchat_subject', msg)
-
- 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 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 getRoomForm(self, room, ifrom=None):
- iq = self.xmpp.makeIqGet()
- iq['to'] = room
- if ifrom is not None:
- iq['from'] = ifrom
- query = ET.Element('{http://jabber.org/protocol/muc#owner}query')
- iq.append(query)
- result = iq.send()
- if result['type'] == 'error':
- return False
- xform = result.xml.find('{http://jabber.org/protocol/muc#owner}query/{jabber:x:data}x')
- if xform is None: return False
- form = self.xmpp.plugin['old_0004'].buildForm(xform)
- return form
-
- def configureRoom(self, room, form=None, ifrom=None):
- if form is None:
- form = self.getRoomForm(room, ifrom=ifrom)
- #form = self.xmpp.plugin['old_0004'].makeForm(ftype='submit')
- #form.addField('FORM_TYPE', value='http://jabber.org/protocol/muc#roomconfig')
- iq = self.xmpp.makeIqSet()
- iq['to'] = room
- if ifrom is not None:
- iq['from'] = ifrom
- query = ET.Element('{http://jabber.org/protocol/muc#owner}query')
- form = form.getXML('submit')
- query.append(form)
- iq.append(query)
- result = iq.send()
- if result['type'] == 'error':
- return False
- return True
-
- def joinMUC(self, room, nick, maxhistory="0", password='', wait=False, pstatus=None, pshow=None):
- """ Join the specified room, requesting 'maxhistory' lines of history.
- """
- stanza = self.xmpp.makePresence(pto="%s/%s" % (room, nick), pstatus=pstatus, pshow=pshow)
- x = ET.Element('{http://jabber.org/protocol/muc}x')
- if password:
- passelement = ET.Element('password')
- passelement.text = password
- x.append(passelement)
- if maxhistory:
- history = ET.Element('history')
- if maxhistory == "0":
- history.attrib['maxchars'] = maxhistory
- else:
- history.attrib['maxstanzas'] = maxhistory
- x.append(history)
- stanza.append(x)
- if not wait:
- self.xmpp.send(stanza)
- else:
- #wait for our own room presence back
- expect = ET.Element("{%s}presence" % self.xmpp.default_ns, {'from':"%s/%s" % (room, nick)})
- self.xmpp.send(stanza, expect)
- self.rooms[room] = {}
- self.ourNicks[room] = nick
-
- def destroy(self, room, reason='', altroom = '', ifrom=None):
- iq = self.xmpp.makeIqSet()
- if ifrom is not None:
- iq['from'] = ifrom
- iq['to'] = room
- query = ET.Element('{http://jabber.org/protocol/muc#owner}query')
- destroy = ET.Element('destroy')
- if altroom:
- destroy.attrib['jid'] = altroom
- xreason = ET.Element('reason')
- xreason.text = reason
- destroy.append(xreason)
- query.append(destroy)
- iq.append(query)
- r = iq.send()
- if r is False or r['type'] == 'error':
- return False
- return True
-
- def setAffiliation(self, room, jid=None, nick=None, affiliation='member'):
- """ Change room affiliation."""
- if affiliation not in ('outcast', 'member', 'admin', 'owner', 'none'):
- raise TypeError
- query = ET.Element('{http://jabber.org/protocol/muc#admin}query')
- if nick is not None:
- item = ET.Element('item', {'affiliation':affiliation, 'nick':nick})
- else:
- item = ET.Element('item', {'affiliation':affiliation, 'jid':jid})
- query.append(item)
- iq = self.xmpp.makeIqSet(query)
- iq['to'] = room
- result = iq.send()
- if result is False or result['type'] != 'result':
- raise ValueError
- return True
-
- def invite(self, room, jid, reason=''):
- """ Invite a jid to a room."""
- msg = self.xmpp.makeMessage(room)
- msg['from'] = self.xmpp.jid
- x = ET.Element('{http://jabber.org/protocol/muc#user}x')
- invite = ET.Element('{http://jabber.org/protocol/muc#user}invite', {'to': jid})
- if reason:
- rxml = ET.Element('reason')
- rxml.text = reason
- invite.append(rxml)
- x.append(invite)
- msg.append(x)
- self.xmpp.send(msg)
-
- def leaveMUC(self, room, nick, msg=''):
- """ Leave the specified room.
- """
- if msg:
- self.xmpp.sendPresence(pshow='unavailable', pto="%s/%s" % (room, nick), pstatus=msg)
- else:
- self.xmpp.sendPresence(pshow='unavailable', pto="%s/%s" % (room, nick))
- del self.rooms[room]
-
- def getRoomConfig(self, room):
- iq = self.xmpp.makeIqGet('http://jabber.org/protocol/muc#owner')
- iq['to'] = room
- iq['from'] = self.xmpp.jid
- result = iq.send()
- if result is None or result['type'] != 'result':
- raise ValueError
- 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'].buildForm(form)
-
- def cancelConfig(self, room):
- query = ET.Element('{http://jabber.org/protocol/muc#owner}query')
- x = ET.Element('{jabber:x:data}x', type='cancel')
- query.append(x)
- iq = self.xmpp.makeIqSet(query)
- iq.send()
-
- def setRoomConfig(self, room, config):
- query = ET.Element('{http://jabber.org/protocol/muc#owner}query')
- x = config.getXML('submit')
- query.append(x)
- iq = self.xmpp.makeIqSet(query)
- iq['to'] = room
- iq['from'] = self.xmpp.jid
- iq.send()
-
- def getJoinedRooms(self):
- return self.rooms.keys()
-
- def getOurJidInRoom(self, roomJid):
- """ Return the jid we're using in a room.
- """
- return "%s/%s" % (roomJid, self.ourNicks[roomJid])
-
- 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 jidProperty in self.rooms[room][nick]:
- return self.rooms[room][nick][jidProperty]
- else:
- return None
-
- 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()
+ """
+ Implements XEP-0045 Multi User Chat
+ """
+
+ def plugin_init(self):
+ self.rooms = {}
+ self.ourNicks = {}
+ self.xep = '0045'
+ self.description = 'Multi User Chat'
+ # load MUC support in presence stanzas
+ registerStanzaPlugin(Presence, MUCPresence)
+ self.xmpp.registerHandler(Callback('MUCPresence', MatchXMLMask("<presence xmlns='%s' />" % self.xmpp.default_ns), self.handle_groupchat_presence))
+ self.xmpp.registerHandler(Callback('MUCMessage', MatchXMLMask("<message xmlns='%s' type='groupchat'><body/></message>" % self.xmpp.default_ns), self.handle_groupchat_message))
+ self.xmpp.registerHandler(Callback('MUCSubject', MatchXMLMask("<message xmlns='%s' type='groupchat'><subject/></message>" % self.xmpp.default_ns), self.handle_groupchat_subject))
+ self.xmpp.registerHandler(Callback('MUCInvite', MatchXPath("{%s}message/{http://jabber.org/protocol/muc#user}x/invite" % self.xmpp.default_ns), self.handle_groupchat_invite))
+
+ def handle_groupchat_invite(self, inv):
+ """ Handle an invite into a muc.
+ """
+ logging.debug("MUC invite to %s from %s: %s" % (inv['from'], inv["from"], inv))
+ if inv['from'] not in self.rooms.keys():
+ self.xmpp.event("groupchat_invite", inv)
+
+ def handle_groupchat_presence(self, pr):
+ """ Handle a presence in a muc.
+ """
+ got_offline = False
+ got_online = False
+ if pr['muc']['room'] not in self.rooms.keys():
+ return
+ entry = pr['muc'].getStanzaValues()
+ entry['show'] = pr['show']
+ entry['status'] = pr['status']
+ if pr['type'] == 'unavailable':
+ if entry['nick'] in self.rooms[entry['room']]:
+ del self.rooms[entry['room']][entry['nick']]
+ got_offline = True
+ else:
+ if entry['nick'] not in self.rooms[entry['room']]:
+ got_online = True
+ self.rooms[entry['room']][entry['nick']] = entry
+ log.debug("MUC presence from %s/%s : %s" % (entry['room'],entry['nick'], entry))
+ self.xmpp.event("groupchat_presence", pr)
+ self.xmpp.event("muc::%s::presence" % entry['room'], pr)
+ if got_offline:
+ self.xmpp.event("muc::%s::got_offline" % entry['room'], pr)
+ if got_online:
+ self.xmpp.event("muc::%s::got_online" % entry['room'], pr)
+
+ def handle_groupchat_message(self, msg):
+ """ Handle a message event in a muc.
+ """
+ self.xmpp.event('groupchat_message', msg)
+ self.xmpp.event("muc::%s::message" % msg['from'].bare, msg)
+
+ def handle_groupchat_subject(self, msg):
+ """ Handle a message coming from a muc indicating
+ a change of subject (or announcing it when joining the room)
+ """
+ self.xmpp.event('groupchat_subject', msg)
+
+ 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 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 getRoomForm(self, room, ifrom=None):
+ iq = self.xmpp.makeIqGet()
+ iq['to'] = room
+ if ifrom is not None:
+ iq['from'] = ifrom
+ query = ET.Element('{http://jabber.org/protocol/muc#owner}query')
+ iq.append(query)
+ result = iq.send()
+ if result['type'] == 'error':
+ return False
+ xform = result.xml.find('{http://jabber.org/protocol/muc#owner}query/{jabber:x:data}x')
+ if xform is None: return False
+ form = self.xmpp.plugin['old_0004'].buildForm(xform)
+ return form
+
+ def configureRoom(self, room, form=None, ifrom=None):
+ if form is None:
+ form = self.getRoomForm(room, ifrom=ifrom)
+ #form = self.xmpp.plugin['old_0004'].makeForm(ftype='submit')
+ #form.addField('FORM_TYPE', value='http://jabber.org/protocol/muc#roomconfig')
+ iq = self.xmpp.makeIqSet()
+ iq['to'] = room
+ if ifrom is not None:
+ iq['from'] = ifrom
+ query = ET.Element('{http://jabber.org/protocol/muc#owner}query')
+ form = form.getXML('submit')
+ query.append(form)
+ iq.append(query)
+ result = iq.send()
+ if result['type'] == 'error':
+ return False
+ return True
+
+ def joinMUC(self, room, nick, maxhistory="0", password='', wait=False, pstatus=None, pshow=None):
+ """ Join the specified room, requesting 'maxhistory' lines of history.
+ """
+ stanza = self.xmpp.makePresence(pto="%s/%s" % (room, nick), pstatus=pstatus, pshow=pshow)
+ x = ET.Element('{http://jabber.org/protocol/muc}x')
+ if password:
+ passelement = ET.Element('password')
+ passelement.text = password
+ x.append(passelement)
+ if maxhistory:
+ history = ET.Element('history')
+ if maxhistory == "0":
+ history.attrib['maxchars'] = maxhistory
+ else:
+ history.attrib['maxstanzas'] = maxhistory
+ x.append(history)
+ stanza.append(x)
+ if not wait:
+ self.xmpp.send(stanza)
+ else:
+ #wait for our own room presence back
+ expect = ET.Element("{%s}presence" % self.xmpp.default_ns, {'from':"%s/%s" % (room, nick)})
+ self.xmpp.send(stanza, expect)
+ self.rooms[room] = {}
+ self.ourNicks[room] = nick
+
+ def destroy(self, room, reason='', altroom = '', ifrom=None):
+ iq = self.xmpp.makeIqSet()
+ if ifrom is not None:
+ iq['from'] = ifrom
+ iq['to'] = room
+ query = ET.Element('{http://jabber.org/protocol/muc#owner}query')
+ destroy = ET.Element('destroy')
+ if altroom:
+ destroy.attrib['jid'] = altroom
+ xreason = ET.Element('reason')
+ xreason.text = reason
+ destroy.append(xreason)
+ query.append(destroy)
+ iq.append(query)
+ r = iq.send()
+ if r is False or r['type'] == 'error':
+ return False
+ return True
+
+ def setAffiliation(self, room, jid=None, nick=None, affiliation='member'):
+ """ Change room affiliation."""
+ if affiliation not in ('outcast', 'member', 'admin', 'owner', 'none'):
+ raise TypeError
+ query = ET.Element('{http://jabber.org/protocol/muc#admin}query')
+ if nick is not None:
+ item = ET.Element('item', {'affiliation':affiliation, 'nick':nick})
+ else:
+ item = ET.Element('item', {'affiliation':affiliation, 'jid':jid})
+ query.append(item)
+ iq = self.xmpp.makeIqSet(query)
+ iq['to'] = room
+ result = iq.send()
+ if result is False or result['type'] != 'result':
+ raise ValueError
+ return True
+
+ def invite(self, room, jid, reason='', mfrom=''):
+ """ Invite a jid to a room."""
+ msg = self.xmpp.makeMessage(room)
+ msg['from'] = mfrom
+ x = ET.Element('{http://jabber.org/protocol/muc#user}x')
+ invite = ET.Element('{http://jabber.org/protocol/muc#user}invite', {'to': jid})
+ if reason:
+ rxml = ET.Element('reason')
+ rxml.text = reason
+ invite.append(rxml)
+ x.append(invite)
+ msg.append(x)
+ self.xmpp.send(msg)
+
+ def leaveMUC(self, room, nick, msg=''):
+ """ Leave the specified room.
+ """
+ if msg:
+ self.xmpp.sendPresence(pshow='unavailable', pto="%s/%s" % (room, nick), pstatus=msg)
+ else:
+ self.xmpp.sendPresence(pshow='unavailable', pto="%s/%s" % (room, nick))
+ del self.rooms[room]
+
+ def getRoomConfig(self, room, ifrom=''):
+ iq = self.xmpp.makeIqGet('http://jabber.org/protocol/muc#owner')
+ iq['to'] = room
+ iq['from'] = ifrom
+ result = iq.send()
+ if result is None or result['type'] != 'result':
+ raise ValueError
+ 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'].buildForm(form)
+
+ def cancelConfig(self, room):
+ query = ET.Element('{http://jabber.org/protocol/muc#owner}query')
+ x = ET.Element('{jabber:x:data}x', type='cancel')
+ query.append(x)
+ iq = self.xmpp.makeIqSet(query)
+ iq.send()
+
+ def setRoomConfig(self, room, config, ifrom=''):
+ query = ET.Element('{http://jabber.org/protocol/muc#owner}query')
+ x = config.getXML('submit')
+ query.append(x)
+ iq = self.xmpp.makeIqSet(query)
+ iq['to'] = room
+ iq['from'] = ifrom
+ iq.send()
+
+ def getJoinedRooms(self):
+ return self.rooms.keys()
+
+ def getOurJidInRoom(self, roomJid):
+ """ Return the jid we're using in a room.
+ """
+ return "%s/%s" % (roomJid, self.ourNicks[roomJid])
+
+ 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 jidProperty in self.rooms[room][nick]:
+ return self.rooms[room][nick][jidProperty]
+ else:
+ return None
+
+ 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()
diff --git a/sleekxmpp/plugins/xep_0050.py b/sleekxmpp/plugins/xep_0050.py
index 5efb9116..439bebb9 100644
--- a/sleekxmpp/plugins/xep_0050.py
+++ b/sleekxmpp/plugins/xep_0050.py
@@ -110,7 +110,7 @@ class xep_0050(base.base_plugin):
if not id:
id = self.xmpp.getNewId()
iq = self.xmpp.makeIqResult(id)
- iq.attrib['from'] = self.xmpp.fulljid
+ iq.attrib['from'] = self.xmpp.boundjid.full
iq.attrib['to'] = to
command = ET.Element('{http://jabber.org/protocol/commands}command')
command.attrib['node'] = node
diff --git a/sleekxmpp/plugins/xep_0060.py b/sleekxmpp/plugins/xep_0060.py
index a7c6d023..93124fca 100644
--- a/sleekxmpp/plugins/xep_0060.py
+++ b/sleekxmpp/plugins/xep_0060.py
@@ -51,7 +51,7 @@ class xep_0060(base.base_plugin):
pubsub.append(configure)
iq = self.xmpp.makeIqSet(pubsub)
iq.attrib['to'] = jid
- iq.attrib['from'] = self.xmpp.fulljid
+ iq.attrib['from'] = self.xmpp.boundjid.full
id = iq['id']
result = iq.send()
if result is False or result is None or result['type'] == 'error': return False
@@ -63,15 +63,15 @@ class xep_0060(base.base_plugin):
subscribe.attrib['node'] = node
if subscribee is None:
if bare:
- subscribe.attrib['jid'] = self.xmpp.jid
+ subscribe.attrib['jid'] = self.xmpp.boundjid.bare
else:
- subscribe.attrib['jid'] = self.xmpp.fulljid
+ subscribe.attrib['jid'] = self.xmpp.boundjid.full
else:
subscribe.attrib['jid'] = subscribee
pubsub.append(subscribe)
iq = self.xmpp.makeIqSet(pubsub)
iq.attrib['to'] = jid
- iq.attrib['from'] = self.xmpp.fulljid
+ iq.attrib['from'] = self.xmpp.boundjid.full
id = iq['id']
result = iq.send()
if result is False or result is None or result['type'] == 'error': return False
@@ -83,15 +83,15 @@ class xep_0060(base.base_plugin):
unsubscribe.attrib['node'] = node
if subscribee is None:
if bare:
- unsubscribe.attrib['jid'] = self.xmpp.jid
+ unsubscribe.attrib['jid'] = self.xmpp.boundjid.bare
else:
- unsubscribe.attrib['jid'] = self.xmpp.fulljid
+ unsubscribe.attrib['jid'] = self.xmpp.boundjid.full
else:
unsubscribe.attrib['jid'] = subscribee
pubsub.append(unsubscribe)
iq = self.xmpp.makeIqSet(pubsub)
iq.attrib['to'] = jid
- iq.attrib['from'] = self.xmpp.fulljid
+ iq.attrib['from'] = self.xmpp.boundjid.full
id = iq['id']
result = iq.send()
if result is False or result is None or result['type'] == 'error': return False
@@ -109,7 +109,7 @@ class xep_0060(base.base_plugin):
iq = self.xmpp.makeIqGet()
iq.append(pubsub)
iq.attrib['to'] = jid
- iq.attrib['from'] = self.xmpp.fulljid
+ iq.attrib['from'] = self.xmpp.boundjid.full
id = iq['id']
#self.xmpp.add_handler("<iq id='%s'/>" % id, self.handlerCreateNodeResponse)
result = iq.send()
@@ -133,7 +133,7 @@ class xep_0060(base.base_plugin):
iq = self.xmpp.makeIqGet()
iq.append(pubsub)
iq.attrib['to'] = jid
- iq.attrib['from'] = self.xmpp.fulljid
+ iq.attrib['from'] = self.xmpp.boundjid.full
id = iq['id']
result = iq.send()
if result is None or result == False or result['type'] == 'error':
@@ -156,7 +156,7 @@ class xep_0060(base.base_plugin):
iq = self.xmpp.makeIqGet()
iq.append(pubsub)
iq.attrib['to'] = jid
- iq.attrib['from'] = self.xmpp.fulljid
+ iq.attrib['from'] = self.xmpp.boundjid.full
id = iq['id']
result = iq.send()
if result is None or result == False or result['type'] == 'error':
@@ -179,7 +179,7 @@ class xep_0060(base.base_plugin):
pubsub.append(delete)
iq.append(pubsub)
iq.attrib['to'] = jid
- iq.attrib['from'] = self.xmpp.fulljid
+ iq.attrib['from'] = self.xmpp.boundjid.full
result = iq.send()
if result is not None and result is not False and result['type'] != 'error':
return True
@@ -196,7 +196,7 @@ class xep_0060(base.base_plugin):
pubsub.append(configure)
iq = self.xmpp.makeIqSet(pubsub)
iq.attrib['to'] = jid
- iq.attrib['from'] = self.xmpp.fulljid
+ iq.attrib['from'] = self.xmpp.boundjid.full
id = iq['id']
result = iq.send()
if result is None or result['type'] == 'error':
@@ -217,7 +217,7 @@ class xep_0060(base.base_plugin):
pubsub.append(publish)
iq = self.xmpp.makeIqSet(pubsub)
iq.attrib['to'] = jid
- iq.attrib['from'] = self.xmpp.fulljid
+ iq.attrib['from'] = self.xmpp.boundjid.full
id = iq['id']
result = iq.send()
if result is None or result is False or result['type'] == 'error': return False
@@ -236,7 +236,7 @@ class xep_0060(base.base_plugin):
pubsub.append(retract)
iq = self.xmpp.makeIqSet(pubsub)
iq.attrib['to'] = jid
- iq.attrib['from'] = self.xmpp.fulljid
+ iq.attrib['from'] = self.xmpp.boundjid.full
id = iq['id']
result = iq.send()
if result is None or result is False or result['type'] == 'error': return False
@@ -287,7 +287,7 @@ class xep_0060(base.base_plugin):
pubsub.append(affs)
iq = self.xmpp.makeIqSet(pubsub)
iq.attrib['to'] = ps_jid
- iq.attrib['from'] = self.xmpp.fulljid
+ iq.attrib['from'] = self.xmpp.boundjid.full
id = iq['id']
result = iq.send()
if result is None or result is False or result['type'] == 'error':
diff --git a/sleekxmpp/plugins/xep_0092.py b/sleekxmpp/plugins/xep_0092.py
index ca02c4a8..c9b418ff 100644
--- a/sleekxmpp/plugins/xep_0092.py
+++ b/sleekxmpp/plugins/xep_0092.py
@@ -42,7 +42,7 @@ class xep_0092(base.base_plugin):
query = ET.Element('{jabber:iq:version}query')
iq.append(query)
iq.attrib['to'] = jid
- iq.attrib['from'] = self.xmpp.fulljid
+ iq.attrib['from'] = self.xmpp.boundjid.full
id = iq.get('id')
result = iq.send()
if result and result is not None and result.get('type', 'error') != 'error':