From 746756cc3ff87fffdf0257ab27b59ab6409dbfc0 Mon Sep 17 00:00:00 2001 From: Andrew Ferrazzutti Date: Wed, 13 Apr 2022 15:29:44 -0400 Subject: [PATCH] Improved power level bridging --- matrix_appservice_kakaotalk/matrix.py | 22 ++--------- matrix_appservice_kakaotalk/portal.py | 55 +++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 18 deletions(-) diff --git a/matrix_appservice_kakaotalk/matrix.py b/matrix_appservice_kakaotalk/matrix.py index 85b90ca..297b2ec 100644 --- a/matrix_appservice_kakaotalk/matrix.py +++ b/matrix_appservice_kakaotalk/matrix.py @@ -172,31 +172,17 @@ class MatrixHandler(BaseMatrixHandler): user_id: UserID, prev_content: PowerLevelStateEventContent, content: PowerLevelStateEventContent, + event_id: EventID, ) -> None: user = await u.User.get_by_mxid(user_id) - if not user or not user.is_connected: + if not user: return portal = await po.Portal.get_by_mxid(room_id) if not portal: return - for target_mxid, power_level in content.users.items(): - if power_level == prev_content.get_user_level(target_mxid): - continue - puppet = await pu.Puppet.get_by_mxid(target_mxid) - if puppet: - perm = TO_PERM_MAP.get(power_level) - try: - await user.client.send_perm(portal.channel_props, puppet.ktid, perm) - except CommandException: - cls.log.exception( - "Failed to handle power level change (%d->%d) for puppet user %s, so changing it back", - prev_content.get_user_level(target_mxid), - power_level, - target_mxid, - ) - await portal.main_intent.set_power_levels(room_id, prev_content) + await portal.handle_matrix_power_level(user, prev_content, content, event_id) async def handle_ephemeral_event( self, evt: ReceiptEvent | Event @@ -216,4 +202,4 @@ class MatrixHandler(BaseMatrixHandler): async def handle_state_event(self, evt: StateEvent) -> None: if evt.type == EventType.ROOM_POWER_LEVELS: - await self.handle_power_level(evt.room_id, evt.sender, evt.prev_content, evt.content) + await self.handle_power_level(evt.room_id, evt.sender, evt.prev_content, evt.content, evt.event_id) diff --git a/matrix_appservice_kakaotalk/portal.py b/matrix_appservice_kakaotalk/portal.py index 4e16ba5..293cc0f 100644 --- a/matrix_appservice_kakaotalk/portal.py +++ b/matrix_appservice_kakaotalk/portal.py @@ -90,6 +90,7 @@ from .kt.client.types import ( ChannelProps, TO_MSGTYPE_MAP, FROM_PERM_MAP, + TO_PERM_MAP, ) from .kt.client.errors import CommandException @@ -1041,6 +1042,60 @@ class Portal(DBPortal, BasePortal): pass """ + async def handle_matrix_power_level( + self, + sender: u.User, + prev_content: PowerLevelStateEventContent, + content: PowerLevelStateEventContent, + event_id: EventID, + ) -> None: + try: + await self._handle_matrix_power_level(sender, prev_content, content) + except Exception as e: + self.log.error( + f"Failed to handle Matrix power level {event_id}: {e}", + exc_info=not isinstance(e, NotImplementedError), + ) + sender.send_remote_checkpoint( + self._status_from_exception(e), + event_id, + self.mxid, + EventType.ROOM_POWER_LEVELS, + error=e, + ) + if not isinstance(e, NotImplementedError): + await self._send_bridge_error( + f"{e}. Reverting the power level change...", + thing="power level change" + ) + # NOTE Redacting instead doesn't work + await self.main_intent.set_power_levels(self.mxid, prev_content) + else: + await self._send_delivery_receipt(event_id) + sender.send_remote_checkpoint( + MessageSendCheckpointStatus.SUCCESS, + event_id, + self.mxid, + EventType.ROOM_POWER_LEVELS, + ) + + async def _handle_matrix_power_level( + self, + sender: u.User, + prev_content: PowerLevelStateEventContent, + content: PowerLevelStateEventContent, + ) -> None: + for target_mxid, power_level in content.users.items(): + if power_level == prev_content.get_user_level(target_mxid): + continue + puppet = await p.Puppet.get_by_mxid(target_mxid) + if puppet: + if sender.is_connected: + perm = TO_PERM_MAP.get(power_level) + await sender.client.send_perm(self.channel_props, puppet.ktid, perm) + else: + raise Exception("Disconnected users cannot set power levels of KakaoTalk users") + async def handle_matrix_leave(self, user: u.User) -> None: if self.is_direct: self.log.info(f"{user.mxid} left private chat portal with {self.ktid}")