make removing single reactions work correctly
This commit is contained in:
		
							parent
							
								
									a396e6f596
								
							
						
					
					
						commit
						6dcf3a383a
					
				
					 7 changed files with 67 additions and 30 deletions
				
			
		| 
						 | 
				
			
			@ -10,8 +10,9 @@ const api = sync.require("../../matrix/api")
 | 
			
		|||
const registerUser = sync.require("./register-user")
 | 
			
		||||
/** @type {import("../actions/create-room")} */
 | 
			
		||||
const createRoom = sync.require("../actions/create-room")
 | 
			
		||||
/** @type {import("../../matrix/file")} */
 | 
			
		||||
const file = sync.require("../../matrix/file")
 | 
			
		||||
/** @type {import("../converters/emoji-to-key")} */
 | 
			
		||||
const emojiToKey = sync.require("../converters/emoji-to-key")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @param {import("discord-api-types/v10").GatewayMessageReactionAddDispatchData} data
 | 
			
		||||
| 
						 | 
				
			
			@ -24,24 +25,7 @@ async function addReaction(data) {
 | 
			
		|||
	if (!parentID) return // Nothing can be done if the parent message was never bridged.
 | 
			
		||||
	assert.equal(typeof parentID, "string")
 | 
			
		||||
 | 
			
		||||
	let key
 | 
			
		||||
	if (data.emoji.id) {
 | 
			
		||||
		// Custom emoji
 | 
			
		||||
		const mxc = select("emoji", "mxc_url", "WHERE id = ?").pluck().get(data.emoji.id)
 | 
			
		||||
		if (mxc) {
 | 
			
		||||
			// The custom emoji is registered and we should send it
 | 
			
		||||
			key = mxc
 | 
			
		||||
		} else {
 | 
			
		||||
			// The custom emoji is not registered. We will register it and then add it.
 | 
			
		||||
			const mxc = await file.uploadDiscordFileToMxc(file.emoji(data.emoji.id, data.emoji.animated))
 | 
			
		||||
			db.prepare("INSERT OR IGNORE INTO emoji (id, name, animated, mxc_url) VALUES (?, ?, ?, ?)").run(data.emoji.id, data.emoji.name, +!!data.emoji.animated, mxc)
 | 
			
		||||
			key = mxc
 | 
			
		||||
			// TODO: what happens if the matrix user also tries adding this reaction? the bridge bot isn't able to use that emoji...
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		// Default emoji
 | 
			
		||||
		key = data.emoji.name
 | 
			
		||||
	}
 | 
			
		||||
	const key = await emojiToKey.emojiToKey(data.emoji)
 | 
			
		||||
 | 
			
		||||
	const roomID = await createRoom.ensureRoom(data.channel_id)
 | 
			
		||||
	const senderMxid = await registerUser.ensureSimJoined(user, roomID)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,12 +7,8 @@ const passthrough = require("../../passthrough")
 | 
			
		|||
const {discord, sync, db, select} = passthrough
 | 
			
		||||
/** @type {import("../../matrix/api")} */
 | 
			
		||||
const api = sync.require("../../matrix/api")
 | 
			
		||||
/** @type {import("./register-user")} */
 | 
			
		||||
const registerUser = sync.require("./register-user")
 | 
			
		||||
/** @type {import("../actions/create-room")} */
 | 
			
		||||
const createRoom = sync.require("../actions/create-room")
 | 
			
		||||
/** @type {import("../../matrix/file")} */
 | 
			
		||||
const file = sync.require("../../matrix/file")
 | 
			
		||||
/** @type {import("../converters/emoji-to-key")} */
 | 
			
		||||
const emojiToKey = sync.require("../converters/emoji-to-key")
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @param {import("discord-api-types/v10").GatewayMessageReactionRemoveDispatchData} data
 | 
			
		||||
| 
						 | 
				
			
			@ -27,10 +23,11 @@ async function removeReaction(data) {
 | 
			
		|||
 | 
			
		||||
	/** @type {Ty.Pagination<Ty.Event.Outer<Ty.Event.M_Reaction>>} */
 | 
			
		||||
	const relations = await api.getRelations(roomID, eventIDForMessage, "m.annotation")
 | 
			
		||||
	const eventIDForReaction = relations.chunk.find(e => e.sender === mxid && e.content["m.relates_to"].key === data.emoji) // TODO: get the key from the emoji
 | 
			
		||||
	const key = await emojiToKey.emojiToKey(data.emoji)
 | 
			
		||||
	const eventIDForReaction = relations.chunk.find(e => e.sender === mxid && e.content["m.relates_to"].key === key)
 | 
			
		||||
	if (!eventIDForReaction) return
 | 
			
		||||
 | 
			
		||||
	await api.redactEvent(roomID, eventIDForReaction, mxid)
 | 
			
		||||
	await api.redactEvent(roomID, eventIDForReaction.event_id, mxid)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports.removeReaction = removeReaction
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										38
									
								
								d2m/converters/emoji-to-key.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								d2m/converters/emoji-to-key.js
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,38 @@
 | 
			
		|||
// @ts-check
 | 
			
		||||
 | 
			
		||||
const assert = require("assert").strict
 | 
			
		||||
const passthrough = require("../../passthrough")
 | 
			
		||||
const {discord, sync, db, select} = passthrough
 | 
			
		||||
/** @type {import("../../matrix/file")} */
 | 
			
		||||
const file = sync.require("../../matrix/file")
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @param {import("discord-api-types/v10").APIEmoji} emoji
 | 
			
		||||
 * @returns {Promise<string>}
 | 
			
		||||
 */
 | 
			
		||||
async function emojiToKey(emoji) {
 | 
			
		||||
	let key
 | 
			
		||||
	if (emoji.id) {
 | 
			
		||||
		// Custom emoji
 | 
			
		||||
		const mxc = select("emoji", "mxc_url", "WHERE id = ?").pluck().get(emoji.id)
 | 
			
		||||
		if (mxc) {
 | 
			
		||||
			// The custom emoji is registered and we should send it
 | 
			
		||||
			key = mxc
 | 
			
		||||
		} else {
 | 
			
		||||
			// The custom emoji is not registered. We will register it and then add it.
 | 
			
		||||
			assert(emoji.name) // The docs say: "name may be null when custom emoji data is not available, for example, if it was deleted from the guild"
 | 
			
		||||
			const mxc = await file.uploadDiscordFileToMxc(file.emoji(emoji.id, emoji.animated))
 | 
			
		||||
			db.prepare("INSERT OR IGNORE INTO emoji (id, name, animated, mxc_url) VALUES (?, ?, ?, ?)").run(emoji.id, emoji.name, +!!emoji.animated, mxc)
 | 
			
		||||
			key = mxc
 | 
			
		||||
			// TODO: what happens if the matrix user also tries adding this reaction? the bridge bot isn't able to use that emoji...
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		// Default emoji
 | 
			
		||||
		const name = emoji.name
 | 
			
		||||
		assert(name)
 | 
			
		||||
		key = name
 | 
			
		||||
	}
 | 
			
		||||
	return key
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports.emojiToKey = emojiToKey
 | 
			
		||||
| 
						 | 
				
			
			@ -155,6 +155,9 @@ const utils = {
 | 
			
		|||
 | 
			
		||||
				} else if (message.t === "MESSAGE_REACTION_ADD") {
 | 
			
		||||
					await eventDispatcher.onReactionAdd(client, message.d)
 | 
			
		||||
 | 
			
		||||
				} else if (message.t === "MESSAGE_REACTION_REMOVE") {
 | 
			
		||||
					await eventDispatcher.onReactionRemove(client, message.d)
 | 
			
		||||
				}
 | 
			
		||||
			} catch (e) {
 | 
			
		||||
				// Let OOYE try to handle errors too
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,6 +10,8 @@ const editMessage = sync.require("./actions/edit-message")
 | 
			
		|||
const deleteMessage = sync.require("./actions/delete-message")
 | 
			
		||||
/** @type {import("./actions/add-reaction")}) */
 | 
			
		||||
const addReaction = sync.require("./actions/add-reaction")
 | 
			
		||||
/** @type {import("./actions/remove-reaction")}) */
 | 
			
		||||
const removeReaction = sync.require("./actions/remove-reaction")
 | 
			
		||||
/** @type {import("./actions/announce-thread")}) */
 | 
			
		||||
const announceThread = sync.require("./actions/announce-thread")
 | 
			
		||||
/** @type {import("./actions/create-room")}) */
 | 
			
		||||
| 
						 | 
				
			
			@ -210,6 +212,15 @@ module.exports = {
 | 
			
		|||
		await addReaction.addReaction(data)
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * @param {import("./discord-client")} client
 | 
			
		||||
	 * @param {import("discord-api-types/v10").GatewayMessageReactionAddDispatchData} data
 | 
			
		||||
	 */
 | 
			
		||||
	async onReactionRemove(client, data) {
 | 
			
		||||
		if (data.user_id === client.user.id) return // m2d reactions are added by the discord bot user - do not reflect them back to matrix.
 | 
			
		||||
		await removeReaction.removeReaction(data)
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * @param {import("./discord-client")} client
 | 
			
		||||
	 * @param {import("discord-api-types/v10").GatewayMessageDeleteDispatchData} data
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,7 +24,8 @@ async function removeReaction(event) {
 | 
			
		|||
	const hash = utils.getEventIDHash(event.redacts)
 | 
			
		||||
	const row = from("reaction").join("message_channel", "message_id").select("channel_id", "message_id", "encoded_emoji").and("WHERE hashed_event_id = ?").get(hash)
 | 
			
		||||
	if (!row) return
 | 
			
		||||
	return discord.snow.channel.deleteReactionSelf(row.channel_id, row.message_id, row.encoded_emoji)
 | 
			
		||||
	await discord.snow.channel.deleteReactionSelf(row.channel_id, row.message_id, row.encoded_emoji)
 | 
			
		||||
	db.prepare("DELETE FROM reaction WHERE hashed_event_id = ?").run(hash)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -155,7 +155,10 @@ async function sendEvent(roomID, type, content, mxid, timestamp) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @returns {Promise<string>} room ID
 | 
			
		||||
 * @param {string} roomID
 | 
			
		||||
 * @param {string} eventID
 | 
			
		||||
 * @param {string?} [mxid]
 | 
			
		||||
 * @returns {Promise<string>} event ID
 | 
			
		||||
 */
 | 
			
		||||
async function redactEvent(roomID, eventID, mxid) {
 | 
			
		||||
	/** @type {Ty.R.EventRedacted} */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue