Compare commits
6 Commits
36598c34f6
...
79fe8748b1
Author | SHA1 | Date | |
---|---|---|---|
79fe8748b1 | |||
d7d8cbbbb6 | |||
d4d02e8aba | |||
fbd3d514e3 | |||
53d3170c04 | |||
45fdd5ca29 |
@ -65,9 +65,13 @@ async def whoami(evt: CommandEvent) -> None:
|
|||||||
await evt.reply(f"Error from KakaoTalk: {e}")
|
await evt.reply(f"Error from KakaoTalk: {e}")
|
||||||
return
|
return
|
||||||
if own_info:
|
if own_info:
|
||||||
|
puppet = await pu.Puppet.get_by_ktid(evt.sender.ktid)
|
||||||
uuid = f"`{own_info.more.uuid}` ({'searchable' if own_info.more.uuidSearchable else 'hidden'})" if own_info.more.uuid else "_none_"
|
uuid = f"`{own_info.more.uuid}` ({'searchable' if own_info.more.uuidSearchable else 'hidden'})" if own_info.more.uuid else "_none_"
|
||||||
await evt.reply(
|
await evt.reply(
|
||||||
f"You're logged in as **{own_info.more.nickName}** (KakaoTalk ID: {uuid}, internal ID: `{evt.sender.ktid}`)"
|
f"You're logged in as **{own_info.more.nickName}**"
|
||||||
|
f"\n* KakaoTalk ID: {uuid}"
|
||||||
|
f"\n* Internal ID: `{evt.sender.ktid}`"
|
||||||
|
f"\n* Matrix user: [{puppet.name}](https://matrix.to/#/{puppet.default_mxid})"
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
await evt.reply(
|
await evt.reply(
|
||||||
@ -153,13 +157,13 @@ async def _set_id_searchable(evt: CommandEvent, searchable: bool) -> None:
|
|||||||
else:
|
else:
|
||||||
await evt.reply(f"Successfully made KakaoTalk ID {'searchable' if searchable else 'hidden'}")
|
await evt.reply(f"Successfully made KakaoTalk ID {'searchable' if searchable else 'hidden'}")
|
||||||
|
|
||||||
|
|
||||||
async def _get_search_result_puppet(source: u.User, friend_struct: FriendStruct) -> pu.Puppet:
|
async def _get_search_result_puppet(source: u.User, friend_struct: FriendStruct) -> pu.Puppet:
|
||||||
puppet = await pu.Puppet.get_by_ktid(friend_struct.userId)
|
puppet = await pu.Puppet.get_by_ktid(friend_struct.userId)
|
||||||
if not puppet.name_set:
|
if not puppet.name_set:
|
||||||
await puppet.update_info_from_friend(source, friend_struct)
|
await puppet.update_info_from_friend(source, friend_struct)
|
||||||
return puppet
|
return puppet
|
||||||
|
|
||||||
|
|
||||||
@command_handler(
|
@command_handler(
|
||||||
needs_auth=True,
|
needs_auth=True,
|
||||||
management_only=False,
|
management_only=False,
|
||||||
@ -311,4 +315,7 @@ 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.portal.leave_kakaotalk_channel()
|
try:
|
||||||
|
await evt.sender.leave_channel(evt.portal)
|
||||||
|
except CommandException as e:
|
||||||
|
await evt.reply(f"Error from KakaoTalk: {e}")
|
||||||
|
@ -1386,10 +1386,6 @@ 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
|
||||||
|
|
||||||
@ -1762,19 +1758,20 @@ class Portal(DBPortal, BasePortal):
|
|||||||
self, source: u.User, sender: p.Puppet | None, removed: p.Puppet
|
self, source: u.User, sender: p.Puppet | None, removed: p.Puppet
|
||||||
) -> None:
|
) -> None:
|
||||||
sender_intent = sender.intent_for(self) if sender else self.main_intent
|
sender_intent = sender.intent_for(self) if sender else self.main_intent
|
||||||
|
removed_user = await u.User.get_by_ktid(removed.ktid)
|
||||||
if sender == removed:
|
if sender == removed:
|
||||||
removed_intent = removed.intent_for(self)
|
if not removed.is_real_user and removed_user:
|
||||||
if removed_intent != self.main_intent:
|
try:
|
||||||
await removed_intent.leave_room(self.mxid)
|
await sender_intent.kick_user(self.mxid, removed_user.mxid, "Left channel from KakaoTalk")
|
||||||
if not removed.is_real_user:
|
except MForbidden:
|
||||||
user = await u.User.get_by_ktid(removed.ktid)
|
pass
|
||||||
if user:
|
await removed.intent_for(self).leave_room(self.mxid)
|
||||||
await self.main_intent.kick_user(self.mxid, user.mxid, "Left channel from KakaoTalk")
|
|
||||||
else:
|
else:
|
||||||
for removed_mxid in (r.mxid for r in (
|
for removed_mxid in (r.mxid for r in (
|
||||||
removed,
|
removed,
|
||||||
await u.User.get_by_ktid(removed.ktid) if not removed.is_real_user else None
|
removed_user if not removed.is_real_user else None
|
||||||
) if r):
|
) if r):
|
||||||
|
# NOTE KakaoTalk kick = Matrix ban
|
||||||
try:
|
try:
|
||||||
await sender_intent.ban_user(
|
await sender_intent.ban_user(
|
||||||
self.mxid, removed_mxid, None if sender else "Kicked by channel admin"
|
self.mxid, removed_mxid, None if sender else "Kicked by channel admin"
|
||||||
@ -1785,7 +1782,11 @@ class Portal(DBPortal, BasePortal):
|
|||||||
await self.main_intent.ban_user(
|
await self.main_intent.ban_user(
|
||||||
self.mxid, removed_mxid, reason=f"Kicked by {sender.name}"
|
self.mxid, removed_mxid, reason=f"Kicked by {sender.name}"
|
||||||
)
|
)
|
||||||
# TODO Clean and delete if removed is real user and portal is direct / not open
|
if self.is_direct and removed.ktid == self.kt_receiver:
|
||||||
|
self.log.info(
|
||||||
|
f"{removed.ktid} was the recipient puppet of this portal. Cleaning up and deleting..."
|
||||||
|
)
|
||||||
|
await self.cleanup_and_delete()
|
||||||
|
|
||||||
# TODO Find when or if there is a listener for this
|
# TODO Find when or if there is a listener for this
|
||||||
# TODO Confirm whether this can refer to any user that was kicked, or only to the current user
|
# TODO Confirm whether this can refer to any user that was kicked, or only to the current user
|
||||||
|
@ -685,7 +685,7 @@ class User(DBUser, BaseUser):
|
|||||||
kt_type = KnownChannelType.MemoChat
|
kt_type = KnownChannelType.MemoChat
|
||||||
memo_ids = await self.client.get_memo_ids()
|
memo_ids = await self.client.get_memo_ids()
|
||||||
if not memo_ids:
|
if not memo_ids:
|
||||||
ktid = Long(0)
|
ktid = None
|
||||||
else:
|
else:
|
||||||
ktid = memo_ids[0]
|
ktid = memo_ids[0]
|
||||||
if len(memo_ids) > 1:
|
if len(memo_ids) > 1:
|
||||||
@ -702,6 +702,13 @@ class User(DBUser, BaseUser):
|
|||||||
ktid, kt_receiver=self.ktid, create=create, kt_type=kt_type
|
ktid, kt_receiver=self.ktid, create=create, kt_type=kt_type
|
||||||
) if ktid else None
|
) if ktid else None
|
||||||
|
|
||||||
|
# region Matrix->KakaoTalk commands
|
||||||
|
|
||||||
|
async def leave_channel(self, portal: po.Portal) -> None:
|
||||||
|
await self.client.leave_channel(portal.channel_props)
|
||||||
|
await self.on_channel_left(portal.ktid, portal.kt_type)
|
||||||
|
|
||||||
|
# endregion
|
||||||
# region KakaoTalk event handling
|
# region KakaoTalk event handling
|
||||||
|
|
||||||
async def on_connect(self, force_sync: bool) -> bool:
|
async def on_connect(self, force_sync: bool) -> bool:
|
||||||
|
@ -155,10 +155,19 @@ class UserClient {
|
|||||||
})
|
})
|
||||||
|
|
||||||
this.#talkClient.on("chat_read", (chat, channel, reader) => {
|
this.#talkClient.on("chat_read", (chat, channel, reader) => {
|
||||||
this.log(`Chat ${chat.logId} read in channel ${channel.channelId} by ${reader.userId}`)
|
let senderId
|
||||||
|
if (reader) {
|
||||||
|
senderId = reader.userId
|
||||||
|
} else if (channel.info.type == "MemoChat") {
|
||||||
|
senderId = channel.clientUser.userId
|
||||||
|
} else {
|
||||||
|
this.error(`Chat ${chat.logId} read in channel ${channel.channelId} by unknown reader (channel type: ${channel.info.type || "none"})`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.log(`Chat ${chat.logId} read in channel ${channel.channelId} by ${senderId}`)
|
||||||
this.write("chat_read", {
|
this.write("chat_read", {
|
||||||
chatId: chat.logId,
|
chatId: chat.logId,
|
||||||
senderId: reader.userId,
|
senderId: senderId,
|
||||||
channelId: channel.channelId,
|
channelId: channel.channelId,
|
||||||
channelType: channel.info.type,
|
channelType: channel.info.type,
|
||||||
})
|
})
|
||||||
@ -298,7 +307,7 @@ class UserClient {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
this.#talkClient.on("disconnected", (reason) => {
|
this.#talkClient.on("disconnected", reason => {
|
||||||
this.log(`Disconnected (reason=${reason})`)
|
this.log(`Disconnected (reason=${reason})`)
|
||||||
this.disconnect()
|
this.disconnect()
|
||||||
this.write("disconnected", {
|
this.write("disconnected", {
|
||||||
@ -313,7 +322,7 @@ class UserClient {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
this.#talkClient.on("error", (err) => {
|
this.#talkClient.on("error", err => {
|
||||||
this.log(`Client error: ${err}`)
|
this.log(`Client error: ${err}`)
|
||||||
this.write("error", {
|
this.write("error", {
|
||||||
error: err,
|
error: err,
|
||||||
@ -1072,7 +1081,7 @@ export default class PeerClient {
|
|||||||
if (!talkChannel.getUserInfo(user)) {
|
if (!talkChannel.getUserInfo(user)) {
|
||||||
throw new ProtocolError("Cannot set permission level of a user that is not a channel participant")
|
throw new ProtocolError("Cannot set permission level of a user that is not a channel participant")
|
||||||
}
|
}
|
||||||
if (req.user_id == talkChannel.clientUser.userId) {
|
if (req.user_id.equals(talkChannel.clientUser.userId)) {
|
||||||
throw new ProtocolError("Cannot change own permission level")
|
throw new ProtocolError("Cannot change own permission level")
|
||||||
}
|
}
|
||||||
return await talkChannel.setUserPerm(user, req.perm)
|
return await talkChannel.setUserPerm(user, req.perm)
|
||||||
@ -1135,13 +1144,31 @@ export default class PeerClient {
|
|||||||
* @param {Long} req.user_id
|
* @param {Long} req.user_id
|
||||||
*/
|
*/
|
||||||
createDirectChat = async (req) => {
|
createDirectChat = async (req) => {
|
||||||
const channelList = this.#getUser(req.mxid).talkClient.channelList.normal
|
const userClient = this.#getUser(req.mxid)
|
||||||
const res = await channelList.createChannel({
|
const channelList = userClient.talkClient.channelList.normal
|
||||||
|
|
||||||
|
const createChannel =
|
||||||
|
!req.user_id.equals(userClient.userId)
|
||||||
|
? channelList.createChannel.bind(channelList, {
|
||||||
userList: [{ userId: req.user_id }],
|
userList: [{ userId: req.user_id }],
|
||||||
})
|
})
|
||||||
if (!res.success) return res
|
: channelList.createMemoChannel.bind(channelList)
|
||||||
|
|
||||||
|
const retry_delay = 2000
|
||||||
|
let retries_left = 1
|
||||||
|
let res
|
||||||
|
do {
|
||||||
|
res = await createChannel()
|
||||||
|
if (res.success) {
|
||||||
return makeCommandResult(res.result.channelId)
|
return makeCommandResult(res.result.channelId)
|
||||||
}
|
}
|
||||||
|
this.error(`Failed to create direct chat, try again in ${retry_delay} ms (${retries_left - 1} tries remaining)`)
|
||||||
|
await new Promise(resolve => setTimeout(resolve, retry_delay))
|
||||||
|
} while (retries_left--)
|
||||||
|
|
||||||
|
this.error(`Failed to create direct chat, not retrying`)
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Object} req
|
* @param {Object} req
|
||||||
|
Loading…
Reference in New Issue
Block a user