From 779d58d5ffff09ffd655e448411ef012a3870996 Mon Sep 17 00:00:00 2001 From: Goffi Date: Sun, 3 May 2026 16:46:15 +0200 Subject: [PATCH] core (xmpp/messages): only send "origin" request for printable messages: "Origin" request are disco requests to know if a message sender is a bot or coming from a gateway. It was sending request on every message, including pubsub/PEP events, resulting in requests done to many entities, including ones not cacheables (bare entities or third party servers, without caps mechanisms). To avoid that, the requests is now done only for printable messages. To use `client.is_message_printable` correctly, origin check has be moved to the end, after `message_parse` trigger, so attachments are added to data. --- libervia/backend/core/xmpp.py | 75 ++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 33 deletions(-) diff --git a/libervia/backend/core/xmpp.py b/libervia/backend/core/xmpp.py index e1b0e6e2..30dee0e2 100644 --- a/libervia/backend/core/xmpp.py +++ b/libervia/backend/core/xmpp.py @@ -1647,39 +1647,6 @@ class SatMessageProtocol(xmppim.MessageProtocol): if getattr(message_elt, "_is_from_archive", False): extra["is_from_archive"] = True - # origin - if not from_jid_bare in (client.jid.userhostJID(), client.server_jid): - try: - # For bare JIDs, query the server instead: bare jids are not cached by - # XEP-0115, so we'll have an actual disco request each time. On the other - # hand, server disco is cached after first request, and should gives us - # the gateway/origin info we need. - # FIXME: Check if this cause trouble in practice. - query_jid = from_jid if from_jid.resource else jid.JID(from_jid.host) - disco_infos = await G.host.memory.disco.get_infos(client, query_jid) - if from_jid_bare.user: - domain_disco_infos = await G.host.memory.disco.get_infos( - client, jid.JID(from_jid_bare.host) - ) - else: - domain_disco_infos = disco_infos - if ("client", "bot") in disco_infos.identities: - extra["is-bot"] = True - for ( - category, - type_, - ), identities_map in domain_disco_infos.identities.items(): - for lang, identity in identities_map.items(): - if category == "gateway": - extra["origin"] = identity.type - if identity.name: - extra["origin_name"] = identity.name - except exceptions.ExternalRequestError: - log.warning( - f"Disco query failed for {from_jid.full()}, skipping identity " - "detection" - ) - # message for e in message_elt.elements(C.NS_CLIENT, "body"): message[e.getAttribute((C.NS_XML, "lang"), "")] = str(e) @@ -1721,6 +1688,48 @@ class SatMessageProtocol(xmppim.MessageProtocol): data["delay_sender"] = parsed_delay.sender.full() G.host.trigger.point("message_parse", client, message_elt, data) + + # origin + + # We set it after "message_parse" trigger, so attachments are added by plugins + # (needed for "is_message_printable") + if ( + from_jid_bare not in (client.jid.userhostJID(), client.server_jid) + # We only want messages with printable contents to avoid making requests for + # nothing to entities (which may not be in cache or cacheable) + and client.is_message_printable(data) + ): + try: + # For bare JIDs, query the server instead: bare jids are not cached by + # XEP-0115, so we'll have an actual disco request each time. On the other + # hand, server disco is cached after first request, and should gives us + # the gateway/origin info we need. + # FIXME: Check if this cause trouble in practice. + query_jid = from_jid if from_jid.resource else jid.JID(from_jid.host) + disco_infos = await G.host.memory.disco.get_infos(client, query_jid) + if from_jid_bare.user: + domain_disco_infos = await G.host.memory.disco.get_infos( + client, jid.JID(from_jid_bare.host) + ) + else: + domain_disco_infos = disco_infos + if ("client", "bot") in disco_infos.identities: + extra["is-bot"] = True + for ( + category, + type_, + ), identities_map in domain_disco_infos.identities.items(): + for lang, identity in identities_map.items(): + if category == "gateway": + extra["origin"] = identity.type + if identity.name: + extra["origin_name"] = identity.name + except exceptions.ExternalRequestError: + log.warning( + f"Disco query failed for {from_jid.full()}, skipping identity " + "detection" + ) + return data def onMessage(self, message: domish.Element) -> None: