A modern, modular Discord bot built with TypeScript and Discord.js v14, featuring a unified command system with dynamically loaded subcommands and real-time weather integration.
/nox
- AI assistant with dynamically loaded subcommands
- Greeting Mode:
/nox
- Random helpful greetings when no query provided - Weather:
/nox weather [location]
- Real weather data from OpenWeatherMap API - Dictionary:
/nox definition [word]
- Portuguese word definitions from Priberam dictionary (displays definition images directly, auto-corrects accents) - Help:
/nox help
- Interactive help system with all available commands - User Info:
/nox userinfo [@user]
- Get detailed user information - Server Info:
/nox guildid
- Get current server/guild ID - Ping Test:
/nox ping
- Test bot response time - Natural Language: Fallback processing for unrecognized queries
- Simple ! Commands - Quick responses stored in JSON configuration
- Easy Maintenance - Add new commands by editing
src/config/prefix-commands.json
- Auto-Cleanup - Bot automatically deletes command messages to prevent channel spam
- Smart Response - Clean responses without user mentions or pings
- Examples:
!hello
β "Hey!" (command message deleted)!love
βhttps://myimageservice.com/image1.png
(command message deleted)!test
β "This is a test response!" (command message deleted)
- Unified Command System - All features accessible through
/nox
subcommands - Dynamic Subcommand Loading - Subcommands auto-discovered from filesystem
- Service-Oriented Design - Clean separation of concerns with dedicated services
- Development-First Registration - Commands register instantly in dev guilds (no duplicates)
- Modular Architecture - Easy to extend with new subcommands
- Production-Ready - Comprehensive error handling and graceful shutdown
nox-discord-bot/
βββ π src/
β βββ π commands/ # Main command implementations
β β βββ nox.ts # Unified AI assistant command
β β βββ π subcommands/ # Dynamic subcommand modules
β β βββ weather.ts # Weather subcommand
β β βββ help.ts # Help subcommand
β β βββ userinfo.ts # User info subcommand
β β βββ guildid.ts # Guild ID subcommand
β β βββ ping.ts # Ping test subcommand
β β βββ definition.ts # Dictionary subcommand
β β βββ naturallanguage.ts # Natural language fallback
β β βββ template.ts.example # Command template (renamed to prevent loading)
β βββ π services/ # Business logic services
β β βββ bot.ts # Discord client wrapper
β β βββ commandHandler.ts # Command execution manager
β β βββ commandRegistrar.ts # Command registration service
β βββ π utils/ # Utility functions
β β βββ commandLoader.ts # Command discovery and loading
β β βββ configLoader.ts # Configuration management with caching
β β βββ environmentValidator.ts # Environment validation
β β βββ logger.ts # Structured logging with emojis
β βββ π config/ # Configuration files
β β βββ client.json # Client settings and intents
β β βββ prefix-commands.json # Simple ! command responses
β β βββ prefix-commands.json.example # Template for prefix commands
β βββ index.ts # Main application entry point
βββ π refresh-commands.ts # Command registration utility
βββ π package.json # Dependencies and scripts
βββ π tsconfig.json # TypeScript configuration
βββ π .env # Environment variables (gitignored)
βββ π .github/
βββ copilot-instructions.md # AI agent development guidelines
- Node.js 18 or higher
- A Discord application and bot token
- OpenWeatherMap API key (optional, for weather commands)
-
Clone the repository
git clone https://github.com/mapherez/nox-discord-bot.git cd nox-discord-bot
-
Install dependencies
npm install
-
Get API keys
- Discord Bot Token: Create a bot at Discord Developer Portal
- OpenWeatherMap API Key: Sign up at OpenWeatherMap (free tier available)
-
Configure environment variables
Edit
.env
with your credentials:DISCORD_TOKEN=your_bot_token_here CLIENT_ID=your_application_id_here GUILD_ID=your_development_guild_id_here # Optional, for instant command updates OPENWEATHER_API_KEY=your_weather_api_key_here # Optional, for weather commands
-
Start the bot
npm start
DISCORD_TOKEN
- Your Discord bot token (required)CLIENT_ID
- Your Discord application ID (required)GUILD_ID
- Development guild ID for instant command updates (optional)OPENWEATHER_API_KEY
- OpenWeatherMap API key for weather commands (optional)
Edit src/config/client.json
to configure Discord intents:
{
"intents": ["Guilds", "GuildMessages", "MessageContent"]
}
Note: The MessageContent
intent is privileged and requires enabling in your Discord Developer Portal under Bot β Privileged Gateway Intents β Message Content Intent.
When generating your bot's invite URL in Discord Developer Portal β OAuth2 β URL Generator, include these permissions:
- Scopes:
bot
- Bot Permissions:
- β Send Messages
- β Use Slash Commands
- β Read Message History
- β Manage Messages (for auto-deleting ! command messages)
Note: Server-level permissions may need to be granted in individual channels if they have custom permission overrides.
The bot uses a dynamic subcommand system where all features are accessible through /nox
. To add a new subcommand:
-
Create a subcommand file in
src/commands/subcommands/yourcommand.ts
:import { ChatInputCommandInteraction } from 'discord.js'; async function yourcommand(interaction: ChatInputCommandInteraction, params: string): Promise<void> { // Your subcommand logic here // params contains any additional arguments from Discord options await interaction.reply('Your command response!'); } export { yourcommand };
-
Add options to nox.ts (if needed) in the
buildCommandWithSubcommands()
function:if (subcommandName === 'yourcommand') { command.addSubcommand(subcommand => subcommand .setName('yourcommand') .setDescription('Description of your command') .addStringOption(option => option.setName('param') .setDescription('Parameter description') .setRequired(false) ) ); }
-
Restart the bot - subcommands are automatically discovered and registered
For commands that don't fit the /nox
subcommand pattern:
-
Create a command file in the
src/commands/
directory:import { SlashCommandBuilder, ChatInputCommandInteraction } from 'discord.js'; export default { data: new SlashCommandBuilder() .setName('yourcommand') .setDescription('Command description'), execute: async (interaction: ChatInputCommandInteraction) => { await interaction.reply('Hello World!'); } };
-
Restart the bot - commands are automatically discovered
For simple !
commands that return predefined responses:
-
Copy the template:
cp src/config/prefix-commands.json.example src/config/prefix-commands.json
-
Edit
src/config/prefix-commands.json
with your custom commands:{ "hello": "Hey there!", "love": "https://myimageservice.com/image1.png", "meme": "Check out this funny meme!", "yourcommand": "Your custom response here" }
-
Restart the bot - prefix commands are automatically loaded
Note: Your prefix-commands.json
file is gitignored to keep your custom commands private.
- Instant Command Updates - Set
GUILD_ID
in.env
for immediate command registration in dev guild only - No Duplicate Registration - Development mode skips global registration to prevent duplicates
- Dynamic Subcommand Loading - New subcommands appear automatically without code changes
- Configuration Caching - JSON configs loaded with caching for improved performance
- Comprehensive Logging - Structured logging with emoji prefixes
- Error Handling - Graceful error handling with user-friendly messages
The npm run refresh
command uses refresh-commands.ts
to:
- Clear all existing slash commands
- Wait 2 seconds for Discord to process
- Register all newly discovered commands
- Provide instant feedback on success/failure
Tip: Use GUILD_ID
in .env
for development to avoid global command registration delays.
npm start # Start the bot in development mode (with ts-node/esm)
npm run dev # Start the bot in watch mode for development (auto-restart on changes)
npm run build # Compile TypeScript to JavaScript (outputs to dist/)
npm run prod # Build and run the production version
npm run refresh # Refresh Discord slash commands (clears existing, registers new)
npm test # Run tests (placeholder)
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
- Follow the existing code structure and naming conventions
- Add appropriate error handling and logging
- Test commands in a development environment before submitting
- Update documentation for new features
- Node.js: 18.0.0 or higher
- TypeScript: 5.9.0 or higher
- Discord.js: v14.22.1
- OpenWeatherMap API Key: For weather commands (optional)
- Permissions: Bot needs appropriate Discord permissions based on commands used
- discord.js v14 - Core Discord bot framework
- TypeScript - Type-safe JavaScript
- dotenv - Environment variable management
- axios - HTTP client for API requests (weather data)
- cheerio - HTML parsing for web scraping
- nodehun - Spell checking library for Portuguese dictionary support
- ts-node - TypeScript execution in Node.js with ESM support
- @types/node - TypeScript definitions for Node.js
This project is licensed under the ISC License - see the LICENSE file for details.
- Built with Discord.js - The most popular Discord library for Node.js
- Weather data provided by OpenWeatherMap API
- Inspired by modern Discord bot development practices
- Thanks to the Discord developer community
Have questions or need help? Feel free to open an issue or join our Discord server!