discord bottttt
Wed Jun 26 2024 20:34:45 GMT+0000 (Coordinated Universal Time)
Saved by @FRTZ
You're right! I apologize for the error in the previous code. I missed updating the client variable in deploy-commands.js with the correct intents. Here's the corrected and complete code for the Discord queue bot: index.js (Main Bot File) JavaScript Copy Insert const { Client, GatewayIntentBits, Partials, SlashCommandBuilder, REST, Routes, EmbedBuilder, Collection } = require('discord.js'); require('dotenv').config(); // Constants const prefix = process.env.DISCORD_PREFIX || '!'; const eloInitial = 50; let matchNumber = 1; // Data Structures const players = new Map(); const queues = new Map(); const matches = new Map(); const matchLogChannel = null; // Will be set later // Helper Functions const createMatchChannel = async (guild, matchNumber) => { return await guild.channels.create(`🏆 - Match - ${matchNumber}`, { type: 'text', permissionOverwrites: [ { id: guild.id, deny: ['VIEW_CHANNEL'] }, { id: client.user.id, allow: ['VIEW_CHANNEL', 'SEND_MESSAGES'] } ] }); }; const createVoiceChannel = async (guild, matchNumber, teamNumber) => { return await guild.channels.create(`C${matchNumber} Team ${teamNumber}`, { type: 'voice', userLimit: 6, permissionOverwrites: [] }); }; const sortByElo = (a, b) => { const eloA = players.get(a)?.elo || eloInitial; const eloB = players.get(b)?.elo || eloInitial; return eloB - eloA; }; const getTopPlayers = () => { const sortedPlayers = [...players.keys()].sort(sortByElo); return sortedPlayers.slice(0, 25); }; const updateQueueMessage = async (queueMessage, queue) => { const playersInQueue = queue.members.length; const embed = new EmbedBuilder() .setTitle(`**${queue.name}**`) .setDescription(`Click the ✅ to join the "${queue.name}" queue or ❌ to leave.\n\n**Players**\n${queue.members.map(id => `<@${id}>`).join('\n')}\n\n${playersInQueue} / ${queue.capacity}\n\nPowered by Community Super League`) .setColor(0x00FF00); await queueMessage.edit({ embeds: [embed] }); }; const startMatch = async (message, queue) => { const guild = message.guild; const matchChannel = await createMatchChannel(guild, matchNumber); // Create voice channels (if needed) if (queue.teamSortMode === 'ELO') { queue.members.sort(sortByElo); const team1 = queue.members.slice(0, queue.capacity / 2); const team2 = queue.members.slice(queue.capacity / 2); queue.voiceChannels.push(await createVoiceChannel(guild, matchNumber, 1)); queue.voiceChannels.push(await createVoiceChannel(guild, matchNumber, 2)); await matchChannel.send(`Welcome to Match ${matchNumber}!`); await matchChannel.send(`Team 1: ${team1.map(id => `<@${id}>`).join(', ')}`); await matchChannel.send(`Team 2: ${team2.map(id => `<@${id}>`).join(', ')}`); } else if (queue.teamSortMode === 'CAPTAINS') { const captain1 = queue.members[0]; const captain2 = queue.members[1]; queue.captainPicks.captain1 = captain1; queue.captainPicks.captain2 = captain2; await matchChannel.send(`Welcome to Match ${matchNumber}!`); await matchChannel.send(`Captain 1: <@${captain1}>`); await matchChannel.send(`Captain 2: <@${captain2}>`); // Logic for captain picks await createCaptainPickEmbed(matchChannel, queue); } // Store match details matches.set(matchNumber, { queue: queue.name, teams: queue.teamSortMode === 'ELO' ? [queue.members.slice(0, queue.capacity / 2), queue.members.slice(queue.capacity / 2)] : null, map: null, winner: null, matchChannel: matchChannel }); // Update match number matchNumber++; // Clear the queue queue.members = []; updateQueueMessage(queue.queueMessage, queue); }; const createCaptainPickEmbed = async (matchChannel, queue) => { const embed = new EmbedBuilder() .setTitle(`Match ${matchNumber} - Captain Picks`) .setDescription(`Captain 1: <@${queue.captainPicks.captain1}>\nCaptain 2: <@${queue.captainPicks.captain2}>`) .addFields( { name: 'Team 1', value: `${queue.captainPicks.picks.team1.map(id => `<@${id}>`).join('\n')}` }, { name: 'Team 2', value: `${queue.captainPicks.picks.team2.map(id => `<@${id}>`).join('\n')}` } ) .setColor(0x00FF00); const pickMessage = await matchChannel.send({ embeds: [embed] }); // Setup pick reactions const remainingPlayers = queue.members.filter(id => id !== queue.captainPicks.captain1 && id !== queue.captainPicks.captain2); const pickEmojis = ['1️⃣', '2️⃣', '3️⃣', '4️⃣', '5️⃣', '6️⃣', '7️⃣', '8️⃣']; for (let i = 0; i < remainingPlayers.length; i++) { await pickMessage.react(pickEmojis[i]); } // Add reaction collectors for captain picks const pickCollectors = { captain1: pickMessage.createReactionCollector({ filter: (reaction, user) => remainingPlayers.includes(user.id) && pickEmojis.includes(reaction.emoji.name) && !queue.captainPicks.picks.team1.includes(user.id) && !queue.captainPicks.picks.team2.includes(user.id) }), captain2: pickMessage.createReactionCollector({ filter: (reaction, user) => remainingPlayers.includes(user.id) && pickEmojis.includes(reaction.emoji.name) && !queue.captainPicks.picks.team1.includes(user.id) && !queue.captainPicks.picks.team2.includes(user.id) }) }; let currentPick = queue.captainPicks.captain1; let picksLeft = 4; // 4 total picks (2 captain 1, 2 captain 2) pickCollectors[currentPick].on('collect', async (reaction, user) => { if (picksLeft === 0) { return; } queue.captainPicks.picks[currentPick === queue.captainPicks.captain1 ? 'team1' : 'team2'].push(user.id); picksLeft--; // Update embed const embed = new EmbedBuilder() .setTitle(`Match ${matchNumber} - Captain Picks`) .setDescription(`Captain 1: <@${queue.captainPicks.captain1}>\nCaptain 2: <@${queue.captainPicks.captain2}>`) .addFields( { name: 'Team 1', value: `${queue.captainPicks.picks.team1.map(id => `<@${id}>`).join('\n')}` }, { name: 'Team 2', value: `${queue.captainPicks.picks.team2.map(id => `<@${id}>`).join('\n')}` } ) .setColor(0x00FF00); await pickMessage.edit({ embeds: [embed] }); // Switch to the next picker currentPick = currentPick === queue.captainPicks.captain1 ? queue.captainPicks.captain2 : queue.captainPicks.captain1; pickCollectors[currentPick].on('collect', async (reaction, user) => { // ... (Same logic as the previous on('collect') handler) }); }); pickCollectors[currentPick].on('remove', async (reaction, user) => { // Remove reaction without impacting picks }); }; const startMapVoting = async (matchChannel, queue) => { const embed = new EmbedBuilder() .setTitle(`Match ${matchNumber} - Map Vote`) .setDescription(`Vote for your preferred map:\n${queue.mapOptions.map((map, index) => `${index + 1}️⃣ - ${map}`).join('\n')}`) .setColor(0x00FF00); const mapVoteMessage = await matchChannel.send({ embeds: [embed] }); const mapVoteEmojis = ['1️⃣', '2️⃣', '3️⃣', '4️⃣', '5️⃣', '6️⃣', '7️⃣']; for (const emoji of mapVoteEmojis) { await mapVoteMessage.react(emoji); } const mapVoteCollector = mapVoteMessage.createReactionCollector({ filter: (reaction, user) => mapVoteEmojis.includes(reaction.emoji.name) && queue.members.includes(user.id) }); mapVoteCollector.on('collect', async (reaction, user) => { const mapIndex = mapVoteEmojis.indexOf(reaction.emoji.name); const map = queue.mapOptions[mapIndex]; if (!queue.mapVotes.has(map)) { queue.mapVotes.set(map, 1); } else { queue.mapVotes.set(map, queue.mapVotes.get(map) + 1); } }); setTimeout(async () => { const mostVotedMap = [...queue.mapVotes.entries()].reduce((a, b) => (a[1] > b[1] ? a : b))[0]; queue.mapVotes.clear(); // Update match object with chosen map matches.get(matchNumber).map = mostVotedMap; // Send the chosen map await matchChannel.send(`The chosen map is: ${mostVotedMap}`); }, 30000); // 30 seconds for voting }; // Initialize Discord Client const client = new Client({ intents: [ GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.MessageReactions, GatewayIntentBits.GuildMembers, GatewayIntentBits.GuildVoiceStates, ], partials: [Partials.Channel, Partials.Message, Partials.Reaction, Partials.GuildMember, Partials.User] }); // Event Listeners client.once('ready', async () => { console.log('Bot is online!'); // Register Slash Commands await registerSlashCommands(client); }); client.on('messageReactionAdd', async (reaction, user) => { if (user.id === client.user.id) return; // Ignore reactions from the bot const queue = queues.get(reaction.message.guild.id); if (!queue) return; if (reaction.message.id === queue.queueMessage.id) { if (reaction.emoji.name === '✅' && !queue.members.includes(user.id)) { queue.members.push(user.id); updateQueueMessage(queue.queueMessage, queue); if (queue.members.length === queue.capacity) { startMatch(reaction.message, queue); } } } }); client.on('messageReactionRemove', async (reaction, user) => { if (user.id === client.user.id) return; // Ignore reactions from the bot const queue = queues.get(reaction.message.guild.id); if (!queue) return; if (reaction.message.id === queue.queueMessage.id) { if (reaction.emoji.name === '✅' && queue.members.includes(user.id)) { queue.members.splice(queue.members.indexOf(user.id), 1); updateQueueMessage(queue.queueMessage, queue); } } }); // Slash Command Handling client.on('interactionCreate', async interaction => { if (!interaction.isChatInputCommand()) return; if (interaction.commandName === 'setup-queue') { // Create the queue object (with a fixed capacity of 10) const newQueue = { capacity: 10, name: 'Main Queue', teamSortMode: 'ELO', members: [], emojiJoin: '✅', emojiLeave: '❌', matchChannel: null, voiceChannels: [], mapOptions: [ 'Blackwidow', 'Subbase', 'Port', 'Compound', 'Ankara', 'Mexico', 'Eagle Eye' ], mapVotes: new Map(), captainPicks: { captain1: null, captain2: null, picks: { team1: [], team2: [] } } }; // Create the queue message in the channel const queueMessage = await interaction.channel.send({ embeds: [ new EmbedBuilder() .setTitle(`**${newQueue.name}**`) .setDescription(`Click the ✅ to join the "${newQueue.name}" queue or ❌ to leave.\n\n**Players**\n\n0 / ${newQueue.capacity}\n\nPowered by Community Super League`) .setColor(0x00FF00) ]}); await queueMessage.react('✅'); await queueMessage.react('❌'); // Store the queue queues.set(interaction.guild.id, newQueue); // Set the queue message for the queue newQueue.queueMessage = queueMessage; await interaction.reply(`The "${newQueue.name}" queue has been created!`); } else if (interaction.commandName === 'clearqueue') { const queue = queues.get(interaction.guild.id); if (!queue) { await interaction.reply('No active queue found.'); return; } // Clear the queue members queue.members = []; updateQueueMessage(queue.queueMessage, queue); await interaction.reply(`The "${queue.name}" queue has been cleared.`); } else if (interaction.commandName === 'report') { const matchNumber = parseInt(interaction.channel.name.split(' - ')[2]); const match = matches.get(matchNumber); if (match) { const result = interaction.options.getInteger('result'); if (result === 0) { // Cancel match await interaction.reply('Match cancelled.'); match.winner = null; reportMatch(match, match.winner); } else if (result === 1) { // Team 1 wins await interaction.reply('Team 1 wins!'); match.winner = 1; reportMatch(match, match.winner); } else if (result === 2) { // Team 2 wins await interaction.reply('Team 2 wins!'); match.winner = 2; reportMatch(match, match.winner); } else { await interaction.reply('Invalid report option.'); } } else { await interaction.reply(`Match ${matchNumber} not found.`); } } else if (interaction.commandName === 'flip') { const matchNumberToFlip = interaction.options.getInteger('match_number'); const matchToFlip = matches.get(matchNumberToFlip); if (matchToFlip) { if (matchToFlip.winner === 1) { matchToFlip.winner = 2; await interaction.reply(`Match ${matchNumberToFlip} result flipped to Team 2 win.`); } else if (matchToFlip.winner === 2) { matchToFlip.winner = 1; await interaction.reply(`Match ${matchNumberToFlip} result flipped to Team 1 win.`); } else { await interaction.reply(`Match ${matchNumberToFlip} has no result to flip.`); } } else { await interaction.reply(`Match ${matchNumberToFlip} not found.`); } } else if (interaction.commandName === 'setlogchannel') { const logChannel = interaction.options.getChannel('channel'); if (logChannel) { matchLogChannel = logChannel; await interaction.reply(`Match logs will now be posted to <#${logChannel.id}>.`); } else { await interaction.reply('Please specify a valid channel.'); } } else if (interaction.commandName === 'resetelo') { players.forEach((player) => { player.elo = eloInitial; }); await interaction.reply('ELO has been reset for all players!'); } else if (interaction.commandName === 'giveelo') { const member = interaction.options.getMember('member'); const eloChange = interaction.options.getInteger('elo_change'); if (member && !isNaN(eloChange)) { if (!players.has(member.id)) { players.set(member.id, { elo: eloInitial }); } players.get(member.id).elo += eloChange; await interaction.reply(`<@${member.id}>'s ELO has been changed by ${eloChange} points.`); } else { await interaction.reply('Please provide a valid member and ELO change.'); } } }); // Helper function to report match results to the log channel const reportMatch = async (match, winner) => { if (matchLogChannel) { let team1Players = []; let team2Players = []; if (match.teams) { team1Players = match.teams[0].map(id => `<@${id}>`); team2Players = match.teams[1].map(id => `<@${id}>`); } else if (match.captainPicks) { team1Players = match.captainPicks.picks.team1.map(id => `<@${id}>`); team2Players = match.captainPicks.picks.team2.map(id => `<@${id}>`); } const winningTeam = winner === 1 ? 'Team 1' : winner === 2 ? 'Team 2' : 'None'; const logMessage = `**Match ${matchNumber - 1}:**\n**${winningTeam} Wins!**\n**Team 1:** ${team1Players.join(', ')}\n**Team 2:** ${team2Players.join(', ')}`; await matchLogChannel.send(logMessage); } }; // Register Slash Commands async function registerSlashCommands(client) { const commands = [ new SlashCommandBuilder() .setName('setup-queue') .setDescription('Sets up the main queue'), new SlashCommandBuilder() .setName('clearqueue') .setDescription('Clears the active queue'), new SlashCommandBuilder() .setName('report') .setDescription('Reports the match result') .addIntegerOption(option => option.setName('result') .setDescription('Match result (0: Cancel, 1: Team 1, 2: Team 2)') .setRequired(true) ), new SlashCommandBuilder() .setName('flip') .setDescription('Flips the result of a match') .addIntegerOption(option => option.setName('match_number') .setDescription('The number of the match to flip') .setRequired(true) ), new SlashCommandBuilder() .setName('setlogchannel') .setDescription('Sets the channel for match logs') .addChannelOption(option => option.setName('channel') .setDescription('The channel to post logs to') .setRequired(true) ), new SlashCommandBuilder() .setName('resetelo') .setDescription('Resets ELO for all players'), new SlashCommandBuilder() .setName('giveelo') .setDescription('Gives ELO to a player') .addUserOption(option => option.setName('member') .setDescription('The player to give ELO to') .setRequired(true) ) .addIntegerOption(option => option.setName('elo_change') .setDescription('The amount of ELO to change') .setRequired(true) ) ]; const rest = new REST({ version: '10' }).setToken(process.env.DISCORD_TOKEN); try { console.log('Started refreshing application (/) commands.'); await rest.put(Routes.applicationCommands(client.application.id), { body: commands }); console.log('Successfully reloaded application (/) commands.'); } catch (error) { console.error(error); } } // Bot login client.login(process.env.DISCORD_TOKEN); deploy-commands.js JavaScript Copy Insert const { REST, Routes } = require('discord.js'); require('dotenv').config(); const commands = [ new SlashCommandBuilder() .setName('setup-queue') .setDescription('Sets up the main queue'), new SlashCommandBuilder() .setName('clearqueue') .setDescription('Clears the active queue'), new SlashCommandBuilder() .setName('report') .setDescription('Reports the match result') .addIntegerOption(option => option.setName('result') .setDescription('Match result (0: Cancel, 1: Team 1, 2: Team 2)') .setRequired(true) ), new SlashCommandBuilder() .setName('flip') .setDescription('Flips the result of a match') .addIntegerOption(option => option.setName('match_number') .setDescription('The number of the match to flip') .setRequired(true) ), new SlashCommandBuilder() .setName('setlogchannel') .setDescription('Sets the channel for match logs') .addChannelOption(option => option.setName('channel') .setDescription('The channel to post logs to') .setRequired(true) ), new SlashCommandBuilder() .setName('resetelo') .setDescription('Resets ELO for all players'), new SlashCommandBuilder() .setName('giveelo') .setDescription('Gives ELO to a player') .addUserOption(option => option.setName('member') .setDescription('The player to give ELO to') .setRequired(true) ) .addIntegerOption(option => option.setName('elo_change') .setDescription('The amount of ELO to change') .setRequired(true) ) ]; const rest = new REST({ version: '10' }).setToken(process.env.DISCORD_TOKEN); (async () => { try { console.log('Started refreshing application (/) commands.'); await rest.put(Routes.applicationCommands(client.application.id), { body: commands }); console.log('Successfully reloaded application (/) commands.'); } catch (error) { console.error(error); } })(); .env File: Copy Insert DISCORD_TOKEN=your_bot_token DISCORD_PREFIX=! Important Notes: deploy-commands.js : This file is used to register your slash commands globally. Make sure to run node deploy-commands.js after making changes to your slash commands in index.js to deploy the updated commands. Intents: Make sure you have the correct intents enabled in your Discord Developer Portal. Let me know if you have any other questions.
Comments