Don't delete our reaction on Discord unless we have 0 of that reaction coming from Matrix #85

Merged
cadence merged 10 commits from ellie/out-of-your-element:ellie-fix-reacts into main 2026-06-01 04:54:39 +00:00
3 changed files with 12 additions and 10 deletions
Showing only changes of commit 28e5bd91a6 - Show all commits

deal with situations where Discord doesn't send us an emoji's name when removing it

Ellie Algase 2026-06-01 00:43:32 -04:00

View file

@ -12,7 +12,7 @@ const utils = sync.require("../../matrix/utils")
In this case, wait until the original message has finished bridging, then retrigger the passed function.
*/
const DEBUG_RETRIGGER = true
const DEBUG_RETRIGGER = false
function debugRetrigger(message) {
if (DEBUG_RETRIGGER) {

View file

@ -383,12 +383,12 @@ module.exports = {
* @param {DiscordTypes.GatewayMessageReactionRemoveDispatchData | DiscordTypes.GatewayMessageReactionRemoveEmojiDispatchData | DiscordTypes.GatewayMessageReactionRemoveAllDispatchData} data
*/
async onSomeReactionsRemoved(client, data) {
// Don't attempt to double-bridge our own deleted reactions, this would go badly if there are race conditions
if ("user_id" in data && data.user_id === botID && data.emoji.name) { // sure hope data.emoji.name exists here
const encodedEmoji = encodeURIComponent(data.emoji.id ? `${data.emoji.name}:${data.emoji.id}` : data.emoji.name)
const i = redact.ourDeletedReactions.findIndex(x => data.message_id === x.message_id && encodedEmoji === x.encoded_emoji)
// Don't attempt to double-bridge our own m2d deleted reactions back to Matrix
if ("user_id" in data && data.user_id === botID) {
const emojiIdOrName = data.emoji.id || data.emoji.name
const i = redact.m2dDeletedReactions.findIndex(x => data.message_id === x.messageID && emojiIdOrName === x.emojiIdOrName)
if (i !== -1) {
redact.ourDeletedReactions.splice(i, 1)
redact.m2dDeletedReactions.splice(i, 1)
return
}
}

View file

@ -10,8 +10,8 @@ const utils = sync.require("../../matrix/utils")
/** @type {import("../../d2m/actions/retrigger")} */
const retrigger = sync.require("../../d2m/actions/retrigger")
/** @type {{message_id: string, encoded_emoji: string}[]} */
const ourDeletedReactions = []
/** @type {{messageID: string, emojiIdOrName: string}[]} */
const m2dDeletedReactions = []
/**
* @param {Ty.Event.Outer_M_Room_Redaction} event
@ -68,7 +68,9 @@ async function removeReaction(event) {
// See how many Matrix-side reactions there are, and delete if it's the last one
const numberOfReactions = from("reaction").where({message_id: row.message_id, encoded_emoji: row.encoded_emoji}).pluckUnsafe("count(*)").get()
if (numberOfReactions === 1) {
ourDeletedReactions.push(row)
// If a unicode emoji, the name is already the Discord preferred version because that's what was added and stored to encoded_emoji
const emojiIdOrName = decodeURIComponent(row.encoded_emoji).split(":").slice(-1)[0]
m2dDeletedReactions.push({messageID: row.message_id, emojiIdOrName})
await discord.snow.channel.deleteReactionSelf(row.reference_channel_id, row.message_id, row.encoded_emoji)
}
db.prepare("DELETE FROM reaction WHERE hashed_event_id = ?").run(hash)
@ -87,4 +89,4 @@ async function handle(event) {
}
module.exports.handle = handle
module.exports.ourDeletedReactions = ourDeletedReactions
module.exports.m2dDeletedReactions = m2dDeletedReactions