Mercurial > libervia-pubsub
diff src/mam.py @ 369:dabee42494ac
config file + cleaning:
- SàT Pubsub can now be configured using the same config file as SàT itself (i.e. sat.conf or .sat.conf), in the same locations (/etc, local dir, xdg dir).
Its options must be in the "pubsub" section
- options on command line override config options
- removed tap and http files which are not used anymore
- changed directory structure to put source in src, to be coherent with SàT and Libervia
- changed options name, db* become db_*, secret become xmpp_pwd
- an exception is raised if jid or xmpp_pwd is are not configured
author | Goffi <goffi@goffi.org> |
---|---|
date | Fri, 02 Mar 2018 12:59:38 +0100 |
parents | sat_pubsub/mam.py@a772f7dac930 |
children | 9a787881b824 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mam.py Fri Mar 02 12:59:38 2018 +0100 @@ -0,0 +1,161 @@ +#!/usr/bin/python +#-*- coding: utf-8 -*- + +# Copyright (c) 2016 Jérôme Poisson +# Copyright (c) 2015-2016 Adrien Cossa +# +# 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/>. + +""" +XMPP Message Archive Management protocol. + +This protocol is specified in +U{XEP-0313<http://xmpp.org/extensions/xep-0313.html>}. +""" + + +from zope.interface import implements + +from twisted.words.xish import domish +from twisted.python import log +from twisted.words.protocols.jabber import error + +from sat_pubsub import const +from sat_pubsub import backend +from wokkel import pubsub + +from wokkel import rsm +from wokkel import mam +from wokkel import delay + + +class MAMResource(object): + implements(mam.IMAMResource) + _errorMap = backend.PubSubResourceFromBackend._errorMap + + def __init__(self, backend_): + self.backend = backend_ + + def _mapErrors(self, failure): + # XXX: come from backend.PubsubResourceFromBackend + e = failure.trap(*self._errorMap.keys()) + + condition, pubsubCondition, feature = self._errorMap[e] + msg = failure.value.msg + + if pubsubCondition: + exc = pubsub.PubSubError(condition, pubsubCondition, feature, msg) + else: + exc = error.StanzaError(condition, text=msg) + + raise exc + + def onArchiveRequest(self, mam_request): + """ + + @param mam_request: The MAM archive request. + @type mam_request: L{MAMQueryReques<wokkel.mam.MAMRequest>} + + @return: A tuple with list of message data (id, element, data) and RSM element + @rtype: C{tuple} + """ + # FIXME: bad result ordering + try: + pep = mam_request.delegated + except AttributeError: + pep = False + ext_data = {'pep': pep} + if mam_request.form: + ext_data['filters'] = mam_request.form.fields.values() + if mam_request.rsm is None: + if const.VAL_RSM_MAX_DEFAULT != None: + log.msg("MAM request without RSM limited to {}".format(const.VAL_RSM_MAX_DEFAULT)) + ext_data['rsm'] = rsm.RSMRequest(const.VAL_RSM_MAX_DEFAULT) + else: + ext_data['rsm'] = mam_request.rsm + + d = self.backend.getItemsData(mam_request.node, mam_request.sender, mam_request.recipient, None, None, ext_data) + + def make_message(elt): + # XXX: http://xmpp.org/extensions/xep-0297.html#sect-idp629952 (rule 3) + message = domish.Element((const.NS_CLIENT, "message")) + event = message.addElement((pubsub.NS_PUBSUB_EVENT, "event")) + items = event.addElement('items') + items["node"] = mam_request.node + items.addChild(elt) + return message + + def cb(items_data): + msg_data = [] + rsm_elt = None + for item_data in items_data: + if item_data.item.name == 'set' and item_data.item.uri == rsm.NS_RSM: + assert rsm_elt is None + rsm_elt = item_data.item + elif item_data.item.name == 'item': + msg_data.append([item_data.item['id'], make_message(item_data.item), item_data.created]) + else: + log.msg("WARNING: unknown element: {}".format(item_data.item.name)) + if pep: + # we need to send privileged message + # so me manage the sending ourself, and return + # an empty msg_data list to avoid double sending + for data in msg_data: + self.forwardPEPMessage(mam_request, *data) + msg_data = [] + return (msg_data, rsm_elt) + + d.addErrback(self._mapErrors) + d.addCallback(cb) + return d + + def forwardPEPMessage(self, mam_request, id_, elt, created): + msg = domish.Element((None, 'message')) + msg['from'] = self.backend.privilege.server_jid.full() + msg['to'] = mam_request.sender.full() + result = msg.addElement((mam.NS_MAM, 'result')) + if mam_request.query_id is not None: + result['queryid'] = mam_request.query_id + result['id'] = id_ + forward = result.addElement((const.NS_FORWARD, 'forwarded')) + forward.addChild(delay.Delay(created).toElement()) + forward.addChild(elt) + self.backend.privilege.sendMessage(msg) + + def onPrefsGetRequest(self, requestor): + """ + + @param requestor: JID of the requestor. + @type requestor: L{JID<twisted.words.protocols.jabber.jid.JID>} + + @return: The current settings. + @rtype: L{wokkel.mam.MAMPrefs} + """ + # TODO: return the actual current settings + return mam.MAMPrefs() + + def onPrefsSetRequest(self, prefs, requestor): + """ + + @param prefs: The new settings to set. + @type prefs: L{wokkel.mam.MAMPrefs} + + @param requestor: JID of the requestor. + @type requestor: L{JID<twisted.words.protocols.jabber.jid.JID>} + + @return: The settings that have actually been set. + @rtype: L{wokkel.mam.MAMPrefs} + """ + # TODO: set the new settings and return them + return mam.MAMPrefs()