Handle replies to state events with no body
This commit is contained in:
parent
8ad0117fd2
commit
69e3d64905
2 changed files with 66 additions and 19 deletions
|
@ -476,7 +476,7 @@ async function eventToMessage(event, guild, di) {
|
||||||
// Try to extract an accurate display name and avatar URL from the member event
|
// Try to extract an accurate display name and avatar URL from the member event
|
||||||
const member = await getMemberFromCacheOrHomeserver(event.room_id, event.sender, di?.api)
|
const member = await getMemberFromCacheOrHomeserver(event.room_id, event.sender, di?.api)
|
||||||
if (member.displayname) displayName = member.displayname
|
if (member.displayname) displayName = member.displayname
|
||||||
if (member.avatar_url) avatarURL = mxUtils.getPublicUrlForMxc(member.avatar_url) || undefined
|
if (member.avatar_url) avatarURL = mxUtils.getPublicUrlForMxc(member.avatar_url)
|
||||||
// If the display name is too long to be put into the webhook (80 characters is the maximum),
|
// If the display name is too long to be put into the webhook (80 characters is the maximum),
|
||||||
// put the excess characters into displayNameRunoff, later to be put at the top of the message
|
// put the excess characters into displayNameRunoff, later to be put at the top of the message
|
||||||
let [displayNameShortened, displayNameRunoff] = splitDisplayName(displayName)
|
let [displayNameShortened, displayNameRunoff] = splitDisplayName(displayName)
|
||||||
|
@ -512,8 +512,7 @@ async function eventToMessage(event, guild, di) {
|
||||||
// Is it editing a reply? We need special handling if it is.
|
// Is it editing a reply? We need special handling if it is.
|
||||||
// Get the original event, then check if it was a reply
|
// Get the original event, then check if it was a reply
|
||||||
const originalEvent = await di.api.getEvent(event.room_id, originalEventId)
|
const originalEvent = await di.api.getEvent(event.room_id, originalEventId)
|
||||||
if (!originalEvent) return
|
const repliedToEventId = originalEvent?.content?.["m.relates_to"]?.["m.in_reply_to"]?.event_id
|
||||||
const repliedToEventId = originalEvent.content["m.relates_to"]?.["m.in_reply_to"]?.event_id
|
|
||||||
if (!repliedToEventId) return
|
if (!repliedToEventId) return
|
||||||
|
|
||||||
// After all that, it's an edit of a reply.
|
// After all that, it's an edit of a reply.
|
||||||
|
@ -576,34 +575,27 @@ async function eventToMessage(event, guild, di) {
|
||||||
if (row) {
|
if (row) {
|
||||||
replyLine += `https://discord.com/channels/${guild.id}/${row.channel_id}/${row.message_id} `
|
replyLine += `https://discord.com/channels/${guild.id}/${row.channel_id}/${row.message_id} `
|
||||||
}
|
}
|
||||||
const sender = repliedToEvent.sender
|
|
||||||
const authorID = getUserOrProxyOwnerID(sender)
|
|
||||||
if (authorID) {
|
|
||||||
replyLine += `<@${authorID}>`
|
|
||||||
} else {
|
|
||||||
let senderName = select("member_cache", "displayname", {mxid: sender}).pluck().get()
|
|
||||||
if (!senderName) {
|
|
||||||
const match = sender.match(/@([^:]*)/)
|
|
||||||
assert(match)
|
|
||||||
senderName = match[1]
|
|
||||||
}
|
|
||||||
replyLine += `**Ⓜ${senderName}**`
|
|
||||||
}
|
|
||||||
// If the event has been edited, the homeserver will include the relation in `unsigned`.
|
// 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"]) {
|
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 = repliedToEvent.unsigned["m.relations"]["m.replace"] // Note: this changes which event_id is in repliedToEvent.
|
||||||
repliedToEvent.content = repliedToEvent.content["m.new_content"]
|
repliedToEvent.content = repliedToEvent.content["m.new_content"]
|
||||||
}
|
}
|
||||||
let contentPreview
|
/** @type {string} */
|
||||||
|
let repliedToContent = repliedToEvent.content.formatted_body || repliedToEvent.content.body
|
||||||
const fileReplyContentAlternative = attachmentEmojis.get(repliedToEvent.content.msgtype)
|
const fileReplyContentAlternative = attachmentEmojis.get(repliedToEvent.content.msgtype)
|
||||||
|
let contentPreview
|
||||||
if (fileReplyContentAlternative) {
|
if (fileReplyContentAlternative) {
|
||||||
contentPreview = " " + fileReplyContentAlternative
|
contentPreview = " " + fileReplyContentAlternative
|
||||||
} else if (repliedToEvent.unsigned?.redacted_because) {
|
} else if (repliedToEvent.unsigned?.redacted_because) {
|
||||||
contentPreview = " (in reply to a deleted message)"
|
contentPreview = " (in reply to a deleted message)"
|
||||||
|
} else if (typeof repliedToContent !== "string") {
|
||||||
|
// in reply to a weird metadata event like m.room.name, m.room.member...
|
||||||
|
// I'm not implementing text fallbacks for arbitrary room events. this should cover most cases
|
||||||
|
// this has never ever happened in the wild anyway
|
||||||
|
repliedToEvent.sender = ""
|
||||||
|
contentPreview = " (channel details edited)"
|
||||||
} else {
|
} else {
|
||||||
// Generate a reply preview for a standard message
|
// Generate a reply preview for a standard message
|
||||||
/** @type {string} */
|
|
||||||
let repliedToContent = repliedToEvent.content.formatted_body || repliedToEvent.content.body
|
|
||||||
repliedToContent = repliedToContent.replace(/.*<\/mx-reply>/s, "") // Remove everything before replies, so just use the actual message body
|
repliedToContent = repliedToContent.replace(/.*<\/mx-reply>/s, "") // Remove everything before replies, so just use the actual message body
|
||||||
repliedToContent = repliedToContent.replace(/^\s*<blockquote>.*?<\/blockquote>(.....)/s, "$1") // If the message starts with a blockquote, don't count it and use the message body afterwards
|
repliedToContent = repliedToContent.replace(/^\s*<blockquote>.*?<\/blockquote>(.....)/s, "$1") // If the message starts with a blockquote, don't count it and use the message body afterwards
|
||||||
repliedToContent = repliedToContent.replace(/(?:\n|<br>)+/g, " ") // Should all be on one line
|
repliedToContent = repliedToContent.replace(/(?:\n|<br>)+/g, " ") // Should all be on one line
|
||||||
|
@ -624,6 +616,15 @@ async function eventToMessage(event, guild, di) {
|
||||||
contentPreview = ""
|
contentPreview = ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const sender = repliedToEvent.sender
|
||||||
|
const authorID = getUserOrProxyOwnerID(sender)
|
||||||
|
if (authorID) {
|
||||||
|
replyLine += `<@${authorID}>`
|
||||||
|
} else {
|
||||||
|
let senderName = select("member_cache", "displayname", {mxid: sender}).pluck().get()
|
||||||
|
if (!senderName) senderName = sender.match(/@([^:]*)/)?.[1]
|
||||||
|
if (senderName) replyLine += `**Ⓜ${senderName}**`
|
||||||
|
}
|
||||||
replyLine = `-# > ${replyLine}${contentPreview}\n`
|
replyLine = `-# > ${replyLine}${contentPreview}\n`
|
||||||
})()
|
})()
|
||||||
|
|
||||||
|
|
|
@ -2625,6 +2625,52 @@ test("event2message: rich reply to a deleted event", async t => {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test("event2message: rich reply to a state event with no body", async t => {
|
||||||
|
t.deepEqual(
|
||||||
|
await eventToMessage({
|
||||||
|
type: "m.room.message",
|
||||||
|
sender: "@ampflower:matrix.org",
|
||||||
|
content: {
|
||||||
|
msgtype: "m.text",
|
||||||
|
body: "> <@ampflower:matrix.org> changed the room topic\n\nnice room topic",
|
||||||
|
format: "org.matrix.custom.html",
|
||||||
|
formatted_body: "<mx-reply><blockquote><a href=\"https://matrix.to/#/!TqlyQmifxGUggEmdBN:cadence.moe/$f-noT-d-Eo_Xgpc05Ww89ErUXku4NwKWYGHLzWKo1kU?via=cadence.moe\">In reply to</a> <a href=\"https://matrix.to/#/@ampflower:matrix.org\">@ampflower:matrix.org</a> changed the room topic<br></blockquote></mx-reply>nice room topic",
|
||||||
|
"m.relates_to": {
|
||||||
|
"m.in_reply_to": {
|
||||||
|
event_id: "$f-noT-d-Eo_Xgpc05Ww89ErUXku4NwKWYGHLzWKo1kU"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
event_id: "$v_Gtr-bzv9IVlSLBO5DstzwmiDd-GSFaNfHX66IupV8",
|
||||||
|
room_id: "!TqlyQmifxGUggEmdBN:cadence.moe"
|
||||||
|
}, data.guild.general, {
|
||||||
|
api: {
|
||||||
|
getEvent: mockGetEvent(t, "!TqlyQmifxGUggEmdBN:cadence.moe", "$f-noT-d-Eo_Xgpc05Ww89ErUXku4NwKWYGHLzWKo1kU", {
|
||||||
|
type: "m.room.topic",
|
||||||
|
sender: "@ampflower:matrix.org",
|
||||||
|
content: {
|
||||||
|
topic: "you're cute"
|
||||||
|
},
|
||||||
|
user_id: "@ampflower:matrix.org"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
ensureJoined: [],
|
||||||
|
messagesToDelete: [],
|
||||||
|
messagesToEdit: [],
|
||||||
|
messagesToSend: [{
|
||||||
|
username: "Ampflower 🌺",
|
||||||
|
content: "-# > <:L1:1144820033948762203><:L2:1144820084079087647> (channel details edited)\nnice room topic",
|
||||||
|
avatar_url: "https://bridge.example.org/download/matrix/cadence.moe/PRfhXYBTOalvgQYtmCLeUXko",
|
||||||
|
allowed_mentions: {
|
||||||
|
parse: ["users", "roles"]
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
test("event2message: raw mentioning discord users in plaintext body works", async t => {
|
test("event2message: raw mentioning discord users in plaintext body works", async t => {
|
||||||
t.deepEqual(
|
t.deepEqual(
|
||||||
await eventToMessage({
|
await eventToMessage({
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue