From 0e1117e796ad6ed1d8ba17e7c6ce35153ffb9b41 Mon Sep 17 00:00:00 2001 From: emerson Date: Wed, 2 Feb 2022 18:55:09 -0500 Subject: [PATCH] Implement message deletion --- docs/specs/edit-message.md | 6 +++--- src/Client.ts | 30 ++++++++++++++++++++++++++++-- src/IRCUser.ts | 22 ++++++++++++++++++++++ src/Message.ts | 2 ++ 4 files changed, 55 insertions(+), 5 deletions(-) diff --git a/docs/specs/edit-message.md b/docs/specs/edit-message.md index 2a895ea..bb7b1d3 100644 --- a/docs/specs/edit-message.md +++ b/docs/specs/edit-message.md @@ -29,9 +29,9 @@ Servers and clients implementing this spec MUST also implement the `message-tags To edit a message, clients send the edited message with a tag of `edit-message`. This tag has a required value of the `msgid` from the original message. The edited message MUST have the same command and first parameter as the original message, unless it is being changed into a multiline message (see below) -Servers MUST support editing `PRIVMSG`, `NOTICE`, `TAGMSG`, and `PART` messages, and MAY support editing any other type of message. Servers SHOULD enforce all checks that they normally would for that specific type of message (line length, color stripping, censoring, etc.) and return appropriate numerics if the message fails a check. +Servers MUST support editing `PRIVMSG`, `NOTICE`, and `TAGMSG` messages, and MAY support editing any other type of message. Servers SHOULD enforce all checks that they normally would for that specific type of message (line length, color stripping, censoring, etc.) and return appropriate numerics if the message fails a check. -Client tags attached to the original message MUST be attached to the edited message to preserve or edit their value. If a client tag in the original message is not included in the edited message, +Client tags attached to the original message MUST be attached to the edited message to preserve or edit their value. If a client tag in the original message is not included in the edited message, clients must consider it removed and no longer a part of the message. If the server has any persistent history store for the type of message that is edited, @@ -41,7 +41,7 @@ To delete a message, clients send a `DELETEMSG` message to the channel or user t Clients who receive a `DELETEMSG` with the `draft/delete-message` tag MUST remove all displayed content from the specified `msgid`. If the original message is ephemeral, clients SHOULD remove it entirely; otherwise they MUST replace the content with the deletion reason or a generic substitute. -Servers MUST ensure that the user requesting deletion has sufficient privileges to delete the specified message. Servers MUST remove the content of the original message from all persistent history stores, and MAY replace the content with a generic deletion message if needed. +Servers MUST ensure that the user requesting deletion has sufficient privileges to delete the specified message. Servers MUST remove the content of the original message from all persistent history stores, and MAY replace the content with the deletion reason or a generic deletion message if needed. ## Examples diff --git a/src/Client.ts b/src/Client.ts index 1e85813..0003bc4 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -115,6 +115,9 @@ export class Client { case 'CAP': this.doCAP(message); break; + case 'DELETEMSG': + this.doDELETEMSG(message); + break; case 'INVITE': this.doINVITE(message); break; @@ -251,6 +254,29 @@ export class Client { } } + doDELETEMSG(message: IRCMessage) { + if (!this.checkIfRegistered() || !this.checkMinParams(message, 1)) + return; + const targetChannel = this.getChannel(message.params[0]); + const eventId = message.tags.get("draft/delete-message"); + if (!this.user || !targetChannel || !eventId) return; + if (!this.checkIfInChannel(targetChannel)) return; + const data = { + "reason": (message.params.length === 2) ? message.params[1] : "" + } + const newTxnid = randomUUID(); + axios.put(`https://${this.user.homeserver}/_matrix/client/v3/rooms/${targetChannel.roomId}/redact/${eventId}/${newTxnid}?access_token=${this.user.accessToken}`, data).catch(function (error) { + if (error.response) { + console.log(error.response.data); + } else if (error.request) { + console.log(error.request); + } else { + console.log('Error', error.message); + console.log(error.config); + } + }) + } + doINVITE(message: IRCMessage) { if (!this.checkIfRegistered() || !this.checkMinParams(message, 2)) return; @@ -566,8 +592,8 @@ export class Client { ['account', 'account-tag'], ['label', 'labeled-response'], ['msgid', 'message-tags'], - ['reflectionircd.chat/delete-message', 'reflectionircd.chat/delete-message'], - ['reflectionircd.chat/edit-message', 'reflectionircd.chat/edit-message'], + ['draft/delete-message', 'draft/delete-message'], + ['draft/edit-message', 'draft/edit-message'], ['time', 'server-time'], ]) const ourTags: Map = new Map(); diff --git a/src/IRCUser.ts b/src/IRCUser.ts index 939aabb..5681aec 100644 --- a/src/IRCUser.ts +++ b/src/IRCUser.ts @@ -210,6 +210,9 @@ export class IRCUser { case 'm.room.power_levels': this.handleMatrixPL(nextEvent, targetChannel); break; + case 'm.room.redaction': + this.handleMatrixRedaction(nextEvent, targetChannel); + break; case 'm.room.topic': this.handleMatrixTopic(nextEvent, targetChannel); break; @@ -479,6 +482,25 @@ export class IRCUser { } } + handleMatrixRedaction(event: any, targetChannel: Channel) { + const sourceUser = this.getOrCreateMatrixUser(event["sender"]); + if (!targetChannel.matrixUsers.has(sourceUser.nick)) { + targetChannel.matrixUsers.set(sourceUser.nick, sourceUser); + const prefix = sourceUser.getMask(); + const joinTags = new Map([["account", sourceUser.accountName], ['time', new Date(event["origin_server_ts"]).toISOString()]]) + this.sendToAllWithCap('extended-join', prefix, "JOIN", [targetChannel.name, sourceUser.accountName, sourceUser.realname], joinTags); + this.sendToAllWithoutCap('extended-join', prefix, "JOIN", [targetChannel.name], joinTags); + } + const reason = event["content"]?.["reason"] || ""; + const tags: Map = new Map(); + tags.set('draft/delete-message', event["redacts"]); + tags.set('account', sourceUser.accountName); + tags.set('time', new Date(event["origin_server_ts"]).toISOString()) + this.clients.forEach((client) => { + client.sendMessage(sourceUser.getMask(), 'DELETEMSG', [targetChannel.name, reason], tags); + }); + } + handleMatrixTopic(event: any, targetChannel: Channel) { const topicText = event["content"]?.["topic"]; if (!topicText) diff --git a/src/Message.ts b/src/Message.ts index 09422ac..e641a37 100644 --- a/src/Message.ts +++ b/src/Message.ts @@ -66,6 +66,8 @@ function encodeTag(value: string): string { function addToTags(key: string): boolean { const tagsToPass = [ 'batch', + 'draft/delete-message', + 'draft/edit-message', 'label', ] return (tagsToPass.includes(key) || key.startsWith('+'));