Compare commits
No commits in common. "c3040f19c2a1e4e0c16c0195062b89d1d3d3dafb" and "4f807159ba0b9a6765e0328f06c6efb2032b668a" have entirely different histories.
c3040f19c2
...
4f807159ba
9 changed files with 38 additions and 81 deletions
|
@ -10,9 +10,8 @@ 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("../converters/emoji-to-key")} */
|
||||
const emojiToKey = sync.require("../converters/emoji-to-key")
|
||||
|
||||
/** @type {import("../../matrix/file")} */
|
||||
const file = sync.require("../../matrix/file")
|
||||
|
||||
/**
|
||||
* @param {import("discord-api-types/v10").GatewayMessageReactionAddDispatchData} data
|
||||
|
@ -25,8 +24,24 @@ async function addReaction(data) {
|
|||
if (!parentID) return // Nothing can be done if the parent message was never bridged.
|
||||
assert.equal(typeof parentID, "string")
|
||||
|
||||
const key = await emojiToKey.emojiToKey(data.emoji)
|
||||
const shortcode = key.startsWith("mxc://") ? `:${data.emoji.name}:` : undefined
|
||||
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 roomID = await createRoom.ensureRoom(data.channel_id)
|
||||
const senderMxid = await registerUser.ensureSimJoined(user, roomID)
|
||||
|
@ -35,8 +50,7 @@ async function addReaction(data) {
|
|||
rel_type: "m.annotation",
|
||||
event_id: parentID,
|
||||
key
|
||||
},
|
||||
shortcode
|
||||
}
|
||||
}, senderMxid)
|
||||
return eventID
|
||||
}
|
||||
|
|
|
@ -7,8 +7,12 @@ const passthrough = require("../../passthrough")
|
|||
const {discord, sync, db, select} = passthrough
|
||||
/** @type {import("../../matrix/api")} */
|
||||
const api = sync.require("../../matrix/api")
|
||||
/** @type {import("../converters/emoji-to-key")} */
|
||||
const emojiToKey = sync.require("../converters/emoji-to-key")
|
||||
/** @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")
|
||||
|
||||
/**
|
||||
* @param {import("discord-api-types/v10").GatewayMessageReactionRemoveDispatchData} data
|
||||
|
@ -23,11 +27,10 @@ async function removeReaction(data) {
|
|||
|
||||
/** @type {Ty.Pagination<Ty.Event.Outer<Ty.Event.M_Reaction>>} */
|
||||
const relations = await api.getRelations(roomID, eventIDForMessage, "m.annotation")
|
||||
const key = await emojiToKey.emojiToKey(data.emoji)
|
||||
const eventIDForReaction = relations.chunk.find(e => e.sender === mxid && e.content["m.relates_to"].key === key)
|
||||
const eventIDForReaction = relations.chunk.find(e => e.sender === mxid && e.content["m.relates_to"].key === data.emoji) // TODO: get the key from the emoji
|
||||
if (!eventIDForReaction) return
|
||||
|
||||
await api.redactEvent(roomID, eventIDForReaction.event_id, mxid)
|
||||
await api.redactEvent(roomID, eventIDForReaction, mxid)
|
||||
}
|
||||
|
||||
module.exports.removeReaction = removeReaction
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
// @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,9 +155,6 @@ 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,8 +10,6 @@ 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")}) */
|
||||
|
@ -212,15 +210,6 @@ 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
|
||||
|
|
|
@ -21,19 +21,16 @@ async function addReaction(event) {
|
|||
let discordPreferredEncoding
|
||||
if (emoji.startsWith("mxc://")) {
|
||||
// Custom emoji
|
||||
let row = select("emoji", ["id", "name"], "WHERE mxc_url = ?").get(emoji)
|
||||
if (!row && event.content.shortcode) {
|
||||
// Use the name to try to find a known emoji with the same name.
|
||||
const name = event.content.shortcode.replace(/^:|:$/g, "")
|
||||
row = select("emoji", ["id", "name"], "WHERE name = ?").get(name)
|
||||
}
|
||||
if (!row) {
|
||||
const row = select("emoji", ["id", "name"], "WHERE mxc_url = ?").get(emoji)
|
||||
if (row) {
|
||||
// Great, we know exactly what this emoji is!
|
||||
discordPreferredEncoding = encodeURIComponent(`${row.name}:${row.id}`)
|
||||
} else {
|
||||
// We don't have this emoji and there's no realistic way to just-in-time upload a new emoji somewhere.
|
||||
// We can't try using a known emoji with the same name because we don't even know what the name is. We only have the mxc url.
|
||||
// Sucks!
|
||||
return
|
||||
}
|
||||
// Cool, we got an exact or a candidate emoji.
|
||||
discordPreferredEncoding = encodeURIComponent(`${row.name}:${row.id}`)
|
||||
} else {
|
||||
// Default emoji
|
||||
// https://github.com/discord/discord-api-docs/issues/2723#issuecomment-807022205 ????????????
|
||||
|
|
|
@ -24,8 +24,7 @@ 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
|
||||
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)
|
||||
return discord.snow.channel.deleteReactionSelf(row.channel_id, row.message_id, row.encoded_emoji)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -155,10 +155,7 @@ async function sendEvent(roomID, type, content, mxid, timestamp) {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param {string} roomID
|
||||
* @param {string} eventID
|
||||
* @param {string?} [mxid]
|
||||
* @returns {Promise<string>} event ID
|
||||
* @returns {Promise<string>} room ID
|
||||
*/
|
||||
async function redactEvent(roomID, eventID, mxid) {
|
||||
/** @type {Ty.R.EventRedacted} */
|
||||
|
|
3
types.d.ts
vendored
3
types.d.ts
vendored
|
@ -171,8 +171,7 @@ export namespace Event {
|
|||
rel_type: "m.annotation"
|
||||
event_id: string // the event that was reacted to
|
||||
key: string // the unicode emoji, mxc uri, or reaction text
|
||||
},
|
||||
"shortcode"?: string // starts and ends with colons
|
||||
}
|
||||
}
|
||||
|
||||
export type Outer_M_Room_Redaction = Outer<{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue