2023-08-17 04:41:28 +00:00
// @ts-check
2024-01-20 11:54:18 +00:00
const assert = require ( "assert" ) . strict
2023-08-17 04:41:28 +00:00
const passthrough = require ( "../../passthrough" )
2023-10-06 03:50:23 +00:00
const { sync , db , select } = passthrough
2023-08-17 04:41:28 +00:00
/** @type {import("../converters/edit-to-changes")} */
const editToChanges = sync . require ( "../converters/edit-to-changes" )
2024-01-20 11:54:18 +00:00
/** @type {import("./register-pk-user")} */
const registerPkUser = sync . require ( "./register-pk-user" )
2023-08-17 04:41:28 +00:00
/** @type {import("../../matrix/api")} */
const api = sync . require ( "../../matrix/api" )
/ * *
* @ param { import ( "discord-api-types/v10" ) . GatewayMessageCreateDispatchData } message
* @ param { import ( "discord-api-types/v10" ) . APIGuild } guild
2024-01-20 11:54:18 +00:00
* @ param { { speedbump _id : string , speedbump _webhook _id : string } | null } row data about the webhook which is proxying messages in this channel
2023-08-17 04:41:28 +00:00
* /
2024-01-20 11:54:18 +00:00
async function editMessage ( message , guild , row ) {
let { roomID , eventsToRedact , eventsToReplace , eventsToSend , senderMxid , promotions } = await editToChanges . editToChanges ( message , guild , api )
if ( row && row . speedbump _webhook _id === message . webhook _id ) {
// Handle the PluralKit public instance
if ( row . speedbump _id === "466378653216014359" ) {
const root = await registerPkUser . fetchMessage ( message . id )
assert ( root . member )
2024-01-22 09:30:31 +00:00
senderMxid = await registerPkUser . ensureSimJoined ( root , roomID )
2024-01-20 11:54:18 +00:00
}
}
2023-07-28 05:05:13 +00:00
// 1. Replace all the things.
2023-08-17 04:41:28 +00:00
for ( const { oldID , newContent } of eventsToReplace ) {
const eventType = newContent . $type
/** @type {Pick<typeof newContent, Exclude<keyof newContent, "$type">> & { $type?: string }} */
const newContentWithoutType = { ... newContent }
delete newContentWithoutType . $type
await api . sendEvent ( roomID , eventType , newContentWithoutType , senderMxid )
// Ensure the database is up to date.
// The columns are event_id, event_type, event_subtype, message_id, channel_id, part, source. Only event_subtype could potentially be changed by a replacement event.
2023-08-25 13:44:50 +00:00
const subtype = newContentWithoutType . msgtype || null
2023-08-17 04:41:28 +00:00
db . prepare ( "UPDATE event_message SET event_subtype = ? WHERE event_id = ?" ) . run ( subtype , oldID )
}
2023-07-28 05:05:13 +00:00
// 2. Redact all the things.
2023-08-17 04:41:28 +00:00
// Not redacting as the last action because the last action is likely to be shown in the room preview in clients, and we don't want it to look like somebody actually deleted a message.
for ( const eventID of eventsToRedact ) {
await api . redactEvent ( roomID , eventID , senderMxid )
2023-08-28 05:32:55 +00:00
db . prepare ( "DELETE FROM event_message WHERE event_id = ?" ) . run ( eventID )
2023-08-17 04:41:28 +00:00
}
2023-07-28 05:05:13 +00:00
2023-10-06 03:50:23 +00:00
// 3. Consistency: Ensure there is exactly one part = 0
2023-10-14 09:08:10 +00:00
const sendNewEventParts = new Set ( )
for ( const promotion of promotions ) {
if ( "eventID" in promotion ) {
db . prepare ( ` UPDATE event_message SET ${ promotion . column } = 0 WHERE event_id = ? ` ) . run ( promotion . eventID )
} else if ( "nextEvent" in promotion ) {
sendNewEventParts . add ( promotion . column )
}
2023-10-06 03:50:23 +00:00
}
// 4. Send all the things.
2023-10-14 09:08:10 +00:00
if ( eventsToSend . length ) {
db . prepare ( "REPLACE INTO message_channel (message_id, channel_id) VALUES (?, ?)" ) . run ( message . id , message . channel _id )
}
2023-08-17 04:41:28 +00:00
for ( const content of eventsToSend ) {
const eventType = content . $type
/** @type {Pick<typeof content, Exclude<keyof content, "$type">> & { $type?: string }} */
const contentWithoutType = { ... content }
delete contentWithoutType . $type
2023-10-14 09:08:10 +00:00
delete contentWithoutType . $sender
2023-08-17 04:41:28 +00:00
2023-10-14 09:08:10 +00:00
const part = sendNewEventParts . has ( "part" ) && eventsToSend [ 0 ] === content ? 0 : 1
const reactionPart = sendNewEventParts . has ( "reaction_part" ) && eventsToSend [ eventsToSend . length - 1 ] === content ? 0 : 1
2023-08-17 04:41:28 +00:00
const eventID = await api . sendEvent ( roomID , eventType , contentWithoutType , senderMxid )
2023-10-14 09:08:10 +00:00
db . prepare ( "INSERT INTO event_message (event_id, event_type, event_subtype, message_id, part, reaction_part, source) VALUES (?, ?, ?, ?, ?, ?, 1)" ) . run ( eventID , eventType , content . msgtype || null , message . id , part , reactionPart ) // source 1 = discord
2023-07-28 05:05:13 +00:00
}
2023-08-17 04:41:28 +00:00
}
2023-07-28 05:05:13 +00:00
2023-08-17 04:41:28 +00:00
module . exports . editMessage = editMessage