diff --git a/mautrix_telegram/formatter/from_matrix.py b/mautrix_telegram/formatter/from_matrix.py index 768643a6..9ee7ead0 100644 --- a/mautrix_telegram/formatter/from_matrix.py +++ b/mautrix_telegram/formatter/from_matrix.py @@ -273,7 +273,6 @@ def matrix_to_telegram(html: str) -> Tuple[str, List[TypeMessageEntity]]: if should_bridge_plaintext_highlights: html = plain_mention_regex.sub(plain_mention_to_html, html) parser.feed(add_surrogates(html)) - print([str(e) for e in parser.entities]) return remove_surrogates(parser.text.strip()), parser.entities except Exception: log.exception("Failed to convert Matrix format:\nhtml=%s", html) diff --git a/mautrix_telegram/portal.py b/mautrix_telegram/portal.py index 778dc8ee..7286fcf9 100644 --- a/mautrix_telegram/portal.py +++ b/mautrix_telegram/portal.py @@ -516,12 +516,10 @@ class Portal: try: current_extension = body[body.rindex("."):] if mimetypes.types_map[current_extension] == mime: - file_name = body - else: - file_name = f"matrix_upload{mimetypes.guess_extension(mime)}" + return body except (ValueError, KeyError): - file_name = f"matrix_upload{mimetypes.guess_extension(mime)}" - return file_name, None if file_name == body else body + pass + return f"matrix_upload{mimetypes.guess_extension(mime)}" async def leave_matrix(self, user, source, event_id): if not user.logged_in: @@ -570,32 +568,53 @@ class Portal: @staticmethod def _preprocess_matrix_message(sender, message): - if message["msgtype"] == "m.emote": + msgtype = message["msgtype"] + if msgtype == "m.emote": if "formatted_body" in message: message["formatted_body"] = f"* {sender.displayname} {message['formatted_body']}" message["body"] = f"* {sender.displayname} {message['body']}" message["msgtype"] = "m.text" elif not sender.logged_in: - if "formatted_body" in message: - html = message["formatted_body"] - message["formatted_body"] = f"<{sender.displayname}> {html}" + html = message["formatted_body"] if "formatted_body" in message else None text = message["body"] - message["body"] = f"<{sender.displayname}> {text}" - return type + if msgtype == "m.text": + if html: + html = f"<{sender.displayname}> {html}" + text = f"<{sender.displayname}> {text}" + else: + msgtype = msgtype[len("m."):] + prefix = { + "file": "a ", + "image": "an ", + "audio": "", + "video": "a ", + "location": "a ", + }.get(msgtype, "") + if html: + html = f"{sender.displayname} sent {prefix}{msgtype}: {html}" + text = ": " + text if text else "" + text = f"{sender.displayname} sent {prefix}{msgtype}{text}" + if html: + message["formatted_body"] = html + message["body"] = text + + async def _matrix_event_to_entities(self, client, event): + try: + if event.get("format", None) == "org.matrix.custom.html": + message, entities = formatter.matrix_to_telegram(event["formatted_body"]) + + # TODO remove this crap + for entity in entities: + if isinstance(entity, InputMessageEntityMentionName): + entity.user_id = await client.get_input_entity(entity.user_id.user_id) + else: + message, entities = formatter.matrix_text_to_telegram(event["body"]) + except KeyError: + message, entities = None, None + return message, entities async def _handle_matrix_text(self, client, message, reply_to): - is_formatted = ("format" in message - and message["format"] == "org.matrix.custom.html" - and "formatted_body" in message) - if is_formatted: - message, entities = formatter.matrix_to_telegram(message["formatted_body"]) - - # TODO remove this crap - for entity in entities: - if isinstance(entity, InputMessageEntityMentionName): - entity.user_id = await client.get_input_entity(entity.user_id.user_id) - else: - message, entities = formatter.matrix_text_to_telegram(message["body"]) + message, entities = await self._matrix_event_to_entities(client, message) return await client.send_message(self.peer, message, entities=entities, reply_to=reply_to) async def _handle_matrix_file(self, client, message, reply_to): @@ -604,32 +623,52 @@ class Portal: info = message["info"] mime = info["mimetype"] - file_name, caption = self._get_file_meta(message["body"], mime) + file_name = self._get_file_meta(message["mxtg_filename"], mime) attributes = [DocumentAttributeFilename(file_name=file_name)] if "w" in info and "h" in info: attributes.append(DocumentAttributeImageSize(w=info["w"], h=info["h"])) + caption = message["body"] if message["body"] != file_name else None return await client.send_file(self.peer, file, mime, caption=caption, attributes=attributes, file_name=file_name, reply_to=reply_to) + async def _handle_matrix_location(self, client, message, reply_to): + try: + lat, long = message["geo_uri"][len("geo:"):].split(",") + lat, long = float(lat), float(long) + except (KeyError, ValueError): + self.log.exception("Failed to parse location") + return None + message, entities = await self._matrix_event_to_entities(client, message) + media = MessageMediaGeo(geo=GeoPoint(lat, long)) + return await client.send_media(self.peer, media, reply_to=reply_to, caption=message, + entities=entities) + async def handle_matrix_message(self, sender, message, event_id): client = sender.client if sender.logged_in else self.bot.client space = (self.tgid if self.peer_type == "channel" # Channels have their own ID space else (sender.tgid if sender.logged_in else self.bot.tgid)) reply_to = formatter.matrix_reply_to_telegram(message, space, room_id=self.mxid) + message["mxtg_filename"] = message["body"] self._preprocess_matrix_message(sender, message) type = message["msgtype"] if type == "m.text" or (self.bridge_notices and type == "m.notice"): response = await self._handle_matrix_text(client, message, reply_to) + elif type == "m.location": + response = await self._handle_matrix_location(client, message, reply_to) elif type in ("m.image", "m.file", "m.audio", "m.video"): response = await self._handle_matrix_file(client, message, reply_to) else: self.log.debug("Unhandled Matrix event: %s", message) + response = None + + if not response: return + self.log.debug("Handled Matrix message: %s", response) self.is_duplicate(response, (event_id, space)) self.db.add(DBMessage( diff --git a/mautrix_telegram/tgclient.py b/mautrix_telegram/tgclient.py index 86bbd711..1b7aea85 100644 --- a/mautrix_telegram/tgclient.py +++ b/mautrix_telegram/tgclient.py @@ -73,6 +73,11 @@ class MautrixTelegramClient(TelegramClient): reply_to_msg_id=reply_to) return self._get_response_message(request, await self(request)) + async def send_media(self, entity, media, caption=None, entities=None, reply_to=None): + request = SendMediaRequest(entity, media, message=caption or "", entities=entities or [], + reply_to_msg_id=reply_to) + return self._get_response_message(request, await self(request)) + async def download_file_bytes(self, location): if isinstance(location, Document): location = InputDocumentFileLocation(location.id, location.access_hash,