Add support for forwarding messages
This commit is contained in:
@@ -5,6 +5,9 @@
|
|||||||
* Added option to not bridge chats with lots of members.
|
* Added option to not bridge chats with lots of members.
|
||||||
* Added option to include captions in the same message as the media to
|
* Added option to include captions in the same message as the media to
|
||||||
implement [MSC2530].
|
implement [MSC2530].
|
||||||
|
* Added support for bridging forwarded messages as forwards on Telegram.
|
||||||
|
* If forwarding fails (e.g. due to it being blocked in the source chat), the
|
||||||
|
bridge will automatically fall back to sending it as a normal new message.
|
||||||
* Added options to make encryption more secure.
|
* Added options to make encryption more secure.
|
||||||
* The `encryption` -> `verification_levels` config options can be used to
|
* The `encryption` -> `verification_levels` config options can be used to
|
||||||
make the bridge require encrypted messages to come from cross-signed
|
make the bridge require encrypted messages to come from cross-signed
|
||||||
|
|||||||
@@ -1897,6 +1897,68 @@ class Portal(DBPortal, BasePortal):
|
|||||||
message_type=content.msgtype,
|
message_type=content.msgtype,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
async def _find_source_msg(
|
||||||
|
self, sender: u.User, content: MessageEventContent
|
||||||
|
) -> DBMessage | None:
|
||||||
|
try:
|
||||||
|
source = content["fi.mau.telegram.source"]
|
||||||
|
except KeyError:
|
||||||
|
return None
|
||||||
|
if not isinstance(source, dict):
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
msg_id = source["id"]
|
||||||
|
space = source["space"]
|
||||||
|
chat_id = source["chat_id"]
|
||||||
|
peer_type = source["peer_type"]
|
||||||
|
except KeyError:
|
||||||
|
return None
|
||||||
|
if (
|
||||||
|
not isinstance(msg_id, int)
|
||||||
|
or not isinstance(chat_id, int)
|
||||||
|
or not isinstance(space, int)
|
||||||
|
or not isinstance(peer_type, str)
|
||||||
|
):
|
||||||
|
return None
|
||||||
|
elif await sender.needs_relaybot(self):
|
||||||
|
return None
|
||||||
|
if peer_type == "user" and space != sender.tgid:
|
||||||
|
return
|
||||||
|
dbm = await DBMessage.get_one_by_tgid(TelegramID(msg_id), TelegramID(space))
|
||||||
|
if dbm and peer_type == "chat" and space != sender.tgid:
|
||||||
|
dbm = DBMessage.get_by_mxid(dbm.mxid, dbm.mx_room, sender.tgid)
|
||||||
|
return dbm
|
||||||
|
|
||||||
|
async def _handle_matrix_forward(
|
||||||
|
self,
|
||||||
|
sender: u.User,
|
||||||
|
msg: DBMessage,
|
||||||
|
event_id: EventID,
|
||||||
|
space: TelegramID,
|
||||||
|
msgtype: MessageType,
|
||||||
|
) -> bool:
|
||||||
|
source_portal = await Portal.get_by_mxid(msg.mx_room)
|
||||||
|
if not source_portal:
|
||||||
|
return False
|
||||||
|
async with self.send_lock(sender.tgid):
|
||||||
|
try:
|
||||||
|
response = await sender.client.forward_messages(
|
||||||
|
self.peer,
|
||||||
|
messages=[msg.tgid],
|
||||||
|
from_peer=source_portal.peer,
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
self.log.warning(
|
||||||
|
f"Failed to send {event_id} from {sender.mxid} as forward of {msg.tgid} "
|
||||||
|
f"from {source_portal.tgid}: {e}, falling back to normal message handling"
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
await self._mark_matrix_handled(
|
||||||
|
sender, EventType.ROOM_MESSAGE, event_id, space, 0, response[0], msgtype
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
|
||||||
async def _handle_matrix_message(
|
async def _handle_matrix_message(
|
||||||
self, sender: u.User, content: MessageEventContent, event_id: EventID
|
self, sender: u.User, content: MessageEventContent, event_id: EventID
|
||||||
) -> None:
|
) -> None:
|
||||||
@@ -1912,6 +1974,11 @@ class Portal(DBPortal, BasePortal):
|
|||||||
if self.peer_type == "channel" # Channels have their own ID space
|
if self.peer_type == "channel" # Channels have their own ID space
|
||||||
else (sender.tgid if logged_in else self.bot.tgid)
|
else (sender.tgid if logged_in else self.bot.tgid)
|
||||||
)
|
)
|
||||||
|
source_msg = await self._find_source_msg(sender, content)
|
||||||
|
if source_msg and await self._handle_matrix_forward(
|
||||||
|
sender, source_msg, event_id, space, content.msgtype
|
||||||
|
):
|
||||||
|
return
|
||||||
reply_to = await formatter.matrix_reply_to_telegram(content, space, room_id=self.mxid)
|
reply_to = await formatter.matrix_reply_to_telegram(content, space, room_id=self.mxid)
|
||||||
|
|
||||||
media = (
|
media = (
|
||||||
|
|||||||
@@ -159,7 +159,16 @@ class TelegramMessageConverter:
|
|||||||
return
|
return
|
||||||
if converted:
|
if converted:
|
||||||
converted.content.external_url = self._get_external_url(evt)
|
converted.content.external_url = self._get_external_url(evt)
|
||||||
|
converted.content["fi.mau.telegram.source"] = {
|
||||||
|
"space": self.portal.tgid if self.portal.peer_type == "channel" else source.tgid,
|
||||||
|
"chat_id": self.portal.tgid,
|
||||||
|
"peer_type": self.portal.peer_type,
|
||||||
|
"id": evt.id,
|
||||||
|
}
|
||||||
if converted.caption:
|
if converted.caption:
|
||||||
|
converted.caption["fi.mau.telegram.source"] = converted.content[
|
||||||
|
"fi.mau.telegram.source"
|
||||||
|
]
|
||||||
converted.caption.external_url = converted.content.external_url
|
converted.caption.external_url = converted.content.external_url
|
||||||
if self.portal.get_config("caption_in_message"):
|
if self.portal.get_config("caption_in_message"):
|
||||||
self._caption_to_message(converted)
|
self._caption_to_message(converted)
|
||||||
|
|||||||
Reference in New Issue
Block a user