diff --git a/.changeset/few-ants-share.md b/.changeset/few-ants-share.md new file mode 100644 index 00000000..4dcf48dd --- /dev/null +++ b/.changeset/few-ants-share.md @@ -0,0 +1,5 @@ +--- +"@buape/carbon": patch +--- + +fix: make ephemeral responses work properly diff --git a/apps/rocko/src/commands/testing/ephemeral.ts b/apps/rocko/src/commands/testing/ephemeral.ts new file mode 100644 index 00000000..c7a589b0 --- /dev/null +++ b/apps/rocko/src/commands/testing/ephemeral.ts @@ -0,0 +1,35 @@ +import { + Command, + type CommandInteraction, + CommandWithSubcommands +} from "@buape/carbon" + +export default class EphemeralCommand extends CommandWithSubcommands { + name = "ephemeral" + description = "Ephemeral test" + ephemeral = true + + subcommands = [new EphemeralNoDefer(), new EphemeralDefer()] +} + +class EphemeralNoDefer extends Command { + name = "no-defer" + description = "Ephemeral test" + ephemeral = true + defer = false + + async run(interaction: CommandInteraction): Promise { + return interaction.reply({ content: "Ephemeral no defer" }) + } +} + +export class EphemeralDefer extends Command { + name = "defer" + description = "Ephemeral test" + ephemeral = true + defer = true + + async run(interaction: CommandInteraction): Promise { + return interaction.reply({ content: "Ephemeral defer" }) + } +} diff --git a/packages/carbon/src/abstracts/BaseInteraction.ts b/packages/carbon/src/abstracts/BaseInteraction.ts index 3cd694c1..80658603 100644 --- a/packages/carbon/src/abstracts/BaseInteraction.ts +++ b/packages/carbon/src/abstracts/BaseInteraction.ts @@ -3,6 +3,7 @@ import { type APIInteraction, InteractionResponseType, type InteractionType, + MessageFlags, type RESTPatchAPIInteractionOriginalResponseJSONBody, type RESTPostAPIInteractionCallbackJSONBody, type RESTPostAPIInteractionFollowupJSONBody, @@ -154,10 +155,12 @@ export abstract class BaseInteraction extends Base { body: { type: InteractionResponseType.ChannelMessageWithSource, data: { - ...serializePayload(data), - flags: options.ephemeral - ? 64 | ("flags" in serialized ? (serialized.flags ?? 0) : 0) - : undefined + ...serialized, + flags: + options.ephemeral || this.defaultEphemeral + ? MessageFlags.Ephemeral | + ("flags" in serialized ? (serialized.flags ?? 0) : 0) + : undefined } } as RESTPostAPIInteractionCallbackJSONBody, files: options.files @@ -171,7 +174,7 @@ export abstract class BaseInteraction extends Base { * If the interaction is already deferred, this will do nothing. * @internal */ - async defer() { + async defer({ ephemeral = false } = {}) { if (this._deferred) return this._deferred = true await this.client.rest.post( @@ -179,8 +182,13 @@ export abstract class BaseInteraction extends Base { { body: { type: InteractionResponseType.DeferredChannelMessageWithSource, - flags: this.defaultEphemeral ? 64 : undefined - } as RESTPostAPIInteractionCallbackJSONBody + data: { + flags: + ephemeral || this.defaultEphemeral + ? MessageFlags.Ephemeral + : undefined + } + } satisfies RESTPostAPIInteractionCallbackJSONBody } ) } @@ -198,7 +206,7 @@ export abstract class BaseInteraction extends Base { body: { type: InteractionResponseType.Modal, data: modal.serialize() - } as RESTPostAPIInteractionCallbackJSONBody + } satisfies RESTPostAPIInteractionCallbackJSONBody } ) } @@ -214,7 +222,8 @@ export abstract class BaseInteraction extends Base { body: { ...serialized, flags: options.ephemeral - ? 64 | ("flags" in serialized ? (serialized.flags ?? 0) : 0) + ? MessageFlags.Ephemeral | + ("flags" in serialized ? (serialized.flags ?? 0) : 0) : undefined } as RESTPostAPIInteractionFollowupJSONBody, files: options.files diff --git a/packages/carbon/src/utils.ts b/packages/carbon/src/utils.ts index 620d0d98..7f507360 100644 --- a/packages/carbon/src/utils.ts +++ b/packages/carbon/src/utils.ts @@ -82,12 +82,20 @@ export function concatUint8Arrays( return merged } -export const serializePayload = (payload: MessagePayload) => { - return typeof payload === "string" - ? { content: payload } - : { - ...payload, - embeds: payload.embeds?.map((embed) => embed.serialize()), - components: payload.components?.map((row) => row.serialize()) - } +export const serializePayload = ( + payload: MessagePayload, + defaultEphemeral = false +) => { + if (typeof payload === "string") { + return { content: payload, flags: defaultEphemeral ? 64 : undefined } + } + const data = { + ...payload, + embeds: payload.embeds?.map((embed) => embed.serialize()), + components: payload.components?.map((row) => row.serialize()) + } + if (defaultEphemeral) { + data.flags = 64 + } + return data }