dscaffold
Version:
A TypeScript framework for scaffolding modular Discord bot projects with dynamic command and event loading
813 lines (711 loc) • 28.2 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ProjectGenerator = void 0;
const path_1 = __importDefault(require("path"));
const utils_1 = require("../utils");
const TemplateRenderer_1 = require("./TemplateRenderer");
class ProjectGenerator {
constructor(config) {
this.config = config;
this.templateRenderer = new TemplateRenderer_1.TemplateRenderer();
}
async generate(targetPath) {
await (0, utils_1.ensureDir)(targetPath);
// Generate package.json
await this.generatePackageJson(targetPath);
// Generate TypeScript/JavaScript config files
if (this.config.language === 'typescript') {
await this.generateTsConfig(targetPath);
}
// Generate main bot file
await this.generateMainFile(targetPath);
// Generate basic structure
await this.generateProjectStructure(targetPath);
// Generate configuration files
await this.generateConfigFiles(targetPath);
// Generate example files
await this.generateExampleFiles(targetPath);
// Generate additional files based on features
if (this.config.features.eslint) {
await this.generateEslintConfig(targetPath);
}
if (this.config.features.prettier) {
await this.generatePrettierConfig(targetPath);
}
if (this.config.features.docker) {
await this.generateDockerFiles(targetPath);
}
// Generate README
await this.generateReadme(targetPath);
}
async generatePackageJson(targetPath) {
const isTs = this.config.language === 'typescript';
const content = this.getPackageJsonContent(isTs);
await (0, utils_1.writeFile)(path_1.default.join(targetPath, 'package.json'), content);
}
getPackageJsonContent(isTypeScript) {
const packageJson = {
name: this.config.name,
version: "1.0.0",
description: "A Discord bot built with Discord.js",
main: isTypeScript ? "dist/index.js" : "src/index.js",
scripts: {
...(isTypeScript ? {
build: "tsc",
start: "node dist/index.js",
dev: "ts-node-dev --respawn --transpile-only src/index.ts",
watch: "tsc --watch"
} : {
start: "node src/index.js",
dev: "nodemon src/index.js"
}),
...(this.config.features.eslint ? {
lint: `eslint ${isTypeScript ? 'src/**/*.ts' : 'src/**/*.js'}`,
"lint:fix": `eslint ${isTypeScript ? 'src/**/*.ts' : 'src/**/*.js'} --fix`
} : {}),
...(this.config.features.prettier ? {
format: `prettier --write ${isTypeScript ? 'src/**/*.ts' : 'src/**/*.js'}`
} : {}),
test: 'echo "Error: no test specified" && exit 1'
},
dependencies: {
"discord.js": "^14.14.1",
"dotenv": "^16.4.5",
"dscaffold": "^1.0.0",
...(this.config.features.database ? { mongoose: "^8.1.1" } : {}),
...(this.config.features.logging ? { winston: "^3.11.0" } : {})
},
devDependencies: {
...(isTypeScript ? {
"@types/node": "^20.11.24",
"ts-node": "^10.9.2",
"ts-node-dev": "^2.0.0",
typescript: "^5.3.3"
} : {
nodemon: "^3.0.3"
}),
...(this.config.features.eslint ? {
eslint: "^8.56.0",
...(isTypeScript ? {
"@typescript-eslint/eslint-plugin": "^6.21.0",
"@typescript-eslint/parser": "^6.21.0"
} : {})
} : {}),
...(this.config.features.prettier ? {
prettier: "^3.2.5",
...(this.config.features.eslint ? { "eslint-config-prettier": "^9.1.0" } : {})
} : {})
},
keywords: ["discord", "bot", "discord.js"],
author: "",
license: "MIT"
};
return JSON.stringify(packageJson, null, 2);
}
async generateTsConfig(targetPath) {
const template = this.getTsConfigTemplate();
const content = this.templateRenderer.render(template, this.config);
await (0, utils_1.writeFile)(path_1.default.join(targetPath, 'tsconfig.json'), content);
}
async generateMainFile(targetPath) {
const isTs = this.config.language === 'typescript';
const extension = isTs ? 'ts' : 'js';
const content = this.getMainFileContent(isTs);
await (0, utils_1.writeFile)(path_1.default.join(targetPath, `src/index.${extension}`), content);
}
getMainFileContent(isTypeScript) {
const intentsArray = this.config.botSettings.intents.map(intent => `GatewayIntentBits.${intent}`).join(', ');
if (isTypeScript) {
return `import { Client, GatewayIntentBits } from 'discord.js';
import dscaffold from 'dscaffold';
import dotenv from 'dotenv';
import path from 'path';
${this.config.features.logging ? "import { logger } from './utils/logger';" : ''}
${this.config.features.database ? "import { connectDB } from './utils/database';" : ''}
dotenv.config();
const client = new Client({
intents: [${intentsArray}],
});
// Initialize dscaffold and load commands/events
async function initialize() {
try {
// Load commands from the commands directory (supports nested folders)
await dscaffold.loadCommands(client, path.join(__dirname, 'commands'));
// Load events from the events directory
await dscaffold.loadEvents(client, path.join(__dirname, 'events'));
${this.config.features.database ? ' // Connect to database\n await connectDB();' : ''}
// Login to Discord
await client.login(process.env.DISCORD_TOKEN);
} catch (error) {
console.error('❌ Failed to initialize bot:', error);
process.exit(1);
}
}
// Handle command interactions
client.on('messageCreate', async (message) => {
if (message.author.bot) return;
const prefix = process.env.PREFIX || '${this.config.botSettings.prefix}';
if (!message.content.startsWith(prefix)) return;
const args = message.content.slice(prefix.length).trim().split(/ +/);
const commandName = args.shift()?.toLowerCase();
if (!commandName) return;
const command = dscaffold.getCommand(commandName);
if (!command) return;
try {
await command.execute(message, args);
} catch (error) {
console.error('❌ Error executing command:', error);
message.reply('There was an error executing that command!');
}
});
// Handle slash command interactions
client.on('interactionCreate', async (interaction) => {
if (!interaction.isChatInputCommand()) return;
const command = dscaffold.getCommand(interaction.commandName);
if (!command) return;
try {
await command.execute(interaction);
} catch (error) {
console.error('❌ Error executing slash command:', error);
await interaction.reply({ content: 'There was an error executing that command!', ephemeral: true });
}
});
// Start the bot
initialize();`;
}
else {
return `const { Client, GatewayIntentBits } = require('discord.js');
const dscaffold = require('dscaffold').default;
require('dotenv').config();
const path = require('path');
${this.config.features.logging ? "const { logger } = require('./utils/logger');" : ''}
${this.config.features.database ? "const { connectDB } = require('./utils/database');" : ''}
const client = new Client({
intents: [${intentsArray}],
});
// Initialize dscaffold and load commands/events
async function initialize() {
try {
// Load commands from the commands directory (supports nested folders)
await dscaffold.loadCommands(client, path.join(__dirname, 'commands'));
// Load events from the events directory
await dscaffold.loadEvents(client, path.join(__dirname, 'events'));
${this.config.features.database ? ' // Connect to database\n await connectDB();' : ''}
// Login to Discord
await client.login(process.env.DISCORD_TOKEN);
} catch (error) {
console.error('❌ Failed to initialize bot:', error);
process.exit(1);
}
}
// Handle command interactions
client.on('messageCreate', async (message) => {
if (message.author.bot) return;
const prefix = process.env.PREFIX || '${this.config.botSettings.prefix}';
if (!message.content.startsWith(prefix)) return;
const args = message.content.slice(prefix.length).trim().split(/ +/);
const commandName = args.shift()?.toLowerCase();
if (!commandName) return;
const command = dscaffold.getCommand(commandName);
if (!command) return;
try {
await command.execute(message, args);
} catch (error) {
console.error('❌ Error executing command:', error);
message.reply('There was an error executing that command!');
}
});
// Handle slash command interactions
client.on('interactionCreate', async (interaction) => {
if (!interaction.isChatInputCommand()) return;
const command = dscaffold.getCommand(interaction.commandName);
if (!command) return;
try {
await command.execute(interaction);
} catch (error) {
console.error('❌ Error executing slash command:', error);
await interaction.reply({ content: 'There was an error executing that command!', ephemeral: true });
}
});
// Start the bot
initialize();`;
}
}
async generateProjectStructure(targetPath) {
const directories = [
'src',
'src/commands',
'src/events',
'config',
];
if (this.config.features.database) {
directories.push('src/models');
}
if (this.config.features.logging) {
directories.push('logs');
}
for (const dir of directories) {
await (0, utils_1.ensureDir)(path_1.default.join(targetPath, dir));
}
}
async generateConfigFiles(targetPath) {
// Generate .env file
const envContent = this.getEnvTemplate();
await (0, utils_1.writeFile)(path_1.default.join(targetPath, '.env'), envContent);
// Generate .env.example
const envExampleContent = this.getEnvExampleTemplate();
await (0, utils_1.writeFile)(path_1.default.join(targetPath, '.env.example'), envExampleContent);
// Generate config file
const isTs = this.config.language === 'typescript';
const extension = isTs ? 'ts' : 'js';
const configTemplate = isTs ? this.getConfigTsTemplate() : this.getConfigJsTemplate();
const content = this.templateRenderer.render(configTemplate, {
prefix: this.config.botSettings.prefix,
intents: this.config.botSettings.intents,
});
await (0, utils_1.writeFile)(path_1.default.join(targetPath, `config/bot.${extension}`), content);
}
async generateExampleFiles(targetPath) {
const isTs = this.config.language === 'typescript';
const extension = isTs ? 'ts' : 'js';
// Generate example command
const commandTemplate = isTs ? this.getExampleCommandTsTemplate() : this.getExampleCommandJsTemplate();
const commandContent = this.templateRenderer.render(commandTemplate, {
prefix: this.config.botSettings.prefix,
});
await (0, utils_1.writeFile)(path_1.default.join(targetPath, `src/commands/ping.${extension}`), commandContent);
// Generate example event
const eventTemplate = isTs ? this.getExampleEventTsTemplate() : this.getExampleEventJsTemplate();
const eventContent = this.templateRenderer.render(eventTemplate, this.config);
await (0, utils_1.writeFile)(path_1.default.join(targetPath, `src/events/ready.${extension}`), eventContent);
}
async generateEslintConfig(targetPath) {
const template = this.getEslintConfigTemplate();
const content = this.templateRenderer.render(template, {
isTypeScript: this.config.language === 'typescript',
});
await (0, utils_1.writeFile)(path_1.default.join(targetPath, '.eslintrc.json'), content);
}
async generatePrettierConfig(targetPath) {
const template = this.getPrettierConfigTemplate();
await (0, utils_1.writeFile)(path_1.default.join(targetPath, '.prettierrc'), template);
}
async generateDockerFiles(targetPath) {
const dockerfileTemplate = this.getDockerfileTemplate();
const dockerfileContent = this.templateRenderer.render(dockerfileTemplate, {
isTypeScript: this.config.language === 'typescript',
});
await (0, utils_1.writeFile)(path_1.default.join(targetPath, 'Dockerfile'), dockerfileContent);
const dockerIgnoreTemplate = this.getDockerIgnoreTemplate();
await (0, utils_1.writeFile)(path_1.default.join(targetPath, '.dockerignore'), dockerIgnoreTemplate);
}
async generateReadme(targetPath) {
const template = this.getReadmeTemplate();
const content = this.templateRenderer.render(template, {
name: this.config.name,
language: this.config.language,
prefix: this.config.botSettings.prefix,
hasDatabase: this.config.features.database,
hasDocker: this.config.features.docker,
});
await (0, utils_1.writeFile)(path_1.default.join(targetPath, 'README.md'), content);
}
// Template methods (simplified for brevity - these would load from actual template files)
getPackageJsonTemplate() {
return `{
"name": "{{name}}",
"version": "1.0.0",
"description": "A Discord bot built with Discord.js",
"main": "{{#isTypeScript}}dist/index.js{{/isTypeScript}}{{^isTypeScript}}src/index.js{{/isTypeScript}}",
"scripts": {
{{#isTypeScript}}"build": "tsc",
"start": "node dist/index.js",
"dev": "ts-node-dev --respawn --transpile-only src/index.ts",
"watch": "tsc --watch",{{/isTypeScript}}
{{^isTypeScript}}"start": "node src/index.js",
"dev": "nodemon src/index.js",{{/isTypeScript}}
{{#hasEslint}}"lint": "eslint {{#isTypeScript}}src/**/*.ts{{/isTypeScript}}{{^isTypeScript}}src/**/*.js{{/isTypeScript}}",
"lint:fix": "eslint {{#isTypeScript}}src/**/*.ts{{/isTypeScript}}{{^isTypeScript}}src/**/*.js{{/isTypeScript}} --fix",{{/hasEslint}}
{{#hasPrettier}}"format": "prettier --write {{#isTypeScript}}src/**/*.ts{{/isTypeScript}}{{^isTypeScript}}src/**/*.js{{/isTypeScript}}",{{/hasPrettier}}
"test": "echo \\"Error: no test specified\\" && exit 1"
},
"dependencies": {
"discord.js": "^14.14.1",
"dotenv": "^16.4.5"{{#hasDatabase}},
"mongoose": "^8.1.1"{{/hasDatabase}}{{#hasLogging}},
"winston": "^3.11.0"{{/hasLogging}}
},
"devDependencies": {
{{#isTypeScript}}"@types/node": "^20.11.24",
"ts-node": "^10.9.2",
"ts-node-dev": "^2.0.0",
"typescript": "^5.3.3"{{/isTypeScript}}
{{^isTypeScript}}"nodemon": "^3.0.3"{{/isTypeScript}}
{{#hasEslint}}{{#isTypeScript}},{{/isTypeScript}}{{^isTypeScript}}{{#hasPrettier}},{{/hasPrettier}}{{/isTypeScript}}
"eslint": "^8.56.0"{{#isTypeScript}},
"@typescript-eslint/eslint-plugin": "^6.21.0",
"@typescript-eslint/parser": "^6.21.0"{{/isTypeScript}}{{/hasEslint}}
{{#hasPrettier}}{{#hasEslint}},{{/hasEslint}}{{^hasEslint}}{{#isTypeScript}},{{/isTypeScript}}{{^isTypeScript}},{{/isTypeScript}}{{/hasEslint}}
"prettier": "^3.2.5"{{#hasEslint}},
"eslint-config-prettier": "^9.1.0"{{/hasEslint}}{{/hasPrettier}}
},
"keywords": ["discord", "bot", "discord.js"],
"author": "",
"license": "MIT"
}`;
}
getTsConfigTemplate() {
return `{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"lib": ["ES2020"],
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"moduleResolution": "node",
"types": ["node"]
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}`;
}
getMainTsTemplate() {
return `import { Client, GatewayIntentBits } from 'discord.js';
import dotenv from 'dotenv';
import path from 'path';
import fs from 'fs';
{{#hasLogging}}import { logger } from './utils/logger';{{/hasLogging}}
{{#hasDatabase}}import { connectDB } from './utils/database';{{/hasDatabase}}
dotenv.config();
const client = new Client({
intents: [{{#intents}}GatewayIntentBits.{{.}},{{/intents}}],
});
// Load commands
const commandsPath = path.join(__dirname, 'commands');
const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.ts') || file.endsWith('.js'));
for (const file of commandFiles) {
const command = require(path.join(commandsPath, file));
// Add command loading logic here
}
// Load events
const eventsPath = path.join(__dirname, 'events');
const eventFiles = fs.readdirSync(eventsPath).filter(file => file.endsWith('.ts') || file.endsWith('.js'));
for (const file of eventFiles) {
const event = require(path.join(eventsPath, file));
if (event.once) {
client.once(event.name, (...args) => event.execute(...args));
} else {
client.on(event.name, (...args) => event.execute(...args));
}
}
{{#hasDatabase}}
// Connect to database
connectDB();
{{/hasDatabase}}
client.login(process.env.DISCORD_TOKEN);`;
}
getMainJsTemplate() {
return `const { Client, GatewayIntentBits } = require('discord.js');
require('dotenv').config();
const path = require('path');
const fs = require('fs');
{{#hasLogging}}const { logger } = require('./utils/logger');{{/hasLogging}}
{{#hasDatabase}}const { connectDB } = require('./utils/database');{{/hasDatabase}}
const client = new Client({
intents: [{{#intents}}GatewayIntentBits.{{.}},{{/intents}}],
});
// Load commands
const commandsPath = path.join(__dirname, 'commands');
const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js'));
for (const file of commandFiles) {
const command = require(path.join(commandsPath, file));
// Add command loading logic here
}
// Load events
const eventsPath = path.join(__dirname, 'events');
const eventFiles = fs.readdirSync(eventsPath).filter(file => file.endsWith('.js'));
for (const file of eventFiles) {
const event = require(path.join(eventsPath, file));
if (event.once) {
client.once(event.name, (...args) => event.execute(...args));
} else {
client.on(event.name, (...args) => event.execute(...args));
}
}
{{#hasDatabase}}
// Connect to database
connectDB();
{{/hasDatabase}}
client.login(process.env.DISCORD_TOKEN);`;
}
getEnvTemplate() {
return `DISCORD_TOKEN=your_bot_token_here
CLIENT_ID=your_client_id_here
{{#hasDatabase}}
DATABASE_URL=mongodb://localhost:27017/discord_bot
{{/hasDatabase}}`;
}
getEnvExampleTemplate() {
return `DISCORD_TOKEN=your_bot_token_here
CLIENT_ID=your_client_id_here
{{#hasDatabase}}
DATABASE_URL=mongodb://localhost:27017/discord_bot
{{/hasDatabase}}`;
}
getConfigTsTemplate() {
return `export const config = {
prefix: '{{prefix}}',
token: process.env.DISCORD_TOKEN,
clientId: process.env.CLIENT_ID,
{{#hasDatabase}}databaseUrl: process.env.DATABASE_URL,{{/hasDatabase}}
};`;
}
getConfigJsTemplate() {
return `module.exports = {
prefix: '{{prefix}}',
token: process.env.DISCORD_TOKEN,
clientId: process.env.CLIENT_ID,
{{#hasDatabase}}databaseUrl: process.env.DATABASE_URL,{{/hasDatabase}}
};`;
}
getExampleCommandTsTemplate() {
return `import { Message } from 'discord.js';
module.exports = {
name: 'ping',
description: 'Test bot latency',
category: 'utility',
async execute(message: Message, args: string[]) {
const sent = await message.reply('🏓 Pinging...');
const latency = sent.createdTimestamp - message.createdTimestamp;
const apiLatency = Math.round(message.client.ws.ping);
await sent.edit(\`🏓 Pong!\\n📡 Latency: \${latency}ms\\n💓 API Latency: \${apiLatency}ms\`);
},
};`;
}
getExampleCommandJsTemplate() {
return `module.exports = {
name: 'ping',
description: 'Test bot latency',
category: 'utility',
async execute(message, args) {
const sent = await message.reply('🏓 Pinging...');
const latency = sent.createdTimestamp - message.createdTimestamp;
const apiLatency = Math.round(message.client.ws.ping);
await sent.edit(\`🏓 Pong!\\n📡 Latency: \${latency}ms\\n💓 API Latency: \${apiLatency}ms\`);
},
};`;
}
getExampleEventTsTemplate() {
return `import { Client } from 'discord.js';
module.exports = {
name: 'ready',
once: true,
execute(client: Client) {
console.log(\`✅ \${client.user?.tag} is online!\`);
console.log(\`📊 Serving \${client.guilds.cache.size} guilds with \${client.users.cache.size} users\`);
// Set bot activity
client.user?.setActivity('Powered by Dscaffold', { type: 'PLAYING' });
},
};`;
}
getExampleEventJsTemplate() {
return `module.exports = {
name: 'ready',
once: true,
execute(client) {
console.log(\`✅ \${client.user?.tag} is online!\`);
console.log(\`📊 Serving \${client.guilds.cache.size} guilds with \${client.users.cache.size} users\`);
// Set bot activity
client.user?.setActivity('Powered by Dscaffold', { type: 'PLAYING' });
},
};`;
}
getEslintConfigTemplate() {
return `{
"env": {
"node": true,
"es2021": true
},
"extends": [
"eslint:recommended"{{#isTypeScript}},
"@typescript-eslint/recommended"{{/isTypeScript}}
],
{{#isTypeScript}}"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 12,
"sourceType": "module"
},
"plugins": ["@typescript-eslint"],{{/isTypeScript}}
"rules": {
"indent": ["error", 2],
"linebreak-style": ["error", "unix"],
"quotes": ["error", "single"],
"semi": ["error", "always"]
}
}`;
}
getPrettierConfigTemplate() {
return `{
"semi": true,
"trailingComma": "es5",
"singleQuote": true,
"printWidth": 80,
"tabWidth": 2
}`;
}
getDockerfileTemplate() {
return `FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
{{#isTypeScript}}
RUN npm run build
CMD ["npm", "start"]
{{/isTypeScript}}
{{^isTypeScript}}
CMD ["npm", "start"]
{{/isTypeScript}}`;
}
getDockerIgnoreTemplate() {
return `node_modules
npm-debug.log
.git
.gitignore
README.md
.env
.nyc_output
coverage
.cache
{{#isTypeScript}}src{{/isTypeScript}}`;
}
getReadmeTemplate() {
return `# {{name}}
A Discord bot built with Discord.js{{#isTypeScript}} and TypeScript{{/isTypeScript}}, powered by **Dscaffold** for dynamic command and event loading.
## ✨ Features
- 🚀 **Dynamic Loading**: Commands and events are automatically loaded from directories
- 📁 **Nested Support**: Organize commands in subfolders (e.g., \`admin/\`, \`moderation/\`)
- 🔥 **Hot Reload**: Commands can be reloaded without restarting the bot
- 📝 **TypeScript Ready**: Full TypeScript support with proper typing
- 🎯 **Category System**: Automatic command categorization
## 🚀 Quick Start
1. **Install dependencies:**
\`\`\`bash
npm install
\`\`\`
2. **Configure environment:**
\`\`\`bash
cp .env.example .env
# Edit .env with your bot token
\`\`\`
3. **Start the bot:**
\`\`\`bash
{{#isTypeScript}}npm run dev{{/isTypeScript}}{{^isTypeScript}}npm run dev{{/isTypeScript}}
\`\`\`
## 📁 Project Structure
\`\`\`
{{name}}/
├── src/
│ ├── commands/ # Bot commands (supports nested folders)
│ │ ├── utility/ # Example: utility commands
│ │ ├── admin/ # Example: admin commands
│ │ └── ping.{{#isTypeScript}}ts{{/isTypeScript}}{{^isTypeScript}}js{{/isTypeScript}} # Example command
│ ├── events/ # Discord event handlers
│ │ └── ready.{{#isTypeScript}}ts{{/isTypeScript}}{{^isTypeScript}}js{{/isTypeScript}} # Example event
{{#hasDatabase}}│ ├── models/ # Database models{{/hasDatabase}}
│ └── index.{{#isTypeScript}}ts{{/isTypeScript}}{{^isTypeScript}}js{{/isTypeScript}} # Main bot file
├── config/
│ └── bot.{{#isTypeScript}}ts{{/isTypeScript}}{{^isTypeScript}}js{{/isTypeScript}} # Bot configuration
└── .env # Environment variables
\`\`\`
## 🎮 Commands
- \`{{prefix}}ping\` - Test bot latency and connection
## 🔧 Development
### Adding Commands
Create a new file in \`src/commands/\` (or any subfolder):
\`\`\`{{#isTypeScript}}typescript{{/isTypeScript}}{{^isTypeScript}}javascript{{/isTypeScript}}
{{#isTypeScript}}// src/commands/utility/info.ts
import { Message } from 'discord.js';
module.exports = {
name: 'info',
description: 'Get bot information',
category: 'utility',
async execute(message: Message, args: string[]) {
await message.reply('Bot info here!');
},
};{{/isTypeScript}}{{^isTypeScript}}// src/commands/utility/info.js
module.exports = {
name: 'info',
description: 'Get bot information',
category: 'utility',
async execute(message, args) {
await message.reply('Bot info here!');
},
};{{/isTypeScript}}
\`\`\`
### Adding Events
Create a new file in \`src/events/\`:
\`\`\`{{#isTypeScript}}typescript{{/isTypeScript}}{{^isTypeScript}}javascript{{/isTypeScript}}
{{#isTypeScript}}// src/events/messageCreate.ts
import { Message } from 'discord.js';
module.exports = {
name: 'messageCreate',
execute(message: Message) {
// Handle message events
},
};{{/isTypeScript}}{{^isTypeScript}}// src/events/messageCreate.js
module.exports = {
name: 'messageCreate',
execute(message) {
// Handle message events
},
};{{/isTypeScript}}
\`\`\`
### Using Dscaffold API
\`\`\`{{#isTypeScript}}typescript{{/isTypeScript}}{{^isTypeScript}}javascript{{/isTypeScript}}
{{#isTypeScript}}import dscaffold from 'dscaffold';
// Get a command
const command = dscaffold.getCommand('ping');
// Get commands by category
const utilityCommands = dscaffold.getCommandsByCategory('utility');
// Get all categories
const categories = dscaffold.getCategories();
// Reload commands (useful for development)
await dscaffold.reloadCommands(client, './src/commands');{{/isTypeScript}}{{^isTypeScript}}const dscaffold = require('dscaffold').default;
// Get a command
const command = dscaffold.getCommand('ping');
// Get commands by category
const utilityCommands = dscaffold.getCommandsByCategory('utility');
// Get all categories
const categories = dscaffold.getCategories();
// Reload commands (useful for development)
await dscaffold.reloadCommands(client, './src/commands');{{/isTypeScript}}
\`\`\`
## 📜 Scripts
{{#isTypeScript}}- \`npm run dev\` - Start with auto-reload (development)
- \`npm run build\` - Build TypeScript to JavaScript
- \`npm start\` - Start the compiled bot (production){{/isTypeScript}}{{^isTypeScript}}- \`npm run dev\` - Start with auto-reload (development)
- \`npm start\` - Start the bot{{/isTypeScript}}
{{#hasDocker}}## 🐳 Docker
\`\`\`bash
# Build and run with Docker
docker build -t {{name}} .
docker run -d --name {{name}} --env-file .env {{name}}
\`\`\`{{/hasDocker}}
## 🔗 Powered By
- **[Dscaffold](https://github.com/dscaffold/dscaffold)** - Dynamic Discord bot framework
- **[Discord.js](https://discord.js.org/)** - Discord API library
## 📝 License
MIT`;
}
}
exports.ProjectGenerator = ProjectGenerator;
//# sourceMappingURL=ProjectGenerator.js.map