Add support for formatted captions
This commit is contained in:
+12
-13
@@ -196,20 +196,19 @@ bridge:
|
||||
# Text msgtypes (m.text, m.notice and m.emote) support HTML, media msgtypes don't.
|
||||
#
|
||||
# Available variables:
|
||||
# $sender_displayname - The display name of the sender (e.g. Example User)
|
||||
# $sender_username - The username (Matrix ID localpart) of the sender (e.g. exampleuser)
|
||||
# $sender_mxid - The Matrix ID of the sender (e.g. @exampleuser:example.com)
|
||||
# $body - The plaintext body (file name for media msgtypes)
|
||||
# $formatted_body - The message content as HTML (for text msgtypes)
|
||||
# $sender_displayname - The display name of the sender (e.g. Example User)
|
||||
# $sender_username - The username (Matrix ID localpart) of the sender (e.g. exampleuser)
|
||||
# $sender_mxid - The Matrix ID of the sender (e.g. @exampleuser:example.com)
|
||||
# $message - The message content
|
||||
message_formats:
|
||||
m.text: "<b>$sender_displayname</b>: $formatted_body"
|
||||
m.notice: "<b>$sender_displayname</b>: $formatted_body"
|
||||
m.emote: "* <b>$sender_displayname</b> $formatted_body"
|
||||
m.file: "$sender_displayname sent a file: $body"
|
||||
m.image: "$sender_displayname sent an image: $body"
|
||||
m.audio: "$sender_displayname sent an audio file: $body"
|
||||
m.video: "$sender_displayname sent a video: $body"
|
||||
m.location: "$sender_displayname sent a location: $body"
|
||||
m.text: "<b>$sender_displayname</b>: $message"
|
||||
m.notice: "<b>$sender_displayname</b>: $message"
|
||||
m.emote: "* <b>$sender_displayname</b> $message"
|
||||
m.file: "<b>$sender_displayname</b> sent a file: $message"
|
||||
m.image: "<b>$sender_displayname</b> sent an image: $message"
|
||||
m.audio: "<b>$sender_displayname</b> sent an audio file: $message"
|
||||
m.video: "<b>$sender_displayname</b> sent a video: $message"
|
||||
m.location: "<b>$sender_displayname</b> sent a location: $message"
|
||||
# Telegram doesn't have built-in emotes, this field specifies how m.emote's from authenticated
|
||||
# users are sent to telegram. All fields in message_formats are supported. Additionally, the
|
||||
# Telegram user info is available in the following variables:
|
||||
|
||||
@@ -18,7 +18,7 @@ from typing import Awaitable, Callable, List, Optional, NamedTuple, Any
|
||||
|
||||
from telethon.errors import FloodWaitError
|
||||
|
||||
from mautrix.types import RoomID, EventID
|
||||
from mautrix.types import RoomID, EventID, MessageEventContent
|
||||
from mautrix.bridge.commands import (HelpSection, CommandEvent as BaseCommandEvent,
|
||||
CommandHandler as BaseCommandHandler,
|
||||
CommandProcessor as BaseCommandProcessor,
|
||||
@@ -42,10 +42,10 @@ class CommandEvent(BaseCommandEvent):
|
||||
sender: u.User
|
||||
|
||||
def __init__(self, processor: 'CommandProcessor', room_id: RoomID, event_id: EventID,
|
||||
sender: u.User, command: str, args: List[str], is_management: bool,
|
||||
is_portal: bool) -> None:
|
||||
super().__init__(processor, room_id, event_id, sender, command, args, is_management,
|
||||
is_portal)
|
||||
sender: u.User, command: str, args: List[str], content: MessageEventContent,
|
||||
is_management: bool, is_portal: bool) -> None:
|
||||
super().__init__(processor, room_id, event_id, sender, command, args, content,
|
||||
is_management, is_portal)
|
||||
self.bridge = processor.bridge
|
||||
self.tgbot = processor.tgbot
|
||||
self.config = processor.config
|
||||
@@ -69,7 +69,7 @@ class CommandHandler(BaseCommandHandler):
|
||||
def __init__(self, handler: Callable[[CommandEvent], Awaitable[EventID]],
|
||||
management_only: bool, name: str, help_text: str, help_args: str,
|
||||
help_section: HelpSection, needs_auth: bool, needs_puppeting: bool,
|
||||
needs_matrix_puppeting: bool, needs_admin: bool,) -> None:
|
||||
needs_matrix_puppeting: bool, needs_admin: bool) -> None:
|
||||
super().__init__(handler, management_only, name, help_text, help_args, help_section,
|
||||
needs_auth=needs_auth, needs_puppeting=needs_puppeting,
|
||||
needs_matrix_puppeting=needs_matrix_puppeting, needs_admin=needs_admin)
|
||||
|
||||
@@ -29,7 +29,7 @@ from telethon.tl.functions.messages import (ImportChatInviteRequest, CheckChatIn
|
||||
GetBotCallbackAnswerRequest, SendVoteRequest)
|
||||
from telethon.tl.functions.channels import JoinChannelRequest
|
||||
|
||||
from mautrix.types import EventID
|
||||
from mautrix.types import EventID, Format
|
||||
|
||||
from ... import puppet as pu, portal as po
|
||||
from ...abstract_user import AbstractUser
|
||||
@@ -45,11 +45,12 @@ async def caption(evt: CommandEvent) -> EventID:
|
||||
if len(evt.args) == 0:
|
||||
return await evt.reply("**Usage:** `$cmdprefix+sp caption <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"
|
||||
prefix = f"{evt.command_prefix} caption "
|
||||
if evt.content.format == Format.HTML:
|
||||
evt.content.formatted_body = evt.content.formatted_body.replace(prefix, "", 1)
|
||||
evt.content.body = evt.content.body.replace(prefix, "", 1)
|
||||
evt.sender.command_status = {"caption": evt.content}
|
||||
return await evt.reply("Your next image or file will be sent with that caption. "
|
||||
"Use `$cmdprefix+sp cancel` to cancel the caption.")
|
||||
|
||||
|
||||
|
||||
@@ -169,7 +169,7 @@ class PortalMatrix(BasePortal, MautrixBasePortal, ABC):
|
||||
|
||||
async def _apply_msg_format(self, sender: 'u.User', content: MessageEventContent
|
||||
) -> None:
|
||||
if isinstance(content, TextMessageEventContent) and content.format != Format.HTML:
|
||||
if not isinstance(content, TextMessageEventContent) or content.format != Format.HTML:
|
||||
content.format = Format.HTML
|
||||
content.formatted_body = escape_html(content.body).replace("\n", "<br/>")
|
||||
|
||||
@@ -179,14 +179,9 @@ class PortalMatrix(BasePortal, MautrixBasePortal, ABC):
|
||||
tpl_args = dict(sender_mxid=sender.mxid,
|
||||
sender_username=sender.mxid_localpart,
|
||||
sender_displayname=escape_html(displayname),
|
||||
body=content.body)
|
||||
if isinstance(content, TextMessageEventContent):
|
||||
tpl_args["formatted_body"] = content.formatted_body
|
||||
tpl_args["message"] = content.formatted_body
|
||||
content.formatted_body = Template(tpl).safe_substitute(tpl_args)
|
||||
else:
|
||||
tpl_args["message"] = content.body
|
||||
content.body = Template(tpl).safe_substitute(tpl_args)
|
||||
message=content.formatted_body,
|
||||
body=content.body, formatted_body=content.formatted_body)
|
||||
content.formatted_body = Template(tpl).safe_substitute(tpl_args)
|
||||
|
||||
async def _apply_emote_format(self, sender: 'u.User',
|
||||
content: TextMessageEventContent) -> None:
|
||||
@@ -248,7 +243,8 @@ class PortalMatrix(BasePortal, MautrixBasePortal, ABC):
|
||||
|
||||
async def _handle_matrix_file(self, sender_id: TelegramID, event_id: EventID,
|
||||
space: TelegramID, client: 'MautrixTelegramClient',
|
||||
content: MediaMessageEventContent, reply_to: TelegramID) -> None:
|
||||
content: MediaMessageEventContent, reply_to: TelegramID,
|
||||
caption: TextMessageEventContent = None) -> None:
|
||||
mime = content.info.mimetype
|
||||
w, h = content.info.width, content.info.height
|
||||
file_name = content["net.maunium.telegram.internal.filename"]
|
||||
@@ -256,7 +252,7 @@ class PortalMatrix(BasePortal, MautrixBasePortal, ABC):
|
||||
|
||||
if config["bridge.parallel_file_transfer"]:
|
||||
file_handle, file_size = await parallel_transfer_to_telegram(client, self.main_intent,
|
||||
content.url, 0)
|
||||
content.url, sender_id)
|
||||
else:
|
||||
file = await self.main_intent.download_media(content.url)
|
||||
|
||||
@@ -283,19 +279,19 @@ class PortalMatrix(BasePortal, MautrixBasePortal, ABC):
|
||||
media = InputMediaUploadedDocument(file=file_handle, attributes=attributes,
|
||||
mime_type=mime or "application/octet-stream")
|
||||
|
||||
caption = content.body if content.body != file_name else None
|
||||
caption, entities = self._matrix_event_to_entities(caption) if caption else (None, None)
|
||||
|
||||
async with self.send_lock(sender_id):
|
||||
if await self._matrix_document_edit(client, content, space, caption, media, event_id):
|
||||
return
|
||||
try:
|
||||
response = await client.send_media(self.peer, media, reply_to=reply_to,
|
||||
caption=caption)
|
||||
caption=caption, entities=entities)
|
||||
except (PhotoInvalidDimensionsError, PhotoSaveFileInvalidError, PhotoExtInvalidError):
|
||||
media = InputMediaUploadedDocument(file=media.file, mime_type=mime,
|
||||
attributes=attributes)
|
||||
response = await client.send_media(self.peer, media, reply_to=reply_to,
|
||||
caption=caption)
|
||||
caption=caption, entities=entities)
|
||||
self._add_telegram_message_to_db(event_id, space, 0, response)
|
||||
|
||||
async def _matrix_document_edit(self, client: 'MautrixTelegramClient',
|
||||
@@ -364,14 +360,18 @@ class PortalMatrix(BasePortal, MautrixBasePortal, ABC):
|
||||
|
||||
media = (MessageType.STICKER, MessageType.IMAGE, MessageType.FILE, MessageType.AUDIO,
|
||||
MessageType.VIDEO)
|
||||
caption_content = None
|
||||
if content.msgtype in media:
|
||||
content["net.maunium.telegram.internal.filename"] = content.body
|
||||
try:
|
||||
content.body = sender.command_status["caption"]
|
||||
caption_content: MessageEventContent = sender.command_status["caption"]
|
||||
caption_content.msgtype = content.msgtype
|
||||
reply_to = reply_to or formatter.matrix_reply_to_telegram(caption_content, space,
|
||||
room_id=self.mxid)
|
||||
sender.command_status = None
|
||||
except (KeyError, TypeError):
|
||||
pass
|
||||
await self._pre_process_matrix_message(sender, not logged_in, content)
|
||||
await self._pre_process_matrix_message(sender, not logged_in, caption_content or content)
|
||||
|
||||
if content.msgtype == MessageType.NOTICE:
|
||||
bridge_notices = self.get_config("bridge_notices.default")
|
||||
@@ -385,7 +385,8 @@ class PortalMatrix(BasePortal, MautrixBasePortal, ABC):
|
||||
await self._handle_matrix_location(sender_id, event_id, space, client, content,
|
||||
reply_to)
|
||||
elif content.msgtype in media:
|
||||
await self._handle_matrix_file(sender_id, event_id, space, client, content, reply_to)
|
||||
await self._handle_matrix_file(sender_id, event_id, space, client, content, reply_to,
|
||||
caption_content)
|
||||
else:
|
||||
self.log.debug(f"Unhandled Matrix event: {content}")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user