From 22f6a1284251e1726b7629bb8d141bb7d5529cff Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Sat, 26 Oct 2019 19:27:03 +0300 Subject: [PATCH] Add command to set caption for telegram files --- mautrix_telegram/commands/telegram/misc.py | 31 +++++++++++++++----- mautrix_telegram/portal/matrix.py | 34 +++++++++------------- 2 files changed, 36 insertions(+), 29 deletions(-) diff --git a/mautrix_telegram/commands/telegram/misc.py b/mautrix_telegram/commands/telegram/misc.py index 60b12181..f6066ad3 100644 --- a/mautrix_telegram/commands/telegram/misc.py +++ b/mautrix_telegram/commands/telegram/misc.py @@ -13,7 +13,7 @@ # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -from typing import List, Optional, Tuple +from typing import List, Optional, Tuple, cast import logging import codecs import base64 @@ -23,7 +23,7 @@ from telethon.errors import (InviteHashInvalidError, InviteHashExpiredError, Opt UserAlreadyParticipantError, ChatIdInvalidError) from telethon.tl.patched import Message from telethon.tl.types import (User as TLUser, TypeUpdates, MessageMediaGame, MessageMediaPoll, - TypePeer) + TypeInputPeer) from telethon.tl.types.messages import BotCallbackAnswer from telethon.tl.functions.messages import (ImportChatInviteRequest, CheckChatInviteRequest, GetBotCallbackAnswerRequest, SendVoteRequest) @@ -38,6 +38,21 @@ from ...types import TelegramID from ...commands import command_handler, CommandEvent, SECTION_MISC, SECTION_CREATING_PORTALS +@command_handler(needs_auth=False, + help_section=SECTION_MISC, help_args="<_caption_>", + help_text="Set a caption for the next image you send") +async def caption(evt: CommandEvent) -> EventID: + if len(evt.args) == 0: + return await evt.reply("**Usage:** `$cmdprefix+sp caption `") + + text = " ".join(evt.args) + evt.sender.command_status = {"caption": text} + quoted_text = "\n".join(f"> {row}" for row in text.split("\n")) + return await evt.reply("Your next image will be captioned with\n\n" + f"{quoted_text}\n\n" + "Use `$cmdprefix+sp cancel` to cancel the caption.") + + @command_handler(help_section=SECTION_MISC, help_args="[_-r|--remote_] <_query_>", help_text="Search your contacts or the Telegram servers for users.") @@ -76,8 +91,7 @@ async def search(evt: CommandEvent) -> EventID: return await evt.reply("\n".join(reply)) -@command_handler(help_section=SECTION_CREATING_PORTALS, - help_args="<_identifier_>", +@command_handler(help_section=SECTION_CREATING_PORTALS, help_args="<_identifier_>", help_text="Open a private chat with the given Telegram user. The identifier is " "either the internal user ID, the username or the phone number. " "**N.B.** The phone numbers you start chats with must already be in " @@ -183,7 +197,7 @@ class MessageIDError(ValueError): async def _parse_encoded_msgid(user: AbstractUser, enc_id: str, type_name: str - ) -> Tuple[TypePeer, Message]: + ) -> Tuple[TypeInputPeer, Message]: try: enc_id += (4 - len(enc_id) % 4) * "=" enc_id = base64.b64decode(enc_id) @@ -212,7 +226,7 @@ async def _parse_encoded_msgid(user: AbstractUser, enc_id: str, type_name: str msg = await user.client.get_messages(entity=peer, ids=msg_id) if not msg: raise MessageIDError(f"Invalid {type_name} ID (message not found)") - return peer, msg + return peer, cast(Message, msg) @command_handler(help_section=SECTION_MISC, @@ -234,12 +248,13 @@ async def play(evt: CommandEvent) -> EventID: if not isinstance(msg.media, MessageMediaGame): return await evt.reply("Invalid play ID (message doesn't look like a game)") - game = await evt.sender.client(GetBotCallbackAnswerRequest(peer=peer, msg_id=msg.id, game=True)) + game = await evt.sender.client( + GetBotCallbackAnswerRequest(peer=peer, msg_id=msg.id, game=True)) if not isinstance(game, BotCallbackAnswer): return await evt.reply("Game request response invalid") return await evt.reply(f"Click [here]({game.url}) to play {msg.media.game.title}:\n\n" - f"{msg.media.game.description}") + f"{msg.media.game.description}") @command_handler(help_section=SECTION_MISC, diff --git a/mautrix_telegram/portal/matrix.py b/mautrix_telegram/portal/matrix.py index 32730da3..a7479472 100644 --- a/mautrix_telegram/portal/matrix.py +++ b/mautrix_telegram/portal/matrix.py @@ -57,19 +57,6 @@ config: Optional['Config'] = None class PortalMatrix(BasePortal, MautrixBasePortal, ABC): - @staticmethod - def _get_file_meta(body: str, mime: str) -> str: - try: - current_extension = body[body.rindex("."):].lower() - body = body[:body.rindex(".")] - if mimetypes.types_map[current_extension] == mime: - return body + current_extension - except (ValueError, KeyError): - pass - if mime: - return f"matrix_upload{sane_mimetypes.guess_extension(mime)}" - return "" - async def _get_state_change_message(self, event: str, user: 'u.User', **kwargs: Any ) -> Optional[str]: tpl = self.get_config(f"state_event_formats.{event}") @@ -266,23 +253,21 @@ class PortalMatrix(BasePortal, MautrixBasePortal, ABC): file = await self.main_intent.download_media(content.url) mime = content.info.mimetype - w, h = content.info.width, content.info.height + file_name = content["net.maunium.telegram.internal.filename"] if content.msgtype == MessageType.STICKER: if mime != "image/gif": mime, file, w, h = util.convert_image(file, source_mime=mime, target_type="webp") else: # Remove sticker description - content["net.maunium.telegram.internal.filename"] = "sticker.gif" - content.body = "" + file_name = "sticker.gif" - file_name = self._get_file_meta(content["net.maunium.telegram.internal.filename"], mime) attributes = [DocumentAttributeFilename(file_name=file_name)] if w and h: attributes.append(DocumentAttributeImageSize(w, h)) - caption = content.body if content.body.lower() != file_name.lower() else None + caption = content.body if content.body != file_name else None media = await client.upload_file_direct( file, mime, attributes, file_name, @@ -364,7 +349,15 @@ class PortalMatrix(BasePortal, MautrixBasePortal, ABC): else (sender.tgid if logged_in else self.bot.tgid)) reply_to = formatter.matrix_reply_to_telegram(content, space, room_id=self.mxid) - content["net.maunium.telegram.internal.filename"] = content.body + media = (MessageType.STICKER, MessageType.IMAGE, MessageType.FILE, MessageType.AUDIO, + MessageType.VIDEO) + if content.msgtype in media: + content["net.maunium.telegram.internal.filename"] = content.body + try: + content.body = sender.command_status["caption"] + sender.command_status = None + except (KeyError, TypeError): + pass await self._pre_process_matrix_message(sender, not logged_in, content) if content.msgtype == MessageType.NOTICE: @@ -378,8 +371,7 @@ class PortalMatrix(BasePortal, MautrixBasePortal, ABC): elif content.msgtype == MessageType.LOCATION: await self._handle_matrix_location(sender_id, event_id, space, client, content, reply_to) - elif content.msgtype in (MessageType.STICKER, MessageType.IMAGE, MessageType.FILE, - MessageType.AUDIO, MessageType.VIDEO): + elif content.msgtype in media: await self._handle_matrix_file(sender_id, event_id, space, client, content, reply_to) else: self.log.debug(f"Unhandled Matrix event: {content}")