feat(bot): add NodeJS implementation and deploy script
This commit is contained in:
104
src/index.js
Normal file
104
src/index.js
Normal file
@@ -0,0 +1,104 @@
|
||||
// Load environment variables from .env file
|
||||
require('dotenv').config();
|
||||
const { Client, GatewayIntentBits, Collection } = require('discord.js');
|
||||
const { Manager } = require('erela.js');
|
||||
const logger = require('./utils/logger');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
// Validate essential environment variables
|
||||
if (!process.env.DISCORD_TOKEN) {
|
||||
logger.error('DISCORD_TOKEN is missing in the .env file!');
|
||||
process.exit(1);
|
||||
}
|
||||
if (!process.env.LAVALINK_HOST || !process.env.LAVALINK_PORT || !process.env.LAVALINK_PASSWORD) {
|
||||
logger.warn('Lavalink connection details (HOST, PORT, PASSWORD) are missing or incomplete in .env. Music functionality will be limited.');
|
||||
// Decide if the bot should exit or continue without music
|
||||
// process.exit(1); // Uncomment to exit if Lavalink is mandatory
|
||||
}
|
||||
|
||||
// Create a new Discord client instance with necessary intents
|
||||
const client = new Client({
|
||||
intents: [
|
||||
GatewayIntentBits.Guilds,
|
||||
GatewayIntentBits.GuildVoiceStates,
|
||||
GatewayIntentBits.GuildMessages, // Add if needed for prefix commands or message content
|
||||
GatewayIntentBits.MessageContent, // Add if needed for message content
|
||||
],
|
||||
});
|
||||
|
||||
// Initialize Erela.js Manager
|
||||
// We need the client to be ready before fully initializing the manager
|
||||
client.manager = new Manager({
|
||||
nodes: [
|
||||
{
|
||||
host: process.env.LAVALINK_HOST || 'localhost', // Default host if not set
|
||||
port: parseInt(process.env.LAVALINK_PORT || '2333'), // Default port if not set
|
||||
password: process.env.LAVALINK_PASSWORD || 'youshallnotpass', // Default password if not set
|
||||
secure: process.env.LAVALINK_SECURE === 'true', // Optional: Use true for wss://
|
||||
},
|
||||
],
|
||||
// Function to send raw voice data to Discord
|
||||
send(id, payload) {
|
||||
const guild = client.guilds.cache.get(id);
|
||||
if (guild) guild.shard.send(payload);
|
||||
},
|
||||
});
|
||||
|
||||
// Collections for commands
|
||||
client.commands = new Collection();
|
||||
|
||||
// --- Command Loading ---
|
||||
const commandsPath = path.join(__dirname, 'commands');
|
||||
const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js'));
|
||||
|
||||
for (const file of commandFiles) {
|
||||
const filePath = path.join(commandsPath, file);
|
||||
try {
|
||||
const command = require(filePath);
|
||||
// Set a new item in the Collection with the key as the command name and the value as the exported module
|
||||
if ('data' in command && 'execute' in command) {
|
||||
client.commands.set(command.data.name, command);
|
||||
logger.info(`Loaded command: ${command.data.name}`);
|
||||
} else {
|
||||
logger.warn(`[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.`);
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error(`Error loading command at ${filePath}: ${error.message}`, error);
|
||||
}
|
||||
}
|
||||
|
||||
// --- Event Handling ---
|
||||
const eventsPath = path.join(__dirname, 'events');
|
||||
const eventFiles = fs.readdirSync(eventsPath).filter(file => file.endsWith('.js'));
|
||||
|
||||
for (const file of eventFiles) {
|
||||
const filePath = path.join(eventsPath, file);
|
||||
const event = require(filePath);
|
||||
if (event.once) {
|
||||
client.once(event.name, (...args) => event.execute(...args, client)); // Pass client to event handlers
|
||||
logger.info(`Loaded event ${event.name} (once)`);
|
||||
} else {
|
||||
client.on(event.name, (...args) => event.execute(...args, client)); // Pass client to event handlers
|
||||
logger.info(`Loaded event ${event.name}`);
|
||||
}
|
||||
}
|
||||
|
||||
// --- Erela.js Event Handling ---
|
||||
// (This is handled within the 'ready' event after manager initialization)
|
||||
logger.info('Erela.js event handling will be attached in the ready event.');
|
||||
|
||||
// Log in to Discord with your client's token
|
||||
client.login(process.env.DISCORD_TOKEN)
|
||||
.then(() => logger.info('Successfully logged in to Discord.'))
|
||||
.catch(error => logger.error(`Failed to log in: ${error.message}`));
|
||||
|
||||
// Basic error handling
|
||||
process.on('unhandledRejection', error => {
|
||||
logger.error('Unhandled promise rejection:', error);
|
||||
});
|
||||
process.on('uncaughtException', error => {
|
||||
logger.error('Uncaught exception:', error);
|
||||
// Optional: exit process on critical uncaught exceptions
|
||||
// process.exit(1);
|
||||
});
|
||||
Reference in New Issue
Block a user