diff --git a/src/Channel.ts b/src/Channel.ts index 8f72a09..3f8e1bf 100644 --- a/src/Channel.ts +++ b/src/Channel.ts @@ -4,28 +4,25 @@ import { IRCUser } from "./IRCUser.js"; import { IRCMessage } from "./Message.js"; import { Client } from "./Client.js"; import numerics from "./numerics.js"; +import axios from "axios"; export class Channel { public name: string private matrixUsers: Map private ircUsers: Map - private nickToMXid: Map private powerLevels: Map private topic: Map; private modes: Map - private messages: Map; - private tsToEventId: Map; + private eventIDsSeen: Set; constructor(public roomId: string, private server: Server) { this.name = roomId; this.matrixUsers = new Map(); this.ircUsers = new Map(); - this.nickToMXid = new Map(); this.powerLevels = new Map(); this.topic = new Map([['text', ''], ['timestamp', '0'], ['setter', 'matrix']]); this.modes = new Map(); this.modes.set('n', ''); - this.messages = new Map(); - this.tsToEventId = new Map(); + this.eventIDsSeen = new Set(); } getNickPowerLevelMapping(nick: string): string { @@ -44,9 +41,9 @@ export class Channel { } joinNewIRCClient(client: Client, passedTags: Map) { - console.log('joining channel') if (!client.user) return; + this.ircUsers.set(client.user.nick, client.user); if (client.enabledCaps.has('extended-join')) { client.sendMessage(client.user.getMask(), "JOIN", [this.name, client.user.accountName, client.user.mxid], new Map([['account', client.user.realname]])); } else { @@ -126,13 +123,19 @@ export class Channel { } routeMatrixEvent(event: any) { - if (!event["type"]) + if (!event["type"] || !event["event_id"] || !event["origin_server_ts"]) return; switch (event["type"]) { case 'm.room.member': this.handleMatrixMember(event); break; + case 'm.room.message': { + if (this.eventIDsSeen.has(event["event_id"])) + return; + this.eventIDsSeen.add(event["event_id"]); + this.handleMatrixMessage(event); + } case 'm.room.power_levels': this.handleMatrixPL(event); break; @@ -145,10 +148,58 @@ export class Channel { } } + joinMatrixUser(matrixUser: MatrixUser, event: any) { + this.matrixUsers.set(matrixUser.nick, matrixUser); + const prefix = matrixUser.getMask(); + if (event) { + const tags = new Map([["account", matrixUser.accountName], ['time', new Date(event["origin_server_ts"]).toISOString()]]) + for (const user of this.ircUsers.values()) { + user.sendToAllWithCap('extended-join', prefix, "JOIN", [this.name, matrixUser.accountName, matrixUser.realname], tags); + user.sendToAllWithoutCap('extended-join', prefix, "JOIN", [this.name], tags); + } + } + } + handleMatrixMember(event: any) { const thisMatrixUser = this.server.getOrCreateMatrixUser(event["sender"]); this.matrixUsers.set(thisMatrixUser.nick, thisMatrixUser); - this.nickToMXid.set(thisMatrixUser.nick, thisMatrixUser.mxid); + } + + handleMatrixMessage(event: any) { + const thisMatrixUser = this.server.getOrCreateMatrixUser(event["sender"]); + if (!this.matrixUsers.has(thisMatrixUser.nick)) { + this.joinMatrixUser(thisMatrixUser, event); + } + const content = event["content"]; + const msgtype = content["msgtype"]; + let messageContent = content["body"]; + const tags: Map = new Map(); + tags.set('msgid', event["event_id"]); + tags.set('account', thisMatrixUser.accountName); + tags.set('time', new Date(event["origin_server_ts"]).toISOString()) + const maybeReply = content["m.relates_to"]?.["m.in_reply_to"]?.["event_id"]; + if (maybeReply) { + tags.set('+draft/reply', maybeReply); + } + const ircCommand = (msgtype === 'm.notice') ? 'NOTICE' : 'PRIVMSG'; + if (msgtype === 'm.emote') { + messageContent = `\x01ACTION ${messageContent}\x01`; + } + else if (['m.image', 'm.file', 'm.audio', 'm.video'].includes(msgtype)) { + let url: string = content["url"]; + if (!url) + return; + messageContent = `\x01ACTION shared ${messageContent}: ${url}\x01`; + } + const msgArray = (messageContent.indexOf('\n') !== -1) ? messageContent.split('\n'): [messageContent]; + msgArray.forEach((msg: string) => { + if (msg) { + this.ircUsers.forEach((user) => { + //@ts-ignore + user.sendToAll(sender.getMask(), ircCommand, [this.name, msg], tags) + }); + } + }); } handleMatrixPL(event: any) {