diff --git a/d2m/actions/create-room.js b/d2m/actions/create-room.js index d8bab51..e8284df 100644 --- a/d2m/actions/create-room.js +++ b/d2m/actions/create-room.js @@ -303,13 +303,9 @@ async function _unbridgeRoom(channelID) { /** @ts-ignore @type {DiscordTypes.APIGuildChannel} */ const channel = discord.channels.get(channelID) assert.ok(channel) - return unbridgeDeletedChannel(channel.id, channel.guild_id) -} - -async function unbridgeDeletedChannel(channelID, guildID) { const roomID = db.prepare("SELECT room_id from channel_room WHERE channel_id = ?").pluck().get(channelID) assert.ok(roomID) - const spaceID = db.prepare("SELECT space_id FROM guild_space WHERE guild_id = ?").pluck().get(guildID) + const spaceID = db.prepare("SELECT space_id FROM guild_space WHERE guild_id = ?").pluck().get(channel.guild_id) assert.ok(spaceID) // remove room from being a space member @@ -317,7 +313,7 @@ async function unbridgeDeletedChannel(channelID, guildID) { await api.sendState(spaceID, "m.space.child", roomID, {}) // remove declaration that the room is bridged - await api.sendState(roomID, "uk.half-shot.bridge", `moe.cadence.ooye://discord/${guildID}/${channelID}`, {}) + await api.sendState(roomID, "uk.half-shot.bridge", `moe.cadence.ooye://discord/${channel.guild_id}/${channel.id}`, {}) // send a notification in the room await api.sendEvent(roomID, "m.room.message", { @@ -333,6 +329,7 @@ async function unbridgeDeletedChannel(channelID, guildID) { assert.equal(changes, 1) } + /** * Async because it gets all space state from the homeserver, then if necessary sends one state event back. * @param {DiscordTypes.APIGuildTextChannel} channel @@ -380,4 +377,3 @@ module.exports.applyKStateDiffToRoom = applyKStateDiffToRoom module.exports.postApplyPowerLevels = postApplyPowerLevels module.exports._convertNameAndTopic = convertNameAndTopic module.exports._unbridgeRoom = _unbridgeRoom -module.exports.unbridgeDeletedChannel = unbridgeDeletedChannel diff --git a/d2m/actions/create-space.js b/d2m/actions/create-space.js index 34cf88a..0bdf1d1 100644 --- a/d2m/actions/create-space.js +++ b/d2m/actions/create-space.js @@ -145,11 +145,7 @@ async function syncSpaceFully(guildID) { for (const roomID of childRooms) { const channelID = db.prepare("SELECT channel_id FROM channel_room WHERE room_id = ?").pluck().get(roomID) if (!channelID) continue - if (discord.channels.has(channelID)) { - await createRoom.syncRoom(channelID) - } else { - await createRoom.unbridgeDeletedChannel(channelID, guildID) - } + await createRoom.syncRoom(channelID) } return spaceID diff --git a/d2m/converters/message-to-event.test.js b/d2m/converters/message-to-event.test.js index 94b67ff..5524543 100644 --- a/d2m/converters/message-to-event.test.js +++ b/d2m/converters/message-to-event.test.js @@ -363,7 +363,7 @@ test("message2event: thread start message reference", async t => { api: { getEvent: mockGetEvent(t, "!PnyBKvUBOhjuCucEfk:cadence.moe", "$FchUVylsOfmmbj-VwEs5Z9kY49_dt2zd0vWfylzy5Yo", { "type": "m.room.message", - "sender": "@_ooye_kyuugryphon:cadence.moe", + "sender": "@_ooye_cadence:cadence.moe", "content": { "m.mentions": {}, "msgtype": "m.text", diff --git a/m2d/converters/event-to-message.js b/m2d/converters/event-to-message.js index 75e04f9..1e66c7a 100644 --- a/m2d/converters/event-to-message.js +++ b/m2d/converters/event-to-message.js @@ -227,7 +227,7 @@ async function eventToMessage(event, guild, di) { await (async () => { const repliedToEventId = event.content["m.relates_to"]?.["m.in_reply_to"]?.event_id if (!repliedToEventId) return - let repliedToEvent = await di.api.getEvent(event.room_id, repliedToEventId) + const repliedToEvent = await di.api.getEvent(event.room_id, repliedToEventId) if (!repliedToEvent) return const row = db.prepare("SELECT channel_id, message_id FROM event_message INNER JOIN message_channel USING (message_id) WHERE event_id = ? ORDER BY part").get(repliedToEventId) if (row) { @@ -239,36 +239,14 @@ async function eventToMessage(event, guild, di) { const senderName = sender.match(/@([^:]*)/)?.[1] || sender const authorID = db.prepare("SELECT discord_id FROM sim WHERE mxid = ?").pluck().get(repliedToEvent.sender) if (authorID) { - replyLine += `<@${authorID}>` + replyLine += `<@${authorID}>:` } else { - replyLine += `Ⓜ️**${senderName}**` + replyLine += `Ⓜ️**${senderName}**:` } - // If the event has been edited, the homeserver will include the relation in `unsigned`. - if (repliedToEvent.unsigned?.["m.relations"]?.["m.replace"]?.content?.["m.new_content"]) { - repliedToEvent = repliedToEvent.unsigned["m.relations"]["m.replace"] // Note: this changes which event_id is in repliedToEvent. - repliedToEvent.content = repliedToEvent.content["m.new_content"] - } - let contentPreview - const fileReplyContentAlternative = - ( repliedToEvent.content.msgtype === "m.image" ? "🖼️" - : repliedToEvent.content.msgtype === "m.video" ? "🎞️" - : repliedToEvent.content.msgtype === "m.audio" ? "🎶" - : repliedToEvent.content.msgtype === "m.file" ? "📄" - : null) - if (fileReplyContentAlternative) { - contentPreview = " " + fileReplyContentAlternative - } else { - const repliedToContent = repliedToEvent.content.formatted_body || repliedToEvent.content.body - const contentPreviewChunks = chunk( - repliedToContent.replace(/.*<\/mx-reply>/, "") // Remove everything before replies, so just use the actual message body - .replace(/.*?<\/blockquote>/, "") // If the message starts with a blockquote, don't count it and use the message body afterwards - .replace(/(?:\n|
)+/g, " ") // Should all be on one line - .replace(/]*data-mx-spoiler\b[^>]*>.*?<\/span>/g, "[spoiler]") // Good enough method of removing spoiler content. (I don't want to break out the HTML parser unless I have to.) - .replace(/<[^>]+>/g, ""), 50) // Completely strip all other formatting. - contentPreview = ":\n> " - contentPreview += contentPreviewChunks.length > 1 ? contentPreviewChunks[0] + "..." : contentPreviewChunks[0] - } - replyLine = `> ${replyLine}${contentPreview}\n` + const repliedToContent = repliedToEvent.content.formatted_body || repliedToEvent.content.body + const contentPreviewChunks = chunk(repliedToContent.replace(/.*<\/mx-reply>/, "").replace(/.*?<\/blockquote>/, "").replace(/(?:\n|
)+/g, " ").replace(/<[^>]+>/g, ""), 50) + const contentPreview = contentPreviewChunks.length > 1 ? contentPreviewChunks[0] + "..." : contentPreviewChunks[0] + replyLine = `> ${replyLine}\n> ${contentPreview}\n` })() if (event.content.format === "org.matrix.custom.html" && event.content.formatted_body) { diff --git a/m2d/converters/event-to-message.test.js b/m2d/converters/event-to-message.test.js index e7d2314..40a4daa 100644 --- a/m2d/converters/event-to-message.test.js +++ b/m2d/converters/event-to-message.test.js @@ -595,82 +595,6 @@ test("event2message: rich reply to a sim user", async t => { ) }) -test("event2message: rich reply to an already-edited message will quote the new message content", async t => { - t.deepEqual( - await eventToMessage({ - "type": "m.room.message", - "sender": "@cadence:cadence.moe", - "content": { - "msgtype": "m.text", - "body": "> <@_ooye_kyuugryphon:cadence.moe> this is the new content. heya!\n\nhiiiii....", - "format": "org.matrix.custom.html", - "formatted_body": "
In reply to @_ooye_kyuugryphon:cadence.moe
this is the new content. heya!
hiiiii....", - "m.relates_to": { - "m.in_reply_to": { - "event_id": "$DSQvWxOBB2DYaei6b83-fb33dQGYt5LJd_s8Nl2a43Q" - } - } - }, - "origin_server_ts": 1693029683016, - "unsigned": { - "age": 91, - "transaction_id": "m1693029682894.510" - }, - "event_id": "$v_Gtr-bzv9IVlSLBO5DstzwmiDd-GSFaNfHX66IupV8", - "room_id": "!fGgIymcYWOqjbSRUdV:cadence.moe" - }, data.guild.general, { - api: { - getEvent: mockGetEvent(t, "!fGgIymcYWOqjbSRUdV:cadence.moe", "$DSQvWxOBB2DYaei6b83-fb33dQGYt5LJd_s8Nl2a43Q", { - type: "m.room.message", - room_id: "!fGgIymcYWOqjbSRUdV:cadence.moe", - sender: "@_ooye_kyuugryphon:cadence.moe", - content: { - "m.mentions": {}, - msgtype: "m.text", - body: "this is the old content. don't use this!" - }, - unsigned: { - "m.relations": { - "m.replace": { - type: "m.room.message", - room_id: "!fGgIymcYWOqjbSRUdV:cadence.moe", - sender: "@_ooye_kyuugryphon:cadence.moe", - content: { - "m.mentions": {}, - msgtype: "m.text", - body: "* this is the new content. heya!", - "m.new_content": { - "m.mentions": {}, - msgtype: "m.text", - body: "this is the new content. heya!" - }, - "m.relates_to": { - rel_type: "m.replace", - event_id: "$DSQvWxOBB2DYaei6b83-fb33dQGYt5LJd_s8Nl2a43Q" - } - }, - event_id: "$JOrl8ycWpo7NIAxZ4u-VJmANVrZFBF41LXyp30y8VvU", - user_id: "@_ooye_kyuugryphon:cadence.moe", - } - } - } - }) - } - }), - { - messagesToDelete: [], - messagesToEdit: [], - messagesToSend: [{ - username: "cadence [they]", - content: "> <:L1:1144820033948762203><:L2:1144820084079087647><@111604486476181504>:" - + "\n> this is the new content. heya!" - + "\nhiiiii....", - avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU" - }] - } - ) -}) - test("event2message: should avoid using blockquote contents as reply preview in rich reply to a sim user", async t => { t.deepEqual( await eventToMessage({ @@ -718,6 +642,8 @@ test("event2message: should avoid using blockquote contents as reply preview in ) }) + + test("event2message: editing a rich reply to a sim user", async t => { const eventsFetched = [] t.deepEqual( @@ -1021,20 +947,20 @@ test("event2message: rich reply to a matrix user's long message with formatting" "type": "m.room.message", "sender": "@cadence:cadence.moe", "content": { - "msgtype": "m.text", - "body": "> <@cadence:cadence.moe> ```\n> i should have a little happy test\n> ```\n> * list **bold** _em_ ~~strike~~\n> # heading 1\n> ## heading 2\n> ### heading 3\n> https://cadence.moe\n> [legit website](https://cadence.moe)\n\nno you can't!!!", - "format": "org.matrix.custom.html", - "formatted_body": "
In reply to @cadence:cadence.moe
i should have a little happy test\n
\n
    \n
  • list bold em ~~strike~~
  • \n
\n

heading 1

\n

heading 2

\n

heading 3

\n

https://cadence.moe
legit website

\n
no you can't!!!", - "m.relates_to": { - "m.in_reply_to": { - "event_id": "$Fxy8SMoJuTduwReVkHZ1uHif9EuvNx36Hg79cltiA04" - } - } + "msgtype": "m.text", + "body": "> <@cadence:cadence.moe> ```\n> i should have a little happy test\n> ```\n> * list **bold** _em_ ~~strike~~\n> # heading 1\n> ## heading 2\n> ### heading 3\n> https://cadence.moe\n> [legit website](https://cadence.moe)\n\nno you can't!!!", + "format": "org.matrix.custom.html", + "formatted_body": "
In reply to @cadence:cadence.moe
i should have a little happy test\n
\n
    \n
  • list bold em ~~strike~~
  • \n
\n

heading 1

\n

heading 2

\n

heading 3

\n

https://cadence.moe
legit website

\n
no you can't!!!", + "m.relates_to": { + "m.in_reply_to": { + "event_id": "$Fxy8SMoJuTduwReVkHZ1uHif9EuvNx36Hg79cltiA04" + } + } }, "origin_server_ts": 1693037401693, "unsigned": { - "age": 381, - "transaction_id": "m1693037401592.521" + "age": 381, + "transaction_id": "m1693037401592.521" }, "event_id": "$v_Gtr-bzv9IVlSLBO5DstzwmiDd-GSFaNfHX66IupV8", "room_id": "!fGgIymcYWOqjbSRUdV:cadence.moe" @@ -1066,116 +992,6 @@ test("event2message: rich reply to a matrix user's long message with formatting" ) }) -test("event2message: rich reply to an image", async t => { - t.deepEqual( - await eventToMessage({ - "type": "m.room.message", - "sender": "@cadence:cadence.moe", - "content": { - "msgtype": "m.text", - "body": "> <@cadence:cadence.moe> sent an image.\n\nCaught in 8K UHD VR QLED Epic Edition", - "format": "org.matrix.custom.html", - "formatted_body": "
In reply to @cadence:cadence.moe
sent an image.
Caught in 8K UHD VR QLED Epic Edition", - "m.relates_to": { - "m.in_reply_to": { - "event_id": "$Fxy8SMoJuTduwReVkHZ1uHif9EuvNx36Hg79cltiA04" - } - } - }, - "origin_server_ts": 1693037401693, - "unsigned": { - "age": 381, - "transaction_id": "m1693037401592.521" - }, - "event_id": "$v_Gtr-bzv9IVlSLBO5DstzwmiDd-GSFaNfHX66IupV8", - "room_id": "!fGgIymcYWOqjbSRUdV:cadence.moe" - }, data.guild.general, { - api: { - getEvent: mockGetEvent(t, "!fGgIymcYWOqjbSRUdV:cadence.moe", "$Fxy8SMoJuTduwReVkHZ1uHif9EuvNx36Hg79cltiA04", { - type: "m.room.message", - sender: "@_ooye_kyuugryphon:cadence.moe", - content: { - "m.mentions": {}, - msgtype: "m.image", - url: "mxc://cadence.moe/ABfYgGdcIECnraZLGpRnoArG", - external_url: "https://cdn.discordapp.com/attachments/1100319550446252084/1149300251648339998/arcafeappx2.png", - body: "arcafeappx2.png", - filename: "arcafeappx2.png", - info: { - mimetype: "image/png", - w: 512, - h: 512, - size: 43990 - } - } - }) - } - }), - { - messagesToDelete: [], - messagesToEdit: [], - messagesToSend: [{ - username: "cadence [they]", - content: "> <:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/112760669178241024/687028734322147344/1144865310588014633 <@111604486476181504> 🖼️" - + "\nCaught in 8K UHD VR QLED Epic Edition", - avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU" - }] - } - ) -}) - -test("event2message: rich reply to a spoiler should ensure the spoiler is hidden", async t => { - t.deepEqual( - await eventToMessage({ - "type": "m.room.message", - "sender": "@cadence:cadence.moe", - "content": { - "msgtype": "m.text", - "body": "> <@cadence:cadence.moe> ||zoe kills a 5 letter noun at the end. don't tell anybody|| cw crossword spoilers you'll never believe\n\nomg NO WAY!!", - "format": "org.matrix.custom.html", - "formatted_body": "
In reply to @cadence:cadence.moe
zoe kills a 5 letter noun at the end. don't tell anybody cw crossword spoilers you'll never believe
omg NO WAY!!", - "m.relates_to": { - "m.in_reply_to": { - "event_id": "$Fxy8SMoJuTduwReVkHZ1uHif9EuvNx36Hg79cltiA04" - } - } - }, - "origin_server_ts": 1693037401693, - "unsigned": { - "age": 381, - "transaction_id": "m1693037401592.521" - }, - "event_id": "$v_Gtr-bzv9IVlSLBO5DstzwmiDd-GSFaNfHX66IupV8", - "room_id": "!fGgIymcYWOqjbSRUdV:cadence.moe" - }, data.guild.general, { - api: { - getEvent: mockGetEvent(t, "!fGgIymcYWOqjbSRUdV:cadence.moe", "$Fxy8SMoJuTduwReVkHZ1uHif9EuvNx36Hg79cltiA04", { - type: "m.room.message", - sender: "@_ooye_kyuugryphon:cadence.moe", - content: { - "m.mentions": {}, - msgtype: "m.text", - body: "||zoe kills a 5 letter noun at the end. don't tell anybody|| cw crossword spoilers you'll never believe", - format: "org.matrix.custom.html", - formatted_body: `zoe kills a 5 letter noun at the end. don't tell anybody cw crossword spoilers you'll never believe` - } - }) - } - }), - { - messagesToDelete: [], - messagesToEdit: [], - messagesToSend: [{ - username: "cadence [they]", - content: "> <:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/112760669178241024/687028734322147344/1144865310588014633 <@111604486476181504>:" - + "\n> [spoiler] cw crossword spoilers you'll never..." - + "\nomg NO WAY!!", - avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU" - }] - } - ) -}) - test("event2message: with layered rich replies, the preview should only be the real text", async t => { t.deepEqual( await eventToMessage({