diff options
Diffstat (limited to 'nbxmpp/modules/pubsub.py')
-rw-r--r-- | nbxmpp/modules/pubsub.py | 134 |
1 files changed, 119 insertions, 15 deletions
diff --git a/nbxmpp/modules/pubsub.py b/nbxmpp/modules/pubsub.py index 8a5a3e2..b1f9edd 100644 --- a/nbxmpp/modules/pubsub.py +++ b/nbxmpp/modules/pubsub.py @@ -20,6 +20,8 @@ import logging from nbxmpp.protocol import NS_PUBSUB from nbxmpp.protocol import NS_PUBSUB_EVENT from nbxmpp.protocol import NS_PUBSUB_PUBLISH_OPTIONS +from nbxmpp.protocol import NS_PUBSUB_OWNER +from nbxmpp.protocol import NS_PUBSUB_CONFIG from nbxmpp.protocol import NS_DATA from nbxmpp.protocol import Node from nbxmpp.protocol import Iq @@ -27,6 +29,9 @@ from nbxmpp.protocol import isResultNode from nbxmpp.structs import StanzaHandler from nbxmpp.structs import PubSubEventData from nbxmpp.structs import CommonResult +from nbxmpp.structs import PubSubConfigResult +from nbxmpp.structs import PubSubPublishResult +from nbxmpp.modules.dataforms import extend_form from nbxmpp.util import call_on_response from nbxmpp.util import callback from nbxmpp.util import raise_error @@ -56,28 +61,36 @@ class PubSub: node, empty=True, deleted=True) return - retract = event.getTag('retract') - if retract is not None: - node = retract.getAttr('node') - item = retract.getTag('item') - id_ = item.getAttr('id') - properties.pubsub_event = PubSubEventData( - node, id_, item, retracted=True) + purge = event.getTag('purge') + if purge is not None: + node = purge.getAttr('node') + item = purge.getTag('item') + properties.pubsub_event = PubSubEventData(node, purged=True) return items = event.getTag('items') if items is not None: + node = items.getAttr('node') + + retract = items.getTag('retract') + if retract is not None: + id_ = retract.getAttr('id') + properties.pubsub_event = PubSubEventData( + node, id_, retracted=True) + return + if len(items.getChildren()) != 1: log.warning('PubSub event with more than one item') log.warning(stanza) - node = items.getAttr('node') + return + item = items.getTag('item') if item is None: return id_ = item.getAttr('id') properties.pubsub_event = PubSubEventData(node, id_, item) - @call_on_response('_default_response') + @call_on_response('_publish_result_received') def publish(self, jid, node, item, id_=None, options=None): query = Iq('set', to=jid) pubsub = query.addChild('pubsub', namespace=NS_PUBSUB) @@ -92,6 +105,87 @@ class PubSub: return query @callback + def _publish_result_received(self, stanza): + if not isResultNode(stanza): + return raise_error(log.warning, stanza) + + jid = stanza.getFrom() + pubsub = stanza.getTag('pubsub', namespace=NS_PUBSUB) + if pubsub is None: + return raise_error(log.warning, stanza, 'stanza-malformed') + + publish = pubsub.getTag('publish') + if publish is None: + return raise_error(log.warning, stanza, 'stanza-malformed') + + node = publish.getAttr('node') + item = publish.getTag('item') + if item is None: + return raise_error(log.warning, stanza, 'stanza-malformed') + + id_ = item.getAttr('id') + return PubSubPublishResult(jid, node, id_) + + @call_on_response('_default_response') + def retract(self, jid, node, id_, notify=True): + query = Iq('set', to=jid) + pubsub = query.addChild('pubsub', namespace=NS_PUBSUB) + attrs = {'node': node} + if notify: + attrs['notify'] = 'true' + retract = pubsub.addChild('retract', attrs=attrs) + retract.addChild('item', {'id': id_}) + return query + + @call_on_response('_default_response') + def set_node_configuration(self, jid, node, form): + log.info('Set configuration for %s %s', node, jid) + query = Iq('set', to=jid) + pubsub = query.addChild('pubsub', namespace=NS_PUBSUB_OWNER) + configure = pubsub.addChild('configure', {'node': node}) + form.setAttr('type', 'submit') + configure.addChild(node=form) + return query + + @call_on_response('_node_configuration_received') + def get_node_configuration(self, jid, node): + log.info('Request node configuration') + query = Iq('get', to=jid) + pubsub = query.addChild('pubsub', namespace=NS_PUBSUB_OWNER) + pubsub.addChild('configure', {'node': node}) + return query + + @callback + def _node_configuration_received(self, stanza): + if not isResultNode(stanza): + return raise_error(log.warning, stanza) + + jid = stanza.getFrom() + pubsub = stanza.getTag('pubsub', namespace=NS_PUBSUB_OWNER) + if pubsub is None: + return raise_error(log.warning, stanza, 'stanza-malformed', + 'No pubsub node found') + + configure = pubsub.getTag('configure') + if configure is None: + return raise_error(log.warning, stanza, 'stanza-malformed', + 'No configure node found') + + node = configure.getAttr('node') + + forms = configure.getTags('x', namespace=NS_DATA) + for form in forms: + dataform = extend_form(node=form) + form_type = dataform.vars.get('FORM_TYPE') + if form_type is None or form_type.value != NS_PUBSUB_CONFIG: + continue + log.info('Node configuration received from: %s', jid) + return PubSubConfigResult(jid=jid, node=node, form=dataform) + + return raise_error(log.warning, stanza, 'stanza-malformed', + 'No valid form type found') + + @callback def _default_response(self, stanza): if not isResultNode(stanza): return raise_error(log.info, stanza) @@ -115,13 +209,23 @@ def get_pubsub_item(stanza): return items_node.getTag('item') -def get_bookmark_publish_options(): - # TODO: Make generic - options = Node(NS_DATA + ' x', - attrs={'type': 'submit'}) +def get_pubsub_items(stanza, node=None): + pubsub_node = stanza.getTag('pubsub') + items_node = pubsub_node.getTag('items') + if node is not None and items_node.getAttr('node') != node: + return + + if items_node is not None: + return items_node.getTags('item') + + +def get_publish_options(config): + options = Node(NS_DATA + ' x', attrs={'type': 'submit'}) field = options.addChild('field', attrs={'var': 'FORM_TYPE', 'type': 'hidden'}) field.setTagData('value', NS_PUBSUB_PUBLISH_OPTIONS) - field = options.addChild('field', attrs={'var': 'pubsub#access_model'}) - field.setTagData('value', 'whitelist') + + for var, value in config.items(): + field = options.addChild('field', attrs={'var': var}) + field.setTagData('value', value) return options |