Mercurial > libervia-backend
annotate sat/plugins/plugin_exp_invitation_pubsub.py @ 3728:b15644cae50d
component AP gateway: JID/node ⟺ AP outbox conversion:
- convert a combination of JID and optional pubsub node to AP actor handle (see
`getJIDAndNode` for details) and vice versa
- the gateway now provides a Pubsub service
- retrieve pubsub node and convert it to AP collection, AP pagination is converted to RSM
- do the opposite: convert AP collection to pubsub and handle RSM request. Due to
ActivityStream collection pagination limitations, some RSM request produce inefficient
requests, but caching should be used most of the time in the future and avoid the
problem.
- set specific name to HTTP Server
- new `local_only` setting (`True` by default) to indicate if the gateway can request or
not XMPP Pubsub nodes from other servers
- disco info now specifies important features such as Pubsub RSM, and nodes metadata
ticket 363
author | Goffi <goffi@goffi.org> |
---|---|
date | Tue, 25 Jan 2022 17:54:06 +0100 |
parents | edc79cefe968 |
children | 26c3e1bc7fb7 |
rev | line source |
---|---|
3462 | 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 | |
3584
edc79cefe968
plugin XEP-0060: `getItem(s)`, `publish` and `(un)subscribe` are now coroutines
Goffi <goffi@goffi.org>
parents:
3462
diff
changeset
|
167 return await self.host.plugins['LIST_INTEREST'].registerPubsub( |
3462 | 168 client, namespace, service, node, item_id, creator, |
169 name, element, extra) |