|
|
|
@ -217,9 +217,14 @@ class Portal(DBPortal, BasePortal): |
|
|
|
|
async def delete(self) -> None: |
|
|
|
|
if self.mxid: |
|
|
|
|
await DBMessage.delete_all_by_room(self.mxid) |
|
|
|
|
self.by_mxid.pop(self.mxid, None) |
|
|
|
|
self.by_ktid.pop(self._ktid_full, None) |
|
|
|
|
self.by_mxid.pop(self.mxid, None) |
|
|
|
|
await super().delete() |
|
|
|
|
self.mxid = None |
|
|
|
|
self.name_set = False |
|
|
|
|
self.avatar_set = False |
|
|
|
|
self.relay_user_id = None |
|
|
|
|
self.encrypted = False |
|
|
|
|
await super().save() |
|
|
|
|
|
|
|
|
|
# endregion |
|
|
|
|
# region Properties |
|
|
|
@ -265,6 +270,11 @@ class Portal(DBPortal, BasePortal): |
|
|
|
|
) |
|
|
|
|
return self._main_intent |
|
|
|
|
|
|
|
|
|
async def get_dm_puppet(self) -> p.Puppet | None: |
|
|
|
|
if not self.is_direct: |
|
|
|
|
return None |
|
|
|
|
return await p.Puppet.get_by_ktid(self.kt_sender) |
|
|
|
|
|
|
|
|
|
# endregion |
|
|
|
|
# region Chat info updating |
|
|
|
|
|
|
|
|
@ -362,7 +372,12 @@ class Portal(DBPortal, BasePortal): |
|
|
|
|
data, decryption_info = encrypt_attachment(data) |
|
|
|
|
upload_mime_type = "application/octet-stream" |
|
|
|
|
filename = None |
|
|
|
|
url = await intent.upload_media(data, mime_type=upload_mime_type, filename=filename) |
|
|
|
|
url = await intent.upload_media( |
|
|
|
|
data, |
|
|
|
|
mime_type=upload_mime_type, |
|
|
|
|
filename=filename, |
|
|
|
|
async_upload=cls.config["homeserver.async_media"], |
|
|
|
|
) |
|
|
|
|
if decryption_info: |
|
|
|
|
decryption_info.url = url |
|
|
|
|
return url, info, decryption_info |
|
|
|
@ -436,6 +451,15 @@ class Portal(DBPortal, BasePortal): |
|
|
|
|
self.avatar_set = False |
|
|
|
|
return True |
|
|
|
|
|
|
|
|
|
async def update_info_from_puppet(self, puppet: p.Puppet | None = None) -> bool: |
|
|
|
|
if not self.is_direct: |
|
|
|
|
return False |
|
|
|
|
if not puppet: |
|
|
|
|
puppet = await self.get_dm_puppet() |
|
|
|
|
changed = await self._update_name(puppet.name) |
|
|
|
|
changed = await self._update_photo_from_puppet(puppet) or changed |
|
|
|
|
return changed |
|
|
|
|
|
|
|
|
|
""" |
|
|
|
|
async def sync_per_room_nick(self, puppet: p.Puppet, name: str) -> None: |
|
|
|
|
intent = puppet.intent_for(self) |
|
|
|
@ -457,31 +481,41 @@ class Portal(DBPortal, BasePortal): |
|
|
|
|
) |
|
|
|
|
""" |
|
|
|
|
|
|
|
|
|
async def _update_participant( |
|
|
|
|
self, source: u.User, participant: UserInfoUnion |
|
|
|
|
) -> bool: |
|
|
|
|
# TODO nick map? |
|
|
|
|
self.log.trace("Syncing participant %s", participant.id) |
|
|
|
|
puppet = await p.Puppet.get_by_ktid(participant.userId) |
|
|
|
|
await puppet.update_info_from_participant(source, participant) |
|
|
|
|
changed = False |
|
|
|
|
if self.is_direct and self._kt_sender == puppet.ktid and self.encrypted: |
|
|
|
|
changed = await self._update_info_from_puppet(puppet.name) or changed |
|
|
|
|
if self.mxid: |
|
|
|
|
if puppet.ktid != self.kt_receiver or puppet.is_real_user: |
|
|
|
|
await puppet.intent_for(self).ensure_joined(self.mxid, bot=self.main_intent) |
|
|
|
|
#if puppet.ktid in nick_map: |
|
|
|
|
# await self.sync_per_room_nick(puppet, nick_map[puppet.ktid]) |
|
|
|
|
return changed |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async def _update_participants(self, source: u.User, participants: list[UserInfoUnion] | None = None) -> bool: |
|
|
|
|
# TODO nick map? |
|
|
|
|
if participants is None: |
|
|
|
|
self.log.debug("Called _update_participants with no participants, fetching them now...") |
|
|
|
|
participants = await source.client.get_participants(self.channel_props) |
|
|
|
|
changed = False |
|
|
|
|
if not self._main_intent: |
|
|
|
|
assert self.is_direct, "_main_intent for non-direct chat portal should have been set already" |
|
|
|
|
self._kt_sender = participants[ |
|
|
|
|
0 if self.kt_type == KnownChannelType.MemoChat or participants[0].userId != source.ktid else 1 |
|
|
|
|
].userId |
|
|
|
|
self._main_intent = (await p.Puppet.get_by_ktid(self._kt_sender)).default_mxid_intent |
|
|
|
|
self._main_intent = (await self.get_dm_puppet()).default_mxid_intent |
|
|
|
|
else: |
|
|
|
|
self._kt_sender = (await p.Puppet.get_by_mxid(self._main_intent.mxid)).ktid if self.is_direct else None |
|
|
|
|
# TODO nick_map? |
|
|
|
|
for participant in participants: |
|
|
|
|
puppet = await p.Puppet.get_by_ktid(participant.userId) |
|
|
|
|
await puppet.update_info_from_participant(source, participant) |
|
|
|
|
if self.is_direct and self._kt_sender == puppet.ktid and self.encrypted: |
|
|
|
|
changed = await self._update_name(puppet.name) or changed |
|
|
|
|
changed = await self._update_photo_from_puppet(puppet) or changed |
|
|
|
|
if self.mxid: |
|
|
|
|
if puppet.ktid != self.kt_receiver or puppet.is_real_user: |
|
|
|
|
await puppet.intent_for(self).ensure_joined(self.mxid, bot=self.main_intent) |
|
|
|
|
#if puppet.ktid in nick_map: |
|
|
|
|
# await self.sync_per_room_nick(puppet, nick_map[puppet.ktid]) |
|
|
|
|
sync_tasks = [ |
|
|
|
|
self._update_participant(source, pcp) for pcp in participants |
|
|
|
|
] |
|
|
|
|
changed = any(await asyncio.gather(*sync_tasks)) |
|
|
|
|
return changed |
|
|
|
|
|
|
|
|
|
# endregion |
|
|
|
@ -833,7 +867,7 @@ class Portal(DBPortal, BasePortal): |
|
|
|
|
if message.relates_to.rel_type == RelationType.REPLY: |
|
|
|
|
reply_to_msg = await DBMessage.get_by_mxid(message.relates_to.event_id, self.mxid) |
|
|
|
|
if reply_to_msg: |
|
|
|
|
reply_to = reply_to_msg.fbid |
|
|
|
|
reply_to = reply_to_msg.ktid |
|
|
|
|
else: |
|
|
|
|
self.log.warning( |
|
|
|
|
f"Couldn't find reply target {message.relates_to.event_id}" |
|
|
|
@ -928,16 +962,6 @@ class Portal(DBPortal, BasePortal): |
|
|
|
|
) |
|
|
|
|
self._typing = users |
|
|
|
|
|
|
|
|
|
async def enable_dm_encryption(self) -> bool: |
|
|
|
|
ok = await super().enable_dm_encryption() |
|
|
|
|
if ok: |
|
|
|
|
try: |
|
|
|
|
puppet = await p.Puppet.get_by_ktid(self.ktid) |
|
|
|
|
await self.main_intent.set_room_name(self.mxid, puppet.name) |
|
|
|
|
except Exception: |
|
|
|
|
self.log.warning(f"Failed to set room name", exc_info=True) |
|
|
|
|
return ok |
|
|
|
|
|
|
|
|
|
# endregion |
|
|
|
|
# region KakaoTalk event handling |
|
|
|
|
|
|
|
|
@ -976,6 +1000,7 @@ class Portal(DBPortal, BasePortal): |
|
|
|
|
sender: p.Puppet, |
|
|
|
|
message: Chatlog, |
|
|
|
|
) -> None: |
|
|
|
|
# TODO Backfill!! This avoids timing conflicts on startup sync |
|
|
|
|
self.log.debug(f"Handling KakaoTalk event {message.logId}") |
|
|
|
|
if not self.mxid: |
|
|
|
|
mxid = await self.create_matrix_room(source) |
|
|
|
@ -1015,6 +1040,7 @@ class Portal(DBPortal, BasePortal): |
|
|
|
|
self.log.warning(f"Unhandled KakaoTalk message {message.logId}") |
|
|
|
|
return |
|
|
|
|
self.log.debug(f"Handled KakaoTalk message {message.logId} -> {event_ids}") |
|
|
|
|
# TODO Might have to handle remote reactions on messages created by bulk_create |
|
|
|
|
await DBMessage.bulk_create( |
|
|
|
|
ktid=message.logId, |
|
|
|
|
kt_chat=self.ktid, |
|
|
|
@ -1232,7 +1258,7 @@ class Portal(DBPortal, BasePortal): |
|
|
|
|
messages = await source.client.get_chats( |
|
|
|
|
self.channel_props, |
|
|
|
|
after_log_id, |
|
|
|
|
limit |
|
|
|
|
limit, |
|
|
|
|
) |
|
|
|
|
if not messages: |
|
|
|
|
self.log.debug("Didn't get any messages from server") |
|
|
|
|