comparison sat/plugins/plugin_exp_invitation_pubsub.py @ 3462:12dc234f698c

plugin invitation: pubsub invitations: - new Pubsub invitation plugin, to have a generic way to manage invitation on Pubsub based features - `invitePreflight` and `onInvitationPreflight` method can be implemented to customise invitation for a namespace - refactored events invitations to use the new plugin - a Pubsub invitation can now be for a whole node instead of a specific item - if invitation is for a node, a namespace can be specified to indicate what this node is about. It is then added in `extra` data - an element (domish.Element) can be added in `extra` data, it will then be added in the invitation - some code modernisation
author Goffi <goffi@goffi.org>
date Fri, 19 Feb 2021 15:50:22 +0100
parents
children edc79cefe968
comparison
equal deleted inserted replaced
3461:02a8d227d5bb 3462:12dc234f698c
1 #!/usr/bin/env python3
2
3 # SàT plugin to send invitations for Pubsub
4 # Copyright (C) 2009-2021 Jérôme Poisson (goffi@goffi.org)
5
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU Affero General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
10
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU Affero General Public License for more details.
15
16 # You should have received a copy of the GNU Affero General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
19 from typing import Optional
20 from twisted.internet import defer
21 from twisted.words.protocols.jabber import jid
22 from twisted.words.xish import domish
23 from sat.core.i18n import _
24 from sat.core.constants import Const as C
25 from sat.core.log import getLogger
26 from sat.core.xmpp import SatXMPPEntity
27 from sat.tools import utils
28 from sat.tools.common import data_format
29
30 log = getLogger(__name__)
31
32
33 PLUGIN_INFO = {
34 C.PI_NAME: "Pubsub Invitation",
35 C.PI_IMPORT_NAME: "PUBSUB_INVITATION",
36 C.PI_TYPE: "EXP",
37 C.PI_PROTOCOLS: [],
38 C.PI_DEPENDENCIES: ["XEP-0060", "INVITATION"],
39 C.PI_RECOMMENDATIONS: [],
40 C.PI_MAIN: "PubsubInvitation",
41 C.PI_HANDLER: "no",
42 C.PI_DESCRIPTION: _("Invitations for pubsub based features"),
43 }
44
45
46 class PubsubInvitation:
47
48 def __init__(self, host):
49 log.info(_("Pubsub Invitation plugin initialization"))
50 self.host = host
51 self._p = host.plugins["XEP-0060"]
52 # namespace to handler map
53 self._ns_handler = {}
54 host.bridge.addMethod(
55 "psInvite",
56 ".plugin",
57 in_sign="sssssss",
58 out_sign="",
59 method=self._sendPubsubInvitation,
60 async_=True
61 )
62
63 def register(
64 self,
65 namespace: str,
66 handler
67 ) -> None:
68 self._ns_handler[namespace] = handler
69 self.host.plugins["INVITATION"].registerNamespace(namespace, self.onInvitation)
70
71 def _sendPubsubInvitation(
72 self, invitee_jid_s, service_s, node, item_id=None,
73 name=None, extra_s='', profile_key=C.PROF_KEY_NONE):
74 client = self.host.getClient(profile_key)
75 invitee_jid = jid.JID(invitee_jid_s)
76 service = jid.JID(service_s)
77 extra = data_format.deserialise(extra_s)
78 return defer.ensureDeferred(
79 self.invite(
80 client,
81 invitee_jid,
82 service,
83 node,
84 item_id or None,
85 name=name or None,
86 extra=extra
87 )
88 )
89
90 async def invite(
91 self,
92 client: SatXMPPEntity,
93 invitee_jid: jid.JID,
94 service: jid.JID,
95 node: str,
96 item_id: Optional[str] = None,
97 name: str = '',
98 extra: Optional[dict] = None,
99 ) -> None:
100 if extra is None:
101 extra = {}
102 else:
103 namespace = extra.get("namespace")
104 if namespace:
105 try:
106 handler = self._ns_handler[namespace]
107 preflight = handler.invitePreflight
108 except KeyError:
109 pass
110 except AttributeError:
111 log.debug(f"no invitePreflight method found for {namespace!r}")
112 else:
113 await utils.asDeferred(
114 preflight,
115 client, invitee_jid, service, node, item_id, name, extra
116 )
117 if item_id is None:
118 item_id = extra.pop("default_item_id", None)
119
120 # we authorize our invitee to see the nodes of interest
121 await self._p.setNodeAffiliations(client, service, node, {invitee_jid: "member"})
122 log.debug(f"affiliation set on {service}'s {node!r} node")
123
124 # now we send the invitation
125 self.host.plugins["INVITATION"].sendPubsubInvitation(
126 client,
127 invitee_jid,
128 service,
129 node,
130 item_id,
131 name=name or None,
132 extra=extra
133 )
134
135 async def onInvitation(
136 self,
137 client: SatXMPPEntity,
138 namespace: str,
139 name: str,
140 extra: dict,
141 service: jid.JID,
142 node: str,
143 item_id: Optional[str],
144 item_elt: domish.Element
145 ) -> None:
146 if extra is None:
147 extra = {}
148 try:
149 handler = self._ns_handler[namespace]
150 preflight = handler.onInvitationPreflight
151 except KeyError:
152 pass
153 except AttributeError:
154 log.debug(f"no onInvitationPreflight method found for {namespace!r}")
155 else:
156 await utils.asDeferred(
157 preflight,
158 client, namespace, name, extra, service, node, item_id, item_elt
159 )
160 if item_id is None:
161 item_id = extra.pop("default_item_id", None)
162 creator = extra.pop("creator", False)
163 element = extra.pop("element", None)
164 if not name:
165 name = extra.pop("name", "")
166
167 return self.host.plugins['LIST_INTEREST'].registerPubsub(
168 client, namespace, service, node, item_id, creator,
169 name, element, extra)