diff --git a/mautrix_telegram/abstract_user.py b/mautrix_telegram/abstract_user.py
index 980473ba..053bc89f 100644
--- a/mautrix_telegram/abstract_user.py
+++ b/mautrix_telegram/abstract_user.py
@@ -31,7 +31,7 @@ from telethon.tl.types import (
UpdateEditChannelMessage, UpdateEditMessage, UpdateNewChannelMessage, UpdateReadHistoryOutbox,
UpdateShortChatMessage, UpdateShortMessage, UpdateUserName, UpdateUserPhoto, UpdateUserStatus,
UpdateUserTyping, User, UserStatusOffline, UserStatusOnline, UpdateReadHistoryInbox,
- UpdateReadChannelInbox)
+ UpdateReadChannelInbox, MessageEmpty)
from mautrix.types import UserID, PresenceState
from mautrix.errors import MatrixError
@@ -164,6 +164,7 @@ class AbstractUser(ABC):
request_retries=config["telegram.connection.request_retries"],
connection=connection,
proxy=proxy,
+ raise_last_call_error=True,
loop=self.loop,
base_logger=base_logger
@@ -387,12 +388,15 @@ class AbstractUser(ABC):
elif isinstance(update, (UpdateNewMessage, UpdateNewChannelMessage,
UpdateEditMessage, UpdateEditChannelMessage)):
update = update.message
+ if isinstance(update, MessageEmpty):
+ return update, None, None
if isinstance(update.to_id, PeerUser) and not update.out:
portal = po.Portal.get_by_tgid(update.from_id, peer_type="user",
tg_receiver=self.tgid)
else:
portal = po.Portal.get_by_entity(update.to_id, receiver_id=self.tgid)
- sender = pu.Puppet.get(update.from_id) if update.from_id else None
+ sender = (pu.Puppet.get(TelegramID(update.from_id.user_id))
+ if isinstance(update.from_id, PeerUser) else None)
else:
self.log.warning("Unexpected message type in User#get_message_details: "
f"{type(update)}")
diff --git a/mautrix_telegram/formatter/from_telegram.py b/mautrix_telegram/formatter/from_telegram.py
index bae332e7..16d2194b 100644
--- a/mautrix_telegram/formatter/from_telegram.py
+++ b/mautrix_telegram/formatter/from_telegram.py
@@ -22,7 +22,7 @@ from telethon.tl.types import (MessageEntityMention, MessageEntityMentionName, M
MessageEntityEmail, MessageEntityTextUrl, MessageEntityBold,
MessageEntityItalic, MessageEntityCode, MessageEntityPre,
MessageEntityBotCommand, MessageEntityHashtag, MessageEntityCashtag,
- MessageEntityPhone, TypeMessageEntity, PeerChannel,
+ MessageEntityPhone, TypeMessageEntity, PeerChannel, PeerChat,
MessageEntityBlockquote, MessageEntityStrike, MessageFwdHeader,
MessageEntityUnderline, PeerUser)
from telethon.tl.custom import Message
@@ -45,11 +45,11 @@ log: logging.Logger = logging.getLogger("mau.fmt.tg")
def telegram_reply_to_matrix(evt: Message, source: 'AbstractUser') -> Optional[RelatesTo]:
- if evt.reply_to_msg_id:
- space = (evt.to_id.channel_id
- if isinstance(evt, Message) and isinstance(evt.to_id, PeerChannel)
+ if evt.reply_to:
+ space = (evt.peer_id.channel_id
+ if isinstance(evt, Message) and isinstance(evt.peer_id, PeerChannel)
else source.tgid)
- msg = DBMessage.get_one_by_tgid(TelegramID(evt.reply_to_msg_id), space)
+ msg = DBMessage.get_one_by_tgid(TelegramID(evt.reply_to.reply_to_msg_id), space)
if msg:
return RelatesTo(rel_type=RelationType.REFERENCE, event_id=msg.mxid)
return None
@@ -61,15 +61,15 @@ async def _add_forward_header(source: 'AbstractUser', content: TextMessageEventC
content.format = Format.HTML
content.formatted_body = escape(content.body)
fwd_from_html, fwd_from_text = None, None
- if fwd_from.from_id:
- user = u.User.get_by_tgid(TelegramID(fwd_from.from_id))
+ if isinstance(fwd_from.from_id, PeerUser):
+ user = u.User.get_by_tgid(TelegramID(fwd_from.from_id.user_id))
if user:
fwd_from_text = user.displayname or user.mxid
fwd_from_html = (f""
f"{escape(fwd_from_text)}")
if not fwd_from_text:
- puppet = pu.Puppet.get(TelegramID(fwd_from.from_id), create=False)
+ puppet = pu.Puppet.get(TelegramID(fwd_from.from_id.user_id), create=False)
if puppet and puppet.displayname:
fwd_from_text = puppet.displayname or puppet.mxid
fwd_from_html = (f""
@@ -77,14 +77,16 @@ async def _add_forward_header(source: 'AbstractUser', content: TextMessageEventC
if not fwd_from_text:
try:
- user = await source.client.get_entity(PeerUser(fwd_from.from_id))
+ user = await source.client.get_entity(fwd_from.from_id)
if user:
fwd_from_text = pu.Puppet.get_displayname(user, False)
fwd_from_html = f"{escape(fwd_from_text)}"
except (ValueError, RPCError):
fwd_from_text = fwd_from_html = "unknown user"
- elif fwd_from.channel_id:
- portal = po.Portal.get_by_tgid(TelegramID(fwd_from.channel_id))
+ elif isinstance(fwd_from.from_id, (PeerChannel, PeerChat)):
+ from_id = (fwd_from.from_id.chat_id if isinstance(fwd_from.from_id, PeerChat)
+ else fwd_from.from_id.channel_id)
+ portal = po.Portal.get_by_tgid(TelegramID(from_id))
if portal:
fwd_from_text = portal.title
if portal.alias:
@@ -94,7 +96,7 @@ async def _add_forward_header(source: 'AbstractUser', content: TextMessageEventC
fwd_from_html = f"channel {escape(fwd_from_text)}"
else:
try:
- channel = await source.client.get_entity(PeerChannel(fwd_from.channel_id))
+ channel = await source.client.get_entity(fwd_from.from_id)
if channel:
fwd_from_text = f"channel {channel.title}"
fwd_from_html = f"channel {escape(channel.title)}"
@@ -116,11 +118,11 @@ async def _add_forward_header(source: 'AbstractUser', content: TextMessageEventC
async def _add_reply_header(source: 'AbstractUser', content: TextMessageEventContent, evt: Message,
main_intent: IntentAPI):
- space = (evt.to_id.channel_id
- if isinstance(evt, Message) and isinstance(evt.to_id, PeerChannel)
+ space = (evt.peer_id.channel_id
+ if isinstance(evt, Message) and isinstance(evt.peer_id, PeerChannel)
else source.tgid)
- msg = DBMessage.get_one_by_tgid(TelegramID(evt.reply_to_msg_id), space)
+ msg = DBMessage.get_one_by_tgid(TelegramID(evt.reply_to.reply_to_msg_id), space)
if not msg:
return
@@ -162,7 +164,7 @@ async def telegram_to_matrix(evt: Message, source: "AbstractUser",
if evt.fwd_from:
await _add_forward_header(source, content, evt.fwd_from)
- if evt.reply_to_msg_id and not no_reply_fallback:
+ if evt.reply_to and not no_reply_fallback:
await _add_reply_header(source, content, evt, main_intent)
if isinstance(evt, Message) and evt.post and evt.post_author:
diff --git a/mautrix_telegram/portal/matrix.py b/mautrix_telegram/portal/matrix.py
index 1a26b659..97c2cb76 100644
--- a/mautrix_telegram/portal/matrix.py
+++ b/mautrix_telegram/portal/matrix.py
@@ -87,9 +87,9 @@ class PortalMatrix(BasePortal, ABC):
message = await self._get_state_change_message(event, user, **kwargs)
if not message:
return
- response = await self.bot.client.send_message(
- self.peer, message,
- parse_mode=self._matrix_event_to_entities)
+ message, entities = formatter.matrix_to_telegram(message)
+ response = await self.bot.client.send_message(self.peer, message,
+ formatting_entities=entities)
space = self.tgid if self.peer_type == "channel" else self.bot.tgid
self.dedup.check(response, (event_id, space))
@@ -231,18 +231,22 @@ class PortalMatrix(BasePortal, ABC):
async def _handle_matrix_text(self, sender_id: TelegramID, event_id: EventID,
space: TelegramID, client: 'MautrixTelegramClient',
content: TextMessageEventContent, reply_to: TelegramID) -> None:
+ if content.formatted_body and content.format == Format.HTML:
+ message, entities = formatter.matrix_to_telegram(content.formatted_body)
+ else:
+ message, entities = formatter.matrix_text_to_telegram(content.body)
async with self.send_lock(sender_id):
lp = self.get_config("telegram_link_preview")
if content.get_edit():
orig_msg = DBMessage.get_by_mxid(content.get_edit(), self.mxid, space)
if orig_msg:
- response = await client.edit_message(self.peer, orig_msg.tgid, content,
- parse_mode=self._matrix_event_to_entities,
+ response = await client.edit_message(self.peer, orig_msg.tgid, message,
+ formatting_entities=entities,
link_preview=lp)
self._add_telegram_message_to_db(event_id, space, -1, response)
return
- response = await client.send_message(self.peer, content, reply_to=reply_to,
- parse_mode=self._matrix_event_to_entities,
+ response = await client.send_message(self.peer, message, reply_to=reply_to,
+ formatting_entities=entities,
link_preview=lp)
self._add_telegram_message_to_db(event_id, space, 0, response)
await self._send_delivery_receipt(event_id)
@@ -297,7 +301,13 @@ class PortalMatrix(BasePortal, ABC):
media = InputMediaUploadedDocument(file=file_handle, attributes=attributes,
mime_type=mime or "application/octet-stream")
- caption, entities = self._matrix_event_to_entities(caption) if caption else (None, None)
+ if caption:
+ if caption.formatted_body and caption.format == Format.HTML:
+ caption, entities = formatter.matrix_to_telegram(caption.formatted_body)
+ else:
+ caption, entities = formatter.matrix_text_to_telegram(content.body)
+ else:
+ caption, entities = None, None
async with self.send_lock(sender_id):
if await self._matrix_document_edit(client, content, space, caption, media, event_id):
@@ -336,7 +346,7 @@ class PortalMatrix(BasePortal, ABC):
except (KeyError, ValueError):
self.log.exception("Failed to parse location")
return None
- caption, entities = self._matrix_event_to_entities(content)
+ caption, entities = formatter.matrix_text_to_telegram(content.body)
media = MessageMediaGeo(geo=GeoPoint(lat, long, access_hash=0))
async with self.send_lock(sender_id):
@@ -372,7 +382,8 @@ class PortalMatrix(BasePortal, ABC):
await self._handle_matrix_message(sender, content, event_id)
except RPCError as e:
if config["bridge.delivery_error_reports"]:
- await self._send_bridge_error(f"\u26a0 Your message may not have been bridged: {e}")
+ await self._send_bridge_error(
+ f"\u26a0 Your message may not have been bridged: {e}")
raise
async def _handle_matrix_message(self, sender: 'u.User', content: MessageEventContent,
@@ -586,6 +597,7 @@ class PortalMatrix(BasePortal, ABC):
self.log.warning(f"Failed to set room name", exc_info=True)
return ok
+
def init(context: Context) -> None:
global config
config = context.config
diff --git a/mautrix_telegram/portal/metadata.py b/mautrix_telegram/portal/metadata.py
index 197baf87..ed240309 100644
--- a/mautrix_telegram/portal/metadata.py
+++ b/mautrix_telegram/portal/metadata.py
@@ -29,7 +29,7 @@ from telethon.tl.types import (
ChatParticipantCreator, ChannelParticipantCreator, UserProfilePhoto, UserProfilePhotoEmpty)
from mautrix.errors import MForbidden
-from mautrix.types import (RoomID, UserID, RoomCreatePreset, EventType, Membership, Member,
+from mautrix.types import (RoomID, UserID, RoomCreatePreset, EventType, Membership,
PowerLevelStateEventContent, RoomTopicStateEventContent,
RoomNameStateEventContent, RoomAvatarStateEventContent,
StateEventContent, EventID)
diff --git a/mautrix_telegram/portal/telegram.py b/mautrix_telegram/portal/telegram.py
index 17ae91d5..a504878c 100644
--- a/mautrix_telegram/portal/telegram.py
+++ b/mautrix_telegram/portal/telegram.py
@@ -99,8 +99,7 @@ class PortalTelegram(BasePortal, ABC):
encrypt=self.encrypted)
if not file:
return None
- if self.get_config("inline_images") and (evt.message
- or evt.fwd_from or evt.reply_to_msg_id):
+ if self.get_config("inline_images") and (evt.message or evt.fwd_from or evt.reply_to):
content = await formatter.telegram_to_matrix(
evt, source, self.main_intent,
prefix_html=f"
",
@@ -439,12 +438,12 @@ class PortalTelegram(BasePortal, ABC):
"max_file_size": min(config["bridge.max_document_size"], 2000) * 1024 * 1024
}
- async def backfill(self, source: 'AbstractUser', is_initial: bool = False,
+ async def backfill(self, source: 'u.User', is_initial: bool = False,
limit: Optional[int] = None, last_id: Optional[int] = None) -> None:
async with self.backfill_method_lock:
await self._locked_backfill(source, is_initial, limit, last_id)
- async def _locked_backfill(self, source: 'AbstractUser', is_initial: bool = False,
+ async def _locked_backfill(self, source: 'u.User', is_initial: bool = False,
limit: Optional[int] = None, last_id: Optional[int] = None) -> None:
limit = limit or (config["bridge.backfill.initial_limit"] if is_initial
else config["bridge.backfill.missed_limit"])
@@ -481,7 +480,7 @@ class PortalTelegram(BasePortal, ABC):
with self.backfill_lock:
await self._backfill(source, min_id, limit)
- async def _backfill(self, source: 'AbstractUser', min_id: Optional[int], limit: int) -> None:
+ async def _backfill(self, source: 'u.User', min_id: Optional[int], limit: int) -> None:
self.backfill_leave = set()
if ((self.peer_type == "user" and self.tgid != source.tgid
and config["bridge.backfill.invite_own_puppet"])):
@@ -514,7 +513,8 @@ class PortalTelegram(BasePortal, ABC):
self.log.debug(f"Iterating all messages starting with {min_id} (approx: {limit})")
messages = client.iter_messages(entity, reverse=True, min_id=min_id)
async for message in messages:
- sender = p.Puppet.get(message.from_id) if message.from_id else None
+ sender = (p.Puppet.get(message.from_id.user_id)
+ if isinstance(message.from_id, PeerUser) else None)
# TODO handle service messages?
await self.handle_telegram_message(source, sender, message)
count += 1
@@ -522,7 +522,8 @@ class PortalTelegram(BasePortal, ABC):
self.log.debug(f"Fetching up to {limit} most recent messages")
messages = await client.get_messages(entity, limit=limit)
for message in reversed(messages):
- sender = p.Puppet.get(message.from_id) if message.from_id else None
+ sender = (p.Puppet.get(TelegramID(message.from_id.user_id))
+ if isinstance(message.from_id, PeerUser) else None)
await self.handle_telegram_message(source, sender, message)
count += 1
return count
@@ -533,7 +534,7 @@ class PortalTelegram(BasePortal, ABC):
self.log.trace("Got telegram message %d, but no room exists, creating...", evt.id)
await self.create_matrix_room(source, invites=[source.mxid], update_if_exists=False)
- if (self.peer_type == "user" and sender.tgid == self.tg_receiver
+ if (self.peer_type == "user" and sender and sender.tgid == self.tg_receiver
and not sender.is_real_user and not await self.az.state_store.is_joined(self.mxid,
sender.mxid)):
self.log.debug(f"Ignoring private chat message {evt.id}@{source.tgid} as receiver does"
diff --git a/requirements.txt b/requirements.txt
index a8089eac..83720268 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -5,6 +5,6 @@ python-magic>=0.4,<0.5
commonmark>=0.8,<0.10
aiohttp>=3,<3.7
yarl<1.6
-mautrix==0.8.0.beta7
-telethon>=1.16,<1.17
+mautrix==0.8.0.beta9
+telethon>=1.17,<1.18
telethon-session-sqlalchemy>=0.2.14,<0.3