Compare commits

...

7 Commits

6 changed files with 29 additions and 19 deletions

View File

@ -24,10 +24,10 @@
* [x] Leave<sup>[3]</sup> * [x] Leave<sup>[3]</sup>
* [ ] Ban<sup>[4]</sup> * [ ] Ban<sup>[4]</sup>
* [ ] Unban<sup>[4]</sup> * [ ] Unban<sup>[4]</sup>
* [ ] Room metadata changes<sup>[1]</sup> * [ ] Room metadata changes
* [x] Name * [x] Name<sup>[1]</sup>
* [x] Topic * [x] Topic<sup>[1]</sup>
* [x] Avatar * [x] Avatar<sup>[1]</sup>
* [ ] Per-room user nick * [ ] Per-room user nick
* KakaoTalk → Matrix * KakaoTalk → Matrix
* [ ] Message content * [ ] Message content
@ -58,7 +58,7 @@
* [x] On live event * [x] On live event
* [x] Kick<sup>[4]</sup> * [x] Kick<sup>[4]</sup>
* [x] Unkick<sup>[4]</sup> * [x] Unkick<sup>[4]</sup>
* [ ] Channel metadata * [x] Channel metadata
* [x] Name * [x] Name
* [x] Description * [x] Description
* [x] Cover photo<sup>[5]</sup> * [x] Cover photo<sup>[5]</sup>
@ -92,4 +92,4 @@
<sup>[2]</sup> Only recently-sent KakaoTalk messages can be deleted <sup>[2]</sup> Only recently-sent KakaoTalk messages can be deleted
<sup>[3]</sup> To make your KakaoTalk account leave a channel, send the `leave` command in a Matrix portal room. Simply leaving a Matrix portal room will keep your KakaoTalk account in the channel. <sup>[3]</sup> To make your KakaoTalk account leave a channel, send the `leave` command in a Matrix portal room. Simply leaving a Matrix portal room will keep your KakaoTalk account in the channel.
<sup>[4]</sup> Kicks in KakaoTalk are equivalent to bans in Matrix <sup>[4]</sup> Kicks in KakaoTalk are equivalent to bans in Matrix
<sup>[5]</sup> Might only get synced on backfill, or on changing channel name/description <sup>[5]</sup> Might not get synced on backfill or initial portal creation. Might get synced on live update to channel name/description

View File

@ -235,7 +235,7 @@ async def _force_login(evt: CommandEvent) -> None:
) )
return return
assert evt.sender.command_status assert evt.sender.command_status
evt.sender.command_status["forced"] = True evt.sender.command_status["req"]["forced"] = True
await evt.mark_read() await evt.mark_read()
await _try_login(evt, evt.sender.command_status.pop("req")) await _try_login(evt, evt.sender.command_status.pop("req"))
@ -277,7 +277,7 @@ async def _handle_login_failure(evt: CommandEvent, e: Exception) -> None:
needs_auth=True, needs_auth=True,
management_only=True, management_only=True,
help_section=SECTION_AUTH, help_section=SECTION_AUTH,
help_text="Delete saved login password, if it was saved" help_text="Delete saved login password, if it was saved",
) )
async def forget_password(evt: CommandEvent) -> None: async def forget_password(evt: CommandEvent) -> None:
creds = await LoginCredential.get_by_mxid(evt.sender.mxid) creds = await LoginCredential.get_by_mxid(evt.sender.mxid)
@ -337,7 +337,8 @@ async def reset_device(evt: CommandEvent) -> None:
@command_handler( @command_handler(
needs_auth=False, needs_auth=False,
help_section=SECTION_AUTH, help_section=SECTION_AUTH,
help_text="When logging in, automatically log out of any other existing KakaoTalk session" help_text="When logging in, automatically log out of any other existing KakaoTalk session",
aliases=["enable-force-login"],
) )
async def enable_forced_login(evt: CommandEvent) -> None: async def enable_forced_login(evt: CommandEvent) -> None:
if evt.sender.force_login: if evt.sender.force_login:
@ -350,7 +351,8 @@ async def enable_forced_login(evt: CommandEvent) -> None:
@command_handler( @command_handler(
needs_auth=False, needs_auth=False,
help_section=SECTION_AUTH, help_section=SECTION_AUTH,
help_text="When logging in, ask before logging out of another existing KakaoTalk session, if one exists" help_text="When logging in, ask before logging out of another existing KakaoTalk session, if one exists",
aliases=["disable-force-login"],
) )
async def disable_forced_login(evt: CommandEvent) -> None: async def disable_forced_login(evt: CommandEvent) -> None:
if not evt.sender.force_login: if not evt.sender.force_login:

View File

@ -76,6 +76,7 @@ async def ping(evt: CommandEvent) -> None:
help_section=SECTION_CONNECTION, help_section=SECTION_CONNECTION,
help_text="(Re)connect to KakaoTalk chats & sync any missed chat updates", help_text="(Re)connect to KakaoTalk chats & sync any missed chat updates",
help_args="[_number of channels to sync_]", help_args="[_number of channels to sync_]",
aliases=["connect"],
) )
async def sync(evt: CommandEvent) -> None: async def sync(evt: CommandEvent) -> None:
try: try:

View File

@ -19,7 +19,7 @@ from typing import TYPE_CHECKING, Awaitable
import asyncio import asyncio
from mautrix.bridge.commands import HelpSection, command_handler from mautrix.bridge.commands import HelpSection, command_handler
from mautrix.types import SerializerError from mautrix.types import Format, SerializerError
from mautrix.util import utf16_surrogate from mautrix.util import utf16_surrogate
from mautrix.util.formatter import ( from mautrix.util.formatter import (
EntityString, EntityString,
@ -237,10 +237,10 @@ async def _edit_friend(evt: CommandEvent, add: bool) -> None:
if not evt.args: if not evt.args:
await evt.reply(f"**Usage:** `$cmdprefix+sp {evt.command} <KakaoTalk ID|Matrix user ID>`") await evt.reply(f"**Usage:** `$cmdprefix+sp {evt.command} <KakaoTalk ID|Matrix user ID>`")
return return
formatted_body = evt.content.get("formatted_body") if evt.content.get("format", None) == Format.HTML and evt.content["formatted_body"]:
if formatted_body: parsed = await MentionParser().parse(utf16_surrogate.add(
arg = formatted_body[len(evt.command):].strip() evt.content["formatted_body"][len(evt.command):].strip()
parsed = await MentionParser().parse(utf16_surrogate.add(arg)) ))
if not parsed.entities: if not parsed.entities:
await evt.reply("No user found") await evt.reply("No user found")
return return
@ -311,5 +311,4 @@ async def leave(evt: CommandEvent) -> None:
await evt.reply("This command may only be used in a KakaoTalk channel portal room") await evt.reply("This command may only be used in a KakaoTalk channel portal room")
return return
await evt.mark_read() await evt.mark_read()
await evt.sender.client.leave_channel(evt.portal.channel_props) await evt.portal.leave_kakaotalk_channel()
await evt.sender.on_channel_left(evt.portal.ktid, evt.portal.kt_type)

View File

@ -154,7 +154,11 @@ async def matrix_to_kakaotalk(
) )
else: else:
reply_to = None reply_to = None
if content.get("format", None) == Format.HTML and content["formatted_body"] and content.msgtype.is_text: if (
content.get("format", None) == Format.HTML and content["formatted_body"] and
content.msgtype.is_text and
not portal.is_direct
):
parsed = await ToKakaoTalkParser().parse(utf16_surrogate.add(content["formatted_body"])) parsed = await ToKakaoTalkParser().parse(utf16_surrogate.add(content["formatted_body"]))
text = utf16_surrogate.remove(parsed.text) text = utf16_surrogate.remove(parsed.text)
mentions_by_user: dict[Long, MentionStruct] = {} mentions_by_user: dict[Long, MentionStruct] = {}

View File

@ -1386,6 +1386,10 @@ class Portal(DBPortal, BasePortal):
else: else:
self.log.debug(f"{user.mxid} left portal to {self.ktid}") self.log.debug(f"{user.mxid} left portal to {self.ktid}")
async def leave_kakaotalk_channel(self, user: u.User) -> None:
await user.client.leave_channel(self.channel_props)
await user.on_channel_left(self.ktid, self.kt_type)
# endregion # endregion
# region KakaoTalk event handling # region KakaoTalk event handling
@ -1866,7 +1870,7 @@ class Portal(DBPortal, BasePortal):
self.log.trace("Leaving room with %s post-backfill", intent.mxid) self.log.trace("Leaving room with %s post-backfill", intent.mxid)
await intent.leave_room(self.mxid) await intent.leave_room(self.mxid)
self.log.info("Backfilled %d messages through %s", len(chats), source.mxid) self.log.info("Backfilled %d messages through %s", len(chats), source.mxid)
self._sync_read_receipts(source) await self._sync_read_receipts(source)
# region Database getters # region Database getters