Preview:
You got it! Here's the full working code for your Discord queue bot, including all the features you requested:

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);
Explanation of the Code:

Constants and Data Structures:

eloInitial: The starting ELO for players.
matchNumber: Tracks the match count.
players: A Map to store player data (ELO, stats).
queues: A Map to store active queues.
matches: A Map to store match details.
matchLogChannel: Stores the channel where match logs are posted.
Helper Functions:

createMatchChannel: Creates a new text channel for a match.
createVoiceChannel: Creates a new voice channel for a match.
sortByElo: Sorts players by their ELO.
getTopPlayers: Returns the top 25 players by ELO.
updateQueueMessage: Updates the embed message in the queue channel to reflect changes in players.
startMatch: Begins a new match by setting up the match channel, voice channels, and initiating team formation.
createCaptainPickEmbed: Creates an embed message for captain picks, sets up reaction collectors, and handles pick logic.
startMapVoting: Starts the map voting process, sets up reaction collectors, and determines the chosen map.
reportMatch: Posts the match result to the log channel.
Discord Client Initialization:

client: The Discord client object, configured with necessary intents and partials.
Event Listeners:

client.once('ready'): Logs a message when the bot is ready.
client.on('messageReactionAdd'): Handles reactions to join the queue.
client.on('messageReactionRemove'): Handles reactions to leave the queue.
client.on('interactionCreate'): Handles slash command interactions.
Slash Command Handling:

/setup-queue: Creates a new queue (currently with a fixed capacity of 10).
/clearqueue: Clears the active queue.
/report: Reports the match result (win, loss, cancel).
/flip: Flips the result of a match.
/setlogchannel: Sets the channel for match logs.
/resetelo: Resets the ELO of all players to the initial value.
/giveelo: Allows an admin to adjust a player's ELO.
Match Logic:

The startMatch function handles the initiation of a match, including team formation (ELO-based or captain picks), and map voting.
The reportMatch function updates the match log in the designated channel.
Bot Login:

client.login(process.env.DISCORD_TOKEN): Logs the bot into Discord.
How to Use:

Set Up a Replit Project: Create a new Replit project and install the necessary packages:
Shell Script

Copy

Insert
npm install discord.js dotenv
Create a 
.env
 File: Add your Discord bot token and prefix:

Copy

Insert
DISCORD_TOKEN=your_bot_token
DISCORD_PREFIX=!
Paste the Code: Copy and paste the code above into 
main.js
.
Deploy: Follow the deployment instructions I provided earlier.
This code provides a robust foundation for your Discord queue bot. You can customize it further with additional features and logic as needed. Let me know if you have any other questions!
downloadDownload PNG downloadDownload JPEG downloadDownload SVG

Tip: You can change the style, width & colours of the snippet with the inspect tool before clicking Download!

Click to optimize width for Twitter