Add reaction viewer to right click menu
This commit is contained in:
parent
a2e3f06e8e
commit
62edffbae0
4 changed files with 87 additions and 10 deletions
|
@ -23,16 +23,7 @@ async function removeSomeReactions(data) {
|
||||||
const eventIDForMessage = select("event_message", "event_id", {message_id: data.message_id, reaction_part: 0}).pluck().get()
|
const eventIDForMessage = select("event_message", "event_id", {message_id: data.message_id, reaction_part: 0}).pluck().get()
|
||||||
if (!eventIDForMessage) return
|
if (!eventIDForMessage) return
|
||||||
|
|
||||||
/** @type {Ty.Event.Outer<Ty.Event.M_Reaction>[]} */
|
const reactions = await api.getFullRelations(roomID, eventIDForMessage, "m.annotation")
|
||||||
let reactions = []
|
|
||||||
/** @type {string | undefined} */
|
|
||||||
let nextBatch = undefined
|
|
||||||
do {
|
|
||||||
/** @type {Ty.Pagination<Ty.Event.Outer<Ty.Event.M_Reaction>>} */
|
|
||||||
const res = await api.getRelations(roomID, eventIDForMessage, {from: nextBatch}, "m.annotation")
|
|
||||||
reactions = reactions.concat(res.chunk)
|
|
||||||
nextBatch = res.next_batch
|
|
||||||
} while (nextBatch)
|
|
||||||
|
|
||||||
// Run the proper strategy and any strategy-specific database changes
|
// Run the proper strategy and any strategy-specific database changes
|
||||||
const removals = await
|
const removals = await
|
||||||
|
|
58
discord/interactions/reactions.js
Normal file
58
discord/interactions/reactions.js
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
// @ts-check
|
||||||
|
|
||||||
|
const DiscordTypes = require("discord-api-types/v10")
|
||||||
|
const {discord, sync, db, select, from} = require("../../passthrough")
|
||||||
|
|
||||||
|
/** @type {import("../../matrix/api")} */
|
||||||
|
const api = sync.require("../../matrix/api")
|
||||||
|
/** @type {import("../../m2d/converters/utils")} */
|
||||||
|
const utils = sync.require("../../m2d/converters/utils")
|
||||||
|
|
||||||
|
/** @param {DiscordTypes.APIContextMenuGuildInteraction} interaction */
|
||||||
|
/** @param {DiscordTypes.APIMessageApplicationCommandGuildInteraction} interaction */
|
||||||
|
async function interact({id, token, data}) {
|
||||||
|
const row = from("event_message").join("message_channel", "message_id").join("channel_room", "channel_id")
|
||||||
|
.select("event_id", "room_id").where({message_id: data.target_id}).get()
|
||||||
|
if (!row) {
|
||||||
|
return discord.snow.interaction.createInteractionResponse(id, token, {
|
||||||
|
type: DiscordTypes.InteractionResponseType.ChannelMessageWithSource,
|
||||||
|
data: {
|
||||||
|
content: "This message hasn't been bridged to Matrix.",
|
||||||
|
flags: DiscordTypes.MessageFlags.Ephemeral
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const reactions = await api.getFullRelations(row.room_id, row.event_id, "m.annotation")
|
||||||
|
|
||||||
|
/** @type {Map<string, string[]>} */
|
||||||
|
const inverted = new Map()
|
||||||
|
for (const reaction of reactions) {
|
||||||
|
if (utils.eventSenderIsFromDiscord(reaction.sender)) continue
|
||||||
|
const key = reaction.content["m.relates_to"].key
|
||||||
|
const displayname = select("member_cache", "displayname", {mxid: reaction.sender, room_id: row.room_id}).pluck().get() || reaction.sender
|
||||||
|
if (!inverted.has(key)) inverted.set(key, [])
|
||||||
|
// @ts-ignore
|
||||||
|
inverted.get(key).push(displayname)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inverted.size === 0) {
|
||||||
|
return discord.snow.interaction.createInteractionResponse(id, token, {
|
||||||
|
type: DiscordTypes.InteractionResponseType.ChannelMessageWithSource,
|
||||||
|
data: {
|
||||||
|
content: "Nobody from Matrix reacted to this message.",
|
||||||
|
flags: DiscordTypes.MessageFlags.Ephemeral
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return discord.snow.interaction.createInteractionResponse(id, token, {
|
||||||
|
type: DiscordTypes.InteractionResponseType.ChannelMessageWithSource,
|
||||||
|
data: {
|
||||||
|
content: [...inverted.entries()].map(([key, value]) => `${key} ⮞ ${value.join(" ⬩ ")}`).join("\n"),
|
||||||
|
flags: DiscordTypes.MessageFlags.Ephemeral
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.interact = interact
|
|
@ -8,6 +8,7 @@ const matrixInfo = sync.require("./interactions/matrix-info.js")
|
||||||
const invite = sync.require("./interactions/invite.js")
|
const invite = sync.require("./interactions/invite.js")
|
||||||
const permissions = sync.require("./interactions/permissions.js")
|
const permissions = sync.require("./interactions/permissions.js")
|
||||||
const bridge = sync.require("./interactions/bridge.js")
|
const bridge = sync.require("./interactions/bridge.js")
|
||||||
|
const reactions = sync.require("./interactions/reactions.js")
|
||||||
|
|
||||||
discord.snow.interaction.bulkOverwriteApplicationCommands(id, [{
|
discord.snow.interaction.bulkOverwriteApplicationCommands(id, [{
|
||||||
name: "Matrix info",
|
name: "Matrix info",
|
||||||
|
@ -18,6 +19,10 @@ discord.snow.interaction.bulkOverwriteApplicationCommands(id, [{
|
||||||
contexts: [DiscordTypes.InteractionContextType.Guild],
|
contexts: [DiscordTypes.InteractionContextType.Guild],
|
||||||
type: DiscordTypes.ApplicationCommandType.Message,
|
type: DiscordTypes.ApplicationCommandType.Message,
|
||||||
default_member_permissions: String(DiscordTypes.PermissionFlagsBits.KickMembers | DiscordTypes.PermissionFlagsBits.ManageRoles)
|
default_member_permissions: String(DiscordTypes.PermissionFlagsBits.KickMembers | DiscordTypes.PermissionFlagsBits.ManageRoles)
|
||||||
|
}, {
|
||||||
|
name: "Reactions",
|
||||||
|
contexts: [DiscordTypes.InteractionContextType.Guild],
|
||||||
|
type: DiscordTypes.ApplicationCommandType.Message
|
||||||
}, {
|
}, {
|
||||||
name: "invite",
|
name: "invite",
|
||||||
contexts: [DiscordTypes.InteractionContextType.Guild],
|
contexts: [DiscordTypes.InteractionContextType.Guild],
|
||||||
|
@ -63,6 +68,8 @@ async function dispatchInteraction(interaction) {
|
||||||
await permissions.interactEdit(interaction)
|
await permissions.interactEdit(interaction)
|
||||||
} else if (interactionId === "bridge") {
|
} else if (interactionId === "bridge") {
|
||||||
await bridge.interact(interaction)
|
await bridge.interact(interaction)
|
||||||
|
} else if (interactionId === "Reactions") {
|
||||||
|
await reactions.interact(interaction)
|
||||||
} else {
|
} else {
|
||||||
throw new Error(`Unknown interaction ${interactionId}`)
|
throw new Error(`Unknown interaction ${interactionId}`)
|
||||||
}
|
}
|
||||||
|
|
|
@ -169,6 +169,26 @@ function getRelations(roomID, eventID, pagination, relType) {
|
||||||
return mreq.mreq("GET", path)
|
return mreq.mreq("GET", path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Like `getRelations` but collects and filters all pages for you.
|
||||||
|
* @param {string} roomID
|
||||||
|
* @param {string} eventID
|
||||||
|
* @param {string?} [relType] type of relations to filter, e.g. "m.annotation" for reactions
|
||||||
|
*/
|
||||||
|
async function getFullRelations(roomID, eventID, relType) {
|
||||||
|
/** @type {Ty.Event.Outer<Ty.Event.M_Reaction>[]} */
|
||||||
|
let reactions = []
|
||||||
|
/** @type {string | undefined} */
|
||||||
|
let nextBatch = undefined
|
||||||
|
do {
|
||||||
|
/** @type {Ty.Pagination<Ty.Event.Outer<Ty.Event.M_Reaction>>} */
|
||||||
|
const res = await getRelations(roomID, eventID, {from: nextBatch}, relType)
|
||||||
|
reactions = reactions.concat(res.chunk)
|
||||||
|
nextBatch = res.next_batch
|
||||||
|
} while (nextBatch)
|
||||||
|
return reactions
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} roomID
|
* @param {string} roomID
|
||||||
* @param {string} type
|
* @param {string} type
|
||||||
|
@ -289,6 +309,7 @@ module.exports.getJoinedMembers = getJoinedMembers
|
||||||
module.exports.getHierarchy = getHierarchy
|
module.exports.getHierarchy = getHierarchy
|
||||||
module.exports.getFullHierarchy = getFullHierarchy
|
module.exports.getFullHierarchy = getFullHierarchy
|
||||||
module.exports.getRelations = getRelations
|
module.exports.getRelations = getRelations
|
||||||
|
module.exports.getFullRelations = getFullRelations
|
||||||
module.exports.sendState = sendState
|
module.exports.sendState = sendState
|
||||||
module.exports.sendEvent = sendEvent
|
module.exports.sendEvent = sendEvent
|
||||||
module.exports.redactEvent = redactEvent
|
module.exports.redactEvent = redactEvent
|
||||||
|
|
Loading…
Reference in a new issue