comparison libervia/backend/core/xmpp.py @ 4375:42becd4b819f

core (xmpp): add `origin` and `origin_label` to message data: If a message comes from a gateway, its type is used as `origin` in `extra`, and it has a name, it's used as `origin_label`. `is-bot` is also set when the sending entity is advertised as a bot. rel 459
author Goffi <goffi@goffi.org>
date Sun, 08 Jun 2025 17:16:56 +0200
parents 90d476a80ce9
children 79d463e3fdeb
comparison
equal deleted inserted replaced
4374:90d476a80ce9 4375:42becd4b819f
22 from functools import partial 22 from functools import partial
23 import mimetypes 23 import mimetypes
24 from pathlib import Path 24 from pathlib import Path
25 import sys 25 import sys
26 import time 26 import time
27 from typing import Callable, Dict, Tuple, Optional 27 from typing import Callable, Dict, Tuple, Optional, cast
28 from urllib.parse import unquote, urlparse 28 from urllib.parse import unquote, urlparse
29 import uuid 29 import uuid
30 30
31 import shortuuid 31 import shortuuid
32 from twisted.internet import defer, error as internet_error, reactor 32 from twisted.internet import defer, error as internet_error, reactor
1314 if elt.uri == namespace: 1314 if elt.uri == namespace:
1315 elt.defaultUri = elt.uri = C.NS_CLIENT 1315 elt.defaultUri = elt.uri = C.NS_CLIENT
1316 for child in elt.elements(): 1316 for child in elt.elements():
1317 self.normalize_ns(child, namespace) 1317 self.normalize_ns(child, namespace)
1318 1318
1319 def parse_message(self, message_elt: domish.Element) -> MessageData: 1319 async def parse_message(self, message_elt: domish.Element) -> MessageData:
1320 """Parse a message XML and return message_data 1320 """Parse a message XML and return message_data
1321 1321
1322 @param message_elt(domish.Element): raw <message> xml 1322 @param message_elt(domish.Element): raw <message> xml
1323 @param client(SatXMPPClient, None): client to map message id to uid 1323 @param client(SatXMPPClient, None): client to map message id to uid
1324 if None, mapping will not be done 1324 if None, mapping will not be done
1344 xml=message_elt.toXml() 1344 xml=message_elt.toXml()
1345 ) 1345 )
1346 ) 1346 )
1347 ) 1347 )
1348 1348
1349 client = self.parent 1349 client = cast(SatXMPPEntity, self.parent)
1350 assert client is not None
1350 1351
1351 if not message_elt.hasAttribute("to"): 1352 if not message_elt.hasAttribute("to"):
1352 message_elt["to"] = client.jid.full() 1353 message_elt["to"] = client.jid.full()
1353 1354
1355 from_jid = jid.JID(message_elt["from"])
1356 from_jid_bare = from_jid.userhostJID()
1354 message = {} 1357 message = {}
1355 subject = {} 1358 subject = {}
1356 extra = {} 1359 extra = {}
1357 data = MessageData({ 1360 data = MessageData({
1358 "from": jid.JID(message_elt["from"]), 1361 "from": from_jid,
1359 "to": jid.JID(message_elt["to"]), 1362 "to": jid.JID(message_elt["to"]),
1360 "uid": message_elt.getAttribute( 1363 "uid": message_elt.getAttribute(
1361 "uid", str(uuid.uuid4()) 1364 "uid", str(uuid.uuid4())
1362 ), # XXX: uid is not a standard attribute but may be added by plugins 1365 ), # XXX: uid is not a standard attribute but may be added by plugins
1363 "message": message, 1366 "message": message,
1370 message_id = extra["message_id"] = message_elt["id"] 1373 message_id = extra["message_id"] = message_elt["id"]
1371 except KeyError: 1374 except KeyError:
1372 pass 1375 pass
1373 else: 1376 else:
1374 client.mess_id2uid[(data["from"], message_id)] = data["uid"] 1377 client.mess_id2uid[(data["from"], message_id)] = data["uid"]
1378
1379 # origin
1380 if not from_jid_bare in (client.jid.userhostJID(), client.server_jid):
1381 disco_infos = await self.host.memory.disco.get_infos(client, from_jid_bare)
1382 if from_jid_bare.user:
1383 domain_disco_infos = await self.host.memory.disco.get_infos(
1384 client, jid.JID(from_jid_bare.host)
1385 )
1386 else:
1387 domain_disco_infos = disco_infos
1388 if ("client", "bot") in disco_infos.identities:
1389 extra["is-bot"] = True
1390 for (category, type_), label in domain_disco_infos.identities.items():
1391 if category == "gateway":
1392 extra["origin"] = type_
1393 if label:
1394 extra["origin_name"] = label
1375 1395
1376 # message 1396 # message
1377 for e in message_elt.elements(C.NS_CLIENT, "body"): 1397 for e in message_elt.elements(C.NS_CLIENT, "body"):
1378 message[e.getAttribute((C.NS_XML, "lang"), "")] = str(e) 1398 message[e.getAttribute((C.NS_XML, "lang"), "")] = str(e)
1379 1399
1478 if not trigger_ret_continue: 1498 if not trigger_ret_continue:
1479 # trigger returned False, we stop the workflow. 1499 # trigger returned False, we stop the workflow.
1480 return 1500 return
1481 1501
1482 try: 1502 try:
1483 data = self.parse_message(message_elt) 1503 data = await self.parse_message(message_elt)
1484 # we now do all post treatments added by plugins 1504 # we now do all post treatments added by plugins
1485 post_treat.callback(data) 1505 post_treat.callback(data)
1486 await post_treat 1506 await post_treat
1487 1507
1488 self.complete_attachments(data) 1508 self.complete_attachments(data)