diff options
Diffstat (limited to 'sleekxmpp/plugins')
-rw-r--r-- | sleekxmpp/plugins/__init__.py | 1 | ||||
-rw-r--r-- | sleekxmpp/plugins/xep_0004/stanza/field.py | 4 | ||||
-rw-r--r-- | sleekxmpp/plugins/xep_0004/stanza/form.py | 42 | ||||
-rw-r--r-- | sleekxmpp/plugins/xep_0045.py | 10 | ||||
-rw-r--r-- | sleekxmpp/plugins/xep_0054/stanza.py | 3 | ||||
-rw-r--r-- | sleekxmpp/plugins/xep_0122/__init__.py | 11 | ||||
-rw-r--r-- | sleekxmpp/plugins/xep_0122/data_validation.py | 19 | ||||
-rw-r--r-- | sleekxmpp/plugins/xep_0122/stanza.py | 94 | ||||
-rw-r--r-- | sleekxmpp/plugins/xep_0202/time.py | 7 | ||||
-rw-r--r-- | sleekxmpp/plugins/xep_0323/sensordata.py | 2 | ||||
-rw-r--r-- | sleekxmpp/plugins/xep_0332/http.py | 6 |
11 files changed, 180 insertions, 19 deletions
diff --git a/sleekxmpp/plugins/__init__.py b/sleekxmpp/plugins/__init__.py index 2c90d357..f501687b 100644 --- a/sleekxmpp/plugins/__init__.py +++ b/sleekxmpp/plugins/__init__.py @@ -47,6 +47,7 @@ __all__ = [ 'xep_0108', # User Activity 'xep_0115', # Entity Capabilities 'xep_0118', # User Tune + 'xep_0122', # Data Forms Validation 'xep_0128', # Extended Service Discovery 'xep_0131', # Standard Headers and Internet Metadata 'xep_0133', # Service Administration diff --git a/sleekxmpp/plugins/xep_0004/stanza/field.py b/sleekxmpp/plugins/xep_0004/stanza/field.py index 51f85995..73e48758 100644 --- a/sleekxmpp/plugins/xep_0004/stanza/field.py +++ b/sleekxmpp/plugins/xep_0004/stanza/field.py @@ -13,8 +13,9 @@ class FormField(ElementBase): namespace = 'jabber:x:data' name = 'field' plugin_attrib = 'field' + plugin_multi_attrib = 'fields' interfaces = set(('answer', 'desc', 'required', 'value', - 'options', 'label', 'type', 'var')) + 'label', 'type', 'var')) sub_interfaces = set(('desc',)) plugin_tag_map = {} plugin_attrib_map = {} @@ -165,6 +166,7 @@ class FieldOption(ElementBase): plugin_attrib = 'option' interfaces = set(('label', 'value')) sub_interfaces = set(('value',)) + plugin_multi_attrib = 'options' FormField.addOption = FormField.add_option diff --git a/sleekxmpp/plugins/xep_0004/stanza/form.py b/sleekxmpp/plugins/xep_0004/stanza/form.py index 1d733760..3dcc7821 100644 --- a/sleekxmpp/plugins/xep_0004/stanza/form.py +++ b/sleekxmpp/plugins/xep_0004/stanza/form.py @@ -9,7 +9,7 @@ import copy import logging -from sleekxmpp.thirdparty import OrderedDict +from sleekxmpp.thirdparty import OrderedDict, OrderedSet from sleekxmpp.xmlstream import ElementBase, ET from sleekxmpp.plugins.xep_0004.stanza import FormField @@ -22,8 +22,7 @@ class Form(ElementBase): namespace = 'jabber:x:data' name = 'x' plugin_attrib = 'form' - interfaces = set(('fields', 'instructions', 'items', - 'reported', 'title', 'type', 'values')) + interfaces = OrderedSet(('instructions', 'reported', 'title', 'type', 'items', )) sub_interfaces = set(('title',)) form_types = set(('cancel', 'form', 'result', 'submit')) @@ -43,12 +42,12 @@ class Form(ElementBase): @property def field(self): - return self['fields'] + return self.get_fields() def set_type(self, ftype): self._set_attr('type', ftype) if ftype == 'submit': - fields = self['fields'] + fields = self.get_fields() for var in fields: field = fields[var] del field['type'] @@ -74,7 +73,8 @@ class Form(ElementBase): field['desc'] = desc field['required'] = required if options is not None: - field['options'] = options + for option in options: + field.add_option(**option) else: del field['type'] self.append(field) @@ -169,7 +169,7 @@ class Form(ElementBase): def get_reported(self): fields = OrderedDict() xml = self.xml.findall('{%s}reported/{%s}field' % (self.namespace, - FormField.namespace)) + FormField.namespace)) for field in xml: field = FormField(xml=field) fields[field['var']] = field @@ -177,7 +177,7 @@ class Form(ElementBase): def get_values(self): values = OrderedDict() - fields = self['fields'] + fields = self.get_fields() for var in fields: values[var] = fields[var]['value'] return values @@ -219,17 +219,33 @@ class Form(ElementBase): self.add_item(item) def set_reported(self, reported): + """ + This either needs a dictionary or dictionaries or a dictionary of form fields. + :param reported: + :return: + """ for var in reported: field = reported[var] - field['var'] = var - self.add_reported(var, **field) + + if isinstance(field, dict): + self.add_reported(**field) + else: + reported = self.xml.find('{%s}reported' % self.namespace) + if reported is None: + reported = ET.Element('{%s}reported' % self.namespace) + self.xml.append(reported) + + fieldXML = ET.Element('{%s}field' % FormField.namespace) + reported.append(fieldXML) + new_field = FormField(xml=fieldXML) + new_field.values = field.values def set_values(self, values): - fields = self['fields'] + fields = self.get_fields() for field in values: - if field not in fields: + if field not in self.get_fields(): fields[field] = self.add_field(var=field) - fields[field]['value'] = values[field] + self.get_fields()[field]['value'] = values[field] def merge(self, other): new = copy.copy(self) diff --git a/sleekxmpp/plugins/xep_0045.py b/sleekxmpp/plugins/xep_0045.py index ca5ed1ef..cc96d66e 100644 --- a/sleekxmpp/plugins/xep_0045.py +++ b/sleekxmpp/plugins/xep_0045.py @@ -397,6 +397,16 @@ class XEP_0045(BasePlugin): return None return self.rooms[room].keys() + def getUsersByAffiliation(cls, room, affiliation='member', ifrom=None): + if affiliation not in ('outcast', 'member', 'admin', 'owner', 'none'): + raise TypeError + query = ET.Element('{http://jabber.org/protocol/muc#admin}query') + item = ET.Element('{http://jabber.org/protocol/muc#admin}item', {'affiliation': affiliation}) + query.append(item) + iq = cls.xmpp.Iq(sto=room, sfrom=ifrom, stype='get') + iq.append(query) + return iq.send() + xep_0045 = XEP_0045 register_plugin(XEP_0045) diff --git a/sleekxmpp/plugins/xep_0054/stanza.py b/sleekxmpp/plugins/xep_0054/stanza.py index 72da0b51..2d017d6e 100644 --- a/sleekxmpp/plugins/xep_0054/stanza.py +++ b/sleekxmpp/plugins/xep_0054/stanza.py @@ -128,7 +128,8 @@ class Telephone(ElementBase): def setup(self, xml=None): super(Telephone, self).setup(xml=xml) - self._set_sub_text('NUMBER', '', keep=True) + ## this blanks out numbers received from server + ##self._set_sub_text('NUMBER', '', keep=True) def set_number(self, value): self._set_sub_text('NUMBER', value, keep=True) diff --git a/sleekxmpp/plugins/xep_0122/__init__.py b/sleekxmpp/plugins/xep_0122/__init__.py new file mode 100644 index 00000000..4b3e9483 --- /dev/null +++ b/sleekxmpp/plugins/xep_0122/__init__.py @@ -0,0 +1,11 @@ + +from sleekxmpp.plugins.base import register_plugin +from sleekxmpp.plugins.xep_0122.stanza import FormValidation +from sleekxmpp.plugins.xep_0122.data_validation import XEP_0122 + + +register_plugin(XEP_0122) + + +# Retain some backwards compatibility +xep_0122 = XEP_0122 diff --git a/sleekxmpp/plugins/xep_0122/data_validation.py b/sleekxmpp/plugins/xep_0122/data_validation.py new file mode 100644 index 00000000..ec2cdfcc --- /dev/null +++ b/sleekxmpp/plugins/xep_0122/data_validation.py @@ -0,0 +1,19 @@ +from sleekxmpp.xmlstream import register_stanza_plugin +from sleekxmpp.plugins import BasePlugin +from sleekxmpp.plugins.xep_0004 import stanza +from sleekxmpp.plugins.xep_0004.stanza import FormField +from sleekxmpp.plugins.xep_0122.stanza import FormValidation + + +class XEP_0122(BasePlugin): + """ + XEP-0004: Data Forms + """ + + name = 'xep_0122' + description = 'XEP-0122: Data Forms Validation' + dependencies = set(['xep_0004']) + stanza = stanza + + def plugin_init(self): + register_stanza_plugin(FormField, FormValidation) diff --git a/sleekxmpp/plugins/xep_0122/stanza.py b/sleekxmpp/plugins/xep_0122/stanza.py new file mode 100644 index 00000000..bc3c177a --- /dev/null +++ b/sleekxmpp/plugins/xep_0122/stanza.py @@ -0,0 +1,94 @@ + +from sleekxmpp.xmlstream import ElementBase, ET + + +class FormValidation(ElementBase): + """ + Validation values for form fields. + + Example: + + <field var='evt.date' type='text-single' label='Event Date/Time'> + <validate xmlns='http://jabber.org/protocol/xdata-validate' + datatype='xs:dateTime'/> + <value>2003-10-06T11:22:00-07:00</value> + </field> + + Questions: + Should this look at the datatype value and convert the range values as appropriate? + Should this stanza provide a pass/fail for a value from the field, or convert field value to datatype? + """ + + namespace = 'http://jabber.org/protocol/xdata-validate' + name = 'validate' + plugin_attrib = 'validate' + interfaces = {'datatype', 'basic', 'open', 'range', 'regex', } + sub_interfaces = {'basic', 'open', 'range', 'regex', } + plugin_attrib_map = {} + plugin_tag_map = {} + + def _add_field(self, name): + self.remove_all() + item_xml = ET.Element('{%s}%s' % (self.namespace, name)) + self.xml.append(item_xml) + return item_xml + + def set_basic(self, value): + if value: + self._add_field('basic') + else: + del self['basic'] + + def set_open(self, value): + if value: + self._add_field('open') + else: + del self['open'] + + def set_regex(self, regex): + if regex: + _regex = self._add_field('regex') + _regex.text = regex + else: + del self['regex'] + + def set_range(self, value, minimum=None, maximum=None): + if value: + _range = self._add_field('range') + _range.attrib['min'] = str(minimum) + _range.attrib['max'] = str(maximum) + else: + del self['range'] + + def remove_all(self, except_tag=None): + for a in self.sub_interfaces: + if a != except_tag: + del self[a] + + def get_basic(self): + present = self.xml.find('{%s}basic' % self.namespace) + return present is not None + + def get_open(self): + present = self.xml.find('{%s}open' % self.namespace) + return present is not None + + def get_regex(self): + present = self.xml.find('{%s}regex' % self.namespace) + if present is not None: + return present.text + + return False + + def get_range(self): + present = self.xml.find('{%s}range' % self.namespace) + if present is not None: + attributes = present.attrib + return_value = dict() + if 'min' in attributes: + return_value['minimum'] = attributes['min'] + if 'max' in attributes: + return_value['maximum'] = attributes['max'] + return return_value + + return False diff --git a/sleekxmpp/plugins/xep_0202/time.py b/sleekxmpp/plugins/xep_0202/time.py index d5b3af37..4e48eae8 100644 --- a/sleekxmpp/plugins/xep_0202/time.py +++ b/sleekxmpp/plugins/xep_0202/time.py @@ -72,9 +72,10 @@ class XEP_0202(BasePlugin): Arguments:
iq -- The Iq time request stanza.
"""
- iq.reply()
- iq['entity_time']['time'] = self.local_time(iq['to'])
- iq.send()
+ if iq['type'] == 'get':
+ iq.reply()
+ iq['entity_time']['time'] = self.local_time(iq['to'])
+ iq.send()
def get_entity_time(self, to, ifrom=None, **iqargs):
"""
diff --git a/sleekxmpp/plugins/xep_0323/sensordata.py b/sleekxmpp/plugins/xep_0323/sensordata.py index 87a62980..a3d4cf34 100644 --- a/sleekxmpp/plugins/xep_0323/sensordata.py +++ b/sleekxmpp/plugins/xep_0323/sensordata.py @@ -482,10 +482,10 @@ class XEP_0323(BasePlugin): if result == "done": self.sessions[session]["commTimers"][nodeId].cancel() self.sessions[session]["nodeDone"][nodeId] = True - msg['fields']['done'] = 'true' if (self._all_nodes_done(session)): # The session is complete, delete it del self.sessions[session] + msg['fields']['done'] = 'true' else: # Restart comm timer self.sessions[session]["commTimers"][nodeId].reset() diff --git a/sleekxmpp/plugins/xep_0332/http.py b/sleekxmpp/plugins/xep_0332/http.py index 03d88b65..70bcafa6 100644 --- a/sleekxmpp/plugins/xep_0332/http.py +++ b/sleekxmpp/plugins/xep_0332/http.py @@ -108,6 +108,8 @@ class XEP_0332(BasePlugin): iq['http-req']['method'] = method iq['http-req']['resource'] = resource iq['http-req']['version'] = '1.1' # TODO: set this implicitly + if 'id' in kwargs: + iq['id'] = kwargs["id"] if data is not None: iq['http-req']['data'] = data return iq.send( @@ -127,6 +129,8 @@ class XEP_0332(BasePlugin): iq['http-resp']['code'] = code iq['http-resp']['message'] = message iq['http-resp']['version'] = '1.1' # TODO: set this implicitly + if 'id' in kwargs: + iq['id'] = kwargs["id"] if data is not None: iq['http-resp']['data'] = data return iq.send( @@ -145,6 +149,8 @@ class XEP_0332(BasePlugin): iq['error']['code'] = ecode iq['error']['type'] = etype iq['error']['condition'] = econd + if 'id' in kwargs: + iq['id'] = kwargs["id"] return iq.send( timeout=kwargs.get('timeout', None), block=kwargs.get('block', True), |