diff --git a/d2m/actions/delete-message.js b/d2m/actions/delete-message.js
new file mode 100644
index 0000000..261c8f9
--- /dev/null
+++ b/d2m/actions/delete-message.js
@@ -0,0 +1,29 @@
+// @ts-check
+
+const passthrough = require("../../passthrough")
+const { sync, db } = passthrough
+/** @type {import("../converters/edit-to-changes")} */
+const editToChanges = sync.require("../converters/edit-to-changes")
+/** @type {import("../../matrix/api")} */
+const api = sync.require("../../matrix/api")
+
+/**
+ * @param {import("discord-api-types/v10").GatewayMessageDeleteDispatchData} data
+ */
+async function deleteMessage(data) {
+ /** @type {string?} */
+ const roomID = db.prepare("SELECT channel_id FROM channel_room WHERE channel_id = ?").pluck().get(data.channel_id)
+ if (!roomID) return
+
+ /** @type {string[]} */
+ const eventsToRedact = db.prepare("SELECT event_id FROM event_message WHERE message_id = ?").pluck().all(data.id)
+
+ for (const eventID of eventsToRedact) {
+ // Unfortuately, we can't specify a sender to do the redaction as, unless we find out that info via the audit logs
+ await api.redactEvent(roomID, eventID)
+ db.prepare("DELETE from event_message WHERE event_id = ?").run(eventID)
+ // TODO: Consider whether this code could be reused between edited messages and deleted messages.
+ }
+}
+
+module.exports.deleteMessage = deleteMessage
diff --git a/d2m/actions/edit-message.js b/d2m/actions/edit-message.js
index 9a329b6..1c1b90e 100644
--- a/d2m/actions/edit-message.js
+++ b/d2m/actions/edit-message.js
@@ -14,7 +14,8 @@ const api = sync.require("../../matrix/api")
async function editMessage(message, guild) {
console.log(`*** applying edit for message ${message.id} in channel ${message.channel_id}`)
const {roomID, eventsToRedact, eventsToReplace, eventsToSend, senderMxid} = await editToChanges.editToChanges(message, guild, api)
- console.log("making these changes:", {eventsToRedact, eventsToReplace, eventsToSend})
+ console.log("making these changes:")
+ console.dir({eventsToRedact, eventsToReplace, eventsToSend}, {depth: null})
// 1. Replace all the things.
for (const {oldID, newContent} of eventsToReplace) {
@@ -34,7 +35,9 @@ async function editMessage(message, guild) {
// Not redacting as the last action because the last action is likely to be shown in the room preview in clients, and we don't want it to look like somebody actually deleted a message.
for (const eventID of eventsToRedact) {
await api.redactEvent(roomID, eventID, senderMxid)
- // TODO: I should almost certainly remove the redacted event from our database now, shouldn't I? I mean, it's literally not there any more... you can't do anything else with it...
+ // TODO: Reconsider whether it's the right thing to do to delete it from our database? I mean, it's literally not there any more... you can't do anything else with it...
+ // and you definitely want to mark it in *some* way to prevent duplicate redactions...
+ db.prepare("DELETE from event_message WHERE event_id = ?").run(eventID)
// TODO: If I just redacted part = 0, I should update one of the other events to make it the new part = 0, right?
// TODO: Consider whether this code could be reused between edited messages and deleted messages.
}
diff --git a/d2m/converters/edit-to-changes.js b/d2m/converters/edit-to-changes.js
index 4e6892d..3f4b2d2 100644
--- a/d2m/converters/edit-to-changes.js
+++ b/d2m/converters/edit-to-changes.js
@@ -22,7 +22,14 @@ async function editToChanges(message, guild, api) {
// Figure out what events we will be replacing
const roomID = db.prepare("SELECT room_id FROM channel_room WHERE channel_id = ?").pluck().get(message.channel_id)
- const senderMxid = await registerUser.ensureSimJoined(message.author, roomID)
+ /** @type {string?} */
+ let senderMxid = db.prepare("SELECT mxid FROM sim WHERE discord_id = ?").pluck().get(message.author.id) ?? null
+ if (senderMxid) {
+ const senderIsInRoom = db.prepare("SELECT * FROM sim_member WHERE room_id = ? and mxid = ?").get(roomID, senderMxid)
+ if (!senderIsInRoom) {
+ senderMxid = null // just send as ooye bot
+ }
+ }
/** @type {{event_id: string, event_type: string, event_subtype: string?, part: number}[]} */
const oldEventRows = db.prepare("SELECT event_id, event_type, event_subtype, part FROM event_message WHERE message_id = ?").all(message.id)
diff --git a/d2m/converters/edit-to-changes.test.js b/d2m/converters/edit-to-changes.test.js
index bb3f3ec..674cb15 100644
--- a/d2m/converters/edit-to-changes.test.js
+++ b/d2m/converters/edit-to-changes.test.js
@@ -3,104 +3,131 @@ const {editToChanges} = require("./edit-to-changes")
const data = require("../../test/data")
const Ty = require("../../types")
+test("edit2changes: edit by webhook", async t => {
+ const {senderMxid, eventsToRedact, eventsToReplace, eventsToSend} = await editToChanges(data.message_update.edit_by_webhook, data.guild.general, {})
+ t.deepEqual(eventsToRedact, [])
+ t.deepEqual(eventsToSend, [])
+ t.deepEqual(eventsToReplace, [{
+ oldID: "$zXSlyI78DQqQwwfPUSzZ1b-nXzbUrCDljJgnGDdoI10",
+ newContent: {
+ $type: "m.room.message",
+ msgtype: "m.text",
+ body: "* test 2",
+ "m.mentions": {},
+ "m.new_content": {
+ // *** Replaced With: ***
+ msgtype: "m.text",
+ body: "test 2",
+ "m.mentions": {}
+ },
+ "m.relates_to": {
+ rel_type: "m.replace",
+ event_id: "$zXSlyI78DQqQwwfPUSzZ1b-nXzbUrCDljJgnGDdoI10"
+ }
+ }
+ }])
+ t.equal(senderMxid, null)
+})
+
test("edit2changes: bot response", async t => {
- const {eventsToRedact, eventsToReplace, eventsToSend} = await editToChanges(data.message_update.bot_response, data.guild.general, {
- async getJoinedMembers(roomID) {
- t.equal(roomID, "!uCtjHhfGlYbVnPVlkG:cadence.moe")
- return new Promise(resolve => {
- setTimeout(() => {
- resolve({
- joined: {
- "@cadence:cadence.moe": {
- display_name: "cadence [they]",
- avatar_url: "whatever"
- },
- "@_ooye_botrac4r:cadence.moe": {
- display_name: "botrac4r",
- avatar_url: "whatever"
- }
- }
- })
- })
- })
- }
- })
- t.deepEqual(eventsToRedact, [])
- t.deepEqual(eventsToSend, [])
- t.deepEqual(eventsToReplace, [{
- oldID: "$fdD9OZ55xg3EAsfvLZza5tMhtjUO91Wg3Otuo96TplY",
- newContent: {
- $type: "m.room.message",
- msgtype: "m.text",
- body: "* :ae_botrac4r: @cadence asked ````, I respond: Stop drinking paint. (No)\n\nHit :bn_re: to reroll.",
- format: "org.matrix.custom.html",
- formatted_body: '* @cadence asked
, I respond: Stop drinking paint. (No)
Hit to reroll.',
- "m.mentions": {
- // Client-Server API spec 11.37.7: Copy Discord's behaviour by not re-notifying anyone that an *edit occurred*
- },
- // *** Replaced With: ***
- "m.new_content": {
- msgtype: "m.text",
- body: ":ae_botrac4r: @cadence asked ````, I respond: Stop drinking paint. (No)\n\nHit :bn_re: to reroll.",
- format: "org.matrix.custom.html",
- formatted_body: '
@cadence asked
, I respond: Stop drinking paint. (No)
Hit to reroll.',
- "m.mentions": {
- // Client-Server API spec 11.37.7: This should contain the mentions for the final version of the event
- "user_ids": ["@cadence:cadence.moe"]
- }
- },
- "m.relates_to": {
- rel_type: "m.replace",
- event_id: "$fdD9OZ55xg3EAsfvLZza5tMhtjUO91Wg3Otuo96TplY"
- }
- }
- }])
+ const {senderMxid, eventsToRedact, eventsToReplace, eventsToSend} = await editToChanges(data.message_update.bot_response, data.guild.general, {
+ async getJoinedMembers(roomID) {
+ t.equal(roomID, "!uCtjHhfGlYbVnPVlkG:cadence.moe")
+ return new Promise(resolve => {
+ setTimeout(() => {
+ resolve({
+ joined: {
+ "@cadence:cadence.moe": {
+ display_name: "cadence [they]",
+ avatar_url: "whatever"
+ },
+ "@_ooye_botrac4r:cadence.moe": {
+ display_name: "botrac4r",
+ avatar_url: "whatever"
+ }
+ }
+ })
+ })
+ })
+ }
+ })
+ t.deepEqual(eventsToRedact, [])
+ t.deepEqual(eventsToSend, [])
+ t.deepEqual(eventsToReplace, [{
+ oldID: "$fdD9OZ55xg3EAsfvLZza5tMhtjUO91Wg3Otuo96TplY",
+ newContent: {
+ $type: "m.room.message",
+ msgtype: "m.text",
+ body: "* :ae_botrac4r: @cadence asked ````, I respond: Stop drinking paint. (No)\n\nHit :bn_re: to reroll.",
+ format: "org.matrix.custom.html",
+ formatted_body: '*
@cadence asked
, I respond: Stop drinking paint. (No)
Hit to reroll.',
+ "m.mentions": {
+ // Client-Server API spec 11.37.7: Copy Discord's behaviour by not re-notifying anyone that an *edit occurred*
+ },
+ // *** Replaced With: ***
+ "m.new_content": {
+ msgtype: "m.text",
+ body: ":ae_botrac4r: @cadence asked ````, I respond: Stop drinking paint. (No)\n\nHit :bn_re: to reroll.",
+ format: "org.matrix.custom.html",
+ formatted_body: '
@cadence asked
, I respond: Stop drinking paint. (No)
Hit to reroll.',
+ "m.mentions": {
+ // Client-Server API spec 11.37.7: This should contain the mentions for the final version of the event
+ "user_ids": ["@cadence:cadence.moe"]
+ }
+ },
+ "m.relates_to": {
+ rel_type: "m.replace",
+ event_id: "$fdD9OZ55xg3EAsfvLZza5tMhtjUO91Wg3Otuo96TplY"
+ }
+ }
+ }])
+ t.equal(senderMxid, "@_ooye_bojack_horseman:cadence.moe")
})
test("edit2changes: remove caption from image", async t => {
- const {eventsToRedact, eventsToReplace, eventsToSend} = await editToChanges(data.message_update.removed_caption_from_image, data.guild.general, {})
- t.deepEqual(eventsToRedact, ["$mtR8cJqM4fKno1bVsm8F4wUVqSntt2sq6jav1lyavuA"])
- t.deepEqual(eventsToSend, [])
- t.deepEqual(eventsToReplace, [])
+ const {eventsToRedact, eventsToReplace, eventsToSend} = await editToChanges(data.message_update.removed_caption_from_image, data.guild.general, {})
+ t.deepEqual(eventsToRedact, ["$mtR8cJqM4fKno1bVsm8F4wUVqSntt2sq6jav1lyavuA"])
+ t.deepEqual(eventsToSend, [])
+ t.deepEqual(eventsToReplace, [])
})
test("edit2changes: add caption back to that image", async t => {
- const {eventsToRedact, eventsToReplace, eventsToSend} = await editToChanges(data.message_update.added_caption_to_image, data.guild.general, {})
- t.deepEqual(eventsToRedact, [])
- t.deepEqual(eventsToSend, [{
- $type: "m.room.message",
- msgtype: "m.text",
- body: "some text",
- "m.mentions": {}
- }])
- t.deepEqual(eventsToReplace, [])
+ const {eventsToRedact, eventsToReplace, eventsToSend} = await editToChanges(data.message_update.added_caption_to_image, data.guild.general, {})
+ t.deepEqual(eventsToRedact, [])
+ t.deepEqual(eventsToSend, [{
+ $type: "m.room.message",
+ msgtype: "m.text",
+ body: "some text",
+ "m.mentions": {}
+ }])
+ t.deepEqual(eventsToReplace, [])
})
test("edit2changes: edit of reply to skull webp attachment with content", async t => {
- const {eventsToRedact, eventsToReplace, eventsToSend} = await editToChanges(data.message_update.edit_of_reply_to_skull_webp_attachment_with_content, data.guild.general, {})
+ const {eventsToRedact, eventsToReplace, eventsToSend} = await editToChanges(data.message_update.edit_of_reply_to_skull_webp_attachment_with_content, data.guild.general, {})
t.deepEqual(eventsToRedact, [])
- t.deepEqual(eventsToSend, [])
- t.deepEqual(eventsToReplace, [{
- oldID: "$vgTKOR5ZTYNMKaS7XvgEIDaOWZtVCEyzLLi5Pc5Gz4M",
- newContent: {
- $type: "m.room.message",
- msgtype: "m.text",
- body: "> Extremity: Image\n\n* Edit",
- format: "org.matrix.custom.html",
- formatted_body:
- '
In reply to Extremity'
- + '
ImageIn reply to Extremity'
+ + '
Image
Gateway event: ${gatewayMessage.t}`
+ + `
${stackLines.join("\n")}` + + `
${util.inspect(gatewayMessage.d, false, 4, false)}