discord-multipurpose-bot/index.js
2025-09-20 02:47:34 +01:00

275 lines
9.1 KiB
JavaScript

require("dotenv").config();
const {
Client,
GatewayIntentBits,
Collection,
REST,
Routes,
PresenceUpdateStatus,
} = require("discord.js");
const { DisTube } = require("distube");
const { SpotifyPlugin } = require("@distube/spotify");
const { SoundCloudPlugin } = require("@distube/soundcloud");
const mongoose = require("mongoose");
const fs = require("fs");
const path = require("path");
const ServerSettings = require("./models/ServerSettings");
const seedShopItems = require("./utils/seedShopItems");
const seedSpyfallLocations = require("./utils/seedSpyfallLocations");
const setupDisTubeEvents = require("./events/distubeEvents");
// Console colors
const colors = {
reset: "\x1b[0m",
bright: "\x1b[1m",
dim: "\x1b[2m",
underscore: "\x1b[4m",
blink: "\x1b[5m",
reverse: "\x1b[7m",
hidden: "\x1b[8m",
black: "\x1b[30m",
red: "\x1b[31m",
green: "\x1b[32m",
yellow: "\x1b[33m",
blue: "\x1b[34m",
magenta: "\x1b[35m",
cyan: "\x1b[36m",
white: "\x1b[37m",
bgBlack: "\x1b[40m",
bgRed: "\x1b[41m",
bgGreen: "\x1b[42m",
bgYellow: "\x1b[43m",
bgBlue: "\x1b[44m",
bgMagenta: "\x1b[45m",
bgCyan: "\x1b[46m",
bgWhite: "\x1b[47m",
};
const printBanner = () => {
console.log(`${colors.magenta}
██████╗██╗██████╗ ██████╗ ██╗ ██╗██████╗ ████████╗██████╗ ██╗██╗ ██╗
██╔════╝██║██╔══██╗██╔══██╗██║ ██║██╔══██╗╚══██╔══╝██╔══██╗██║╚██╗██╔╝
██║ ██║██████╔╝██████╔╝██║ ██║██████╔╝ ██║ ██████╔╝██║ ╚███╔╝
██║ ██║██╔══██╗██╔══██╗██║ ██║██╔══██╗ ██║ ██╔══██╗██║ ██╔██╗
╚██████╗██║██║ ██║██║ ██║╚██████╔╝██║ ██║ ██║ ██║ ██║██║██╔╝ ██╗
╚═════╝╚═╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝╚═╝ ╚═╝
${colors.reset}`);
console.log(
`${colors.cyan}${colors.bright}⚡ Circuitrix Discord Bot ${colors.reset}`
);
console.log(
`${colors.cyan}${colors.bright}✨ Developed with ❤️ by Ayden ${colors.reset}`
);
console.log(
`${colors.cyan}${colors.bright}🌐 https://github.com/aydenjahola ${colors.reset}\n`
);
};
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent,
GatewayIntentBits.GuildVoiceStates,
],
});
client.commands = new Collection();
// Initialize DisTube
client.distube = new DisTube(client, {
emitNewSongOnly: true,
plugins: [new SpotifyPlugin(), new SoundCloudPlugin()],
});
// Function to recursively read commands from subdirectories
function loadCommands(dir) {
const files = fs.readdirSync(dir);
for (const file of files) {
const filePath = path.join(dir, file);
if (fs.statSync(filePath).isDirectory()) {
loadCommands(filePath);
} else if (file.endsWith(".js")) {
try {
const command = require(filePath);
if (command.data && command.data.name) {
client.commands.set(command.data.name, command);
console.log(
`${colors.green}✅ Loaded command: ${colors.reset}${colors.cyan}/${command.data.name}${colors.reset}`
);
}
} catch (error) {
console.log(
`${colors.red}❌ Failed to load command: ${filePath}${colors.reset}`
);
console.error(error);
}
}
}
}
// Load commands
console.log(
`${colors.yellow}${colors.bright}📦 Loading commands...${colors.reset}`
);
loadCommands(path.join(__dirname, "commands"));
console.log(
`${colors.green}✅ Successfully loaded ${colors.bright}${client.commands.size}${colors.reset}${colors.green} commands!${colors.reset}\n`
);
async function registerCommands(guildId) {
const commands = client.commands.map((cmd) => cmd.data.toJSON());
const rest = new REST({ version: "10" }).setToken(process.env.BOT_TOKEN);
try {
await rest.put(Routes.applicationGuildCommands(client.user.id, guildId), {
body: commands,
});
console.log(
`${colors.green}🔄 Registered ${colors.bright}${commands.length}${colors.reset}${colors.green} commands for guild: ${colors.cyan}${guildId}${colors.reset}`
);
} catch (error) {
console.log(
`${colors.red}❌ Error registering commands for guild ${guildId}:${colors.reset}`
);
console.error(error);
}
}
client.once("ready", async () => {
printBanner();
console.log(
`${colors.green}${colors.bright}🚀 Bot successfully logged in as ${colors.cyan}${client.user.tag}${colors.reset}`
);
console.log(
`${colors.green}${colors.bright}📊 Serving ${colors.cyan}${client.guilds.cache.size}${colors.reset}${colors.green} servers${colors.reset}`
);
console.log(
`${colors.green}${colors.bright}👥 Watching ${colors.cyan}${client.users.cache.size}${colors.reset}${colors.green} users${colors.reset}\n`
);
// Set up DisTube events
setupDisTubeEvents(client.distube, client.user.username);
const guilds = client.guilds.cache.map((guild) => guild.id);
console.log(
`${colors.yellow}${colors.bright}⚙️ Initializing server configurations...${colors.reset}`
);
await Promise.all(
guilds.map(async (guildId) => {
await seedShopItems(guildId);
await seedSpyfallLocations(guildId);
await registerCommands(guildId);
})
);
client.user.setPresence({
activities: [{ name: "Powering Servers! 🚀", type: 3 }],
status: PresenceUpdateStatus.Online,
});
console.log(
`\n${colors.green}${colors.bright}🎉 Bot is now fully operational and ready!${colors.reset}`
);
console.log(
`${colors.cyan}${colors.bright}==============================================${colors.reset}\n`
);
});
client.on("guildCreate", async (guild) => {
try {
await ServerSettings.create({ guildId: guild.id });
console.log(
`${colors.green}✅ Registered new server: ${colors.cyan}${guild.name}${colors.reset} ${colors.dim}(${guild.id})${colors.reset}`
);
await seedShopItems(guild.id);
await seedSpyfallLocations(guild.id);
await registerCommands(guild.id);
console.log(
`${colors.green}🎉 Successfully initialized ${colors.cyan}${guild.name}${colors.reset}${colors.green} with all features!${colors.reset}`
);
} catch (error) {
console.log(`${colors.red}❌ Error registering new server:${colors.reset}`);
console.error(error);
}
});
// MongoDB connection
console.log(
`${colors.yellow}${colors.bright}🔗 Connecting to MongoDB...${colors.reset}`
);
mongoose
.connect(process.env.MONGODB_URI)
.then(() => {
console.log(
`${colors.green}✅ Successfully connected to MongoDB!${colors.reset}\n`
);
})
.catch((err) => {
console.log(`${colors.red}❌ Failed to connect to MongoDB:${colors.reset}`);
console.error(err);
process.exit(1);
});
client.on("interactionCreate", async (interaction) => {
if (!interaction.isCommand()) return;
const command = client.commands.get(interaction.commandName);
if (!command) return;
try {
await command.execute(interaction, client);
} catch (err) {
console.log(
`${colors.red}❌ Error executing command ${colors.cyan}/${interaction.commandName}${colors.reset}`
);
console.error(err);
const replyOptions = {
content: "❌ There was an error while executing this command!",
ephemeral: true,
};
if (interaction.deferred || interaction.replied) {
await interaction.followUp(replyOptions);
} else {
await interaction.reply(replyOptions);
}
}
});
client.on("error", (err) => {
console.log(`${colors.red}${colors.bright}⚠️ Client error:${colors.reset}`);
console.error(err);
});
process.on("unhandledRejection", (error) => {
console.log(
`${colors.red}${colors.bright}⚠️ Unhandled promise rejection:${colors.reset}`
);
console.error(error);
});
process.on("uncaughtException", (error) => {
console.log(
`${colors.red}${colors.bright}⚠️ Uncaught exception:${colors.reset}`
);
console.error(error);
});
// Login
console.log(
`${colors.yellow}${colors.bright}🔐 Logging in to Discord...${colors.reset}`
);
client
.login(process.env.BOT_TOKEN)
.then(() => {
console.log(
`${colors.green}✅ Authentication successful!${colors.reset}\n`
);
})
.catch((error) => {
console.log(`${colors.red}❌ Failed to login to Discord:${colors.reset}`);
console.error(error);
process.exit(1);
});