m->d start coding message edits

This commit is contained in:
Cadence Ember 2023-08-28 01:30:07 +12:00
parent 6a03c96984
commit 55da70f8fc
3 changed files with 54 additions and 6 deletions

View file

@ -29,13 +29,15 @@ 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 // 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 messages = await eventToMessage.eventToMessage(event, guild, {api}) const {messagesToEdit, messagesToSend, messagesToDelete} = await eventToMessage.eventToMessage(event, guild, {api})
assert(Array.isArray(messages)) // sanity
/** @type {DiscordTypes.APIMessage[]} */ /** @type {DiscordTypes.APIMessage[]} */
const messageResponses = [] const messageResponses = []
let eventPart = 0 // 0 is primary, 1 is supporting let eventPart = 0 // 0 is primary, 1 is supporting
for (const message of messages) { // for (const message of messagesToEdit) {
// eventPart = 1
// TODO ...
for (const message of messagesToSend) {
const messageResponse = await channelWebhook.sendMessageWithWebhook(channelID, message, threadID) 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 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

View file

@ -130,6 +130,8 @@ async function eventToMessage(event, guild, di) {
let displayName = event.sender let displayName = event.sender
let avatarURL = undefined let avatarURL = undefined
/** @type {string[]} */
let messageIDsToEdit = []
let replyLine = "" let replyLine = ""
// Extract a basic display name from the sender // Extract a basic display name from the sender
const match = event.sender.match(/^@(.*?):/) const match = event.sender.match(/^@(.*?):/)
@ -152,9 +154,37 @@ async function eventToMessage(event, guild, di) {
// input = input.replace(/ /g, " ") // input = input.replace(/ /g, " ")
// There is also a corresponding test to uncomment, named "event2message: whitespace is retained" // There is also a corresponding test to uncomment, named "event2message: whitespace is retained"
// Handling replies. We'll look up the data of the replied-to event from the Matrix homeserver. // 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 () => { await (async () => {
const repliedToEventId = event.content["m.relates_to"]?.["m.in_reply_to"].event_id 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 <mx-reply> 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
if (!repliedToEventId) return if (!repliedToEventId) return
const repliedToEvent = await di.api.getEvent(event.room_id, repliedToEventId) const repliedToEvent = await di.api.getEvent(event.room_id, repliedToEventId)
if (!repliedToEvent) return if (!repliedToEvent) return
@ -235,7 +265,21 @@ async function eventToMessage(event, guild, di) {
avatar_url: avatarURL avatar_url: avatarURL
}))) })))
return messages 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
}
} }
module.exports.eventToMessage = eventToMessage module.exports.eventToMessage = eventToMessage

2
types.d.ts vendored
View file

@ -75,6 +75,8 @@ export namespace Event {
"m.in_reply_to": { "m.in_reply_to": {
event_id: string event_id: string
} }
rel_type?: "m.replace"
event_id?: string
} }
} }