Compare commits

..

2 commits

4 changed files with 240 additions and 19 deletions

View file

@ -199,9 +199,10 @@ async function attachmentToEvent(mentions, attachment) {
/** /**
* @param {DiscordTypes.APIMessage} message * @param {DiscordTypes.APIMessage} message
* @param {DiscordTypes.APIGuild} guild * @param {DiscordTypes.APIGuild} guild
* @param {{includeReplyFallback?: boolean, includeEditFallbackStar?: boolean}} options default values: * @param {{includeReplyFallback?: boolean, includeEditFallbackStar?: boolean, alwaysReturnFormattedBody?: boolean}} options default values:
* - includeReplyFallback: true * - includeReplyFallback: true
* - includeEditFallbackStar: false * - includeEditFallbackStar: false
* - alwaysReturnFormattedBody: false - formatted_body will be skipped if it is the same as body because the message is plaintext. if you want the formatted_body to be returned anyway, for example to merge it with another message, then set this to true.
* @param {{api: import("../../matrix/api")}} di simple-as-nails dependency injection for the matrix API * @param {{api: import("../../matrix/api")}} di simple-as-nails dependency injection for the matrix API
*/ */
async function messageToEvent(message, guild, options = {}, di) { async function messageToEvent(message, guild, options = {}, di) {
@ -496,7 +497,7 @@ async function messageToEvent(message, guild, options = {}, di) {
const isPlaintext = body === html const isPlaintext = body === html
if (!isPlaintext) { if (!isPlaintext || options.alwaysReturnFormattedBody) {
Object.assign(newTextMessageEvent, { Object.assign(newTextMessageEvent, {
format: "org.matrix.custom.html", format: "org.matrix.custom.html",
formatted_body: html formatted_body: html
@ -520,18 +521,20 @@ async function messageToEvent(message, guild, options = {}, di) {
const eventID = select("event_message", "event_id", {message_id: message.message_reference.message_id}).pluck().get() const eventID = select("event_message", "event_id", {message_id: message.message_reference.message_id}).pluck().get()
const room = select("channel_room", ["room_id", "name", "nick"], {channel_id: message.message_reference.channel_id}).get() const room = select("channel_room", ["room_id", "name", "nick"], {channel_id: message.message_reference.channel_id}).get()
const forwardedNotice = new mxUtils.MatrixStringBuilder() const forwardedNotice = new mxUtils.MatrixStringBuilder()
if (eventID && room) { if (room) {
const roomName = room && (room.nick || room.name)
const via = await getViaServersMemo(room.room_id) const via = await getViaServersMemo(room.room_id)
forwardedNotice.addLine( if (eventID) {
`[🔀 Forwarded from #${room.nick || room.name}]`, forwardedNotice.addLine(
tag`🔀 <em>Forwarded from <a href="https://matrix.to/#/${room.room_id}/${eventID}?${via}">${room.nick || room.name}</a></em>` `[🔀 Forwarded from #${roomName}]`,
) tag`🔀 <em>Forwarded from <a href="https://matrix.to/#/${room.room_id}/${eventID}?${via}">${roomName}</a></em>`
} else if (room) { )
const via = await getViaServersMemo(room.room_id) } else {
forwardedNotice.addLine( forwardedNotice.addLine(
`[🔀 Forwarded from #${room.nick || room.name}]`, `[🔀 Forwarded from #${roomName}]`,
tag`🔀 <em>Forwarded from <a href="https://matrix.to/#/${room.room_id}?${via}">${room.nick || room.name}</a></em>` tag`🔀 <em>Forwarded from <a href="https://matrix.to/#/${room.room_id}?${via}">${roomName}</a></em>`
) )
}
} else { } else {
forwardedNotice.addLine( forwardedNotice.addLine(
`[🔀 Forwarded message]`, `[🔀 Forwarded message]`,
@ -541,7 +544,7 @@ async function messageToEvent(message, guild, options = {}, di) {
// Forwarded content // Forwarded content
// @ts-ignore // @ts-ignore
const forwardedEvents = await messageToEvent(message.message_snapshots[0].message, guild, {includeReplyFallback: false, includeEditFallbackStar: false}, di) const forwardedEvents = await messageToEvent(message.message_snapshots[0].message, guild, {includeReplyFallback: false, includeEditFallbackStar: false, alwaysReturnFormattedBody: true}, di)
// Indent // Indent
for (const event of forwardedEvents) { for (const event of forwardedEvents) {
@ -555,9 +558,8 @@ async function messageToEvent(message, guild, options = {}, di) {
// Try to merge the forwarded content with the forwarded notice // Try to merge the forwarded content with the forwarded notice
let {body, formatted_body} = forwardedNotice.get() let {body, formatted_body} = forwardedNotice.get()
if (forwardedEvents.length >= 1 && ["m.text", "m.notice"].includes(forwardedEvents[0].msgtype)) { // Try to merge the forwarded content and the forwarded notice if (forwardedEvents.length >= 1 && ["m.text", "m.notice"].includes(forwardedEvents[0].msgtype)) { // Try to merge the forwarded content and the forwarded notice
forwardedNotice.add("\n", "<br>") forwardedEvents[0].body = body + "\n" + forwardedEvents[0].body
forwardedEvents[0].body = body + forwardedEvents[0].body forwardedEvents[0].formatted_body = formatted_body + "<br>" + forwardedEvents[0].formatted_body
forwardedEvents[0].formatted_body = formatted_body + forwardedEvents[0].formatted_body
} else { } else {
await addTextEvent(body, formatted_body, "m.notice") await addTextEvent(body, formatted_body, "m.notice")
} }

View file

@ -1043,3 +1043,94 @@ test("message2event: forwarded image", async t => {
}, },
]) ])
}) })
test("message2event: constructed forwarded message", async t => {
const events = await messageToEvent(data.message.constructed_forwarded_message, {}, {}, {
api: {
async getJoinedMembers() {
return {
joined: {
"@_ooye_bot:cadence.moe": {display_name: null, avatar_url: null},
"@user:matrix.org": {display_name: null, avatar_url: null}
}
}
}
}
})
t.deepEqual(events, [
{
$type: "m.room.message",
body: "[🔀 Forwarded from #wonderland]"
+ "\n» What's cooking, good looking? :hipposcope:",
format: "org.matrix.custom.html",
formatted_body: `🔀 <em>Forwarded from <a href="https://matrix.to/#/!qzDBLKlildpzrrOnFZ:cadence.moe/$tBIT8mO7XTTCgIINyiAIy6M2MSoPAdJenRl_RLyYuaE?via=cadence.moe&amp;via=matrix.org">wonderland</a></em>`
+ `<br><blockquote>What's cooking, good looking? <img data-mx-emoticon height="32" src="mxc://cadence.moe/WbYqNlACRuicynBfdnPYtmvc" title=":hipposcope:" alt=":hipposcope:"></blockquote>`,
"m.mentions": {},
msgtype: "m.notice",
},
{
$type: "m.room.message",
body: "100km.gif",
external_url: "https://bridge.example.org/download/discordcdn/112760669178241024/1296237494987133070/100km.gif",
filename: "100km.gif",
info: {
h: 300,
mimetype: "image/gif",
size: 2965649,
w: 300,
},
"m.mentions": {},
msgtype: "m.image",
url: "mxc://cadence.moe/qDAotmebTfEIfsAIVCEZptLh",
},
{
$type: "m.room.message",
body: "» | ## This man"
+ "\n» | "
+ "\n» | ## This man is 100 km away from your house"
+ "\n» | "
+ "\n» | ### Distance away"
+ "\n» | 99 km"
+ "\n» | "
+ "\n» | ### Distance away"
+ "\n» | 98 km",
format: "org.matrix.custom.html",
formatted_body: "<blockquote><blockquote><p><strong>This man</strong></p><p><strong>This man is 100 km away from your house</strong></p><p><strong>Distance away</strong><br>99 km</p><p><strong>Distance away</strong><br>98 km</p></blockquote></blockquote>",
"m.mentions": {},
msgtype: "m.notice"
}
])
})
test("message2event: constructed forwarded text", async t => {
const events = await messageToEvent(data.message.constructed_forwarded_text, {}, {}, {
api: {
async getJoinedMembers() {
return {
joined: {
"@_ooye_bot:cadence.moe": {display_name: null, avatar_url: null},
"@user:matrix.org": {display_name: null, avatar_url: null}
}
}
}
}
})
t.deepEqual(events, [
{
$type: "m.room.message",
body: "[🔀 Forwarded from #amanda-spam]"
+ "\n» What's cooking, good looking?",
format: "org.matrix.custom.html",
formatted_body: `🔀 <em>Forwarded from <a href="https://matrix.to/#/!CzvdIdUQXgUjDVKxeU:cadence.moe?via=cadence.moe&amp;via=matrix.org">amanda-spam</a></em>`
+ `<br><blockquote>What's cooking, good looking?</blockquote>`,
"m.mentions": {},
msgtype: "m.notice",
},
{
$type: "m.room.message",
body: "What's cooking everybody ‼️",
"m.mentions": {},
msgtype: "m.text",
}
])
})

View file

@ -2190,6 +2190,132 @@ module.exports = {
} }
} }
] ]
},
constructed_forwarded_message: { type: 0,
content: "",
mentions: [],
mention_roles: [],
attachments: [],
embeds: [],
timestamp: "2024-10-16T22:25:01.973000+00:00",
edited_timestamp: null,
flags: 16384,
components: [],
id: "1296237495993892916",
channel_id: "112760669178241024",
author: {
id: "113340068197859328",
username: "kumaccino",
avatar: "a8829abe66866d7797b36f0bfac01086",
discriminator: "0",
public_flags: 128,
flags: 128,
banner: null,
accent_color: null,
global_name: "kumaccino",
avatar_decoration_data: null,
banner_color: null,
clan: null
},
pinned: false,
mention_everyone: false,
tts: false,
message_reference: {
type: 1,
channel_id: "176333891320283136",
message_id: "1191567971970191490"
},
position: 0,
message_snapshots: [
{
message: {
type: 0,
content: "What's cooking, good looking? <:hipposcope:393635038903926784>",
mentions: [],
mention_roles: [],
attachments: [
{
id: "1296237494987133070",
filename: "100km.gif",
size: 2965649,
url: "https://cdn.discordapp.com/attachments/112760669178241024/1296237494987133070/100km.gif?ex=67118ebd&is=67103d3d&hm=8ed76d424f92f11366989f2ebc713d4f8206706ef712571e934da45b59944f77&", proxy_url: "https://media.discordapp.net/attachments/112760669178241024/1296237494987133070/100km.gif?ex=67118ebd&is=67103d3d&hm=8ed76d424f92f11366989f2ebc713d4f8206706ef712571e934da45b59944f77&", width: 300,
height: 300,
content_type: "image/gif"
}
],
embeds: [{
type: "rich",
title: "This man is 100 km away from your house",
author: {
name: "This man"
},
fields: [{
name: "Distance away",
value: "99 km"
}, {
name: "Distance away",
value: "98 km"
}]
}],
timestamp: "2022-09-15T01:20:58.177000+00:00",
edited_timestamp: null,
flags: 0,
components: []
}
}
]
},
constructed_forwarded_text: { type: 0,
content: "What's cooking everybody ‼️",
mentions: [],
mention_roles: [],
attachments: [],
embeds: [],
timestamp: "2024-10-16T22:25:01.973000+00:00",
edited_timestamp: null,
flags: 16384,
components: [],
id: "1296237495993892916",
channel_id: "112760669178241024",
author: {
id: "113340068197859328",
username: "kumaccino",
avatar: "a8829abe66866d7797b36f0bfac01086",
discriminator: "0",
public_flags: 128,
flags: 128,
banner: null,
accent_color: null,
global_name: "kumaccino",
avatar_decoration_data: null,
banner_color: null,
clan: null
},
pinned: false,
mention_everyone: false,
tts: false,
message_reference: {
type: 1,
channel_id: "497161350934560778",
message_id: "0"
},
position: 0,
message_snapshots: [
{
message: {
type: 0,
content: "What's cooking, good looking?",
mentions: [],
mention_roles: [],
attachments: [],
embeds: [],
timestamp: "2022-09-15T01:20:58.177000+00:00",
edited_timestamp: null,
flags: 0,
components: []
}
}
]
} }
}, },
pk_message: { pk_message: {

View file

@ -64,7 +64,8 @@ INSERT INTO message_channel (message_id, channel_id) VALUES
('1273204543739396116', '687028734322147344'), ('1273204543739396116', '687028734322147344'),
('1273743950028607530', '1100319550446252084'), ('1273743950028607530', '1100319550446252084'),
('1278002262400176128', '1100319550446252084'), ('1278002262400176128', '1100319550446252084'),
('1278001833876525057', '1100319550446252084'); ('1278001833876525057', '1100319550446252084'),
('1191567971970191490', '176333891320283136');
INSERT INTO event_message (event_id, event_type, event_subtype, message_id, part, reaction_part, source) VALUES INSERT INTO event_message (event_id, event_type, event_subtype, message_id, part, reaction_part, source) VALUES
('$X16nfVks1wsrhq4E9SSLiqrf2N8KD0erD0scZG7U5xg', 'm.room.message', 'm.text', '1126786462646550579', 0, 0, 1), ('$X16nfVks1wsrhq4E9SSLiqrf2N8KD0erD0scZG7U5xg', 'm.room.message', 'm.text', '1126786462646550579', 0, 0, 1),
@ -103,7 +104,8 @@ INSERT INTO event_message (event_id, event_type, event_subtype, message_id, part
('$qmyjr-ISJtnOM5WTWLI0fT7uSlqRLgpyin2d2NCglCU', 'm.room.message', 'm.text', '1273204543739396116', 0, 0, 0), ('$qmyjr-ISJtnOM5WTWLI0fT7uSlqRLgpyin2d2NCglCU', 'm.room.message', 'm.text', '1273204543739396116', 0, 0, 0),
('$W1nsDhNIojWrcQOdnOD9RaEvrz2qyZErQoNhPRs1nK4', 'm.room.message', 'm.text', '1273743950028607530', 0, 0, 0), ('$W1nsDhNIojWrcQOdnOD9RaEvrz2qyZErQoNhPRs1nK4', 'm.room.message', 'm.text', '1273743950028607530', 0, 0, 0),
('$UTqiL3Zj3FC4qldxRLggN1fhygpKl8sZ7XGY5f9MNbF', 'm.room.message', 'm.text', '1278002262400176128', 0, 0, 1), ('$UTqiL3Zj3FC4qldxRLggN1fhygpKl8sZ7XGY5f9MNbF', 'm.room.message', 'm.text', '1278002262400176128', 0, 0, 1),
('$aLVZyiC3HlOu-prCSIaXlQl68I8leUdnPFiCwkgn6qM', 'm.room.message', 'm.text', '1278001833876525057', 0, 0, 1); ('$aLVZyiC3HlOu-prCSIaXlQl68I8leUdnPFiCwkgn6qM', 'm.room.message', 'm.text', '1278001833876525057', 0, 0, 1),
('$tBIT8mO7XTTCgIINyiAIy6M2MSoPAdJenRl_RLyYuaE', 'm.room.message', 'm.text', '1191567971970191490', 0, 0, 1);
INSERT INTO file (discord_url, mxc_url) VALUES INSERT INTO file (discord_url, mxc_url) VALUES
('https://cdn.discordapp.com/attachments/497161332244742154/1124628646431297546/image.png', 'mxc://cadence.moe/qXoZktDqNtEGuOCZEADAMvhM'), ('https://cdn.discordapp.com/attachments/497161332244742154/1124628646431297546/image.png', 'mxc://cadence.moe/qXoZktDqNtEGuOCZEADAMvhM'),