Mercurial > libervia-backend
diff sat/plugins/plugin_exp_list_of_interest.py @ 2912:a3faf1c86596
plugin events: refactored invitation and personal lists logic:
- invitation logic has been moved to a new generic "plugin_exp_invitation" plugin
- plugin_misc_invitations has be rename "plugin_exp_email_invitation" to avoid confusion
- personal event list has be refactored to use a new experimental "list of interest", which regroup all interestings items, events or other ones
author | Goffi <goffi@goffi.org> |
---|---|
date | Sun, 14 Apr 2019 08:21:51 +0200 |
parents | |
children | 672e6be3290f |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sat/plugins/plugin_exp_list_of_interest.py Sun Apr 14 08:21:51 2019 +0200 @@ -0,0 +1,154 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +# SAT plugin to detect language (experimental) +# Copyright (C) 2009-2019 Jérôme Poisson (goffi@goffi.org) + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. + +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +from sat.core.i18n import _ +from sat.core.constants import Const as C +from sat.core.log import getLogger +from wokkel import disco, iwokkel, pubsub +from zope.interface import implements +from twisted.internet import defer +from twisted.words.protocols.jabber import error as jabber_error +from twisted.words.protocols.jabber.xmlstream import XMPPHandler +from twisted.words.xish import domish + +log = getLogger(__name__) + + +PLUGIN_INFO = { + C.PI_NAME: "List of Interest", + C.PI_IMPORT_NAME: "LIST_INTEREST", + C.PI_TYPE: "EXP", + C.PI_PROTOCOLS: [], + C.PI_DEPENDENCIES: ["XEP-0060"], + C.PI_RECOMMENDATIONS: [], + C.PI_MAIN: "ListInterest", + C.PI_HANDLER: "yes", + C.PI_DESCRIPTION: _(u"Experimental handling of interesting XMPP locations"), +} + +NS_LIST_INTEREST = "https://salut-a-toi/protocol/list-interest:0" + + +class ListInterest(object): + namespace = NS_LIST_INTEREST + + def __init__(self, host): + log.info(_(u"List of Interest plugin initialization")) + self.host = host + self._p = self.host.plugins["XEP-0060"] + + def getHandler(self, client): + return ListInterestHandler(self) + + @defer.inlineCallbacks + def createNode(self, client): + try: + # TODO: check auto-create, no need to create node first if available + options = {self._p.OPT_ACCESS_MODEL: self._p.ACCESS_WHITELIST} + yield self._p.createNode( + client, + client.jid.userhostJID(), + nodeIdentifier=NS_LIST_INTEREST, + options=options, + ) + except jabber_error.StanzaError as e: + if e.condition == u"conflict": + log.debug(_(u"requested node already exists")) + + @defer.inlineCallbacks + def registerPubsub(self, client, namespace, service, node, item_id=None, + creator=False, name=None, element=None): + """Register an interesting element in personal list + + @param namespace(unicode): namespace of the interest + this is used as a cache, to avoid the need to retrieve the item only to get + its namespace + @param service(jid.JID): pubsub service of the + @param node(unicode): target pubsub node + @param item_id(unicode, None): target pubsub id + @param creator(bool): True if client's profile is the creator of the node + This is used a cache, to avoid the need to retrieve affiliations + @param name(unicode, None): name of the interest + @param element(domish.Element, None): element to attach + may be used to cache some extra data + """ + yield self.createNode(client) + interest_elt = domish.Element((NS_LIST_INTEREST, u"interest")) + interest_elt[u"namespace"] = namespace + if name is not None: + interest_elt[u'name'] = name + pubsub_elt = interest_elt.addElement(u"pubsub") + pubsub_elt[u"service"] = service.full() + pubsub_elt[u"node"] = node + if item_id is not None: + pubsub_elt[u"item"] = item_id + if creator: + pubsub_elt[u"creator"] = C.BOOL_TRUE + if element is not None: + pubsub_elt.addChild(element) + item_elt = pubsub.Item(payload=interest_elt) + yield self._p.publish( + client, client.jid.userhostJID(), NS_LIST_INTEREST, items=[item_elt] + ) + + @defer.inlineCallbacks + def listInterests(self, client, service=None, node=None, namespace=None): + """Retrieve list of interests + + @param service(jid.JID, None): service to use + None to use own PEP + @param node(unicode, None): node to use + None to use default node + @param namespace(unicode, None): filter interests of this namespace + None to retrieve all interests + @return: same as [XEP_0060.getItems] + """ + # TODO: if a MAM filter were available, it would improve performances + if not node: + node = NS_LIST_INTEREST + items, metadata = yield self._p.getItems(client, service, node) + if namespace is not None: + filtered_items = [] + for item in items: + try: + interest_elt = next(item.elements(NS_LIST_INTEREST, u"interest")) + except StopIteration: + log.warning(_(u"Missing interest element: {xml}").format( + xml=interest_elt.toXml())) + continue + if interest_elt.getAttribute(u"namespace") == namespace: + filtered_items.append(item) + items = filtered_items + + defer.returnValue((items, metadata)) + + +class ListInterestHandler(XMPPHandler): + implements(iwokkel.IDisco) + + def __init__(self, plugin_parent): + self.plugin_parent = plugin_parent + + def getDiscoInfo(self, requestor, target, nodeIdentifier=""): + return [ + disco.DiscoFeature(NS_LIST_INTEREST), + ] + + def getDiscoItems(self, requestor, target, nodeIdentifier=""): + return []