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")
|
const registerUser = sync.require("./register-user")
|
||||||
/** @type {import("../actions/create-room")} */
|
/** @type {import("../actions/create-room")} */
|
||||||
const createRoom = sync.require("../actions/create-room")
|
const createRoom = sync.require("../actions/create-room")
|
||||||
/** @type {import("../../matrix/file")} */
|
/** @type {import("../converters/emoji-to-key")} */
|
||||||
const file = sync.require("../../matrix/file")
|
const emojiToKey = sync.require("../converters/emoji-to-key")
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {import("discord-api-types/v10").GatewayMessageReactionAddDispatchData} data
|
* @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.
|
if (!parentID) return // Nothing can be done if the parent message was never bridged.
|
||||||
assert.equal(typeof parentID, "string")
|
assert.equal(typeof parentID, "string")
|
||||||
|
|
||||||
let key
|
const key = await emojiToKey.emojiToKey(data.emoji)
|
||||||
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 roomID = await createRoom.ensureRoom(data.channel_id)
|
const roomID = await createRoom.ensureRoom(data.channel_id)
|
||||||
const senderMxid = await registerUser.ensureSimJoined(user, roomID)
|
const senderMxid = await registerUser.ensureSimJoined(user, roomID)
|
||||||
|
|
|
@ -7,12 +7,8 @@ const passthrough = require("../../passthrough")
|
||||||
const {discord, sync, db, select} = passthrough
|
const {discord, sync, db, select} = passthrough
|
||||||
/** @type {import("../../matrix/api")} */
|
/** @type {import("../../matrix/api")} */
|
||||||
const api = sync.require("../../matrix/api")
|
const api = sync.require("../../matrix/api")
|
||||||
/** @type {import("./register-user")} */
|
/** @type {import("../converters/emoji-to-key")} */
|
||||||
const registerUser = sync.require("./register-user")
|
const emojiToKey = sync.require("../converters/emoji-to-key")
|
||||||
/** @type {import("../actions/create-room")} */
|
|
||||||
const createRoom = sync.require("../actions/create-room")
|
|
||||||
/** @type {import("../../matrix/file")} */
|
|
||||||
const file = sync.require("../../matrix/file")
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {import("discord-api-types/v10").GatewayMessageReactionRemoveDispatchData} data
|
* @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>>} */
|
/** @type {Ty.Pagination<Ty.Event.Outer<Ty.Event.M_Reaction>>} */
|
||||||
const relations = await api.getRelations(roomID, eventIDForMessage, "m.annotation")
|
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
|
if (!eventIDForReaction) return
|
||||||
|
|
||||||
await api.redactEvent(roomID, eventIDForReaction, mxid)
|
await api.redactEvent(roomID, eventIDForReaction.event_id, mxid)
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports.removeReaction = removeReaction
|
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") {
|
} else if (message.t === "MESSAGE_REACTION_ADD") {
|
||||||
await eventDispatcher.onReactionAdd(client, message.d)
|
await eventDispatcher.onReactionAdd(client, message.d)
|
||||||
|
|
||||||
|
} else if (message.t === "MESSAGE_REACTION_REMOVE") {
|
||||||
|
await eventDispatcher.onReactionRemove(client, message.d)
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Let OOYE try to handle errors too
|
// 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")
|
const deleteMessage = sync.require("./actions/delete-message")
|
||||||
/** @type {import("./actions/add-reaction")}) */
|
/** @type {import("./actions/add-reaction")}) */
|
||||||
const addReaction = sync.require("./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")}) */
|
/** @type {import("./actions/announce-thread")}) */
|
||||||
const announceThread = sync.require("./actions/announce-thread")
|
const announceThread = sync.require("./actions/announce-thread")
|
||||||
/** @type {import("./actions/create-room")}) */
|
/** @type {import("./actions/create-room")}) */
|
||||||
|
@ -210,6 +212,15 @@ module.exports = {
|
||||||
await addReaction.addReaction(data)
|
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-client")} client
|
||||||
* @param {import("discord-api-types/v10").GatewayMessageDeleteDispatchData} data
|
* @param {import("discord-api-types/v10").GatewayMessageDeleteDispatchData} data
|
||||||
|
|
|
@ -24,7 +24,8 @@ async function removeReaction(event) {
|
||||||
const hash = utils.getEventIDHash(event.redacts)
|
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)
|
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
|
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) {
|
async function redactEvent(roomID, eventID, mxid) {
|
||||||
/** @type {Ty.R.EventRedacted} */
|
/** @type {Ty.R.EventRedacted} */
|
||||||
|
|
Loading…
Reference in a new issue