From f62bbc4ab7d58738da1bbaf4a554ad40753fe486 Mon Sep 17 00:00:00 2001 From: Ayden Jahola Date: Sat, 20 Sep 2025 02:47:34 +0100 Subject: [PATCH] seperate distube and change startup console theme --- events/distubeEvents.js | 113 +++++++++++++++++++++ index.js | 215 +++++++++++++++++++++++++++++++--------- 2 files changed, 279 insertions(+), 49 deletions(-) create mode 100644 events/distubeEvents.js diff --git a/events/distubeEvents.js b/events/distubeEvents.js new file mode 100644 index 0000000..be9aed7 --- /dev/null +++ b/events/distubeEvents.js @@ -0,0 +1,113 @@ +const { EmbedBuilder } = require("discord.js"); + +module.exports = (distube, botName) => { + const footerConfig = { + text: `Powered by ${botName}, developed with ❀️ by Ayden`, + iconURL: "https://github.com/aydenjahola.png", + }; + + const createEmbed = (color, title, description, thumbnail = null) => { + const embed = new EmbedBuilder() + .setColor(color) + .setTitle(title) + .setDescription(description) + .setFooter(footerConfig); + + if (thumbnail) { + embed.setThumbnail(thumbnail); + } + + return embed; + }; + + distube + .on("playSong", (queue, song) => { + const embed = createEmbed( + 0x0099ff, + "🎢 Now Playing", + `**${song.name}** - \`${song.formattedDuration}\``, + song.thumbnail + ); + queue.textChannel.send({ embeds: [embed] }); + }) + .on("addSong", (queue, song) => { + const embed = createEmbed( + 0x00ff00, + "βœ… Song Added", + `**${song.name}** - \`${song.formattedDuration}\``, + song.thumbnail + ); + queue.textChannel.send({ embeds: [embed] }); + }) + .on("error", (channel, error) => { + console.error("DisTube error:", error); + const embed = createEmbed( + 0xff0000, + "❌ Error", + `An error occurred: ${error.message}` + ); + if (channel && channel.send) { + channel.send({ embeds: [embed] }); + } + }) + .on("finish", (queue) => { + if (queue.textChannel) { + const embed = createEmbed( + 0x0099ff, + "🎡 Queue Finished", + "The music queue has ended." + ); + queue.textChannel.send({ embeds: [embed] }); + } + }) + .on("pause", (queue) => { + if (queue.textChannel) { + const embed = createEmbed( + 0xffff00, + "⏸️ Music Paused", + "Playback has been paused." + ); + queue.textChannel.send({ embeds: [embed] }); + } + }) + .on("resume", (queue) => { + if (queue.textChannel) { + const embed = createEmbed( + 0x00ff00, + "▢️ Music Resumed", + "Playback has been resumed." + ); + queue.textChannel.send({ embeds: [embed] }); + } + }) + .on("volumeChange", (queue, volume) => { + if (queue.textChannel) { + const embed = createEmbed( + 0x0099ff, + "πŸ”Š Volume Changed", + `Volume set to ${volume}%` + ); + queue.textChannel.send({ embeds: [embed] }); + } + }) + .on("noRelated", (queue) => { + if (queue.textChannel) { + const embed = createEmbed( + 0xff0000, + "❌ No Related Videos", + "Could not find related video for autoplay!" + ); + queue.textChannel.send({ embeds: [embed] }); + } + }) + .on("empty", (queue) => { + if (queue.textChannel) { + const embed = createEmbed( + 0xff0000, + "πŸ”‡ Voice Channel Empty", + "Voice channel is empty! Leaving the channel." + ); + queue.textChannel.send({ embeds: [embed] }); + } + }); +}; diff --git a/index.js b/index.js index 2b50161..ffba001 100644 --- a/index.js +++ b/index.js @@ -16,6 +16,56 @@ 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: [ @@ -34,38 +84,6 @@ client.distube = new DisTube(client, { plugins: [new SpotifyPlugin(), new SoundCloudPlugin()], }); -// DisTube event listeners -client.distube - .on("playSong", (queue, song) => { - queue.textChannel.send( - `🎢 Playing: **${song.name}** - \`${song.formattedDuration}\`` - ); - }) - .on("addSong", (queue, song) => { - queue.textChannel.send( - `βœ… Added: **${song.name}** - \`${song.formattedDuration}\`` - ); - }) - .on("error", (queue, error) => { - console.error("DisTube error:", error); - queue.textChannel.send("❌ An error occurred: " + error.message); - }) - .on("finish", (queue) => { - queue.textChannel.send("🎡 Queue finished!"); - }) - .on("pause", (queue) => { - queue.textChannel.send("⏸️ Music paused!"); - }) - .on("resume", (queue) => { - queue.textChannel.send("▢️ Music resumed!"); - }) - .on("volumeChange", (queue, volume) => { - queue.textChannel.send(`πŸ”Š Volume changed to ${volume}%`); - }) - .on("noRelated", (queue) => { - queue.textChannel.send("❌ Could not find related video for autoplay!"); - }); - // Function to recursively read commands from subdirectories function loadCommands(dir) { const files = fs.readdirSync(dir); @@ -74,13 +92,32 @@ function loadCommands(dir) { if (fs.statSync(filePath).isDirectory()) { loadCommands(filePath); } else if (file.endsWith(".js")) { - const command = require(filePath); - client.commands.set(command.data.name, command); + 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()); @@ -89,18 +126,38 @@ async function registerCommands(guildId) { await rest.put(Routes.applicationGuildCommands(client.user.id, guildId), { body: commands, }); - console.log(`πŸ”„ Registered commands for guild: ${guildId}`); + console.log( + `${colors.green}πŸ”„ Registered ${colors.bright}${commands.length}${colors.reset}${colors.green} commands for guild: ${colors.cyan}${guildId}${colors.reset}` + ); } catch (error) { - console.error("Error registering commands:", error); + console.log( + `${colors.red}❌ Error registering commands for guild ${guildId}:${colors.reset}` + ); + console.error(error); } } client.once("ready", async () => { - console.log(`\n==============================`); - console.log(`πŸ€– Logged in as ${client.user.tag}`); - console.log(`==============================`); + 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); @@ -110,29 +167,53 @@ client.once("ready", async () => { ); client.user.setPresence({ - activities: [{ name: "Powering Servers!", type: 3 }], + activities: [{ name: "Powering Servers! πŸš€", type: 3 }], status: PresenceUpdateStatus.Online, }); - console.log(`\n==============================\n`); + + 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(`βœ… Registered new server: ${guild.name} (ID: ${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.error("Error registering new server or commands:", 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("βœ… Connected to MongoDB")) - .catch((err) => console.error("❌ Failed to connect to MongoDB", err)); + .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; @@ -141,9 +222,12 @@ client.on("interactionCreate", async (interaction) => { try { await command.execute(interaction, client); } catch (err) { - console.error("Error executing command:", err); + console.log( + `${colors.red}❌ Error executing command ${colors.cyan}/${interaction.commandName}${colors.reset}` + ); + console.error(err); const replyOptions = { - content: "Error executing command!", + content: "❌ There was an error while executing this command!", ephemeral: true, }; if (interaction.deferred || interaction.replied) { @@ -154,5 +238,38 @@ client.on("interactionCreate", async (interaction) => { } }); -client.on("error", (err) => console.error("Client error:", err)); -client.login(process.env.BOT_TOKEN); +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); + });