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:
parent
c40c9747e4
commit
6727da086a
|
@ -148,6 +148,7 @@ type Message struct {
|
||||||
ReplyBody string // The full body of the message this message is in reply to, if any.
|
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.
|
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.
|
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
|
// A Attachment represents additional binary data (e.g. images, videos, documents) provided alongside
|
||||||
|
|
|
@ -3,6 +3,7 @@ from datetime import datetime, timezone
|
||||||
from typing import TYPE_CHECKING, Optional
|
from typing import TYPE_CHECKING, Optional
|
||||||
|
|
||||||
from slidge.group import LegacyBookmarks, LegacyMUC, LegacyParticipant, MucType
|
from slidge.group import LegacyBookmarks, LegacyMUC, LegacyParticipant, MucType
|
||||||
|
from slidge.util.types import Mention
|
||||||
from slixmpp.exceptions import XMPPError
|
from slixmpp.exceptions import XMPPError
|
||||||
|
|
||||||
from .generated import whatsapp
|
from .generated import whatsapp
|
||||||
|
@ -96,7 +97,7 @@ class MUC(LegacyMUC[str, str, Participant, str]):
|
||||||
participant.role = "moderator"
|
participant.role = "moderator"
|
||||||
|
|
||||||
def replace_mentions(self, t: str):
|
def replace_mentions(self, t: str):
|
||||||
return replace_mentions(
|
return replace_whatsapp_mentions(
|
||||||
t,
|
t,
|
||||||
participants=(
|
participants=(
|
||||||
{
|
{
|
||||||
|
@ -168,10 +169,19 @@ class Bookmarks(LegacyBookmarks[str, MUC]):
|
||||||
return whatsapp_group_id
|
return whatsapp_group_id
|
||||||
|
|
||||||
|
|
||||||
def replace_mentions(t: str, participants: dict[str, str]):
|
def replace_xmpp_mentions(text: str, mentions: list[Mention]):
|
||||||
def match(m: re.Match):
|
offset: int = 0
|
||||||
mat = m.group(0)
|
result: str = ""
|
||||||
sub = participants.get(mat.replace("@", "+"), mat)
|
for m in mentions:
|
||||||
return sub
|
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)
|
||||||
|
|
|
@ -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 {
|
if payload == nil {
|
||||||
payload = &proto.Message{Conversation: &message.Body}
|
payload = &proto.Message{Conversation: &message.Body}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ from slidge.contact.roster import ContactIsUser
|
||||||
from slidge.util import is_valid_phone_number
|
from slidge.util import is_valid_phone_number
|
||||||
from slidge.util.types import (
|
from slidge.util.types import (
|
||||||
LegacyAttachment,
|
LegacyAttachment,
|
||||||
|
Mention,
|
||||||
MessageReference,
|
MessageReference,
|
||||||
PseudoPresenceShow,
|
PseudoPresenceShow,
|
||||||
ResourceDict,
|
ResourceDict,
|
||||||
|
@ -26,7 +27,7 @@ from . import config
|
||||||
from .contact import Contact, Roster
|
from .contact import Contact, Roster
|
||||||
from .gateway import Gateway
|
from .gateway import Gateway
|
||||||
from .generated import go, whatsapp
|
from .generated import go, whatsapp
|
||||||
from .group import MUC, Bookmarks
|
from .group import MUC, Bookmarks, replace_xmpp_mentions
|
||||||
from .util import get_bytes_temp
|
from .util import get_bytes_temp
|
||||||
|
|
||||||
MESSAGE_PAIR_SUCCESS = (
|
MESSAGE_PAIR_SUCCESS = (
|
||||||
|
@ -244,7 +245,7 @@ class Session(BaseSession[str, Recipient]):
|
||||||
reply_to_msg_id: Optional[str] = None,
|
reply_to_msg_id: Optional[str] = None,
|
||||||
reply_to_fallback_text: Optional[str] = None,
|
reply_to_fallback_text: Optional[str] = None,
|
||||||
reply_to=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_id = self.whatsapp.GenerateMessageID()
|
||||||
message_preview = await self.__get_preview(text) or whatsapp.Preview()
|
message_preview = await self.__get_preview(text) or whatsapp.Preview()
|
||||||
message = whatsapp.Message(
|
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)
|
set_reply_to(chat, message, reply_to_msg_id, reply_to_fallback_text, reply_to)
|
||||||
self.whatsapp.SendMessage(message)
|
self.whatsapp.SendMessage(message)
|
||||||
|
|
|
@ -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"
|
text = "Hayo @1234, it's cool in here in with @5678!! @123333"
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
replace_mentions(
|
replace_whatsapp_mentions(
|
||||||
text,
|
text,
|
||||||
{"+1234": "bibi", "+5678": "baba"},
|
{"+1234": "bibi", "+5678": "baba"},
|
||||||
)
|
)
|
||||||
== "Hayo bibi, it's cool in here in with baba!! @123333"
|
== "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"
|
"@123333", "prout"
|
||||||
)
|
)
|
||||||
|
|
||||||
assert replace_mentions("+1234", {"+1234": "bibi", "+5678": "baba"}) == "+1234"
|
assert (
|
||||||
|
replace_whatsapp_mentions("+1234", {"+1234": "bibi", "+5678": "baba"})
|
||||||
|
== "+1234"
|
||||||
|
)
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
replace_mentions("@1234@1234@123", {"+1234": "bibi", "+5678": "baba"})
|
replace_whatsapp_mentions("@1234@1234@123", {"+1234": "bibi", "+5678": "baba"})
|
||||||
== "bibibibi@123"
|
== "bibibibi@123"
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue