From 8772f9734111488b6278d24c34f636b038dd18ac Mon Sep 17 00:00:00 2001 From: emerson Date: Mon, 24 Jan 2022 20:08:38 -0500 Subject: [PATCH] handle PL changes --- README.md | 2 +- src/Channel.ts | 18 +++++++++++++++++- src/IRCUser.ts | 51 ++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 67 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index bbf989d..d4c84b3 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ That said, it is usable for basic chatting. | Channel bans | 🟨 | ❌ | Single-user bans show up on IRC as kicks, there's no banlist yet | | Channel invites | ✅ | ✅ || | Channel topics | ✅ | ✅ || -| Channel powers | ❌ | ❌ || +| Channel powers | ✅ | ❌ || | Channel lists/searching | ⬜ | ❌ || | Encrypted rooms | ❌ | ⬜ || | Rich text | ❌ | ❌ || diff --git a/src/Channel.ts b/src/Channel.ts index d4e96a3..863c9f5 100644 --- a/src/Channel.ts +++ b/src/Channel.ts @@ -47,6 +47,7 @@ export class Channel { }) this.syncLocks.add("m.room.topic"); axios.get(`https://${this.ircUser.homeserver}/_matrix/client/v3/rooms/${this.roomId}/event/m.room.topic?access_token=${this.ircUser.accessToken}`).then(response => { + this.syncLocks.delete("m.room.topic") const topicText = response.data["content"]?.["topic"]; if (!topicText) return; @@ -55,7 +56,6 @@ export class Channel { this.topic.set("text", topicText); this.topic.set("timestamp", topicTS.substring(0,10)) this.topic.set('setter', topicSetter.nick); - this.syncLocks.delete("m.room.topic") }).catch(e => { this.syncLocks.delete("m.room.topic") }) @@ -70,6 +70,22 @@ export class Channel { }).catch(e => { this.syncLocks.delete("m.room.members") }) + this.syncLocks.add("m.room.power_levels") + axios.get(`https://${this.ircUser.homeserver}/_matrix/client/v3/rooms/${this.roomId}/event/m.room.power_levels?access_token=${this.ircUser.accessToken}`).then(response => { + this.syncLocks.delete("m.room.power_levels") + const users = response.data["content"]?.["users"]; + if (!users) + return; + for (const [mxid, pl] of Object.entries(users)) { + const nextMatrixUser = this.ircUser.getOrCreateMatrixUser(mxid); + this.matrixUsers.set(nextMatrixUser.nick, nextMatrixUser); + const numPl = Number(pl); + if (numPl > 0) + this.powerLevels.set(nextMatrixUser.nick, numPl); + } + }).catch(e => { + this.syncLocks.delete("m.room.power_levels") + }) } checkChannelSync() { diff --git a/src/IRCUser.ts b/src/IRCUser.ts index 6d9d495..6feead7 100644 --- a/src/IRCUser.ts +++ b/src/IRCUser.ts @@ -400,12 +400,59 @@ export class IRCUser { }); } + convertPLToMode(pl: number, direction: string) { + let modeString: string = ""; + if (pl > 99) modeString = `${direction}o` + else if (pl > 49) modeString = `${direction}h` + else if (pl > 0) modeString = `${direction}v` + return modeString; + } + handleMatrixPL(event: any, targetChannel: Channel) { const allUsers = event["content"]["users"]; + const sourceUser = this.getOrCreateMatrixUser(event["sender"]); + if (!allUsers) return; + for (const [mxid, pl] of Object.entries(allUsers)) { - const thisMatrixUser = this.getOrCreateMatrixUser(event["sender"]); + const thisMatrixUser = this.getOrCreateMatrixUser(mxid); targetChannel.matrixUsers.set(thisMatrixUser.nick, thisMatrixUser); - targetChannel.powerLevels.set(thisMatrixUser.nick, Number(pl)); + const oldPl = targetChannel.powerLevels.get(thisMatrixUser.nick); + const newPl = Number(pl); + if (oldPl === undefined) { + targetChannel.powerLevels.set(thisMatrixUser.nick, newPl); + const modeChange = this.convertPLToMode(newPl, "+"); + this.clients.forEach(c => { + c.sendMessage(sourceUser.getMask(), "MODE", [targetChannel.name, modeChange, thisMatrixUser.nick]); + }) + } + else if (oldPl !== newPl) { + const oldModeChange = this.convertPLToMode(oldPl, "-"); + this.clients.forEach(c => { + c.sendMessage(sourceUser.getMask(), "MODE", [targetChannel.name, oldModeChange, thisMatrixUser.nick]); + }) + if (newPl !== 0) { + const newModeChange = this.convertPLToMode(newPl, "+"); + this.clients.forEach(c => { + c.sendMessage(sourceUser.getMask(), "MODE", [targetChannel.name, newModeChange, thisMatrixUser.nick]); + }) + } else { + targetChannel.powerLevels.delete(thisMatrixUser.nick) + } + } + } + if (targetChannel.powerLevels.size !== Object.keys(allUsers).length) { + for (const pl of targetChannel.powerLevels.keys()) { + const nextUser = this.nickToMatrixUser.get(pl); + if (!nextUser) return; + if (!(nextUser.mxid in allUsers)) { + const oldPl = targetChannel.powerLevels.get(pl); + if (!oldPl) return; + const oldMode = this.convertPLToMode(oldPl, "-"); + this.clients.forEach(c => { + c.sendMessage(sourceUser.getMask(), "MODE", [targetChannel.name, oldMode, nextUser.nick]); + }) + } + } } }