-
Notifications
You must be signed in to change notification settings - Fork 19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
chore: scaffold community server discord bot #220
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
dist/ | ||
node_modules/ | ||
cooldownDB.sqlite | ||
tsconfig.tsbuildinfo |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MIT License | ||
|
||
Copyright (c) 2024 RileCraft | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
<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.7-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> | ||
Comment on lines
+1
to
+8
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add alt text to images for accessibility Images should have descriptive alt text for accessibility. Update the image tags: - <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.7-05122A?style=for-the-badge">
+ <img src="https://media.discordapp.net/attachments/774290264764055582/1093484780525469757/A_banner_for_a_discord_bots_template_made_using_discord.js.png" alt="Discord Bot Template Banner" height="200" width="400"><br>
+ <img src="https://img.shields.io/badge/version-1.0.7-05122A?style=for-the-badge" alt="Version 1.0.7">
🧰 Tools🪛 Markdownlint (0.37.0)2-2: null (MD045, no-alt-text) 3-3: null (MD045, no-alt-text) 4-4: null (MD045, no-alt-text) 5-5: null (MD045, no-alt-text) 6-6: null (MD045, no-alt-text) 7-7: null (MD045, no-alt-text) |
||
|
||
# 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. | ||
Comment on lines
+10
to
+12
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add community server context to introduction The introduction should be customized to include the specific purpose of this bot implementation - linking server roles to third-party applications (as mentioned in PR #217). Add a section like: This Discord bot implementation serves as the foundation for the community server, specifically designed to:
- Manage server roles in conjunction with third-party applications
- Integrate with the community portal (see issue #217)
- Facilitate automated role assignments based on external application states |
||
|
||
## Changelog | ||
|
||
### IMPORTANT UPDATE 1.0.7 | ||
|
||
- **Fixed Windows Support and SlashCommands & ContextMenus not Registering.** | ||
- Added dependency of `simple-json-db` for the cooldown system as i rage quit and can't do it with `fs` myself. | ||
- Fixed subDirectories not working for commands. | ||
- Latest Discord.js adaptation. | ||
- Following JavaScript Naming Convention. | ||
- Removed `node-recursive-directory` dependency. | ||
- Support for `AutoCompleteInteraction` added. | ||
- 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"]` | ||
- In a slashCommand you do not need to assign the `type: ApplicationCommandType` property as the handler by default assumes it as `ChatInput`. | ||
|
||
Comment on lines
+14
to
+39
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Remove or adapt changelog section Since this is a new implementation based on the template, the changelog section should either be:
Also, maintain professional language in documentation: -Added dependency of `simple-json-db` for the cooldown system as i rage quit and can't do it with `fs` myself.
+Added dependency of `simple-json-db` for the cooldown system management.
🧰 Tools🪛 LanguageTool[uncategorized] ~19-~19: Did you mean “I”? (I_LOWERCASE_PREMIUM) [misspelling] ~19-~19: This word is normally spelled with a hyphen. (EN_COMPOUNDS_RAGE_QUIT) |
||
## Documentation | ||
|
||
For detailed documentation on command options and managers, please refer to the following links: | ||
|
||
### Command Options | ||
|
||
- [ReturnErrors](/.github/DOCS/commandOptions/returnErrors.md) | ||
- [Ignore](/.github/DOCS/commandOptions/ignore.md) | ||
- [AllClientPermissions](/.github/DOCS/commandOptions/allClientPermissions.md) | ||
- [AllowBots](/.github/DOCS/commandOptions/allowBots.md) | ||
- [AllowInDms](/.github/DOCS/commandOptions/allowInDms.md) | ||
- [AllUserPermissions](/.github/DOCS/commandOptions/allUserPermissions.md) | ||
- [AnyClientPermissions](/.github/DOCS/commandOptions/anyClientPermissions.md) | ||
- [AnyUserPermissions](/.github/DOCS/commandOptions/anyUserPermissions.md) | ||
- [ChannelCooldown](/.github/DOCS/commandOptions/channelCooldown.md) | ||
- [GlobalCooldown](/.github/DOCS/commandOptions/globalCooldown.md) | ||
- [GuildCooldown](/.github/DOCS/commandOptions/guildCooldown.md) | ||
- [OnlyChannels](/.github/DOCS/commandOptions/onlyChannels.md) | ||
- [OnlyGuilds](/.github/DOCS/commandOptions/onlyGuilds.md) | ||
- [OnlyRoles](/.github/DOCS/commandOptions/onlyRoles.md) | ||
- [OnlyUsers](/.github/DOCS/commandOptions/onlyUsers.md) | ||
- [OwnerOnly](/.github/DOCS/commandOptions/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) | ||
- [ContextMenus](/.github/DOCS/managers/contextMenus.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. | ||
|
||
Comment on lines
+40
to
+81
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Customize documentation for this implementation
🧰 Tools🪛 LanguageTool[style] ~78-~78: The phrase “a variety of” may be wordy. To make your writing clearer, consider replacing it. (A_VARIETY_OF) |
||
## 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 | ||
|
||
Comment on lines
+82
to
+96
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add documentation for community server integration The README lacks information about the specific purpose of this bot in the community server context. Consider adding a new section: ## Community Server Integration
This bot serves as a foundation for linking server roles to third-party applications. Key features include:
- Role management integration capabilities
- Third-party application linking support
- Portal integration (see issue #217)
For development and contribution guidelines specific to the community server features, see [CONTRIBUTING.md]. 🧰 Tools🪛 LanguageTool[style] ~86-~86: Specify a number, remove phrase, or simply use “many” or “numerous” (LARGE_NUMBER_OF) |
||
## 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. | ||
Comment on lines
+101
to
+104
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Update installation instructions The installation instructions need to be updated:
|
||
|
||
You can also use `npm run dev` to run the application in development mode, which will refresh the application after any | ||
changes. If the interaction elements loading logs are excessive, set `LOG_READY_EXPLICIT` to `false` in `src/config.ts`. | ||
|
||
## 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. | ||
Comment on lines
+109
to
+116
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Align contribution guidelines with project standards The contribution guidelines should be updated to:
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"watch": ["src"], | ||
"ext": "ts", | ||
"exec": "tsc --incremental && node dist/bot.js" | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
{ | ||
"name": "discord-bot", | ||
"type": "module", | ||
"description": "", | ||
"license": "", | ||
"main": "./src/bot.ts", | ||
"scripts": { | ||
"build": "tsc && echo 'Finishing Building'", | ||
"dev": "nodemon", | ||
"start": "node ./dist/bot.js" | ||
}, | ||
"dependencies": { | ||
"discord.js": "^14.14.1", | ||
"ms": "^2.1.3", | ||
"simple-json-db": "^2.0.0", | ||
"tasai": "^1.0.0", | ||
"undici-types": "^5.26.5" | ||
}, | ||
"devDependencies": { | ||
"@types/ms": "^0.7.34", | ||
"@types/node": "^20.11.5", | ||
"nodemon": "^3.1.7", | ||
"typescript": "^5.3.3" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,53 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import type { DiscordClient } from 'discord.js' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import type { ButtonCommand, ClientEvent, ContextMenu, MessageCommand, ModalForm, SelectMenu, SlashCommand } from './types.js' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { dirname } from 'node:path' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { Client, GatewayIntentBits, Partials } from 'discord.js' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import JSONdb from 'simple-json-db' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { BOT_TOKEN } from './config.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' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const __dirname: string = dirname(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, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+19
to
+31
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Optimize Discord intents for security The bot is requesting more intents than might be necessary, including the privileged
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.cooldownDB = new JSONdb('./cooldownDB.json') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
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) // Includes context menu handling as they belong to same command type. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
})() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+46
to
+53
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add error handling and startup logging The initialization sequence lacks error handling and logging. Consider:
+ try {
await MessageCMDManager(client, __dirname)
+ console.log('Message commands loaded')
await EventManager(client, __dirname)
+ console.log('Events loaded')
await ButtonManager(client, __dirname)
+ console.log('Button commands loaded')
await SelectMenuManager(client, __dirname)
+ console.log('Select menus loaded')
await ModalManager(client, __dirname)
+ console.log('Modal forms loaded')
await client.login(BOT_TOKEN)
+ console.log('Bot logged in successfully')
await SlashManager(client, __dirname)
+ console.log('Slash commands loaded')
+ } catch (error) {
+ console.error('Failed to initialize bot:', error)
+ process.exit(1)
+ }
+
+ process.on('SIGTERM', () => {
+ console.log('Received SIGTERM, shutting down gracefully')
+ client.destroy()
+ process.exit(0)
+ }) 📝 Committable suggestion
Suggested change
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export const LOG_READY_EXPLICIT = true // Set to 'false' to reduce terminal spam for development server | ||
|
||
export const PREFIX: Array<string> = ['Bot Prefix'] | ||
export const BOT_TOKEN: string = 'Bot Token' | ||
export const OWNER_IDS: Array<string> = ['Bot Owner Discord ID'] | ||
Comment on lines
+1
to
+5
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Store sensitive configuration in environment variables. |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,15 @@ | ||||||
import type { ClientEvent } from '../types.js' | ||||||
// import process from 'node:process' | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Uncomment the process import The process import is required for the error handlers. Remove the comment to enable proper error handling functionality. -// import process from 'node:process'
+import process from 'node:process' 📝 Committable suggestion
Suggested change
|
||||||
|
||||||
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) | ||||||
// }) | ||||||
Comment on lines
+8
to
+13
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Uncomment and enhance error handling implementation The error handlers are currently commented out, leaving the bot without any error management. This could lead to silent failures or unexpected crashes in production. Consider this enhanced implementation: - // process.on('unhandledRejection', (error: Error) => {
- // console.log(error)
- // })
- // process.on('uncaughtException', (error: Error) => {
- // console.log(error)
- // })
+ process.on('unhandledRejection', (error: Error) => {
+ console.error('[Unhandled Rejection]', {
+ name: error.name,
+ message: error.message,
+ stack: error.stack
+ });
+ // TODO: Add error reporting service integration
+ });
+
+ process.on('uncaughtException', (error: Error) => {
+ console.error('[Uncaught Exception]', {
+ name: error.name,
+ message: error.message,
+ stack: error.stack
+ });
+ // TODO: Add error reporting service integration
+
+ // Gracefully shutdown after uncaught exception
+ process.exit(1);
+ });
|
||||||
}, | ||||||
} // Error Handler to avoid the bot from crashing on error. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import type { DiscordClient, Interaction } from 'discord.js' | ||
import type { ButtonCommand, ClientEvent, ContextMenu, ModalForm, SelectMenu, SlashCommand } from '../types.js' | ||
import commandOptionsChecker from '../structures/commandOptions/processor.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.isAutocomplete()) { | ||
const slashCommand: SlashCommand | undefined = client.slashCommands?.get(interaction.commandName) | ||
if (!slashCommand || !slashCommand.autocomplete) | ||
return | ||
|
||
if (!await commandOptionsChecker(client, interaction, slashCommand, 'SlashCommand')) | ||
return | ||
else slashCommand.autocomplete(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) | ||
} | ||
Comment on lines
+38
to
+56
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Consolidate repeated checks with a helper |
||
|
||
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) | ||
}; | ||
Comment on lines
+8
to
+66
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Refactor interaction handling to reduce duplication The interaction handling logic follows a repetitive pattern. Consider refactoring to reduce duplication and improve maintainability. Create a handler factory: interface InteractionHandler {
getCommand: (interaction: Interaction) => Command | undefined;
validateCommand: (command: Command) => boolean;
executeCommand: (command: Command, interaction: Interaction, client: DiscordClient) => Promise<void>;
}
const handlers: Record<string, InteractionHandler> = {
chatInput: {
getCommand: (interaction) => client.slashCommands?.get(interaction.commandName),
validateCommand: (command) => !!command,
executeCommand: async (command, interaction, client) => {
if (await commandOptionsChecker(client, interaction, command, 'SlashCommand')) {
command.run(interaction, client);
}
}
},
// Add other handlers...
}; This would make the code more maintainable and easier to extend. |
||
}, | ||
} // InteractionCreate event to handle all interactions and execute them. | ||
Comment on lines
+1
to
+68
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add error handling for command execution The command execution lacks try-catch blocks for error handling. Consider adding error boundaries. async function executeCommand(command: Command, interaction: Interaction, client: DiscordClient) {
try {
await command.run(interaction, client);
} catch (error) {
console.error(`Error executing command ${command.name}:`, error);
// Handle error appropriately
await interaction.reply({
content: 'An error occurred while executing the command',
ephemeral: true
}).catch(console.error);
}
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,30 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import type { DiscordClient, Message } from 'discord.js' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import type { ClientEvent, MessageCommand } from '../types.js' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { PREFIX } from '../config.js' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import commandOptionsChecker from '../structures/commandOptions/processor.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) ?? '') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+14
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Improve type safety and error handling in command resolution The command resolution chain has multiple optional chaining operations that could be simplified and made more type-safe. - const command: MessageCommand | undefined = client.messageCommands?.get(commandName) ?? client.messageCommands?.get(client.messageCommands_Aliases?.get(commandName) ?? '')
+ const messageCommands = client.messageCommands
+ if (!messageCommands) return
+
+ const command = messageCommands.get(commandName) ??
+ messageCommands.get(client.messageCommands_Aliases?.get(commandName) ?? '') 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (!command) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const args: Array<string> = message.content.slice(botPrefix.length).trim().slice(commandName.length).trim().split(' ') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add input validation for command arguments The current implementation splits arguments without validation, which could lead to security issues. - const args: Array<string> = message.content.slice(botPrefix.length).trim().slice(commandName.length).trim().split(' ')
+ const args: Array<string> = message.content
+ .slice(botPrefix.length)
+ .trim()
+ .slice(commandName.length)
+ .trim()
+ .split(' ')
+ .filter(arg => arg.length > 0)
+ .map(arg => arg.replace(/[^\w\s-]/gi, '')) // Basic sanitization 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const processedCommandOptionsChecker: boolean = await commandOptionsChecker(client, message, command, 'MessageCommand') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (!command.allowInDms && !message.guild) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (!command.allowBots && message.author.bot) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (processedCommandOptionsChecker) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
await command.run(client, message, args) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+11
to
+28
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Replace forEach with for...of for async operations Using - PREFIX.forEach(async (botPrefix: string) => {
+ for (const botPrefix of PREFIX) {
+ try {
if (!message.content.startsWith(botPrefix))
- return
+ continue;
// ... rest of the code ...
if (processedCommandOptionsChecker)
await command.run(client, message, args)
+ } catch (error) {
+ console.error('Error processing command:', error);
+ // Consider sending an error message to the channel
+ }
- })
+ } 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} // MessageCreate event to handle all messages and execute messageCommands (if found). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Update repository links for this project
The badge links still point to the original template repository (
RileCraft/DiscordBot-Template-ts
). These should be updated to point to this project's repository.🧰 Tools
🪛 Markdownlint (0.37.0)
4-4: null
Images should have alternate text (alt text)
(MD045, no-alt-text)
5-5: null
Images should have alternate text (alt text)
(MD045, no-alt-text)
6-6: null
Images should have alternate text (alt text)
(MD045, no-alt-text)
7-7: null
Images should have alternate text (alt text)
(MD045, no-alt-text)