diff --git a/d2m/event-dispatcher.js b/d2m/event-dispatcher.js index 049df27..6939c59 100644 --- a/d2m/event-dispatcher.js +++ b/d2m/event-dispatcher.js @@ -61,10 +61,10 @@ module.exports = { formatted_body: "\u26a0 Bridged event from Discord not delivered" + `
Gateway event: ${gatewayMessage.t}` + `
${e.toString()}` - + `
Error trace` - + `
${stackLines.join("\n")}
` - + `
Original payload` - + `
${util.inspect(gatewayMessage.d, false, 4, false)}
`, + + `
Error trace` + + `
${stackLines.join("\n")}
` + + `
Original payload` + + `
${util.inspect(gatewayMessage.d, false, 4, false)}
`, "m.mentions": { user_ids: ["@cadence:cadence.moe"] } diff --git a/m2d/actions/send-event.js b/m2d/actions/send-event.js index 3aa6346..016768e 100644 --- a/m2d/actions/send-event.js +++ b/m2d/actions/send-event.js @@ -29,15 +29,13 @@ async function sendEvent(event) { // no need to sync the matrix member to the other side. but if I did need to, this is where I'd do it - const {messagesToEdit, messagesToSend, messagesToDelete} = await eventToMessage.eventToMessage(event, guild, {api}) + const messages = await eventToMessage.eventToMessage(event, guild, {api}) + assert(Array.isArray(messages)) // sanity /** @type {DiscordTypes.APIMessage[]} */ const messageResponses = [] let eventPart = 0 // 0 is primary, 1 is supporting - // for (const message of messagesToEdit) { - // eventPart = 1 - // TODO ... - for (const message of messagesToSend) { + for (const message of messages) { const messageResponse = await channelWebhook.sendMessageWithWebhook(channelID, message, threadID) db.prepare("INSERT INTO event_message (event_id, event_type, event_subtype, message_id, channel_id, part, source) VALUES (?, ?, ?, ?, ?, ?, 0)").run(event.event_id, event.type, event.content.msgtype || null, messageResponse.id, channelID, eventPart) // source 0 = matrix diff --git a/m2d/converters/event-to-message.js b/m2d/converters/event-to-message.js index 70a0a69..22ed377 100644 --- a/m2d/converters/event-to-message.js +++ b/m2d/converters/event-to-message.js @@ -130,8 +130,6 @@ async function eventToMessage(event, guild, di) { let displayName = event.sender let avatarURL = undefined - /** @type {string[]} */ - let messageIDsToEdit = [] let replyLine = "" // Extract a basic display name from the sender const match = event.sender.match(/^@(.*?):/) @@ -154,37 +152,9 @@ async function eventToMessage(event, guild, di) { // input = input.replace(/ /g, " ") // There is also a corresponding test to uncomment, named "event2message: whitespace is retained" - // Handling edits. If the edit was an edit of a reply, edits do not include the reply reference, so we need to fetch up to 2 more events. - // this event ---is an edit of--> original event ---is a reply to--> past event - await (async () => { - if (!event.content["m.new_content"]) return - const relatesTo = event.content["m.relates_to"] - if (!relatesTo) return - // Check if we have a pointer to what was edited - const relType = relatesTo.rel_type - if (relType !== "m.replace") return - const originalEventId = relatesTo.event_id - if (!originalEventId) return - console.log("a", originalEventId) - messageIDsToEdit = db.prepare("SELECT message_id FROM event_message WHERE event_id = ? ORDER BY part").pluck().all(originalEventId) - if (!messageIDsToEdit.length) return - // Get the original event, then check if it was a reply - 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 - if (!repliedToEventId) return - console.log("c") - // After all that, it's an edit of a reply. - // We'll be sneaky and prepare the message data so that everything else can handle it just like original messages. - Object.assign(event.content, event.content["m.new_content"]) - input = event.content.formatted_body || event.content.body - relatesTo["m.in_reply_to"] = {event_id: repliedToEventId} - })() - // Handling replies. We'll look up the data of the replied-to event from the Matrix homeserver. - // Note that an element is not guaranteed because this might be m.new_content. await (async () => { - const repliedToEventId = event.content["m.relates_to"]?.["m.in_reply_to"]?.event_id + const repliedToEventId = event.content["m.relates_to"]?.["m.in_reply_to"].event_id if (!repliedToEventId) return const repliedToEvent = await di.api.getEvent(event.room_id, repliedToEventId) if (!repliedToEvent) return @@ -203,9 +173,9 @@ async function eventToMessage(event, guild, di) { replyLine += `Ⓜ️**${senderName}**: ` } const repliedToContent = repliedToEvent.content.formatted_body || repliedToEvent.content.body - const contentPreviewChunks = chunk(repliedToContent.replace(/.*<\/mx-reply>/, "").replace(/(?:\n|
)+/g, " ").replace(/<[^>]+>/g, ""), 50) + const contentPreviewChunks = chunk(repliedToContent.replace(/.*<\/mx-reply>/, "").replace(/(?:\n|
)+/g, " ").replace(/<[^>]+>/g, ""), 24) const contentPreview = contentPreviewChunks.length > 1 ? contentPreviewChunks[0] + "..." : contentPreviewChunks[0] - replyLine = `> ${replyLine}\n> ${contentPreview}\n` + replyLine += contentPreview + "\n" })() // Handling mentions of Discord users @@ -265,21 +235,7 @@ async function eventToMessage(event, guild, di) { avatar_url: avatarURL }))) - const messagesToEdit = [] - const messagesToSend = [] - for (let i = 0; i < messages.length; i++) { - if (messageIDsToEdit.length) { - messagesToEdit.push({id: messageIDsToEdit.shift(), message: messages[i]}) - } else { - messagesToSend.push(messages[i]) - } - } - - return { - messagesToEdit, - messagesToSend, - messagesToDelete: messageIDsToEdit - } + return messages } module.exports.eventToMessage = eventToMessage diff --git a/m2d/event-dispatcher.js b/m2d/event-dispatcher.js index 6adacf7..9a575fc 100644 --- a/m2d/event-dispatcher.js +++ b/m2d/event-dispatcher.js @@ -40,10 +40,10 @@ function guard(type, fn) { formatted_body: "\u26a0 Matrix event not delivered to Discord" + `
Event type: ${type}` + `
${e.toString()}` - + `
Error trace` - + `
${stackLines.join("\n")}
` - + `
Original payload` - + `
${util.inspect(event, false, 4, false)}
`, + + `
Error trace` + + `
${stackLines.join("\n")}
` + + `
Original payload` + + `
${util.inspect(event, false, 4, false)}
`, "m.mentions": { user_ids: ["@cadence:cadence.moe"] } diff --git a/notes.md b/notes.md index aa9066d..7383d3e 100644 --- a/notes.md +++ b/notes.md @@ -1,27 +1,5 @@ # d2m -## Known issues - -- m->d attachments do not work -- m->d edits do not work -- m->d spoilers do not work -- d->m support the rest of the attachments by reading the matrix spec instead of the current approach of whitelisting mime types -- d->m emojis do not work at all (inline chat, single emoji size, reactions, bridged state) -- m->d code blocks have slightly too much spacing -- m->d some reactions don't work because of the variation selector -- <--> check whether I implemented deletions -- rooms will be set up even if the bridge does not have permission for them, then break when it restarts and tries to reach messages - - test private threads as part of this - - solution part 1: calculate the permissions to see if the bot should be able to do stuff - - solution part 2: attempt a get messages request anyway before bridging a new room, just to make sure! - - solution part 3: revisit the permissions to add newly available rooms and to close newly inaccessible rooms -- consider a way to jump to a timestamp by making up a discord snowflake. practical? helpful? -- clean up and write documentation to selfhost -- pluralkit considerations for artemis -- consider whether to use nested spaces for channel categories and threads - -## Mapping - Remember that a discord message may be transformed to multiple matrix messages. A database will be used to store the discord id to matrix event id mapping. Table columns: diff --git a/types.d.ts b/types.d.ts index dcde3ad..5475904 100644 --- a/types.d.ts +++ b/types.d.ts @@ -75,8 +75,6 @@ export namespace Event { "m.in_reply_to": { event_id: string } - rel_type?: "m.replace" - event_id?: string } }