diff --git a/README.md b/README.md index 3d98127..9e4ce8b 100644 --- a/README.md +++ b/README.md @@ -22,8 +22,8 @@ That said, it is usable for basic chatting. | Name | M->I | I->M | Notes | | ---- | :--: | :--: | ----- | -| text, notice, emote messages | ❌ | ❌ || -| image, file, audio, video messages | ❌ | ❌ || +| text, notice, emote messages | ✅ | ✅ || +| image, file, audio, video messages | 🟨 | ❌ | Show up as MXC links on IRC | | Channel joins | ❌ | ❌ || | Channel parts | ❌ | ❌ || | Channel kicks | ❌ | ❌ || diff --git a/src/Client.ts b/src/Client.ts index a333dee..dd1b640 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -79,10 +79,22 @@ export class Client { } break; } + case 'NOTICE': { + if (this.user) { + this.user.sendMessageToMatrix(message, this); + } + break; + } case 'PING': { this.sendMessage(this.server.name, "PONG", message.params, message.tags); break; } + case 'PRIVMSG': { + if (this.user) { + this.user.sendMessageToMatrix(message, this); + } + break; + } case 'WHO': { if (!this.user) { return; diff --git a/src/IRCUser.ts b/src/IRCUser.ts index ebe7747..e23a9b7 100644 --- a/src/IRCUser.ts +++ b/src/IRCUser.ts @@ -1,6 +1,8 @@ import axios from "axios"; +import { randomUUID } from "crypto"; import { Channel } from "./Channel.js"; import { Client } from "./Client.js"; +import { IRCMessage } from "./Message.js"; import { Server } from "./Server.js"; export class IRCUser { @@ -11,7 +13,7 @@ export class IRCUser { private hostname: string public accountName: string public realname: string - private txnIdStore: Set + private txnIdStore: Map public nextBatch: string private initialSync: boolean private syncIntervalID: NodeJS.Timeout; @@ -24,7 +26,7 @@ export class IRCUser { this.hostname = mxidSplit[1]; this.accountName = mxid.slice(1); this.realname = this.accountName; - this.txnIdStore = new Set(); + this.txnIdStore = new Map(); this.nextBatch = ""; this.initialSync = false; this.syncIntervalID = setInterval(this.doSync.bind(this), 15000); @@ -72,6 +74,29 @@ export class IRCUser { }) } + sendMessageToMatrix(message: IRCMessage, client: Client) { + const channel = this.server.matrixRooms.get(message.params[0]); + if (!channel) { + return; + } + let msgtype = 'm.text'; + let msgbody = message.params[1]; + if (message.command === 'NOTICE') + msgtype = 'm.notice'; + else if (message.params[1].startsWith('\x01')) { + msgtype = 'm.emote'; + msgbody = msgbody.replace(/\x01(ACTION\s)?/gi, ''); + } + const roomId = channel.roomId; + const content = { + "body": msgbody, + "msgtype": msgtype, + } + const newTxnid = randomUUID(); + this.txnIdStore.set(newTxnid, client); + axios.put(`https://matrix.org/_matrix/client/v3/rooms/${channel.roomId}/send/m.room.message/${newTxnid}?access_token=${this.accessToken}`, content); + } + sendToAll(prefix: string, command: string, params: string[], tags: Map = new Map(), skipClient: Client|null = null) { this.clients.forEach(client => { if (client !== skipClient) {