KO
|
EN
gitlite β search
Search
#java
#android
#javascript
#ios
#security
#react
#kotlin
#python
#game
#php
#webpack
#spring-boot
sunar
β 76
Open GitHub β
A simple and easy to use discord.js framework.
Download README (.md)
Explore Similar Repositories
djs-class-handler
:
A Discord.js Command Class Handler example using Slash Commands and Context Menus.
discordjs-bot-template
:
πΎ A complete template for simple discord.js bots, with command / event handlers & many useful built in features.
python-logging-discord-handler
:
Redirect your Python log output to Discord
discord-js-v14-handler
:
Discord.js V14 Slash-Command and Context-Menu Handler. Most efficient and advanced Handler out there!
jellycommands
:
A command handler for Discord.js
// repository documentation
Was this content helpful?
β 0
(0 ratings)
Select Rating:
β
β
β
β
β
Submit Feedback
Recent Feedback
×
Download README
Do you want to download the
README.md
file for
sunar
?
Download (.md)
<div align="center"> <br /> <p> <a href="https://sunar.js.org"><img src="https://sunar.js.org/simple-banner.png" alt="Sunar simple banner" /></a> </p> </div> <div align="center"> [](https://www.npmjs.com/package/sunar) [](https://www.npmjs.com/package/sunar) [](https://opensource.org/licenses/MIT) [](https://www.typescriptlang.org/) </div> A simple and easy to use Discord.js framework that provides a structured approach to building Discord bots with **ESM-only** support, built-in command handling, and modular architecture. > **Note**: This project is actively maintained and continuously improved. Check the [changelog](https://github.com/sunarjs/sunar/releases) for latest updates. ## π Features - **π― Type-Safe**: Full TypeScript support with comprehensive type definitions - **β‘ Modern**: Built for Discord.js v14 with ESM support - **π§ Modular**: Clean separation of concerns with builders, handlers, and stores - **π‘οΈ Protected**: Built-in cooldown and permission protection system - **π¨ Flexible**: Support for slash commands, buttons, modals, context menus, and more - **π¦ Tree-Shakable**: Optimized bundle size with selective imports - **π Auto-Loading**: Automatic command registration and file loading - **πͺ Signals**: Custom event system for enhanced bot functionality ## π¦ Installation ```bash npm install sunar discord.js ``` ```bash yarn add sunar discord.js ``` ```bash pnpm add sunar discord.js ``` ```bash bun add sunar discord.js ``` > **Note**: Sunar is **ESM-only**. Make sure your project has `"type": "module"` in your `package.json` or use `.mjs` file extensions. ## π Quick Start ### 1. Initialize the client ```javascript // src/index.js import { Client, GatewayIntentBits, load } from 'sunar'; const start = async () => { const client = new Client({ intents: [ GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages ] }); // Load all commands, signals, and components await load('src/{commands,signals,components}/**/*.js'); await client.login(); // uses process.env.DISCORD_TOKEN by default }; start(); ``` ### 2. Create your first signal ```javascript // src/signals/ready.js import { Signal, execute } from 'sunar'; import { registerCommands } from 'sunar/registry'; const ready = new Signal('ready', { once: true }); execute(ready, async (client) => { // β οΈ WARNING: Command registration in ready event is for demonstration only! // For production, create a separate script to register commands. // This approach registers commands every time the bot starts. await registerCommands(client.application); console.log(`${client.user.tag} is ready! π`); }); export { ready }; ``` > **β οΈ Command Registration Best Practices:** > > - **Development**: Use `registerCommands()` for quick testing and development > - **Production**: Create a separate deployment script to register commands only when needed > - **Guild-specific**: Use `registerGuildCommands()` for testing in specific servers > - **Global**: Use `registerGlobalCommands()` for production deployment > > Registering commands on every bot startup can hit Discord's rate limits and is unnecessary in production. ### 3. Create your first command ```javascript // src/commands/ping.js import { Slash, execute } from 'sunar'; const ping = new Slash({ name: 'ping', description: 'Show client ws ping' }); execute(ping, (interaction) => { interaction.reply({ content: `Client WS Ping: ${interaction.client.ws.ping}ms π` }); }); export { ping }; ``` ### 4. Handle interactions ```javascript // src/signals/interactionCreate.js import { Signal, execute } from 'sunar'; import { handleInteraction } from 'sunar/handlers'; const interactionCreate = new Signal('interactionCreate'); execute(interactionCreate, async (interaction) => { await handleInteraction(interaction); }); export { interactionCreate }; ``` ## π Core Concepts ### Builders Sunar provides various builders for different Discord interactions: - **`Slash`** - Slash commands (`/command`) - **`Button`** - Interactive buttons - **`Modal`** - Popup forms - **`ContextMenu`** - Right-click context menus - **`SelectMenu`** - Dropdown selection menus - **`Signal`** - Custom events and Discord events - **`SlashParent`** - Parent commands for subcommands - **`SlashSubcommand`** - Subcommands and grouped commands - **`Protector`** - Middleware for authorization and validation ### Mutators Enhance your builders with additional functionality: ```javascript import { Slash, execute, config, protect, Protector } from 'sunar'; // Create a protector const adminOnly = new Protector({ commands: ['slash'] }); execute(adminOnly, (interaction, next) => { if (!interaction.memberPermissions?.has('Administrator')) { interaction.reply({ content: 'Admin only!', ephemeral: true }); return; // Block execution } return next(); // Allow execution }); const slash = new Slash({ name: 'admin', description: 'Admin only command' }); // Add configuration config(slash, { guildIds: ['123456789'], // Guild-specific command cooldown: 5000 // 5 second cooldown (in milliseconds) }); // Add protection protect(slash, [adminOnly]); execute(slash, (interaction) => { interaction.reply('Admin command executed!'); }); export { slash, adminOnly }; ``` ## π― Advanced Examples ### Modal with Form Handling ```javascript import { Slash, Modal, execute } from 'sunar'; import { ModalBuilder, TextInputBuilder, TextInputStyle, ActionRowBuilder } from 'discord.js'; // Slash command to trigger modal const feedback = new Slash({ name: 'feedback', description: 'Submit feedback' }); execute(feedback, (interaction) => { const modal = new ModalBuilder() .setCustomId('feedback-modal') .setTitle('Submit Feedback') .addComponents( new ActionRowBuilder().addComponents( new TextInputBuilder() .setCustomId('message') .setLabel('Your feedback') .setStyle(TextInputStyle.Paragraph) .setRequired(true) ) ); interaction.showModal(modal); }); // Modal handler const feedbackModal = new Modal({ id: 'feedback-modal' }); execute(feedbackModal, (interaction) => { const message = interaction.fields.getTextInputValue('message'); // Process feedback... interaction.reply({ content: 'Thank you for your feedback! π', ephemeral: true }); }); export { feedback, feedbackModal }; ``` ### Dynamic Button Handling with Regex ```javascript import { Button, execute } from 'sunar'; // Handle buttons with dynamic IDs like "delete-123", "delete-456" const deleteButton = new Button({ id: /^delete-\d+$/ }); execute(deleteButton, (interaction) => { const id = interaction.customId.split('-')[1]; // Delete logic here... interaction.reply({ content: `Item ${id} deleted successfully!`, ephemeral: true }); }); export { deleteButton }; ``` ### Subcommands and Groups ```javascript import { SlashParent, SlashSubcommand, execute } from 'sunar'; import { ApplicationCommandOptionType } from 'discord.js'; // Parent command const music = new SlashParent({ name: 'music', description: 'Music commands', groups: [{ name: "playlist", description: "Playlist commands" }] }); // Subcommand const play = new SlashSubcommand('music', { name: 'play', description: 'Play a song', options: [{ name: 'query', description: 'Song to play', type: ApplicationCommandOptionType.String, required: true }] }); // Grouped subcommand const addToPlaylist = new SlashSubcommand('music', 'playlist', { name: 'add', description: 'Add song to playlist' }); execute(play, (interaction) => { const query = interaction.options.getString('query', true); interaction.reply(`Now playing: ${query} π΅`); }); execute(addToPlaylist, (interaction) => { interaction.reply('Song added to playlist! π'); }); export { music, play, addToPlaylist }; ``` ## π Recommended Project Structure ``` src/ βββ commands/ # Slash commands β βββ utility/ β β βββ ping.js β β βββ avatar.js β βββ music/ βββ parent.js β βββ play.js β βββ playlist.js βββ components/ # Interactive components β βββ buttons/ β β βββ confirm.js β β βββ delete.js β βββ modals/ β β βββ feedback.js β βββ selects/ β βββ role-select.js βββ protectors/ # Middleware β βββ admin-only.js β βββ cooldown.js βββ signals/ # Event handlers β βββ ready.js β βββ interactionCreate.js β βββ messageCreate.js βββ index.js # Bot entry point ``` ## π§ TypeScript Support Sunar provides full TypeScript support. For TypeScript projects: ### TypeScript Example ```typescript import { Client, GatewayIntentBits, Slash, execute } from 'sunar'; const client = new Client({ intents: [GatewayIntentBits.Guilds] }); const ping = new Slash({ name: 'ping', description: 'Replies with Pong!' }); execute(ping, (interaction) => { interaction.reply(`Pong! ${interaction.client.ws.ping}ms`); }); await client.login(); // uses process.env.DISCORD_TOKEN by default ``` ## π API Reference ### Core Exports ```javascript // Main client and builders import { Client, Slash, Button, Modal, ContextMenu, SelectMenu, Signal, SlashParent, SlashSubcommand, Protector } from 'sunar'; // Mutators and utilities import { execute, config, protect, load } from 'sunar'; ``` ### Selective Imports ```javascript // Registry import { registerCommands } from 'sunar/registry'; // Handlers import { handleInteraction, handleSlash } from 'sunar/handlers'; // Utilities import { isSlashBuilder, isButtonBuilder } from 'sunar/utils'; // Stores import { context, slashes, buttons } from 'sunar/stores'; ``` ## π Development ### Building ```bash bun run build ``` ### Testing ```bash bun run test ``` ### Development Mode ```bash bun run test:dev ``` ## π€ Contributing Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change. 1. Fork the repository 2. Create your feature branch (`git checkout -b feature/amazing-feature`) 3. Commit your changes (`git commit -m 'Add some amazing feature'`) 4. Push to the branch (`git push origin feature/amazing-feature`) 5. Open a Pull Request ## π License This project is licensed under the MIT License - see the [LICENSE](https://github.com/sunarjs/sunar/blob/main/LICENSE) file for details. ## β€οΈ Support If you find Sunar helpful, please consider: - β Starring the repository on [GitHub](https://github.com/sunarjs/sunar) - π Reporting bugs or issues - π‘ Suggesting new features - π Contributing to documentation - π¬ Sharing your projects built with Sunar ## π Links - **π Documentation**: [https://sunar.js.org](https://sunar.js.org) - **π¦ NPM Package**: [https://www.npmjs.com/package/sunar](https://www.npmjs.com/package/sunar) - **π GitHub Repository**: [https://github.com/sunarjs/sunar](https://github.com/sunarjs/sunar) - **π Issues & Bug Reports**: [https://github.com/sunarjs/sunar/issues](https://github.com/sunarjs/sunar/issues) - **π¬ Discord.js Documentation**: [https://discord.js.org](https://discord.js.org) ## π Credits Special thanks to: - **[Discord.js](https://discord.js.org)** - The incredible library that powers Sunar - **[Fumadocs](https://fumadocs.dev/)** - Excellent framework for creating documentation --- **Made with β€οΈ by [Usse](https://github.com/ussego)**