diff --git a/README.md b/README.md index 0aed098..333727f 100644 --- a/README.md +++ b/README.md @@ -24,10 +24,11 @@ That said, it is usable for basic chatting. | ---- | :--: | :--: | ----- | | text, notice, emote messages | ✅ | ✅ || | image, file, audio, video messages | 🟨 | ❌ | Show up as links on IRC | -| Channel joins | ❌ | ❌ || -| Channel parts | ❌ | ❌ || -| Channel kicks | ❌ | ❌ || -| Channel bans | ❌ | ❌ || +| Channel joins | ✅ | ❌ || +| Channel parts | ✅ | ❌ || +| Channel kicks | ✅ | ❌ || +| Channel bans | 🟨 | ❌ | Bans show up on IRC as kicks | +| Channel invites | ✅ | ❌ || | Channel topics | ❌ | ❌ || | Channel powers | ❌ | ❌ || | Encrypted rooms | ❌ | ❌ || diff --git a/src/Channel.ts b/src/Channel.ts index d9e86b7..6be3fe0 100644 --- a/src/Channel.ts +++ b/src/Channel.ts @@ -164,11 +164,55 @@ export class Channel { } handleMatrixMember(event: any) { - const thisMatrixUser = this.server.getOrCreateMatrixUser(event["sender"]); - // During initial sync, all past/present members are returned, so we filter out non-joined members - if (event["content"]["membership"] !== "join" && !this.matrixUsers.has(thisMatrixUser.nick)) + const targetUser = this.server.getOrCreateMatrixUser(event["state_key"]); + const sourceUser = this.server.getOrCreateMatrixUser(event["sender"]); + const content = event["content"]; + if (!content) return; - this.matrixUsers.set(thisMatrixUser.nick, thisMatrixUser); + + const membershipStatus = content["membership"]; + + const messageTags = new Map(); + messageTags.set('time', new Date(event["origin_server_ts"]).toISOString()); + messageTags.set('account', sourceUser.accountName); + if (membershipStatus === "invite") { + this.ircUsers.forEach((user) => { + user.sendToAllWithCap('invite-notify', sourceUser.getMask(), 'INVITE', [targetUser.nick, this.name], messageTags); + }); + } + else if (membershipStatus === "join") { + if (!this.matrixUsers.has(targetUser.nick)) + this.joinMatrixUser(targetUser, event); + } + else if (membershipStatus === "leave") { + if (!this.matrixUsers.has(targetUser.nick)) + return; + if (targetUser.mxid === sourceUser.mxid) { + const reason = content["reason"] || 'User left'; + this.ircUsers.forEach((user) => { + user.sendToAll(sourceUser.getMask(), 'PART', [this.name, reason], messageTags); + }); + } + else { + const reason = content["reason"] || 'User was kicked'; + this.ircUsers.forEach((user) => { + user.sendToAll(sourceUser.getMask(), 'KICK', [this.name, targetUser.nick, reason], messageTags); + }); + } + this.matrixUsers.delete(targetUser.nick) + } + else if (membershipStatus === "ban") { + if (!this.matrixUsers.has(targetUser.nick)) + return; + const reason = content["reason"] || 'User was banned'; + this.ircUsers.forEach((user) => { + user.sendToAll(sourceUser.getMask(), 'KICK', [this.name, targetUser.nick, reason], messageTags); + }); + this.matrixUsers.delete(targetUser.nick) + } + else { + console.log(`Got unknown m.room.member event: ${event}`); + } } handleMatrixMessage(event: any) {