-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 4c56ffa
Showing
41 changed files
with
1,530 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
.github/ | ||
Dist/ | ||
node_modules/ | ||
cooldownDB.sqlite |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
<p align="center"> | ||
<img src="https://media.discordapp.net/attachments/774290264764055582/1093484780525469757/A_banner_for_a_discord_bots_template_made_using_discord.js.png" height="200" width="400"><br> | ||
<img src="https://img.shields.io/badge/version-1.0.0-05122A?style=for-the-badge"> | ||
<a href="https://discord.gg/VStdRr8nP2"><img src="https://img.shields.io/badge/discord-invite-5865f2?style=for-the-badge&logo=discord&logoColor=white"></a> | ||
<img src="https://img.shields.io/github/issues/RileCraft/DiscordBot-Template-ts.svg?style=for-the-badge"> | ||
<img src="https://img.shields.io/github/forks/RileCraft/DiscordBot-Template-ts.svg?style=for-the-badge"> | ||
<img src="https://img.shields.io/github/stars/RileCraft/DiscordBot-Template-ts.svg?style=for-the-badge"> | ||
</p> | ||
|
||
# Discord Bot Template TS | ||
|
||
The Discord Bot Template provides a solid foundation for creating feature-rich Discord bots using Discord.js. It includes various managers for handling message commands, buttons, select menus, slash commands, context menus, and modal forms. The template offers customization options, colorful logging, and a simple code structure. | ||
|
||
## Changelog | ||
|
||
- Latest Discord.js adaptation. | ||
- Removed `node-recursive-directory` dependency. | ||
- Converted from `CommonJS` to `ESM Module`. | ||
- Improved handling of all events, commands with lower memory usage. | ||
- Main file `Bot.ts` has been shifted to `Src`. | ||
- Config file has been shifted to `Src`. | ||
- Moved from `Collections` to `Map`. | ||
- `messageCommandsAliases` has been renamed to `messageCommands_Aliases` | ||
- `Quick.DB` has been removed and instead all cooldowns data will be now stored in `CooldownDB.txt` in the root directory using `fs`. | ||
- Refactored command options. | ||
- `chalk` has been replaced with `tasai`. | ||
- Extended all command options support to interactions. | ||
- All custom types and interfaces are exported from `./Src/Types.ts`. | ||
- `SlashCommands` and `ContextMenus` has been seperated into different folders and managed differently. | ||
- `SlashCommands` have been simplified as now instead of `Guilds/<GuildID>/<Files Here>`, you can use `guilds: ["GUILD ID"]` property to easier manage your code and `type` property is not required as the handlers automatically assigns the `ChatInput` type. | ||
|
||
## Documentation | ||
|
||
For detailed documentation on command options and managers, please refer to the following links: | ||
|
||
### Command Options | ||
|
||
- [ReturnErrors](/.github/Docs/CMDOptions/ReturnErrors.md) | ||
- [Ignore](/.github/Docs/CMDOptions/Ignore.md) | ||
- [AllClientPermissions](/.github/Docs/CMDOptions/AllClientPermissions.md) | ||
- [AllowBots](/.github/Docs/CMDOptions/AllowBots.md) | ||
- [AllowInDms](/.github/Docs/CMDOptions/AllowInDms.md) | ||
- [AllUserPermissions](/.github/Docs/CMDOptions/AllUserPermissions.md) | ||
- [AnyClientPermissions](/.github/Docs/CMDOptions/AnyClientPermissions.md) | ||
- [AnyUserPermissions](/.github/Docs/CMDOptions/AnyUserPermissions.md) | ||
- [ChannelCooldown](/.github/Docs/CMDOptions/ChannelCooldown.md) | ||
- [GlobalCooldown](/.github/Docs/CMDOptions/GlobalCooldown.md) | ||
- [GuildCooldown](/.github/Docs/CMDOptions/GuildCooldown.md) | ||
- [OnlyChannels](/.github/Docs/CMDOptions/OnlyChannels.md) | ||
- [OnlyGuilds](/.github/Docs/CMDOptions/OnlyGuilds.md) | ||
- [OnlyRoles](/.github/Docs/CMDOptions/OnlyRoles.md) | ||
- [OnlyUsers](/.github/Docs/CMDOptions/OnlyUsers.md) | ||
- [OwnerOnly](/.github/Docs/CMDOptions/OwnerOnly.md) | ||
|
||
### Managers | ||
|
||
- [MessageCommands](/.github/Docs/Managers/MessageCommands.md) | ||
- [SelectMenus](/.github/Docs/Managers/SelectMenus.md) | ||
- [Buttons](/.github/Docs/Managers/Buttons.md) | ||
- [Events](/.github/Docs/Managers/Events.md) | ||
- [SlashCommands](/.github/Docs/Managers/SlashCommands.md) | ||
- [ModalForms](/.github/Docs/Managers/ModalForms.md) | ||
|
||
## Features | ||
|
||
- Colorful and organized logging. | ||
- Customization options to suit your needs. | ||
- Supports management of message commands, buttons, select menus, slash commands, context menus, and modal forms. | ||
- Includes a variety of commonly used command options (not applicable to events). | ||
- Supports management of custom events. | ||
- Simple and understandable code structure. | ||
|
||
## Notes | ||
|
||
- Recommended Node.js version: 16 and above. | ||
- Global slash commands and context menus may take time to refresh as it is controlled by Discord. | ||
- Guild commands may take time to refresh if there are a large number of different guild commands. | ||
- Collections where command and event data is stored and used: | ||
- `<Client>.messageCommands`: Message commands cache | ||
- `<Client>.messageCommands_Aliases`: Message command aliases cache | ||
- `<Client>.events`: Client events cache | ||
- `<Client>.buttonCommands`: Button interactions cache | ||
- `<Client>.selectMenus`: Select menu interactions cache | ||
- `<Client>.modalForms`: Modal form interactions cache | ||
- `<Client>.slashCommands`: Slash commands cache | ||
- `<Client>.contextMenus`: ContextMenus commands cache | ||
|
||
## Installation | ||
|
||
To get started with the Discord Bot Template, follow these steps: | ||
|
||
1. Clone the repository by downloading it as a ZIP file or running the command `git clone https://github.com/rilecraft/discordbot-template-ts`. | ||
2. Navigate to the template's directory and run the command `npm install` (make sure npm is installed). | ||
3. Once all the required modules are installed, open the `Src/Config.ts` file and fill in the necessary information. | ||
4. Run the command `npm run build && npm run start` to start the bot. | ||
|
||
## Contribution | ||
|
||
Contributions to the Discord Bot Template are welcome. To contribute, please follow these guidelines: | ||
|
||
1. Fork the `Unstable` branch. **Important: All changes must be made to the Unstable branch.** | ||
2. Make your changes in your forked repository. | ||
3. Open a pull request to the `Unstable` branch, and it will be reviewed promptly. | ||
4. If everything checks out, the pull request will be merged. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import { Client, DiscordClient, GatewayIntentBits, Partials } from "discord.js"; | ||
import { BOT_TOKEN } from "./Config.js"; | ||
import { fileURLToPath } from "url"; | ||
import { dirname } from "path"; | ||
import { ButtonCommand, ClientEvent, ContextMenu, MessageCommand, ModalForm, SelectMenu, SlashCommand } from "./Types.js"; | ||
import { ButtonManager } from "./Structures/Managers/ButtonCommands.js"; | ||
import { EventManager } from "./Structures/Managers/Events.js"; | ||
import { MessageCMDManager } from "./Structures/Managers/MessageCommands.js"; | ||
import { ModalManager } from "./Structures/Managers/ModalForms.js"; | ||
import { SelectMenuManager } from "./Structures/Managers/SelectMenus.js"; | ||
import { SlashManager } from "./Structures/Managers/SlashCommands.js"; | ||
import { ContextManager } from "./Structures/Managers/ContextMenus.js"; | ||
|
||
const __dirname: string = dirname(fileURLToPath(import.meta.url)); | ||
export const rootPath = __dirname; | ||
|
||
(async(): Promise<void> => { | ||
const client: DiscordClient = new Client({ | ||
intents: [ | ||
GatewayIntentBits.Guilds, | ||
GatewayIntentBits.GuildMessages, | ||
GatewayIntentBits.GuildPresences, | ||
GatewayIntentBits.DirectMessages, | ||
GatewayIntentBits.MessageContent, // Only for bots with message content intent access. | ||
GatewayIntentBits.DirectMessageReactions, | ||
GatewayIntentBits.GuildMembers, | ||
GatewayIntentBits.GuildMessageReactions, | ||
GatewayIntentBits.GuildWebhooks, | ||
GatewayIntentBits.GuildVoiceStates, | ||
GatewayIntentBits.GuildInvites, | ||
], | ||
partials: [Partials.Channel] | ||
}); | ||
|
||
client.messageCommands = new Map<string, MessageCommand>(); | ||
client.messageCommands_Aliases = new Map<string, string>(); | ||
client.events = new Map<string, ClientEvent>(); | ||
client.buttonCommands = new Map<string, ButtonCommand>(); | ||
client.selectMenus = new Map<string, SelectMenu>(); | ||
client.modalForms = new Map<string, ModalForm>(); | ||
client.contextMenus = new Map<string, ContextMenu>(); | ||
client.slashCommands = new Map<string, SlashCommand>(); | ||
|
||
await MessageCMDManager(client, __dirname); | ||
await EventManager(client, __dirname); | ||
await ButtonManager(client, __dirname); | ||
await SelectMenuManager(client, __dirname); | ||
await ModalManager(client, __dirname); | ||
await client.login(BOT_TOKEN); | ||
await SlashManager(client, __dirname); | ||
await ContextManager(client, __dirname); | ||
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
/* | ||
PREFIX: The prefix for your message commands which will be applied before the command itself. Example: !ping (! is the prefix). | ||
BOT_TOKEN: It is the token of your bot which is to be acquired from the https://discord.com/developers/applications. | ||
OWNER_IDS: It is the User IDs of the people who will be allowed to use commands that have the property ownerOnly = true. | ||
*/ | ||
|
||
export const PREFIX: Array<string> = ["Prefix"]; | ||
export const BOT_TOKEN: string = "Bot Token"; | ||
export const OWNER_IDS: Array<string> = ["Discord User ID"]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { ClientEvent } from "../Types.js"; | ||
|
||
export const Event: ClientEvent = { | ||
name: "errorManager", | ||
customEvent: true, | ||
run: (): void => { | ||
process.on('unhandledRejection', (error: Error) => { | ||
console.log(error); | ||
}); | ||
process.on('uncaughtException', (error: Error) => { | ||
console.log(error); | ||
}); | ||
} | ||
}; // Error Handler to avoid the bot from crashing on error. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import { DiscordClient, Interaction } from "discord.js"; | ||
import commandOptionsChecker from "../Structures/CommandOptions/Processor.js"; | ||
import { ButtonCommand, ClientEvent, ContextMenu, ModalForm, SelectMenu, SlashCommand } from "../Types.js"; | ||
|
||
export const Event: ClientEvent = { | ||
name: "interactionCreate", | ||
run: async(interaction: Interaction<"cached">, client: DiscordClient): Promise<void> => { | ||
if (interaction.isChatInputCommand()) { | ||
const slashCommand: SlashCommand | undefined = client.slashCommands?.get(interaction.commandName); | ||
if (!slashCommand) return; | ||
|
||
if (!await commandOptionsChecker(client, interaction, slashCommand, "SlashCommand")) return; | ||
else slashCommand.run(interaction, client); | ||
} | ||
|
||
else if (interaction.isContextMenuCommand()) { | ||
const contextMenu: ContextMenu | undefined = client.contextMenus?.get(interaction.commandName); | ||
if (!contextMenu) return; | ||
|
||
if (!await commandOptionsChecker(client, interaction, contextMenu, "ContextMenu")) return; | ||
else contextMenu.run(interaction, client); | ||
} | ||
|
||
else if (interaction.isAnySelectMenu()) { | ||
const selectMenuCommand: SelectMenu | undefined = client.selectMenus?.get(interaction.values[0]) ?? client.selectMenus?.get(interaction.customId); | ||
if (!selectMenuCommand) return; | ||
|
||
if (!await commandOptionsChecker(client, interaction, selectMenuCommand, "SelectMenu")) return; | ||
else selectMenuCommand.run(interaction, client); | ||
} | ||
|
||
else if (interaction.isButton()) { | ||
const buttonInteraction: ButtonCommand | undefined = client.buttonCommands?.get(interaction.customId); | ||
if (!buttonInteraction) return; | ||
|
||
if (!await commandOptionsChecker(client, interaction, buttonInteraction, "Button")) return; | ||
else buttonInteraction.run(interaction, client); | ||
} | ||
|
||
else if (interaction.isModalSubmit()) { | ||
const modalInteraction: ModalForm | undefined = client.modalForms?.get(interaction.customId); | ||
if (!modalInteraction) return; | ||
|
||
if (!await commandOptionsChecker(client, interaction, modalInteraction, "ModalForm")) return; | ||
else modalInteraction.run(interaction, client); | ||
} | ||
} | ||
}; // InteractionCreate event to handle all interactions and execute them. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import commandOptionsChecker from "../Structures/CommandOptions/Processor.js"; | ||
import { PREFIX } from "../Config.js"; | ||
import { ClientEvent, MessageCommand } from "../Types.js"; | ||
import { DiscordClient, Message } from "discord.js"; | ||
|
||
export const Event: ClientEvent = { | ||
name: "messageCreate", | ||
run: (message: Message, client: DiscordClient): void => { | ||
if (!Array.isArray(PREFIX)) return; | ||
PREFIX.forEach(async(botPrefix: string) => { | ||
if (!message.content.startsWith(botPrefix)) return; | ||
const commandName: string = message.content.toLowerCase().slice(botPrefix.length).trim().split(" ")[0]; | ||
const command: MessageCommand | undefined = client.messageCommands?.get(commandName) ?? client.messageCommands?.get(client.messageCommands_Aliases?.get(commandName) ?? ""); | ||
if (!command) return; | ||
const args: Array<string> = message.content.slice(botPrefix.length).trim().slice(commandName.length).trim().split(" "); | ||
const processedCommandOptionsChecker: boolean = await commandOptionsChecker(client, message, command, "MessageCommand"); | ||
|
||
if (command?.allowInDms) return processedCommandOptionsChecker ? await command.run(client, message, args) : null; | ||
else if (!message.guild) return; | ||
else if (command?.allowBots) return processedCommandOptionsChecker ? await command.run(client, message, args) : null; | ||
else if (message.author.bot) return; | ||
else return processedCommandOptionsChecker ? await command.run(client, message, args) : null; | ||
}); | ||
} | ||
}; // MessageCreate event to handle all messages and execute messageCommands (if found). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import { ActivityType, DiscordClient } from "discord.js"; | ||
import { rootPath } from "../Bot.js"; | ||
import { ClientEvent, ContextMenu, SlashCommand } from "../Types.js"; | ||
import { FileReader } from "../Utils/FileReader.js"; | ||
import { t } from "tasai"; | ||
|
||
export const Event: ClientEvent = { | ||
name: "ready", | ||
runOnce: true, | ||
run: async(client: DiscordClient): Promise<void> => { | ||
client.user?.setActivity("Humans.", { | ||
type: ActivityType.Watching | ||
}); | ||
|
||
let allSlashCommands: Array<string> = FileReader(`${rootPath}/Interactions/SlashCommands`); | ||
allSlashCommands = await allSlashCommands.reduce(async(array: any, slash: string): Promise<Array<string>> => { | ||
const command: SlashCommand | undefined = (await import(slash))?.Slash; | ||
|
||
if (command?.ignore || !command?.name) return array; | ||
else return (await array).concat(slash) | ||
}, []); | ||
|
||
let allContextMenus: Array<string> = FileReader(`${rootPath}/Interactions/ContextMenus`); | ||
allContextMenus = await allContextMenus.reduce(async(array: any, context: string): Promise<Array<string>> => { | ||
const command: ContextMenu | undefined = (await import(context))?.Context; | ||
|
||
if (command?.ignore || !command?.name || !command?.type) return array; | ||
else return (await array).concat(context) | ||
}, []); | ||
|
||
console.log(t.bold.green.toFunction()("[Client] ") + t.bold.blue.toFunction()(`Logged into ${client.user?.tag}`)); | ||
if ((client.messageCommands?.size ?? 0) > 0) console.log(t.bold.red.toFunction()("[MessageCommands] ") + t.bold.cyan.toFunction()(`Loaded ${(client.messageCommands?.size ?? 0)} MessageCommands with ${t.bold.white.toFunction()(`${client.messageCommands_Aliases?.size} Aliases`)}.`)); | ||
if ((client.events?.size ?? 0) > 0) console.log(t.bold.yellow.toFunction()("[Events] ") + t.bold.magenta.toFunction()(`Loaded ${(client.events?.size ?? 0)} Events.`)); | ||
if ((client.buttonCommands?.size ?? 0) > 0) console.log(t.bold.brightGreen.toFunction()("[ButtonCommands] ") + t.bold.brightYellow.toFunction()(`Loaded ${(client.buttonCommands?.size ?? 0)} Buttons.`)); | ||
if ((client.selectMenus?.size ?? 0) > 0) console.log(t.bold.red.toFunction()("[SelectMenus] ") + t.bold.brightBlue.toFunction()(`Loaded ${(client.selectMenus?.size ?? 0)} SelectMenus.`)); | ||
if ((client.modalForms?.size ?? 0) > 0) console.log(t.bold.brightCyan.toFunction()("[ModalForms] ") + t.bold.brightYellow.toFunction()(`Loaded ${(client.modalForms?.size ?? 0)} Modals.`)); | ||
if (allSlashCommands?.length > 0) console.log(t.bold.magenta.toFunction()("[SlashCommands] ") + t.bold.white.toFunction()(`Loaded ${allSlashCommands.length} SlashCommands.`)); | ||
if (allContextMenus?.length > 0) console.log(t.bold.magenta.toFunction()("[ContextMenus] ") + t.bold.white.toFunction()(`Loaded ${allContextMenus.length} ContextMenus.`)); | ||
} | ||
}; // Log all data about the client on login. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { ButtonCommand } from "../../Types.js"; | ||
|
||
export const Button: ButtonCommand = { | ||
name: "deleteOutput", | ||
ownerOnly: true, | ||
run: (interaction): void => { | ||
interaction?.message?.delete(); | ||
} | ||
}; // ButtonCommand of the deleteOutput button. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { ApplicationCommandType, UserContextMenuCommandInteraction } from "discord.js"; | ||
import { ContextMenu } from "../../Types.js"; | ||
|
||
export const Context: ContextMenu = { | ||
name: "getuser", | ||
type: ApplicationCommandType.User, | ||
guilds: ["1186230608851120188"], | ||
run: (interaction): void => { | ||
const userContextMenuInteraction = interaction as UserContextMenuCommandInteraction<"cached">; // If you want to use UserContextMenuCommandInteraction specifically. | ||
|
||
let member = interaction.guild.members.cache.get(interaction.targetId); | ||
if (!member) member = interaction.member; | ||
|
||
userContextMenuInteraction.reply({ | ||
content: `That is ${member.user.tag}.` | ||
}); | ||
} | ||
}; // Simple UserContextMenu example |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { ModalForm } from "../../Types.js"; | ||
|
||
export const Modal: ModalForm = { | ||
name: "ExampleModal", | ||
run: (interaction): void => { | ||
interaction.reply({ | ||
content: "This modal is correctly functioning." | ||
}); | ||
} | ||
}; // Code for the ExampleModal ModalForm |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { StringSelectMenuInteraction } from "discord.js"; | ||
import { SelectMenu } from "../../Types.js"; | ||
|
||
export const Menu: SelectMenu = { | ||
name: "SelectMenuExample", | ||
run: (interaction): void => { | ||
const stringSelectMenuInteraction = interaction as StringSelectMenuInteraction; // If you want to use StringSelectMenuInteraction specifically. | ||
stringSelectMenuInteraction.reply({ | ||
content: "Here is your cookie! :cookie:" | ||
}); | ||
} | ||
}; // Code for SelectMenuExample SelectMenu |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { ActionRowBuilder, ModalBuilder, TextInputBuilder, TextInputStyle } from "discord.js"; | ||
import { SlashCommand } from "../../Types.js"; | ||
|
||
export const Slash: SlashCommand = { | ||
name: "testmodal", | ||
description: "Test Modal", | ||
guilds: ["1186230608851120188"], | ||
run: async(interaction): Promise<void> => { | ||
const modal = new ModalBuilder() | ||
.setCustomId('ExampleModal') | ||
.setTitle('My Modal'); | ||
|
||
const favoriteColorInput = new TextInputBuilder() | ||
.setCustomId('favoriteColorInput') | ||
.setLabel("What's your favorite color?") | ||
.setStyle(TextInputStyle.Short); | ||
|
||
const hobbiesInput = new TextInputBuilder() | ||
.setCustomId('hobbiesInput') | ||
.setLabel("What's some of your favorite hobbies?") | ||
.setStyle(TextInputStyle.Paragraph); | ||
|
||
const firstActionRow = new ActionRowBuilder<TextInputBuilder>().addComponents(favoriteColorInput); | ||
const secondActionRow = new ActionRowBuilder<TextInputBuilder>().addComponents(hobbiesInput); | ||
|
||
modal.addComponents(firstActionRow, secondActionRow); | ||
|
||
await interaction.showModal(modal); | ||
} | ||
}; // Call an example modal on execution. |
Oops, something went wrong.