diff --git a/src/helpers/interactions/commands/edit_slash_response.ts b/src/helpers/interactions/commands/edit_slash_response.ts index d3f186b17..3f81faccf 100644 --- a/src/helpers/interactions/commands/edit_slash_response.ts +++ b/src/helpers/interactions/commands/edit_slash_response.ts @@ -1,6 +1,7 @@ import type { DiscordenoEditWebhookMessage } from "../../../types/discordeno/edit_webhook_message.ts"; import type { Bot } from "../../../bot.ts"; import { DiscordAllowedMentionsTypes } from "../../../types/messages/allowed_mentions_types.ts"; +import { DiscordMessageComponentTypes } from "../../../types/messages/components/message_component_types.ts"; /** To edit your response to a slash command. If a messageId is not provided it will default to editing the original response. */ export async function editSlashResponse(bot: Bot, token: string, options: DiscordenoEditWebhookMessage) { @@ -57,8 +58,49 @@ export async function editSlashResponse(bot: Bot, token: string, options: Discor } : undefined, attachments: options.attachments, - // TODO: Snakelize components?? - components: options.components, + components: options.components?.map((component) => ({ + type: component.type, + components: component.components.map((subcomponent) => { + if (subcomponent.type === DiscordMessageComponentTypes.SelectMenu) + return { + type: subcomponent.type, + custom_id: subcomponent.customId, + placeholder: subcomponent.placeholder, + min_values: subcomponent.minValues, + max_values: subcomponent.maxValues, + options: subcomponent.options.map((option) => ({ + label: option.label, + value: option.value, + description: option.description, + emoji: option.emoji + ? { + id: option.emoji.id?.toString(), + name: option.emoji.name, + animated: option.emoji.animated, + } + : undefined, + default: option.default, + })), + }; + + return { + type: subcomponent.type, + custom_id: subcomponent.customId, + label: subcomponent.label, + customId: subcomponent.customId, + style: subcomponent.style, + emoji: subcomponent.emoji + ? { + id: subcomponent.emoji.id?.toString(), + name: subcomponent.emoji.name, + animated: subcomponent.emoji.animated, + } + : undefined, + url: subcomponent.url, + disabled: subcomponent.disabled, + }; + }), + })), message_id: options.messageId, } ); diff --git a/src/helpers/interactions/send_interaction_response.ts b/src/helpers/interactions/send_interaction_response.ts index 9a7e8e890..3ba10dd93 100644 --- a/src/helpers/interactions/send_interaction_response.ts +++ b/src/helpers/interactions/send_interaction_response.ts @@ -5,6 +5,7 @@ import { AllowedMentions } from "../../types/messages/allowed_mentions.ts"; import { MessageReference } from "../../types/messages/message_reference.ts"; import { FileContent } from "../../types/discordeno/file_content.ts"; import { MessageComponents } from "../../types/messages/components/message_components.ts"; +import { DiscordMessageComponentTypes } from "../../types/messages/components/message_component_types.ts"; // TODO: v12 remove | string /** @@ -95,8 +96,49 @@ export async function sendInteractionResponse( replied_user: allowedMentions?.repliedUser, }, file: options.data.file, - // TODO: Snakelize components?? - components: options.data.components, + components: options.data.components?.map((component) => ({ + type: component.type, + components: component.components.map((subcomponent) => { + if (subcomponent.type === DiscordMessageComponentTypes.SelectMenu) + return { + type: subcomponent.type, + custom_id: subcomponent.customId, + placeholder: subcomponent.placeholder, + min_values: subcomponent.minValues, + max_values: subcomponent.maxValues, + options: subcomponent.options.map((option) => ({ + label: option.label, + value: option.value, + description: option.description, + emoji: option.emoji + ? { + id: option.emoji.id?.toString(), + name: option.emoji.name, + animated: option.emoji.animated, + } + : undefined, + default: option.default, + })), + }; + + return { + type: subcomponent.type, + custom_id: subcomponent.customId, + label: subcomponent.label, + customId: subcomponent.customId, + style: subcomponent.style, + emoji: subcomponent.emoji + ? { + id: subcomponent.emoji.id?.toString(), + name: subcomponent.emoji.name, + animated: subcomponent.emoji.animated, + } + : undefined, + url: subcomponent.url, + disabled: subcomponent.disabled, + }; + }), + })), flags: options.data.flags, }); } @@ -171,8 +213,49 @@ export async function sendInteractionResponse( replied_user: allowedMentions?.repliedUser, }, file: options.data.file, - // TODO: Snakelize components?? - components: options.data.components, + components: options.data.components?.map((component) => ({ + type: component.type, + components: component.components.map((subcomponent) => { + if (subcomponent.type === DiscordMessageComponentTypes.SelectMenu) + return { + type: subcomponent.type, + custom_id: subcomponent.customId, + placeholder: subcomponent.placeholder, + min_values: subcomponent.minValues, + max_values: subcomponent.maxValues, + options: subcomponent.options.map((option) => ({ + label: option.label, + value: option.value, + description: option.description, + emoji: option.emoji + ? { + id: option.emoji.id?.toString(), + name: option.emoji.name, + animated: option.emoji.animated, + } + : undefined, + default: option.default, + })), + }; + + return { + type: subcomponent.type, + custom_id: subcomponent.customId, + label: subcomponent.label, + customId: subcomponent.customId, + style: subcomponent.style, + emoji: subcomponent.emoji + ? { + id: subcomponent.emoji.id?.toString(), + name: subcomponent.emoji.name, + animated: subcomponent.emoji.animated, + } + : undefined, + url: subcomponent.url, + disabled: subcomponent.disabled, + }; + }), + })), flags: options.data.flags, } ); diff --git a/src/helpers/messages/edit_message.ts b/src/helpers/messages/edit_message.ts index 5e656c1eb..09cdc88bd 100644 --- a/src/helpers/messages/edit_message.ts +++ b/src/helpers/messages/edit_message.ts @@ -4,6 +4,7 @@ import type { Message } from "../../types/messages/message.ts"; import type { PermissionStrings } from "../../types/permissions/permission_strings.ts"; import type { Bot } from "../../bot.ts"; import type { SnakeCasedPropertiesDeep } from "../../types/util.ts"; +import { DiscordMessageComponentTypes } from "../../types/messages/components/message_component_types.ts"; /** Edit the message. */ export async function editMessage(bot: Bot, channelId: bigint, messageId: bigint, content: string | EditMessage) { @@ -92,7 +93,49 @@ export async function editMessage(bot: Bot, channelId: bigint, messageId: bigint replied_user: content.allowedMentions?.repliedUser, }, file: content.file, - components: content.components, + components: content.components?.map((component) => ({ + type: component.type, + components: component.components.map((subcomponent) => { + if (subcomponent.type === DiscordMessageComponentTypes.SelectMenu) + return { + type: subcomponent.type, + custom_id: subcomponent.customId, + placeholder: subcomponent.placeholder, + min_values: subcomponent.minValues, + max_values: subcomponent.maxValues, + options: subcomponent.options.map((option) => ({ + label: option.label, + value: option.value, + description: option.description, + emoji: option.emoji + ? { + id: option.emoji.id?.toString(), + name: option.emoji.name, + animated: option.emoji.animated, + } + : undefined, + default: option.default, + })), + }; + + return { + type: subcomponent.type, + custom_id: subcomponent.customId, + label: subcomponent.label, + customId: subcomponent.customId, + style: subcomponent.style, + emoji: subcomponent.emoji + ? { + id: subcomponent.emoji.id?.toString(), + name: subcomponent.emoji.name, + animated: subcomponent.emoji.animated, + } + : undefined, + url: subcomponent.url, + disabled: subcomponent.disabled, + }; + }), + })), } ); diff --git a/src/helpers/messages/send_message.ts b/src/helpers/messages/send_message.ts index 691d14812..548b98e55 100644 --- a/src/helpers/messages/send_message.ts +++ b/src/helpers/messages/send_message.ts @@ -5,6 +5,7 @@ import type { CreateMessage } from "../../types/messages/create_message.ts"; import type { Message } from "../../types/messages/message.ts"; import type { PermissionStrings } from "../../types/permissions/permission_strings.ts"; import type { Bot } from "../../bot.ts"; +import { DiscordMessageComponentTypes } from "../../types/messages/components/message_component_types.ts"; /** Send a message to the channel. Requires SEND_MESSAGES permission. */ export async function sendMessage(bot: Bot, channelId: bigint, content: string | CreateMessage) { @@ -137,8 +138,49 @@ export async function sendMessage(bot: Bot, channelId: bigint, content: string | } : undefined, file: content.file, - // TODO: Snakelize components?? - components: content.components, + components: content.components?.map((component) => ({ + type: component.type, + components: component.components.map((subcomponent) => { + if (subcomponent.type === DiscordMessageComponentTypes.SelectMenu) + return { + type: subcomponent.type, + custom_id: subcomponent.customId, + placeholder: subcomponent.placeholder, + min_values: subcomponent.minValues, + max_values: subcomponent.maxValues, + options: subcomponent.options.map((option) => ({ + label: option.label, + value: option.value, + description: option.description, + emoji: option.emoji + ? { + id: option.emoji.id?.toString(), + name: option.emoji.name, + animated: option.emoji.animated, + } + : undefined, + default: option.default, + })), + }; + + return { + type: subcomponent.type, + custom_id: subcomponent.customId, + label: subcomponent.label, + customId: subcomponent.customId, + style: subcomponent.style, + emoji: subcomponent.emoji + ? { + id: subcomponent.emoji.id?.toString(), + name: subcomponent.emoji.name, + animated: subcomponent.emoji.animated, + } + : undefined, + url: subcomponent.url, + disabled: subcomponent.disabled, + }; + }), + })), ...(content.messageReference?.messageId ? { message_reference: { diff --git a/src/helpers/webhooks/edit_webhook_message.ts b/src/helpers/webhooks/edit_webhook_message.ts index b343bdced..17de8967c 100644 --- a/src/helpers/webhooks/edit_webhook_message.ts +++ b/src/helpers/webhooks/edit_webhook_message.ts @@ -3,6 +3,7 @@ import type { EditWebhookMessage } from "../../types/webhooks/edit_webhook_messa import type { Bot } from "../../bot.ts"; import { DiscordAllowedMentionsTypes } from "../../types/messages/allowed_mentions_types.ts"; import type { SnakeCasedPropertiesDeep } from "../../types/util.ts"; +import { DiscordMessageComponentTypes } from "../../types/messages/components/message_component_types.ts"; export async function editWebhookMessage( bot: Bot, @@ -61,8 +62,49 @@ export async function editWebhookMessage( replied_user: options.allowedMentions.repliedUser, } : undefined, attachments: options.attachments, - // TODO: Snakelize components?? - components: options.components, + components: options.components?.map((component) => ({ + type: component.type, + components: component.components.map((subcomponent) => { + if (subcomponent.type === DiscordMessageComponentTypes.SelectMenu) + return { + type: subcomponent.type, + custom_id: subcomponent.customId, + placeholder: subcomponent.placeholder, + min_values: subcomponent.minValues, + max_values: subcomponent.maxValues, + options: subcomponent.options.map((option) => ({ + label: option.label, + value: option.value, + description: option.description, + emoji: option.emoji + ? { + id: option.emoji.id?.toString(), + name: option.emoji.name, + animated: option.emoji.animated, + } + : undefined, + default: option.default, + })), + }; + + return { + type: subcomponent.type, + custom_id: subcomponent.customId, + label: subcomponent.label, + customId: subcomponent.customId, + style: subcomponent.style, + emoji: subcomponent.emoji + ? { + id: subcomponent.emoji.id?.toString(), + name: subcomponent.emoji.name, + animated: subcomponent.emoji.animated, + } + : undefined, + url: subcomponent.url, + disabled: subcomponent.disabled, + }; + }), + })), message_id: options.messageId, } ); diff --git a/tests/mod.ts b/tests/mod.ts index 9c94c5a44..990e83110 100644 --- a/tests/mod.ts +++ b/tests/mod.ts @@ -103,13 +103,13 @@ Deno.test("[Bot] - Starting Tests", async (t) => { }, ...sanitizeMode, }), - // t.step({ - // name: "[message] send message with components", - // fn: async (t) => { - // await sendMessageWithComponents(bot, channel.id, t); - // }, - // ...sanitizeMode, - // }), + t.step({ + name: "[message] send message with components", + fn: async (t) => { + await sendMessageWithComponents(bot, channel.id, t); + }, + ...sanitizeMode, + }), t.step({ name: "[message] delete message without a reason", fn: async (t) => {