Fixes to outbound channel name & topic setting

- Use the correct API for open channels
- Allow changing the name (title) of normal channels
This commit is contained in:
Andrew Ferrazzutti 2022-05-16 01:53:21 -04:00
parent bccd0ed4e0
commit 1541732d0b
3 changed files with 91 additions and 35 deletions

View File

@ -25,8 +25,8 @@
* [ ] Ban<sup>[4]</sup> * [ ] Ban<sup>[4]</sup>
* [ ] Unban<sup>[4]</sup> * [ ] Unban<sup>[4]</sup>
* [ ] Room metadata changes * [ ] Room metadata changes
* [x] Name<sup>[1]</sup> * [x] Name
* [x] Topic<sup>[1]</sup> * [x] Topic
* [ ] Avatar * [ ] Avatar
* [ ] Per-room user nick * [ ] Per-room user nick
* KakaoTalk → Matrix * KakaoTalk → Matrix

View File

@ -1219,9 +1219,6 @@ class Portal(DBPortal, BasePortal):
# Misses should be guarded by supports_state_event, but handle this just in case # Misses should be guarded by supports_state_event, but handle this just in case
self.log.error(f"Skipping Matrix state event {evt.event_id} of unsupported type {evt.type}") self.log.error(f"Skipping Matrix state event {evt.event_id} of unsupported type {evt.type}")
return return
if not self.is_open:
self.log.info(f"Not bridging f{handler.action_name} change of portal for non-open channel")
return
try: try:
effective_sender, _ = await self.get_relay_sender(sender, f"{handler.action_name} {evt.event_id}") effective_sender, _ = await self.get_relay_sender(sender, f"{handler.action_name} {evt.event_id}")
if effective_sender: if effective_sender:
@ -1338,6 +1335,9 @@ class Portal(DBPortal, BasePortal):
) -> None: ) -> None:
if content.topic == prev_content.topic: if content.topic == prev_content.topic:
return return
if not self.is_open:
self.log.info(f"Not bridging topic change of portal for non-open channel")
return
if not (sender and sender.is_connected): if not (sender and sender.is_connected):
raise Exception( raise Exception(
"Only users connected to KakaoTalk can set the description of a KakaoTalk channel" "Only users connected to KakaoTalk can set the description of a KakaoTalk channel"

View File

@ -366,20 +366,39 @@ class UserClient {
* @param {ChannelProps} channelProps * @param {ChannelProps} channelProps
*/ */
async getChannel(channelProps) { async getChannel(channelProps) {
let channel = this.#talkClient.channelList.get(channelProps.id) const talkChannel = this.#talkClient.channelList.get(channelProps.id)
if (channel) { if (talkChannel) {
return channel return talkChannel
} else {
const channelList = getChannelListForType(
this.#talkClient.channelList,
channelProps.type
)
const res = await channelList.addChannel({ channelId: channelProps.id })
if (!res.success) {
throw new Error(`Unable to add ${channelProps.type} channel ${channelProps.id}`)
}
return res.result
} }
const channelList = getChannelListForType(
this.#talkClient.channelList,
channelProps.type
)
const res = await channelList.addChannel({ channelId: channelProps.id })
if (!res.success) {
this.error(`Unable to add ${channelProps.type} channel ${channelProps.id}`)
throw res
}
return res.result
}
/**
* @param {Long} channelId
*/
async getNormalChannel(channelId) {
const channelList = this.#talkClient.channelList.normal
const talkChannel = channelList.get(channelId)
if (talkChannel) {
return talkChannel
}
const res = await channelList.addChannel({ channelId: channelId })
if (!res.success) {
this.error(`Unable to add normal channel ${channelProps.id}`)
throw res
}
return res.result
} }
/** /**
@ -600,14 +619,32 @@ export default class PeerClient {
const userClient = this.#getUser(mxid) const userClient = this.#getUser(mxid)
const talkChannel = await userClient.getChannel(channelProps) const talkChannel = await userClient.getChannel(channelProps)
if (permNeeded) { if (permNeeded) {
const permActual = talkChannel.getUserInfo({ userId: userClient.userId }).perm await this.#requireChannelPerm(talkChannel, permNeeded, action)
if (permNeeded.indexOf(permActual) == -1) {
throw new PermError(permNeeded, permActual, action)
}
} }
return talkChannel return talkChannel
} }
/**
* @param {TalkOpenChannel} talkChannel
* @param {OpenChannelUserPerm[]} permNeeded Throw if the user's permission level matches none of the values in this list.
* @param {string} action The action requiring permission
* @throws {PermError} if the user does not have the specified permission level.
*/
async #requireChannelPerm(talkChannel, permNeeded, action) {
const permActual = talkChannel.getUserInfo({ userId: talkChannel.clientUser.userId }).perm
if (permNeeded.indexOf(permActual) == -1) {
throw new PermError(permNeeded, permActual, action)
}
}
/**
* @param {string} mxid
* @param {Long} channelId
*/
async #getUserNormalChannel(mxid, channelId) {
return await this.#getUser(mxid).getNormalChannel(channelId)
}
/** /**
* @param {object} req * @param {object} req
* @param {string} req.mxid * @param {string} req.mxid
@ -1104,13 +1141,12 @@ export default class PeerClient {
* @param {string} req.name * @param {string} req.name
*/ */
setChannelName = async (req) => { setChannelName = async (req) => {
const talkChannel = await this.#getUserChannel( if (!isChannelTypeOpen(req.channel_props.type)) {
req.mxid, const talkChannel = await this.#getUserNormalChannel(req.mxid, req.channel_props.id)
req.channel_props, return await talkChannel.setTitleMeta(req.name)
[OpenChannelUserPerm.OWNER], } else {
"change channel name" return await this.#setOpenChannelProperty(req.mxid, req.channel_props, "linkName", req.name)
) }
return await talkChannel.setTitleMeta(req.name)
} }
/** /**
@ -1120,13 +1156,33 @@ export default class PeerClient {
* @param {string} req.description * @param {string} req.description
*/ */
setChannelDescription = async (req) => { setChannelDescription = async (req) => {
const talkChannel = await this.#getUserChannel( return await this.#setOpenChannelProperty(req.mxid, req.channel_props, "description", req.description)
req.mxid, }
req.channel_props,
[OpenChannelUserPerm.OWNER], /**
"change channel description" * @param {string} mxid
* @param {ChannelProps} channelProps
* @param {string} propertyName
* @param {any} propertyValue
*/
async #setOpenChannelProperty(mxid, channelProps, propertyName, propertyValue) {
if (isChannelTypeOpen(channelProps)) {
throw ProtocolError(`Cannot set ${propertyName} of non-open channel ${channelProps.id} (type = ${channelProps.type})`)
}
const userClient = this.#getUser(mxid)
/** @type {TalkOpenChannel} */
const talkChannel = await userClient.getChannel(channelProps)
this.#requireChannelPerm(talkChannel, [OpenChannelUserPerm.OWNER], `change channel ${propertyName}`)
const linkRes = await talkChannel.getLatestOpenLink()
if (!linkRes.success) throw linkRes
const link = linkRes.result
link[propertyName] = propertyValue
return await userClient.talkClient.channelList.open.updateOpenLink(
{ linkId: link.linkId }, link
) )
return await talkChannel.setNoticeMeta(req.description)
} }
/* /*