Add anti-timeout system to reactions interaction

This commit is contained in:
Cadence Ember
2025-01-12 14:31:32 +13:00
parent f3b0d01400
commit 1e4952f1b8
2 changed files with 51 additions and 28 deletions

View File

@@ -2,6 +2,8 @@
const DiscordTypes = require("discord-api-types/v10") const DiscordTypes = require("discord-api-types/v10")
const {discord, sync, select, from} = require("../../passthrough") const {discord, sync, select, from} = require("../../passthrough")
const {id: botID} = require("../../../addbot")
const {InteractionMethods} = require("snowtransfer")
/** @type {import("../../matrix/api")} */ /** @type {import("../../matrix/api")} */
const api = sync.require("../../matrix/api") const api = sync.require("../../matrix/api")
@@ -11,21 +13,28 @@ const utils = sync.require("../../m2d/converters/utils")
/** /**
* @param {DiscordTypes.APIMessageApplicationCommandGuildInteraction} interaction * @param {DiscordTypes.APIMessageApplicationCommandGuildInteraction} interaction
* @param {{api: typeof api}} di * @param {{api: typeof api}} di
* @returns {Promise<DiscordTypes.APIInteractionResponse>} * @returns {AsyncGenerator<{[k in keyof InteractionMethods]?: Parameters<InteractionMethods[k]>[2]}>}
*/ */
async function _interact({data}, {api}) { async function* _interact({data}, {api}) {
const row = from("event_message").join("message_channel", "message_id").join("channel_room", "channel_id") 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() .select("event_id", "room_id").where({message_id: data.target_id}).get()
if (!row) { if (!row) {
return { return yield {createInteractionResponse: {
type: DiscordTypes.InteractionResponseType.ChannelMessageWithSource, type: DiscordTypes.InteractionResponseType.ChannelMessageWithSource,
data: { data: {
content: "This message hasn't been bridged to Matrix.", content: "This message hasn't been bridged to Matrix.",
flags: DiscordTypes.MessageFlags.Ephemeral flags: DiscordTypes.MessageFlags.Ephemeral
} }
} }}
} }
yield {createInteractionResponse: {
type: DiscordTypes.InteractionResponseType.DeferredChannelMessageWithSource,
data: {
flags: DiscordTypes.MessageFlags.Ephemeral
}
}}
const reactions = await api.getFullRelations(row.room_id, row.event_id, "m.annotation") const reactions = await api.getFullRelations(row.room_id, row.event_id, "m.annotation")
/** @type {Map<string, string[]>} */ /** @type {Map<string, string[]>} */
@@ -40,29 +49,27 @@ async function _interact({data}, {api}) {
} }
if (inverted.size === 0) { if (inverted.size === 0) {
return { return yield {editOriginalInteractionResponse: {
type: DiscordTypes.InteractionResponseType.ChannelMessageWithSource, content: "Nobody from Matrix reacted to this message.",
data: { }}
content: "Nobody from Matrix reacted to this message.",
flags: DiscordTypes.MessageFlags.Ephemeral
}
}
} }
return { return yield {editOriginalInteractionResponse: {
type: DiscordTypes.InteractionResponseType.ChannelMessageWithSource, content: [...inverted.entries()].map(([key, value]) => `${key}${value.join(" ⬩ ")}`).join("\n"),
data: { }}
content: [...inverted.entries()].map(([key, value]) => `${key}${value.join(" ⬩ ")}`).join("\n"),
flags: DiscordTypes.MessageFlags.Ephemeral
}
}
} }
/* c8 ignore start */ /* c8 ignore start */
/** @param {DiscordTypes.APIMessageApplicationCommandGuildInteraction} interaction */ /** @param {DiscordTypes.APIMessageApplicationCommandGuildInteraction} interaction */
async function interact(interaction) { async function interact(interaction) {
await discord.snow.interaction.createInteractionResponse(interaction.id, interaction.token, await _interact(interaction, {api})) for await (const response of _interact(interaction, {api})) {
if (response.createInteractionResponse) {
await discord.snow.interaction.createInteractionResponse(interaction.id, interaction.token, response.createInteractionResponse)
} else if (response.editOriginalInteractionResponse) {
await discord.snow.interaction.editOriginalInteractionResponse(botID, interaction.token, response.editOriginalInteractionResponse)
}
}
} }
module.exports.interact = interact module.exports.interact = interact

View File

@@ -1,17 +1,31 @@
const {test} = require("supertape") const {test} = require("supertape")
const {_interact} = require("./reactions") const {_interact} = require("./reactions")
/**
* @template T
* @param {AsyncIterable<T>} ai
* @returns {Promise<T[]>}
*/
async function fromAsync(ai) {
const result = []
for await (const value of ai) {
result.push(value)
}
return result
}
test("reactions: checks if message is bridged", async t => { test("reactions: checks if message is bridged", async t => {
const msg = await _interact({ const msgs = await fromAsync(_interact({
data: { data: {
target_id: "0" target_id: "0"
} }
}, {}) }, {}))
t.equal(msg.data.content, "This message hasn't been bridged to Matrix.") t.equal(msgs.length, 1)
t.equal(msgs[0].createInteractionResponse.data.content, "This message hasn't been bridged to Matrix.")
}) })
test("reactions: different response if nobody reacted", async t => { test("reactions: different response if nobody reacted", async t => {
const msg = await _interact({ const msgs = await fromAsync(_interact({
data: { data: {
target_id: "1126786462646550579" target_id: "1126786462646550579"
} }
@@ -23,13 +37,14 @@ test("reactions: different response if nobody reacted", async t => {
return [] return []
} }
} }
}) }))
t.equal(msg.data.content, "Nobody from Matrix reacted to this message.") t.equal(msgs.length, 2)
t.equal(msgs[1].editOriginalInteractionResponse.content, "Nobody from Matrix reacted to this message.")
}) })
test("reactions: shows reactions if there are some, ignoring discord users", async t => { test("reactions: shows reactions if there are some, ignoring discord users", async t => {
let called = 1 let called = 1
const msg = await _interact({ const msgs = await fromAsync(_interact({
data: { data: {
target_id: "1126786462646550579" target_id: "1126786462646550579"
} }
@@ -73,9 +88,10 @@ test("reactions: shows reactions if there are some, ignoring discord users", asy
}] }]
} }
} }
}) }))
t.equal(msgs.length, 2)
t.equal( t.equal(
msg.data.content, msgs[1].editOriginalInteractionResponse.content,
"🐈 ⮞ cadence [they] ⬩ @rnl:cadence.moe" "🐈 ⮞ cadence [they] ⬩ @rnl:cadence.moe"
+ "\n🐈⬛ ⮞ cadence [they]" + "\n🐈⬛ ⮞ cadence [they]"
) )