Inbound replies (and some kwarg cleanup)
This commit is contained in:
parent
ce5006269f
commit
3ced968494
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue