diff --git a/src/d2m/converters/message-to-event.js b/src/d2m/converters/message-to-event.js index 78829ba..449303a 100644 --- a/src/d2m/converters/message-to-event.js +++ b/src/d2m/converters/message-to-event.js @@ -542,16 +542,9 @@ async function messageToEvent(message, guild, options = {}, di) { $type: "m.room.message", "m.mentions": mentions, msgtype, - body: body - } - - const isPlaintext = body === html - - if (!isPlaintext || options.alwaysReturnFormattedBody) { - Object.assign(newTextMessageEvent, { - format: "org.matrix.custom.html", - formatted_body: html - }) + body: body, + format: "org.matrix.custom.html", + formatted_body: html } events.push(newTextMessageEvent) @@ -695,7 +688,18 @@ async function messageToEvent(message, guild, options = {}, di) { // Then attachments if (message.attachments) { const attachmentEvents = await Promise.all(message.attachments.map(attachmentToEvent.bind(null, mentions))) - events.push(...attachmentEvents) + + // Try to merge attachment events with the previous event + // This means that if the attachments ended up as a text link, and especially if there were many of them, the events will be joined together. + let prev = events.at(-1) + for (const atch of attachmentEvents) { + if (atch.msgtype === "m.text" && prev?.body && prev?.formatted_body && ["m.text", "m.notice"].includes(prev?.msgtype)) { + prev.body = prev.body + "\n" + atch.body + prev.formatted_body = prev.formatted_body + "
" + atch.formatted_body + } else { + events.push(atch) + } + } } // Then embeds @@ -829,6 +833,16 @@ async function messageToEvent(message, guild, options = {}, di) { }) } + // Strip formatted_body where equivalent to body + if (!options.alwaysReturnFormattedBody) { + for (const event of events) { + if (["m.text", "m.notice"].includes(event.msgtype) && event.body === event.formatted_body) { + delete event.format + delete event.formatted_body + } + } + } + return events } diff --git a/src/d2m/converters/message-to-event.test.js b/src/d2m/converters/message-to-event.test.js index fa51eae..3c0c5d9 100644 --- a/src/d2m/converters/message-to-event.test.js +++ b/src/d2m/converters/message-to-event.test.js @@ -869,14 +869,62 @@ test("message2event: very large attachment is linked instead of being uploaded", $type: "m.room.message", "m.mentions": {}, msgtype: "m.text", - body: "hey" - }, { + body: "hey\n๐Ÿ“„ Uploaded file: https://bridge.example.org/download/discordcdn/123/456/789.mega (100 MB)", + format: "org.matrix.custom.html", + formatted_body: 'hey
๐Ÿ“„ Uploaded file: hey.jpg (100 MB)' + }]) +}) + +test("message2event: multiple attachments are combined into the same event where possible", async t => { + const events = await messageToEvent({ + content: "hey", + attachments: [{ + filename: "hey.jpg", + url: "https://cdn.discordapp.com/attachments/123/456/789.mega", + content_type: "application/i-made-it-up", + size: 100e6 + }, { + filename: "SPOILER_secret.jpg", + url: "https://cdn.discordapp.com/attachments/123/456/SPOILER_secret.jpg", + content_type: "image/jpeg", + size: 38291 + }, { + filename: "my enemies.txt", + url: "https://cdn.discordapp.com/attachments/123/456/my_enemies.txt", + content_type: "text/plain", + size: 8911 + }, { + filename: "hey.jpg", + url: "https://cdn.discordapp.com/attachments/123/456/789.mega", + content_type: "application/i-made-it-up", + size: 100e6 + }] + }) + t.deepEqual(events, [{ $type: "m.room.message", "m.mentions": {}, msgtype: "m.text", - body: "๐Ÿ“„ Uploaded file: https://bridge.example.org/download/discordcdn/123/456/789.mega (100 MB)", + body: "hey" + + "\n๐Ÿ“„ Uploaded file: https://bridge.example.org/download/discordcdn/123/456/789.mega (100 MB)" + + "\n๐Ÿ“ธ Uploaded SPOILER file: https://bridge.example.org/download/discordcdn/123/456/SPOILER_secret.jpg (38 KB)" + + "\n๐Ÿ“„ Uploaded file: https://bridge.example.org/download/discordcdn/123/456/789.mega (100 MB)", format: "org.matrix.custom.html", - formatted_body: '๐Ÿ“„ Uploaded file: hey.jpg (100 MB)' + formatted_body: "hey" + + `
๐Ÿ“„ Uploaded file: hey.jpg (100 MB)` + + `
๐Ÿ“ธ Uploaded SPOILER file: https://bridge.example.org/download/discordcdn/123/456/SPOILER_secret.jpg (38 KB)
` + + `
๐Ÿ“„ Uploaded file: hey.jpg (100 MB)` + }, { + $type: "m.room.message", + "m.mentions": {}, + msgtype: "m.file", + body: "my enemies.txt", + filename: "my enemies.txt", + external_url: "https://bridge.example.org/download/discordcdn/123/456/my_enemies.txt", + url: "mxc://cadence.moe/y89EOTRp2lbeOkgdsEleGOge", + info: { + mimetype: "text/plain", + size: 8911 + } }]) }) @@ -1494,21 +1542,12 @@ test("message2event: forwarded message with unreferenced mention", async t => { } ] }) - t.deepEqual(events, [ - { - $type: "m.room.message", - msgtype: "m.text", - body: "[๐Ÿ”€ Forwarded message]\nยป @unknown-user:", - format: "org.matrix.custom.html", - formatted_body: `๐Ÿ”€ Forwarded message
@unknown-user:
`, - "m.mentions": {} - }, { - $type: "m.room.message", - msgtype: "m.text", - body: "ยป ๐ŸŽž๏ธ Uploaded file: https://bridge.example.org/download/discordcdn/893634327722721290/1463174815119704114/2022-10-18_16-49-46.mp4 (51 MB)", - format: "org.matrix.custom.html", - formatted_body: "
๐ŸŽž๏ธ Uploaded file: 2022-10-18_16-49-46.mp4 (51 MB)
", - "m.mentions": {} - } - ]) + t.deepEqual(events, [{ + $type: "m.room.message", + msgtype: "m.text", + body: "[๐Ÿ”€ Forwarded message]\nยป @unknown-user:\nยป ๐ŸŽž๏ธ Uploaded file: https://bridge.example.org/download/discordcdn/893634327722721290/1463174815119704114/2022-10-18_16-49-46.mp4 (51 MB)", + format: "org.matrix.custom.html", + formatted_body: "๐Ÿ”€ Forwarded message
@unknown-user:
๐ŸŽž๏ธ Uploaded file: 2022-10-18_16-49-46.mp4 (51 MB)
", + "m.mentions": {} + }]) }) diff --git a/test/ooye-test-data.sql b/test/ooye-test-data.sql index ef3dc5f..04e6b9b 100644 --- a/test/ooye-test-data.sql +++ b/test/ooye-test-data.sql @@ -151,7 +151,8 @@ INSERT INTO file (discord_url, mxc_url) VALUES ('https://cdn.discordapp.com/attachments/112760669178241024/1197621094786531358/Ins_1960637570.mp4', 'mxc://cadence.moe/kMqLycqMURhVpwleWkmASpnU'), ('https://cdn.discordapp.com/attachments/1099031887500034088/1112476845502365786/voice-message.ogg', 'mxc://cadence.moe/MRRPDggXQMYkrUjTpxQbmcxB'), ('https://cdn.discordapp.com/attachments/122155380120748034/1174514575220158545/the.yml', 'mxc://cadence.moe/HnQIYQmmlIKwOQsbFsIGpzPP'), -('https://cdn.discordapp.com/attachments/112760669178241024/1296237494987133070/100km.gif', 'mxc://cadence.moe/qDAotmebTfEIfsAIVCEZptLh'); +('https://cdn.discordapp.com/attachments/112760669178241024/1296237494987133070/100km.gif', 'mxc://cadence.moe/qDAotmebTfEIfsAIVCEZptLh'), +('https://cdn.discordapp.com/attachments/123/456/my_enemies.txt', 'mxc://cadence.moe/y89EOTRp2lbeOkgdsEleGOge'); INSERT INTO emoji (emoji_id, name, animated, mxc_url) VALUES ('230201364309868544', 'hippo', 0, 'mxc://cadence.moe/qWmbXeRspZRLPcjseyLmeyXC'),