Inbound replies (and some kwarg cleanup)

This commit is contained in:
Andrew Ferrazzutti 2022-04-05 02:44:03 -04:00
parent ce5006269f
commit 3ced968494
1 changed files with 78 additions and 49 deletions

View File

@ -31,7 +31,7 @@ import time
from mautrix.appservice import IntentAPI from mautrix.appservice import IntentAPI
from mautrix.bridge import BasePortal, NotificationDisabler, async_getter_lock from mautrix.bridge import BasePortal, NotificationDisabler, async_getter_lock
from mautrix.errors import MatrixError from mautrix.errors import MatrixError, MForbidden, MNotFound, SessionNotFound
from mautrix.types import ( from mautrix.types import (
AudioInfo, AudioInfo,
ContentURI, ContentURI,
@ -73,6 +73,7 @@ from .kt.types.chat.attachment import (
MediaAttachment, MediaAttachment,
MultiPhotoAttachment, MultiPhotoAttachment,
PhotoAttachment, PhotoAttachment,
ReplyAttachment,
VideoAttachment, VideoAttachment,
) )
@ -190,6 +191,7 @@ class Portal(DBPortal, BasePortal):
# TODO More # TODO More
cls._message_type_handler_map = { cls._message_type_handler_map = {
KnownChatType.TEXT: cls._handle_remote_text, KnownChatType.TEXT: cls._handle_remote_text,
KnownChatType.REPLY: cls._handle_remote_reply,
KnownChatType.PHOTO: cls._handle_remote_photo, KnownChatType.PHOTO: cls._handle_remote_photo,
KnownChatType.MULTIPHOTO: cls._handle_remote_multiphoto, KnownChatType.MULTIPHOTO: cls._handle_remote_multiphoto,
KnownChatType.VIDEO: cls._handle_remote_video, KnownChatType.VIDEO: cls._handle_remote_video,
@ -953,6 +955,38 @@ class Portal(DBPortal, BasePortal):
return False return False
return True return True
async def _add_remote_reply(
self, content: MessageEventContent, reply_to: ReplyAttachment
) -> None:
message = await DBMessage.get_by_ktid(reply_to.src_logId, self.kt_receiver)
if not message:
self.log.warning(
f"Couldn't find reply target {reply_to.src_logId} to bridge reply metadata to Matrix"
)
return
content.set_reply(message.mxid)
if not isinstance(content, TextMessageEventContent):
return
try:
evt = await self.main_intent.get_event(message.mx_room, message.mxid)
except (MNotFound, MForbidden):
evt = None
if not evt:
return
if evt.type == EventType.ROOM_ENCRYPTED:
try:
evt = await self.matrix.e2ee.decrypt(evt, wait_session_timeout=0)
except SessionNotFound:
return
if isinstance(evt.content, TextMessageEventContent):
evt.content.trim_reply_fallback()
content.set_reply(evt)
async def handle_remote_message( async def handle_remote_message(
self, self,
source: u.User, source: u.User,
@ -1039,52 +1073,58 @@ class Portal(DBPortal, BasePortal):
type_str, type_str,
f"text = {message_text}" if message_text is not None else "no text", f"text = {message_text}" if message_text is not None else "no text",
) )
if message_text:
events = await self._handle_remote_text(
intent=intent,
timestamp=timestamp,
message_text=message_text,
)
else:
events = []
content = TextMessageEventContent( content = TextMessageEventContent(
msgtype=MessageType.NOTICE, msgtype=MessageType.NOTICE,
body=f"\u26a0 Unbridgeable message ({type_str})", body=f"\u26a0 Unbridgeable message ({type_str})",
) )
# TODO Replies if events:
return [await self._send_message(intent, content, timestamp=timestamp)] content.set_reply(events[-1])
events.append(await self._send_message(intent, content, timestamp=timestamp))
return events
async def _handle_remote_text( async def _handle_remote_text(
self, self,
intent: IntentAPI, intent: IntentAPI,
timestamp: int, timestamp: int,
message_text: str, message_text: str | None,
**_ **_
) -> list[EventID]: ) -> list[EventID]:
# TODO Handle mentions properly # TODO Handle mentions properly
content = await kakaotalk_to_matrix(message_text) content = await kakaotalk_to_matrix(message_text)
# TODO Replies
return [await self._send_message(intent, content, timestamp=timestamp)] return [await self._send_message(intent, content, timestamp=timestamp)]
def _handle_remote_photo( async def _handle_remote_reply(
self, self,
source: u.User,
intent: IntentAPI, intent: IntentAPI,
attachment: PhotoAttachment, attachment: ReplyAttachment,
timestamp: int, timestamp: int,
message_text: str | None, message_text: str,
**_ **_
) -> Awaitable[list[EventID]]: ) -> list[EventID]:
return asyncio.gather(self._handle_remote_uniphoto( content = await kakaotalk_to_matrix(message_text)
source, intent, attachment, timestamp, message_text await self._add_remote_reply(content, attachment)
)) return [await self._send_message(intent, content, timestamp=timestamp)]
def _handle_remote_photo(self, **kwargs) -> Awaitable[list[EventID]]:
return asyncio.gather(self._handle_remote_uniphoto(**kwargs))
async def _handle_remote_multiphoto( async def _handle_remote_multiphoto(
self, self,
source: u.User,
intent: IntentAPI,
attachment: MultiPhotoAttachment, attachment: MultiPhotoAttachment,
timestamp: int, **kwargs
message_text: str | None,
**_
) -> Awaitable[list[EventID]]: ) -> Awaitable[list[EventID]]:
# TODO Upload media concurrently, but post messages sequentially # TODO Upload media concurrently, but post messages sequentially
return [ return [
await self._handle_remote_uniphoto( await self._handle_remote_uniphoto(
source, intent, attachment=PhotoAttachment(
PhotoAttachment(
shout=attachment.shout, shout=attachment.shout,
mentions=attachment.mentions, mentions=attachment.mentions,
urls=attachment.urls, urls=attachment.urls,
@ -1099,22 +1139,18 @@ class Portal(DBPortal, BasePortal):
cs=attachment.csl[i], cs=attachment.csl[i],
mt=attachment.mtl[i], mt=attachment.mtl[i],
), ),
timestamp, message_text, **kwargs
) )
for i in range(len(attachment.imageUrls)) for i in range(len(attachment.imageUrls))
] ]
def _handle_remote_uniphoto( def _handle_remote_uniphoto(
self, self,
source: u.User,
intent: IntentAPI,
attachment: PhotoAttachment, attachment: PhotoAttachment,
timestamp: int, **kwargs
message_text: str | None,
**_
) -> Awaitable[EventID]: ) -> Awaitable[EventID]:
return self._handle_remote_media( return self._handle_remote_media(
source, intent, attachment, timestamp, message_text, attachment,
ImageInfo( ImageInfo(
mimetype=attachment.mt, mimetype=attachment.mt,
size=attachment.s, size=attachment.s,
@ -1122,72 +1158,66 @@ class Portal(DBPortal, BasePortal):
height=attachment.h, height=attachment.h,
), ),
MessageType.IMAGE, MessageType.IMAGE,
**kwargs
) )
def _handle_remote_video( def _handle_remote_video(
self, self,
source: u.User,
intent: IntentAPI,
attachment: VideoAttachment, attachment: VideoAttachment,
timestamp: int, **kwargs
message_text: str | None,
**_
) -> Awaitable[list[EventID]]: ) -> Awaitable[list[EventID]]:
return asyncio.gather(self._handle_remote_media( return asyncio.gather(self._handle_remote_media(
source, intent, attachment, timestamp, message_text, attachment,
VideoInfo( VideoInfo(
duration=attachment.d, duration=attachment.d,
width=attachment.w, width=attachment.w,
height=attachment.h, height=attachment.h,
), ),
MessageType.VIDEO, MessageType.VIDEO,
**kwargs
)) ))
def _handle_remote_audio( def _handle_remote_audio(
self, self,
source: u.User,
intent: IntentAPI,
attachment: AudioAttachment, attachment: AudioAttachment,
timestamp: int, **kwargs
message_text: str | None,
**_
) -> Awaitable[list[EventID]]: ) -> Awaitable[list[EventID]]:
return asyncio.gather(self._handle_remote_media( return asyncio.gather(self._handle_remote_media(
source, intent, attachment, timestamp, message_text, attachment,
AudioInfo( AudioInfo(
size=attachment.s, size=attachment.s,
duration=attachment.d, duration=attachment.d,
), ),
MessageType.AUDIO, MessageType.AUDIO,
**kwargs
)) ))
""" TODO Find what auth is required for reading file contents """ TODO Find what auth is required for reading file contents
def _handle_remote_file( def _handle_remote_file(
self, self,
source: u.User,
intent: IntentAPI,
attachment: FileAttachment, attachment: FileAttachment,
timestamp: int, **kwargs
message_text: str | None,
) -> Awaitable[list[EventID]]: ) -> Awaitable[list[EventID]]:
return asyncio.gather(self._handle_remote_media( return asyncio.gather(self._handle_remote_media(
source, intent, attachment, timestamp, message_text, attachment,
FileInfo( FileInfo(
size=attachment.size, size=attachment.size,
), ),
MessageType.FILE, MessageType.FILE,
**kwargs
)) ))
""" """
async def _handle_remote_media( async def _handle_remote_media(
self, self,
source: u.User,
intent: IntentAPI,
attachment: MediaAttachment, attachment: MediaAttachment,
timestamp: int,
message_text: str | None,
info: MediaInfo, info: MediaInfo,
msgtype: MessageType, msgtype: MessageType,
*,
source: u.User,
intent: IntentAPI,
timestamp: int,
message_text: str | None,
**_ **_
) -> EventID: ) -> EventID:
mxc, additional_info, decryption_info = await self._reupload_remote_file( mxc, additional_info, decryption_info = await self._reupload_remote_file(
@ -1203,7 +1233,6 @@ class Portal(DBPortal, BasePortal):
content = MediaMessageEventContent( content = MediaMessageEventContent(
url=mxc, file=decryption_info, msgtype=msgtype, body=message_text, info=info url=mxc, file=decryption_info, msgtype=msgtype, body=message_text, info=info
) )
# TODO Replies
return await self._send_message(intent, content, timestamp=timestamp) return await self._send_message(intent, content, timestamp=timestamp)
# TODO Many more remote handlers # TODO Many more remote handlers