From 7d2d97fa754d68b5d72f10281047700c6d7e661f Mon Sep 17 00:00:00 2001 From: Goffi Date: Fri, 26 Jun 2026 23:03:24 +0200 Subject: [PATCH] plugin XEP-0045: Notification on mention: If a mention is detected in a MUC (`groupchat`, not DM), a notification is sent. --- libervia/backend/memory/memory.py | 8 +++ libervia/backend/plugins/plugin_xep_0045.py | 58 ++++++++++++++++++--- 2 files changed, 59 insertions(+), 7 deletions(-) diff --git a/libervia/backend/memory/memory.py b/libervia/backend/memory/memory.py index 259aca92..078d7166 100644 --- a/libervia/backend/memory/memory.py +++ b/libervia/backend/memory/memory.py @@ -2218,6 +2218,14 @@ class Memory: data_format.serialise(extra) if extra else "", C.PROF_KEY_ALL if is_global else client.profile, ) + log.debug( + f"Notification sent:\n" + f" title: {title!r}\n" + f" body_plain: {body_plain!r}\n" + f" type: {type_.value}\n" + f" priority: {priority.value}\n" + f" profile: {C.PROF_KEY_ALL if is_global else client.profile}" + ) def _get_notifications(self, filters_s: str, profile_key: str) -> defer.Deferred: """Fetch notifications for bridge with given filters and profile key. diff --git a/libervia/backend/plugins/plugin_xep_0045.py b/libervia/backend/plugins/plugin_xep_0045.py index 2b423e0a..3c20706a 100644 --- a/libervia/backend/plugins/plugin_xep_0045.py +++ b/libervia/backend/plugins/plugin_xep_0045.py @@ -17,24 +17,23 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . +from collections.abc import Sequence from dataclasses import dataclass import difflib from enum import StrEnum +import re import time from typing import TYPE_CHECKING, cast -from collections.abc import Sequence - -from twisted.python.failure import Failure import uuid -from zope.interface import implementer -from pydantic import Field +from pydantic import BaseModel, Field import shortuuid from twisted.internet import defer from twisted.python import failure from twisted.words.protocols.jabber import jid from twisted.words.protocols.jabber.error import StanzaError from tx_xmpp import disco, itx_xmpp, mam, muc, rsm +from zope.interface import implementer from libervia.backend import G from libervia.backend.core import exceptions @@ -43,6 +42,9 @@ from libervia.backend.core.core_types import SatXMPPEntity from libervia.backend.core.i18n import D_, _ from libervia.backend.core.log import getLogger from libervia.backend.memory import memory +from libervia.backend.memory.sqla_mapping import NotificationType +from libervia.backend.models.core import MessageData +from libervia.backend.models.types import JIDType from libervia.backend.plugins import plugin_misc_jid_search from libervia.backend.plugins.plugin_xep_0313 import XEP_0313 from libervia.backend.plugins.plugin_xep_0359 import XEP_0359 @@ -105,6 +107,15 @@ class OccupantInfo: role: str +class NotificationExtraMention(BaseModel): + """Extra data for a MUC mention notification.""" + + message_uid: str + from_jid: JIDType + to_jid: JIDType + room_jid: JIDType + + class PluginsMucSettings(PluginSettings, plugin_info=PLUGIN_INFO): default_muc: str = Field(default="libervia@chat.jabberfr.org") @@ -279,13 +290,46 @@ class XEP_0045: ).muc_client.joined_rooms ): log.warning( - "Received groupchat message for unjoined room, ignoring: %s", - message_elt.toXml(), + "Received groupchat message for unjoined room, ignoring: " + f"{message_elt.toXml()}" ) return False + post_treat.addCallback( + lambda data: defer.ensureDeferred(self._check_mention(data, client, room_jid)) + ) return True + async def _check_mention( + self, data: MessageData, client: SatXMPPEntity, room_jid: jid.JID + ) -> MessageData: + from_jid = data["from"] + room = self.get_room(client, room_jid) + if from_jid == room.occupantJID: + return data + + body = data["message"].get("") or next(iter(data["message"].values()), "") + if not body: + return data + + if not re.search(rf"(?