diff --git a/slixmpp_omemo/__init__.py b/slixmpp_omemo/__init__.py index 3c64855..49957fe 100644 --- a/slixmpp_omemo/__init__.py +++ b/slixmpp_omemo/__init__.py @@ -54,6 +54,7 @@ except (ImportError,): TRUE_VALUES = {True, 'true', '1'} PUBLISH_OPTIONS_NODE = 'http://jabber.org/protocol/pubsub#publish-options' +PUBSUB_ERRORS = 'http://jabber.org/protocol/pubsub#errors' def b64enc(data: bytes) -> str: @@ -245,6 +246,38 @@ class XEP_0384(BasePlugin): def my_device_id(self) -> int: return self._device_id + def _set_node_config( + self, + node: str, + persist_items: bool = True, + access_model: Optional[str] = None, + ) -> asyncio.Future: + form = Form() + form['type'] = 'submit' + form.add_field( + var='FORM_TYPE', + ftype='hidden', + value='http://jabber.org/protocol/pubsub#node_config', + ) + if persist_items: + form.add_field( + var='pubsub#persist_items', + ftype='boolean', + value=True, + ) + if access_model is not None: + form.add_field( + var='FORM_TYPE', + ftype='text-single', + value=access_model, + ) + + return self.xmpp['xep_0060'].set_node_config( + self.xmpp.boundjid.bare, + node, + form, + ) + async def _generate_bundle_iq(self) -> Iq: bundle = self._omemo.public_bundle.serialize(self.omemo_backend) @@ -286,7 +319,19 @@ class XEP_0384(BasePlugin): async def _publish_bundle(self) -> None: if self._omemo.republish_bundle: iq = await self._generate_bundle_iq() - await iq.send() + try: + await iq.send() + except IqError as e: + # TODO: Slixmpp should handle pubsub#errors so we don't have to + # fish the element ourselves + precondition = e.iq['error'].xml.find( + '{%s}%s' % (PUBSUB_ERRORS, 'precondition-not-met'), + ) + if precondition is not None: + log.debug('The node we tried to publish was already ' + 'existing with a different configuration. ' + 'Trying to configure manually..') + await self._set_node_config(OMEMO_BUNDLES_NS) async def _fetch_bundle(self, jid: str, device_id: int) -> Optional[ExtendedPublicBundle]: node = '%s:%d' % (OMEMO_BUNDLES_NS, device_id) @@ -374,9 +419,21 @@ class XEP_0384(BasePlugin): 'pubsub#access_model': 'open', }) - await self.xmpp['xep_0060'].publish( - own_jid.bare, OMEMO_DEVICES_NS, payload=payload, options=options, - ) + try: + await self.xmpp['xep_0060'].publish( + own_jid.bare, OMEMO_DEVICES_NS, payload=payload, options=options, + ) + except IqError as e: + # TODO: Slixmpp should handle pubsub#errors so we don't have to + # fish the element ourselves + precondition = e.iq['error'].xml.find( + '{%s}%s' % (PUBSUB_ERRORS, 'precondition-not-met'), + ) + if precondition is not None: + log.debug('The node we tried to publish was already ' + 'existing with a different configuration. ' + 'Trying to configure manually..') + await self._set_node_config(OMEMO_DEVICES_NS) def get_device_list(self, jid: JID) -> List[str]: """Return active device ids. Always contains our own device id."""