comparison libervia/backend/plugins/plugin_exp_invitation.py @ 4270:0d7bb4df2343

Reformatted code base using black.
author Goffi <goffi@goffi.org>
date Wed, 19 Jun 2024 18:44:57 +0200
parents 4b842c1fb686
children
comparison
equal deleted inserted replaced
4269:64a85ce8be70 4270:0d7bb4df2343
43 C.PI_HANDLER: "yes", 43 C.PI_HANDLER: "yes",
44 C.PI_DESCRIPTION: _("Experimental handling of invitations"), 44 C.PI_DESCRIPTION: _("Experimental handling of invitations"),
45 } 45 }
46 46
47 NS_INVITATION = "https://salut-a-toi/protocol/invitation:0" 47 NS_INVITATION = "https://salut-a-toi/protocol/invitation:0"
48 INVITATION = '/message/invitation[@xmlns="{ns_invit}"]'.format( 48 INVITATION = '/message/invitation[@xmlns="{ns_invit}"]'.format(ns_invit=NS_INVITATION)
49 ns_invit=NS_INVITATION
50 )
51 NS_INVITATION_LIST = NS_INVITATION + "#list" 49 NS_INVITATION_LIST = NS_INVITATION + "#list"
52 50
53 51
54 class Invitation(object): 52 class Invitation(object):
55 53
89 - path(unicode, None): path of the repository 87 - path(unicode, None): path of the repository
90 @raise exceptions.ConflictError: this namespace is already registered 88 @raise exceptions.ConflictError: this namespace is already registered
91 """ 89 """
92 if namespace in self._ns_cb: 90 if namespace in self._ns_cb:
93 raise exceptions.ConflictError( 91 raise exceptions.ConflictError(
94 "invitation namespace {namespace} is already register with {callback}" 92 "invitation namespace {namespace} is already register with {callback}".format(
95 .format(namespace=namespace, callback=self._ns_cb[namespace])) 93 namespace=namespace, callback=self._ns_cb[namespace]
94 )
95 )
96 self._ns_cb[namespace] = callback 96 self._ns_cb[namespace] = callback
97 97
98 def _generate_base_invitation(self, client, invitee_jid, name, extra): 98 def _generate_base_invitation(self, client, invitee_jid, name, extra):
99 """Generate common mess_data end invitation_elt 99 """Generate common mess_data end invitation_elt
100 100
116 client.generate_message_xml(mess_data) 116 client.generate_message_xml(mess_data)
117 self._h.add_hint_elements(mess_data["xml"], [self._h.HINT_STORE]) 117 self._h.add_hint_elements(mess_data["xml"], [self._h.HINT_STORE])
118 invitation_elt = mess_data["xml"].addElement("invitation", NS_INVITATION) 118 invitation_elt = mess_data["xml"].addElement("invitation", NS_INVITATION)
119 if name is not None: 119 if name is not None:
120 invitation_elt["name"] = name 120 invitation_elt["name"] = name
121 thumb_url = extra.get('thumb_url') 121 thumb_url = extra.get("thumb_url")
122 if thumb_url: 122 if thumb_url:
123 if not thumb_url.startswith('http'): 123 if not thumb_url.startswith("http"):
124 log.warning( 124 log.warning(
125 "only http URLs are allowed for thumbnails, got {url}, ignoring" 125 "only http URLs are allowed for thumbnails, got {url}, ignoring".format(
126 .format(url=thumb_url)) 126 url=thumb_url
127 )
128 )
127 else: 129 else:
128 invitation_elt['thumb_url'] = thumb_url 130 invitation_elt["thumb_url"] = thumb_url
129 return mess_data, invitation_elt 131 return mess_data, invitation_elt
130 132
131 def send_pubsub_invitation( 133 def send_pubsub_invitation(
132 self, 134 self,
133 client: SatXMPPEntity, 135 client: SatXMPPEntity,
134 invitee_jid: jid.JID, 136 invitee_jid: jid.JID,
135 service: jid.JID, 137 service: jid.JID,
136 node: str, 138 node: str,
137 item_id: Optional[str], 139 item_id: Optional[str],
138 name: Optional[str], 140 name: Optional[str],
139 extra: Optional[dict] 141 extra: Optional[dict],
140 ) -> None: 142 ) -> None:
141 """Send an pubsub invitation in a <message> stanza 143 """Send an pubsub invitation in a <message> stanza
142 144
143 @param invitee_jid: entitee to send invitation to 145 @param invitee_jid: entitee to send invitation to
144 @param service: pubsub service 146 @param service: pubsub service
149 @param extra: see [_generate_base_invitation] 151 @param extra: see [_generate_base_invitation]
150 """ 152 """
151 if extra is None: 153 if extra is None:
152 extra = {} 154 extra = {}
153 mess_data, invitation_elt = self._generate_base_invitation( 155 mess_data, invitation_elt = self._generate_base_invitation(
154 client, invitee_jid, name, extra) 156 client, invitee_jid, name, extra
157 )
155 pubsub_elt = invitation_elt.addElement("pubsub") 158 pubsub_elt = invitation_elt.addElement("pubsub")
156 pubsub_elt["service"] = service.full() 159 pubsub_elt["service"] = service.full()
157 pubsub_elt["node"] = node 160 pubsub_elt["node"] = node
158 if item_id is None: 161 if item_id is None:
159 try: 162 try:
171 if "element" in extra: 174 if "element" in extra:
172 invitation_elt.addChild(extra.pop("element")) 175 invitation_elt.addChild(extra.pop("element"))
173 client.send(mess_data["xml"]) 176 client.send(mess_data["xml"])
174 177
175 async def send_file_sharing_invitation( 178 async def send_file_sharing_invitation(
176 self, client, invitee_jid, service, repos_type=None, namespace=None, path=None, 179 self,
177 name=None, extra=None 180 client,
181 invitee_jid,
182 service,
183 repos_type=None,
184 namespace=None,
185 path=None,
186 name=None,
187 extra=None,
178 ): 188 ):
179 """Send a file sharing invitation in a <message> stanza 189 """Send a file sharing invitation in a <message> stanza
180 190
181 @param invitee_jid(jid.JID): entitee to send invitation to 191 @param invitee_jid(jid.JID): entitee to send invitation to
182 @param service(jid.JID): file sharing service 192 @param service(jid.JID): file sharing service
194 li_plg.normalise_file_sharing_service(client, service) 204 li_plg.normalise_file_sharing_service(client, service)
195 205
196 # FIXME: not the best place to adapt permission, but it's necessary to check them 206 # FIXME: not the best place to adapt permission, but it's necessary to check them
197 # for UX 207 # for UX
198 try: 208 try:
199 await self.host.plugins['XEP-0329'].affiliationsSet( 209 await self.host.plugins["XEP-0329"].affiliationsSet(
200 client, service, namespace, path, {invitee_jid: "member"} 210 client, service, namespace, path, {invitee_jid: "member"}
201 ) 211 )
202 except Exception as e: 212 except Exception as e:
203 log.warning(f"Can't set affiliation: {e}") 213 log.warning(f"Can't set affiliation: {e}")
204 214
212 "no thumbnail found for file sharing interest at " 222 "no thumbnail found for file sharing interest at "
213 f"[{service}/{namespace}]{path}" 223 f"[{service}/{namespace}]{path}"
214 ) 224 )
215 else: 225 else:
216 try: 226 try:
217 extra['thumb_url'] = own_interest['thumb_url'] 227 extra["thumb_url"] = own_interest["thumb_url"]
218 except KeyError: 228 except KeyError:
219 pass 229 pass
220 230
221 mess_data, invitation_elt = self._generate_base_invitation( 231 mess_data, invitation_elt = self._generate_base_invitation(
222 client, invitee_jid, name, extra) 232 client, invitee_jid, name, extra
233 )
223 file_sharing_elt = invitation_elt.addElement("file_sharing") 234 file_sharing_elt = invitation_elt.addElement("file_sharing")
224 file_sharing_elt["service"] = service.full() 235 file_sharing_elt["service"] = service.full()
225 if repos_type is not None: 236 if repos_type is not None:
226 if repos_type not in ("files", "photos"): 237 if repos_type not in ("files", "photos"):
227 msg = "unknown repository type: {repos_type}".format( 238 msg = "unknown repository type: {repos_type}".format(
228 repos_type=repos_type) 239 repos_type=repos_type
240 )
229 log.warning(msg) 241 log.warning(msg)
230 raise exceptions.DateError(msg) 242 raise exceptions.DateError(msg)
231 file_sharing_elt["type"] = repos_type 243 file_sharing_elt["type"] = repos_type
232 if namespace is not None: 244 if namespace is not None:
233 file_sharing_elt["namespace"] = namespace 245 file_sharing_elt["namespace"] = namespace
248 try: 260 try:
249 items, metadata = await self._p.get_items( 261 items, metadata = await self._p.get_items(
250 client, service, node, item_ids=[item_id] 262 client, service, node, item_ids=[item_id]
251 ) 263 )
252 except Exception as e: 264 except Exception as e:
253 log.warning(_("Can't get item linked with invitation: {reason}").format( 265 log.warning(
254 reason=e)) 266 _("Can't get item linked with invitation: {reason}").format(reason=e)
267 )
255 try: 268 try:
256 item_elt = items[0] 269 item_elt = items[0]
257 except IndexError: 270 except IndexError:
258 log.warning(_("Invitation was linking to a non existing item")) 271 log.warning(_("Invitation was linking to a non existing item"))
259 raise exceptions.DataError 272 raise exceptions.DataError
260 273
261 try: 274 try:
262 namespace = item_elt.firstChildElement().uri 275 namespace = item_elt.firstChildElement().uri
263 except Exception as e: 276 except Exception as e:
264 log.warning(_("Can't retrieve namespace of invitation: {reason}").format( 277 log.warning(
265 reason = e)) 278 _("Can't retrieve namespace of invitation: {reason}").format(reason=e)
279 )
266 raise exceptions.DataError 280 raise exceptions.DataError
267 281
268 args = [service, node, item_id, item_elt] 282 args = [service, node, item_id, item_elt]
269 else: 283 else:
270 try: 284 try:
271 node_data_elt = next(pubsub_elt.elements(NS_INVITATION, "node_data")) 285 node_data_elt = next(pubsub_elt.elements(NS_INVITATION, "node_data"))
272 except StopIteration: 286 except StopIteration:
273 raise exceptions.DataError("Bad invitation, ignoring") 287 raise exceptions.DataError("Bad invitation, ignoring")
274 namespace = node_data_elt['namespace'] 288 namespace = node_data_elt["namespace"]
275 args = [service, node, None, node_data_elt] 289 args = [service, node, None, node_data_elt]
276 290
277 return namespace, args 291 return namespace, args
278 292
279 async def _parse_file_sharing_elt(self, client, file_sharing_elt): 293 async def _parse_file_sharing_elt(self, client, file_sharing_elt):
294 invitation_elt = message_elt.invitation 308 invitation_elt = message_elt.invitation
295 309
296 name = invitation_elt.getAttribute("name") 310 name = invitation_elt.getAttribute("name")
297 extra = {} 311 extra = {}
298 if invitation_elt.hasAttribute("thumb_url"): 312 if invitation_elt.hasAttribute("thumb_url"):
299 extra['thumb_url'] = invitation_elt['thumb_url'] 313 extra["thumb_url"] = invitation_elt["thumb_url"]
300 314
301 for elt in invitation_elt.elements(): 315 for elt in invitation_elt.elements():
302 if elt.uri != NS_INVITATION: 316 if elt.uri != NS_INVITATION:
303 log.warning("unexpected element: {xml}".format(xml=elt.toXml())) 317 log.warning("unexpected element: {xml}".format(xml=elt.toXml()))
304 continue 318 continue
305 if elt.name == "pubsub": 319 if elt.name == "pubsub":
306 method = self._parse_pubsub_elt 320 method = self._parse_pubsub_elt
307 elif elt.name == "file_sharing": 321 elif elt.name == "file_sharing":
308 method = self._parse_file_sharing_elt 322 method = self._parse_file_sharing_elt
309 else: 323 else:
310 log.warning("not implemented invitation element: {xml}".format( 324 log.warning(
311 xml = elt.toXml())) 325 "not implemented invitation element: {xml}".format(xml=elt.toXml())
326 )
312 continue 327 continue
313 try: 328 try:
314 namespace, args = await method(client, elt) 329 namespace, args = await method(client, elt)
315 except exceptions.DataError: 330 except exceptions.DataError:
316 log.warning("Can't parse invitation element: {xml}".format( 331 log.warning(
317 xml = elt.toXml())) 332 "Can't parse invitation element: {xml}".format(xml=elt.toXml())
333 )
318 continue 334 continue
319 335
320 try: 336 try:
321 cb = self._ns_cb[namespace] 337 cb = self._ns_cb[namespace]
322 except KeyError: 338 except KeyError:
323 log.warning(_( 339 log.warning(
324 'No handler for namespace "{namespace}", invitation ignored') 340 _(
325 .format(namespace=namespace)) 341 'No handler for namespace "{namespace}", invitation ignored'
342 ).format(namespace=namespace)
343 )
326 else: 344 else:
327 await utils.as_deferred(cb, client, namespace, name, extra, *args) 345 await utils.as_deferred(cb, client, namespace, name, extra, *args)
328 346
329 347
330 @implementer(iwokkel.IDisco) 348 @implementer(iwokkel.IDisco)