1
0
Fork 0

feat: bridge XMPP mentions as proper whatsapp mentions

This has outgoing mentions of participant usernames in MUCs be correctly
represented as mentions in official WhatsApp clients.
This commit is contained in:
nicoco 2024-02-10 07:10:42 +01:00
parent c40c9747e4
commit 6727da086a
5 changed files with 47 additions and 17 deletions

View File

@ -148,6 +148,7 @@ type Message struct {
ReplyBody string // The full body of the message this message is in reply to, if any.
Attachments []Attachment // The list of file (image, video, etc.) attachments contained in this message.
Preview Preview // A short description for the URL provided in the message body, if any.
MentionJIDs []string // A list of JIDs mentioned in this message, if any.
}
// A Attachment represents additional binary data (e.g. images, videos, documents) provided alongside

View File

@ -3,6 +3,7 @@ from datetime import datetime, timezone
from typing import TYPE_CHECKING, Optional
from slidge.group import LegacyBookmarks, LegacyMUC, LegacyParticipant, MucType
from slidge.util.types import Mention
from slixmpp.exceptions import XMPPError
from .generated import whatsapp
@ -96,7 +97,7 @@ class MUC(LegacyMUC[str, str, Participant, str]):
participant.role = "moderator"
def replace_mentions(self, t: str):
return replace_mentions(
return replace_whatsapp_mentions(
t,
participants=(
{
@ -168,10 +169,19 @@ class Bookmarks(LegacyBookmarks[str, MUC]):
return whatsapp_group_id
def replace_mentions(t: str, participants: dict[str, str]):
def match(m: re.Match):
mat = m.group(0)
sub = participants.get(mat.replace("@", "+"), mat)
return sub
def replace_xmpp_mentions(text: str, mentions: list[Mention]):
offset: int = 0
result: str = ""
for m in mentions:
legacy_id = "@" + m.contact.legacy_id[: m.contact.legacy_id.find("@")]
result = result + text[offset : m.start] + legacy_id
offset = m.end
return result + text[offset:] if offset > 0 else text
return re.sub(r"@\d+", match, t)
def replace_whatsapp_mentions(text: str, participants: dict[str, str]):
def match(m: re.Match):
group = m.group(0)
return participants.get(group.replace("@", "+"), group)
return re.sub(r"@\d+", match, text)

View File

@ -303,6 +303,17 @@ func (s *Session) getMessagePayload(message Message) *proto.Message {
}
}
// Attach any inline mentions extended metadata.
if len(message.MentionJIDs) > 0 {
if payload == nil {
payload = &proto.Message{ExtendedTextMessage: &proto.ExtendedTextMessage{Text: &message.Body}}
}
if payload.ExtendedTextMessage.ContextInfo == nil {
payload.ExtendedTextMessage.ContextInfo = &proto.ContextInfo{}
}
payload.ExtendedTextMessage.ContextInfo.MentionedJid = message.MentionJIDs
}
if payload == nil {
payload = &proto.Message{Conversation: &message.Body}
}

View File

@ -17,6 +17,7 @@ from slidge.contact.roster import ContactIsUser
from slidge.util import is_valid_phone_number
from slidge.util.types import (
LegacyAttachment,
Mention,
MessageReference,
PseudoPresenceShow,
ResourceDict,
@ -26,7 +27,7 @@ from . import config
from .contact import Contact, Roster
from .gateway import Gateway
from .generated import go, whatsapp
from .group import MUC, Bookmarks
from .group import MUC, Bookmarks, replace_xmpp_mentions
from .util import get_bytes_temp
MESSAGE_PAIR_SUCCESS = (
@ -244,7 +245,7 @@ class Session(BaseSession[str, Recipient]):
reply_to_msg_id: Optional[str] = None,
reply_to_fallback_text: Optional[str] = None,
reply_to=None,
mentions=None,
mentions: Optional[list[Mention]] = None,
**_,
):
"""
@ -253,7 +254,11 @@ class Session(BaseSession[str, Recipient]):
message_id = self.whatsapp.GenerateMessageID()
message_preview = await self.__get_preview(text) or whatsapp.Preview()
message = whatsapp.Message(
ID=message_id, JID=chat.legacy_id, Body=text, Preview=message_preview
ID=message_id,
JID=chat.legacy_id,
Body=replace_xmpp_mentions(text, mentions) if mentions else text,
Preview=message_preview,
MentionJIDs=go.Slice_string([m.contact.legacy_id for m in mentions or []]),
)
set_reply_to(chat, message, reply_to_msg_id, reply_to_fallback_text, reply_to)
self.whatsapp.SendMessage(message)

View File

@ -1,26 +1,29 @@
from slidge_whatsapp.group import replace_mentions
from slidge_whatsapp.group import replace_whatsapp_mentions
def test_replace_mentions():
def test_replace_whatsapp_mentions():
text = "Hayo @1234, it's cool in here in with @5678!! @123333"
assert (
replace_mentions(
replace_whatsapp_mentions(
text,
{"+1234": "bibi", "+5678": "baba"},
)
== "Hayo bibi, it's cool in here in with baba!! @123333"
)
assert replace_mentions(text, {}) == text
assert replace_whatsapp_mentions(text, {}) == text
assert replace_mentions(text, {"+123333": "prout"}) == text.replace(
assert replace_whatsapp_mentions(text, {"+123333": "prout"}) == text.replace(
"@123333", "prout"
)
assert replace_mentions("+1234", {"+1234": "bibi", "+5678": "baba"}) == "+1234"
assert (
replace_whatsapp_mentions("+1234", {"+1234": "bibi", "+5678": "baba"})
== "+1234"
)
assert (
replace_mentions("@1234@1234@123", {"+1234": "bibi", "+5678": "baba"})
replace_whatsapp_mentions("@1234@1234@123", {"+1234": "bibi", "+5678": "baba"})
== "bibibibi@123"
)