const warnCommand = async (message, args) => { const roles = [PermissionsBitField.Flags.Administrator, '1075756565023445022']; if (!message.member.permissions.has(PermissionsBitField.Flags.Administrator) && !message.member.roles.cache.has(roles[1])) { return message.reply('You do not have permission to use this command.'); } try { if (!args[0] || !args[0].match(/^<@!?(\d+)>$/)) { return message.reply('Please mention a valid user to warn.'); } const userId = args[0].replace('<@', '').replace('>', ''); const reason = args.slice(1).join(' ') || 'No reason provided'; if (!playerWarnings[userId]) { playerWarnings[userId] = { count: 0, reasons: [] }; } playerWarnings[userId].count += 1; playerWarnings[userId].reasons.push(reason); saveData(); const embed = new EmbedBuilder() .setColor('#ff4500') .setTitle('User Warned') .addFields( { name: 'User', value: `<@${userId}>`, inline: true }, { name: 'Warnings', value: playerWarnings[userId].count.toString(), inline: true }, { name: 'Reason', value: reason, inline: true } ) .setThumbnail('https://i.imgur.com/wTF3RuJ.png') .setFooter({ text: 'Stay in line, soldier!', iconURL: 'https://i.imgur.com/wTF3RuJ.png' }) .setTimestamp(); message.reply({ embeds: [embed] }); } catch (error) { console.error('Error warning user:', error); message.reply('There was an error warning the user.'); } }; const warnsCommand = async (message, args) => { const roles = [PermissionsBitField.Flags.Administrator, '1075756565023445022']; if (!message.member.permissions.has(PermissionsBitField.Flags.Administrator) && !message.member.roles.cache.has(roles[1])) { return message.reply('You do not have permission to use this command.'); } try { const userId = args[0] ? args[0].replace('<@', '').replace('>', '') : message.author.id; const userWarnings = playerWarnings[userId] ? playerWarnings[userId].count : 0; const reasons = playerWarnings[userId] ? playerWarnings[userId].reasons : []; const username = message.mentions.users.first() ? message.mentions.users.first().username : message.author.username; const embed = new EmbedBuilder() .setColor('#ff4500') .setTitle(`${username}'s Warnings`) .addFields( { name: 'Warnings', value: userWarnings.toString(), inline: true }, { name: 'Reasons', value: reasons.length > 0 ? reasons.join('\n') : 'No warnings', inline: true } ) .setThumbnail('https://i.imgur.com/wTF3RuJ.png') .setFooter({ text: 'Stay in line, soldier!', iconURL: 'https://i.imgur.com/wTF3RuJ.png' }) .setTimestamp(); message.reply({ embeds: [embed] }); } catch (error) { console.error('Error fetching warnings:', error); message.reply('There was an error fetching the warnings.'); } }; const profileCommand = async (message, args) => { const userId = args[0] ? args[0].replace('<@', '').replace('>', '') : message.author.id; const user = await message.guild.members.fetch(userId); const username = user.nickname || user.user.username; const elo = playersELO[userId] || 0; const userKarma = karma[userId] || 0; const stats = playerStats[userId] || {}; const defaultMapStats = { wins: 0, losses: 0 }; const maps = { BW: stats.BW || defaultMapStats, PORT: stats.PORT || defaultMapStats, ANK: stats.ANK || defaultMapStats, COMP: stats.COMP || defaultMapStats, SB: stats.SB || defaultMapStats, MEX: stats.MEX || defaultMapStats, EE: stats.EE || defaultMapStats }; const totalWins = Object.values(maps).reduce((acc, map) => acc + map.wins, 0); const totalLosses = Object.values(maps).reduce((acc, map) => acc + map.losses, 0); const embed = new EmbedBuilder() .setTitle(`${username}'s Profile`) .setThumbnail(user.user.displayAvatarURL({ dynamic: true })) .addFields( { name: 'ELO', value: elo.toString(), inline: true }, { name: 'Karma', value: userKarma.toString(), inline: true }, { name: '\u200B', value: '\u200B', inline: true } ) .addFields( { name: 'Map Stats:', value: '\u200B' }, { name: 'Black Widow', value: `${maps.BW.wins} wins ${maps.BW.losses} losses`, inline: true }, { name: 'Port', value: `${maps.PORT.wins} wins ${maps.PORT.losses} losses`, inline: true }, { name: 'Ankara', value: `${maps.ANK.wins} wins ${maps.ANK.losses} losses`, inline: true }, { name: 'Compound', value: `${maps.COMP.wins} wins ${maps.COMP.losses} losses`, inline: true }, { name: 'Sub Base', value: `${maps.SB.wins} wins ${maps.SB.losses} losses`, inline: true }, { name: 'Mexico', value: `${maps.MEX.wins} wins ${maps.MEX.losses} losses`, inline: true }, { name: 'Eagle Eye', value: `${maps.EE.wins} wins ${maps.EE.losses} losses`, inline: true }, { name: 'Total Wins', value: totalWins.toString(), inline: true }, { name: 'Total Losses', value: totalLosses.toString(), inline: true } ) .setColor('#ff4500') .setFooter({ text: 'FPS Game Stats', iconURL: 'https://i.imgur.com/wTF3RuJ.png' }) .setTimestamp(); message.reply({ embeds: [embed] }); }; const leaderboardCommand = async (message) => { try { const sortedPlayers = Object.entries(playersELO).sort((a, b) => b[1] - a[1]).slice(0, 25); const leaderboard = await Promise.all( sortedPlayers.map(async ([userId, elo], index) => { const user = await message.guild.members.fetch(userId).catch(() => null); return `#${index + 1} | ${elo} | ${user ? `<@${user.id}>` : `Unknown User`}`; }) ); if (leaderboard.length === 0) { leaderboard.push('No players available'); } const embed = new EmbedBuilder() .setColor('#00ff26') .setTitle('Top 25 Pug Players') .addFields({ name: 'Rank | Elo | Player', value: leaderboard.join('\n') }) .setFooter({ text: 'Use .lb or .leaderboard to see the leaderboard at any time', iconURL: 'https://i.imgur.com/wTF3RuJ.png' }) .setTimestamp(); message.reply({ embeds: [embed] }); } catch (error) { console.error('Error fetching leaderboard:', error); message.reply('There was an error fetching the leaderboard.'); } }; const eloCommand = async (message, args) => { try { const userId = args[0] ? args[0].replace('<@', '').replace('>', '') : message.author.id; const elo = playersELO[userId] || 0; message.reply(`<@${userId}> has ${elo} ELO.`); } catch (error) { console.error('Error fetching ELO:', error); message.reply('There was an error fetching the ELO.'); } }; const pickCommand = async (message, args) => { try { if (!args[0] || !args[0].match(/^<@!?(\d+)>$/)) { return message.reply('Please mention a valid user to pick.'); } const playerId = args[0].replace('<@', '').replace('>', ''); const userId = message.author.id; const matchId = findUserMatch(userId); if (!matchId) { return message.reply('You are not part of any active matches.'); } const match = matches[matchId]; const currentPickIndex = match.team1.length + match.team2.length - 2; if (currentPickIndex >= match.pickingOrder.length) { return message.reply('All picks have already been made.'); } const pickingTeam = match.pickingOrder[currentPickIndex] === 'team1' ? 'team1' : 'team2'; if (!match.remaining.includes(playerId)) { return message.reply('Invalid player ID for picking.'); } match[pickingTeam].push(playerId); match.remaining = match.remaining.filter(id => id !== playerId); await updateMatchMessage(matchId); message.reply(`Player <@${playerId}> picked for ${pickingTeam === 'team1' ? 'Team 1' : 'Team 2'}.`); } catch (error) { console.error('Error picking player:', error); message.reply('There was an error picking the player.'); } }; const needSubCommand = async (message, args) => { const roles = ['1255072045574652035', '1075756565023445022', '1258877265870192673']; if (!message.member.permissions.has(PermissionsBitField.Flags.Administrator) && !roles.some(role => message.member.roles.cache.has(role))) { return message.reply('You do not have permission to use this command.'); } try { if (!args[0] || !args[0].match(/^<@!?(\d+)>$/)) { return message.reply('Please mention a valid user to sub.'); } const userId = message.author.id; const playerId = args[0].replace('<@', '').replace('>', ''); const matchId = findUserMatch(userId); if (!matchId) { return message.reply('You are not part of any active matches.'); } const match = matches[matchId]; const team = match.team1.includes(playerId) ? 'team1' : 'team2'; const playerIndex = match[team].indexOf(playerId); if (playerIndex === -1) { return message.reply('Player not found in any team.'); } const subMessage = await message.channel.send(`<@${playerId}> has requested a substitution. React with ❌ within 2 minutes if you are still here.`); await subMessage.react('❌'); const filter = (reaction, user) => reaction.emoji.name === '❌' && user.id === playerId; const collector = subMessage.createReactionCollector({ filter, time: 120000 }); collector.on('collect', () => { subMessage.edit(`<@${playerId}> is still active.`); collector.stop(); }); collector.on('end', async collected => { if (collected.size === 0) { const newPlayerId = queue.shift(); if (!newPlayerId) { return message.channel.send('No available substitutes in the queue.'); } match[team][playerIndex] = newPlayerId; await updateMatchMessage(matchId); message.channel.send(`<@${playerId}> has been substituted by <@${newPlayerId}> in ${team === 'team1' ? 'Team 1' : 'Team 2'}.`); } }); } catch (error) { console.error('Error handling substitution:', error); message.reply('There was an error handling the substitution.'); } }; const replaceCommand = async (message, args) => { const roleIds = ['1075756565023445022', '1258877265870192673']; // Array of role IDs const hasAdminPermission = message.member.permissions.has(PermissionsBitField.Flags.Administrator); const hasRequiredRole = roleIds.some(roleId => message.member.roles.cache.has(roleId)); const hasPermission = hasAdminPermission || hasRequiredRole; // Check for permissions let matchId = Object.keys(matches).find(id => matches[id].textChannelId === message.channel.id); if (!matchId && hasPermission) { matchId = args[2]; } if (!matchId || !matches[matchId]) { return message.reply('Invalid match ID or no active match found.'); } if (!hasPermission) { // Check if user has the necessary permissions return message.reply('You do not have permission to replace players.'); } try { if (args.length < 2 || !args[0].match(/^<@!?(\d+)>$/) || !args[1].match(/^<@!?(\d+)>$/)) { return message.reply('Please mention the old player and the new player in the correct format.'); } const oldPlayerId = args[0].replace('<@', '').replace('>', '').replace('!', ''); const newPlayerId = args[1].replace('<@', '').replace('>', '').replace('!', ''); const match = matches[matchId]; const team = match.team1.includes(oldPlayerId) ? 'team1' : match.team2.includes(oldPlayerId) ? 'team2' : null; if (!team) { return message.reply('Old player is not found in any team.'); } const playerIndex = match[team].indexOf(oldPlayerId); if (playerIndex === -1) { return message.reply('Old player not found in the team.'); } match[team][playerIndex] = newPlayerId; await updateMatchMessage(matchId); message.reply(`Player <@${oldPlayerId}> has been replaced by <@${newPlayerId}> in ${team === 'team1' ? 'Team 1' : 'Team 2'}.`); } catch (error) { console.error('Error replacing player:', error); message.reply('There was an error replacing the player.'); } }; const ptCommand = async (message, args) => { const roles = [PermissionsBitField.Flags.Administrator, '1075756565023445022', '1258877265870192673']; if (!message.member.permissions.has(PermissionsBitField.Flags.Administrator) && !message.member.roles.cache.has(roles[1]) && !message.member.roles.cache.has(roles[2])) { return message.reply('You do not have permission to use this command.'); } try { if (args.length < 1) { return message.reply('Please specify the team number (1, 2, or 0) and an optional message.'); } const userId = message.author.id; const teamNumber = parseInt(args[0]); if (isNaN(teamNumber) || (teamNumber < 0 || teamNumber > 2)) { return message.reply('Invalid team number. Use 1 for Team 1, 2 for Team 2, or 0 for both teams.'); } const additionalMessage = args.slice(1).join(' '); let matchId = Object.keys(matches).find(id => matches[id].textChannelId === message.channel.id); if (!matchId) { return message.reply('You are not part of any active matches.'); } const match = matches[matchId]; let teamMentions = ''; if (teamNumber === 0) { const allTeams = [...match.team1, ...match.team2]; teamMentions = allTeams.map(id => `<@${id}>`).join(' '); } else if (teamNumber === 1) { teamMentions = match.team1.map(id => `<@${id}>`).join(' '); } else if (teamNumber === 2) { teamMentions = match.team2.map(id => `<@${id}>`).join(' '); } const finalMessage = `${teamMentions} ${additionalMessage}`; try { const matchCategory = await message.client.channels.fetch(process.env.MATCH_CATEGORY_ID); const matchText = matchCategory.children.cache.find(c => c.name === `match-${matchId}`); if (!matchText) { return message.reply('Match text channel not found.'); } await matchText.send(finalMessage); message.reply('Message sent.'); } catch (error) { console.error('Error sending message:', error); message.reply('There was an error sending the message. Please try again later.'); } } catch (error) { console.error('Error in PT command:', error); message.reply('There was an error executing the PT command.'); } }; const cancelMatchCommand = async (message, args) => { const roleIds = ['1075756565023445022', '1258877265870192673']; // Array of role IDs const hasAdminPermission = message.member.permissions.has(PermissionsBitField.Flags.Administrator); const hasRequiredRole = roleIds.some(roleId => message.member.roles.cache.has(roleId)); const hasPermission = hasAdminPermission || hasRequiredRole; // Check for permissions let matchId = Object.keys(matches).find(id => matches[id].textChannelId === message.channel.id); if (!matchId && hasPermission) { matchId = args[0]; } if (!matchId || !matches[matchId]) { try { await message.reply('Invalid match ID or no active match found.'); } catch (error) { console.error('Error sending reply:', error); } return; } if (!hasPermission) { // Check if user has the necessary permissions try { await message.reply('You do not have permission to cancel matches.'); } catch (error) { console.error('Error sending reply:', error); } return; } try { const match = matches[matchId]; delete matches[matchId]; saveMatchData(); const guild = message.guild; const matchCategory = await guild.channels.fetch(process.env.MATCH_CATEGORY_ID); // Fetch channels from cache or fetch from API if not cached const team1Voice = guild.channels.cache.get(match.team1VoiceChannelId) || await guild.channels.fetch(match.team1VoiceChannelId); const team2Voice = guild.channels.cache.get(match.team2VoiceChannelId) || await guild.channels.fetch(match.team2VoiceChannelId); const matchText = guild.channels.cache.get(match.textChannelId) || await guild.channels.fetch(match.textChannelId); if (team1Voice) await team1Voice.delete(); if (team2Voice) await team2Voice.delete(); if (matchText) await matchText.delete(); await message.reply(`Match ${matchId} has been canceled.`); } catch (error) { console.error('Error canceling match:', error); try { await message.reply('There was an error canceling the match.'); } catch (replyError) { console.error('Error sending error reply:', replyError); } } }; const suspendUserCommand = async (message, args) => { try { const userId = args[0].replace('<@', '').replace('>', ''); const duration = parseInt(args[1]); const reason = args.slice(2).join(' '); if (!karma[userId]) karma[userId] = {}; karma[userId].suspendedUntil = Date.now() + duration * 60000; karma[userId].reason = reason; saveData(); message.reply(`<@${userId}> has been suspended for ${duration} minutes. Reason: ${reason}`); } catch (error) { console.error('Error suspending user:', error); message.reply('There was an error suspending the user.'); } }; const unSuspendUserCommand = async (message, args) => { const roles = [PermissionsBitField.Flags.Administrator, '1075756565023445022']; if (!message.member.permissions.has(PermissionsBitField.Flags.Administrator) && !message.member.roles.cache.has(roles[1])) { return message.reply('You do not have permission to use this command.'); } try { const userId = args[0].replace('<@', '').replace('>', ''); if (karma[userId] && karma[userId].suspendedUntil) { delete karma[userId].suspendedUntil; delete karma[userId].reason; saveData(); message.reply(`<@${userId}>'s suspension has been lifted.`); } else { message.reply(`<@${userId}> is not currently suspended.`); } } catch (error) { console.error('Error unsuspending user:', error); message.reply('There was an error lifting the suspension.'); } }; const saveData = () => { const data = { playersELO, playerWarnings, karma, playerStats }; fs.writeFileSync(dataFilePath, JSON.stringify(data, null, 2), 'utf-8'); }; const logMatch = (matchId, winningTeam, losingTeam, result, reporter) => { const logChannel = client.channels.cache.get(process.env.MATCH_LOG_CHANNEL_ID); if (!logChannel) { console.error('Match log channel not found'); return; } const embed = new EmbedBuilder() .setTitle(`Match #${matchId} Log`) .setColor('#ff4500') // Orange-red color suitable for a competitive FPS theme .addFields( { name: 'Winners | Team 1', value: winningTeam.map(id => `<@${id}>`).join(' '), inline: true }, { name: 'Losers | Team 2', value: losingTeam.map(id => `<@${id}>`).join(' '), inline: true }, { name: 'Reported by', value: `${reporter.username}#${reporter.discriminator} (${reporter.id})` } ) .setFooter({ text: 'Powered by Maverick', iconURL: 'https://i.imgur.com/wTF3RuJ.png' }) .setTimestamp(); logChannel.send({ embeds: [embed] }); }; const updateElo = (winningTeam, losingTeam) => { winningTeam.forEach(player => { if (!playersELO[player]) playersELO[player] = 50; playersELO[player] += 6; }); losingTeam.forEach(player => { if (!playersELO[player]) playersELO[player] = 50; playersELO[player] -= 5; }); saveData(); }; const registerCommands = () => { const commands = [ { name: 'setupreaction', description: 'Recreates the reaction message to join the queue', type: 1, }, { name: 'eloreset', description: 'Resets all ELO, must be superuser', type: 1, }, { name: 'warningreset', description: 'Resets all warnings, must be admin', type: 1, }, { name: 'leaderboard', description: 'Leaderboard in the stats channel', type: 1, } ]; const guild = client.guilds.cache.first(); guild.commands.set(commands).then(() => console.log('Commands registered')); }; client.login(process.env.DISCORD_TOKEN);
Preview:
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