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

Open
ellie wants to merge 8 commits from ellie/out-of-your-element:ellie-fix-reacts into main
3 changed files with 32 additions and 1 deletions
Showing only changes of commit 5f27fedd86 - Show all commits

View file

@ -2,7 +2,9 @@
const {EventEmitter} = require("events")
const passthrough = require("../../passthrough")
const {select} = passthrough
const {select, sync} = passthrough
/** @type {import("../../matrix/utils")} */
const utils = sync.require("../../matrix/utils")
const DEBUG_RETRIGGER = false
@ -57,6 +59,30 @@ function eventNotFoundThenRetrigger(inputID, fn, ...rest) {
return true // event was not found, then retrigger
}
function reactionNotFoundThenRetrigger(reactionEventID, fn, ...rest){
cadence marked this conversation as resolved Outdated

Is it more or less gross if these were abstracted into a common base?

Is it more or less gross if these were abstracted into a common base?

It was less gross

It was less gross
const reactionEventHash = utils.getEventIDHash(reactionEventID)
const reaction = select("reaction", "encoded_emoji", {hashed_event_id: reactionEventHash})
if (reaction) {
debugRetrigger(`[retrigger] OK eid <-> reaction = ${reactionEventID} <-> ${reactionEventHash}`)
return false
}
debugRetrigger(`[retrigger] WAIT id = ${reactionEventID}`)
emitter.once(reactionEventID, () => {
debugRetrigger(`[retrigger] TRIGGER id = ${reactionEventID}`)
fn(...rest)
})
// if the event never arrives, don't trigger the callback, just clean up
setTimeout(() => {
if (emitter.listeners(reactionEventID).length) {
debugRetrigger(`[retrigger] EXPIRE id = ${reactionEventID}`)
}
emitter.removeAllListeners(reactionEventID)
}, 60 * 1000) // 1 minute
return true // event was not found, then retrigger
}
/**
* Anything calling retrigger during the callback will be paused and retriggered after the callback resolves.
* @template T
@ -88,5 +114,6 @@ function messageFinishedBridging(messageID) {
}
module.exports.eventNotFoundThenRetrigger = eventNotFoundThenRetrigger
module.exports.reactionNotFoundThenRetrigger = reactionNotFoundThenRetrigger
module.exports.messageFinishedBridging = messageFinishedBridging
module.exports.pauseChanges = pauseChanges

View file

@ -50,6 +50,8 @@ async function addReaction(event) {
}
db.prepare("REPLACE INTO reaction (hashed_event_id, message_id, encoded_emoji, original_encoding) VALUES (?, ?, ?, ?)").run(utils.getEventIDHash(event.event_id), messageID, discordPreferredEncoding, key)
retrigger.messageFinishedBridging(event.event_id)
cadence marked this conversation as resolved Outdated

Is this really the correct function to call here?

Is this really the correct function to call here?
}
module.exports.addReaction = addReaction

View file

@ -41,6 +41,8 @@ async function suppressEmbeds(event) {
* @param {Ty.Event.Outer_M_Room_Redaction} event
*/
async function removeReaction(event) {
if (retrigger.reactionNotFoundThenRetrigger(event.redacts, () => as.emit("type:m.room.redaction", event))) return
cadence marked this conversation as resolved Outdated

Retrigger target should be this function, not as.emit, otherwise other operations related to redaction could possibly be duplicated

Retrigger target should be this function, not as.emit, otherwise other operations related to redaction could possibly be duplicated
const hash = utils.getEventIDHash(event.redacts)
const row = from("reaction").join("message_room", "message_id").join("historical_channel_room", "historical_room_index")
.select("reference_channel_id", "message_id", "encoded_emoji").where({hashed_event_id: hash}).get()