From b3c0f5ba40239e45039ff32518f05d43e7e02734 Mon Sep 17 00:00:00 2001 From: artie Date: Mon, 17 Mar 2025 20:43:32 +0100 Subject: [PATCH] make context menu commands ephemeral in DMs --- src/commands/language/translateEnglishMenu.ts | 3 ++- src/commands/language/translateMenu.ts | 3 ++- src/commands/ocr/ocrMenu.ts | 4 +-- src/commands/ocr/ocrTranslateEnglishMenu.ts | 4 +-- src/commands/ocr/ocrTranslateMenu.ts | 4 +-- src/utils/functions.ts | 27 ++++++++++++++++++- 6 files changed, 36 insertions(+), 9 deletions(-) diff --git a/src/commands/language/translateEnglishMenu.ts b/src/commands/language/translateEnglishMenu.ts index bf6a263..176d3c0 100644 --- a/src/commands/language/translateEnglishMenu.ts +++ b/src/commands/language/translateEnglishMenu.ts @@ -2,6 +2,7 @@ import { ApplicationCommandType, ContextMenuCommandBuilder } from "discord.js"; import { defineCommand } from ".."; import { translateImpl } from "./translate"; import { abort } from "../../utils/error"; +import { defer } from "../../utils/functions"; export default defineCommand({ data: new ContextMenuCommandBuilder() @@ -14,7 +15,7 @@ export default defineCommand({ const text = interaction.targetMessage.content; if (!text) abort("No text to translate"); - await interaction.deferReply(); + await defer(interaction); const payload = await translateImpl(text, null, "en-US"); await interaction.editReply(payload); diff --git a/src/commands/language/translateMenu.ts b/src/commands/language/translateMenu.ts index 03133b1..2639e3a 100644 --- a/src/commands/language/translateMenu.ts +++ b/src/commands/language/translateMenu.ts @@ -11,6 +11,7 @@ import { defineCommand } from ".."; import { abort } from "../../utils/error"; import { translateImpl } from "./translate"; import { findFuzzyLanguage } from "../../utils/deepl"; +import { defer } from "../../utils/functions"; export function buildTranslateModal() { return new ModalBuilder() @@ -58,7 +59,7 @@ export default defineCommand({ time: 60000 * 5, }) .then(async interaction => { - await interaction.deferReply(); + await defer(interaction); const sourceField = interaction.fields.getTextInputValue("source") || "auto"; diff --git a/src/commands/ocr/ocrMenu.ts b/src/commands/ocr/ocrMenu.ts index bcc924c..0128c56 100644 --- a/src/commands/ocr/ocrMenu.ts +++ b/src/commands/ocr/ocrMenu.ts @@ -1,7 +1,7 @@ import { ApplicationCommandType, ContextMenuCommandBuilder } from "discord.js"; import { defineCommand } from ".."; import { buildOcrPayload, ocrImpl } from "./ocr"; -import { getImageUrlFromMessage } from "../../utils/functions"; +import { defer, getImageUrlFromMessage } from "../../utils/functions"; export default defineCommand({ data: new ContextMenuCommandBuilder() @@ -13,7 +13,7 @@ export default defineCommand({ const imageUrl = getImageUrlFromMessage(interaction.targetMessage); - await interaction.deferReply(); + await defer(interaction); const { text, language, model } = await ocrImpl(imageUrl); const payload = buildOcrPayload(text, language, model); diff --git a/src/commands/ocr/ocrTranslateEnglishMenu.ts b/src/commands/ocr/ocrTranslateEnglishMenu.ts index 85079f6..2435d75 100644 --- a/src/commands/ocr/ocrTranslateEnglishMenu.ts +++ b/src/commands/ocr/ocrTranslateEnglishMenu.ts @@ -2,7 +2,7 @@ import { ApplicationCommandType, ContextMenuCommandBuilder } from "discord.js"; import { defineCommand } from ".."; import { translateImpl } from "../language/translate"; import { ocrImpl } from "./ocr"; -import { getImageUrlFromMessage } from "../../utils/functions"; +import { defer, getImageUrlFromMessage } from "../../utils/functions"; export default defineCommand({ data: new ContextMenuCommandBuilder() @@ -14,7 +14,7 @@ export default defineCommand({ const imageUrl = getImageUrlFromMessage(interaction.targetMessage); - await interaction.deferReply(); + await defer(interaction); const { text, model } = await ocrImpl(imageUrl); const payload = await translateImpl(text, null, "en-US", model); diff --git a/src/commands/ocr/ocrTranslateMenu.ts b/src/commands/ocr/ocrTranslateMenu.ts index 4e08593..e93ef56 100644 --- a/src/commands/ocr/ocrTranslateMenu.ts +++ b/src/commands/ocr/ocrTranslateMenu.ts @@ -5,7 +5,7 @@ import { ocrImpl } from "./ocr"; import { buildTranslateModal } from "../language/translateMenu"; import { abort } from "../../utils/error"; import { findFuzzyLanguage } from "../../utils/deepl"; -import { getImageUrlFromMessage } from "../../utils/functions"; +import { defer, getImageUrlFromMessage } from "../../utils/functions"; export default defineCommand({ data: new ContextMenuCommandBuilder() @@ -26,7 +26,7 @@ export default defineCommand({ time: 60000 * 5, }) .then(async interaction => { - await interaction.deferReply(); + await defer(interaction); const sourceField = interaction.fields.getTextInputValue("source") || null; diff --git a/src/utils/functions.ts b/src/utils/functions.ts index de61587..613bb99 100644 --- a/src/utils/functions.ts +++ b/src/utils/functions.ts @@ -2,7 +2,14 @@ import * as cheerio from "cheerio"; import { execa } from "execa"; import { customAlphabet } from "nanoid"; import { URL_REGEX } from "./constants"; -import { Message, type ChatInputCommandInteraction } from "discord.js"; +import { + ChannelType, + Message, + MessageContextMenuCommandInteraction, + MessageFlags, + ModalSubmitInteraction, + type ChatInputCommandInteraction, +} from "discord.js"; import { abort } from "./error"; export const nanoid = customAlphabet("1234567890abcdef"); @@ -105,3 +112,21 @@ export function languageCodeToName(code: string) { return undefined; } } + +// deferReply helper with flag heuristics +export async function defer( + interaction: + | MessageContextMenuCommandInteraction + | ModalSubmitInteraction + | ChatInputCommandInteraction +) { + const isDMBased = interaction.channel?.isDMBased(); + const isBotDM = + isDMBased && + interaction.channel.type === ChannelType.DM && + interaction.channel.recipientId === interaction.client.user.id; + + await interaction.deferReply({ + flags: isDMBased && !isBotDM ? MessageFlags.Ephemeral : undefined, + }); +}