discord-container-builder
Version:
A simplified, developer-friendly API for Discord.js v2 Components that reduces boilerplate and improves code readability.
379 lines (339 loc) • 15.3 kB
JavaScript
const { Client, GatewayIntentBits } = require('discord.js');
const {
ContainerBuilder,
SeparatorSpacingSize,
MessageFlags,
EMOJIS
} = require('discord-container-builder');
const client = new Client({
intents: [GatewayIntentBits.Guilds]
});
// Mock game lobby data
const gameLobbies = new Map();
client.on('ready', () => {
console.log(`${client.user.tag} Game Lobby System is ready!`);
});
// Example: Game Lobby Management System
client.on('interactionCreate', async (interaction) => {
if (!interaction.isChatInputCommand()) return;
if (interaction.commandName === 'lobby') {
const action = interaction.options.getString('action') || 'list';
if (action === 'create') {
const lobbyId = `lobby_${Date.now()}`;
const gameName = interaction.options.getString('game') || 'Valorant';
const maxPlayers = interaction.options.getInteger('max_players') || 5;
gameLobbies.set(lobbyId, {
id: lobbyId,
game: gameName,
host: interaction.user,
players: [interaction.user],
maxPlayers: maxPlayers,
status: 'waiting',
createdAt: new Date()
});
const container = new ContainerBuilder()
.addText(`${EMOJIS.GAME_DIE} **New Game Lobby Created!**`)
.addText(`**Game:** ${gameName}`)
.addText(`**Host:** ${interaction.user.displayName || interaction.user.username}`)
.addText(`**Players:** 1/${maxPlayers}`)
.addSeparator({ spacing: SeparatorSpacingSize.Small, divider: true })
.addText(`${EMOJIS.ID} **Lobby ID:** ${lobbyId}`)
.addText(`${EMOJIS.CLOCK} **Created:** <t:${Math.floor(Date.now() / 1000)}:R>`)
.addSeparator({ spacing: SeparatorSpacingSize.Medium })
.addActionRow((row) => {
row.addButton((btn) => btn.asPrimary(`join_${lobbyId}`, 'Join Lobby'))
.addButton((btn) => btn.asSecondary(`spectate_${lobbyId}`, 'Spectate'))
.addButton((btn) => btn.asDanger(`leave_${lobbyId}`, 'Leave'));
})
.addActionRow((row) => {
row.addSelectMenu((menu) => {
menu.setCustomId(`lobby_settings_${lobbyId}`)
.setPlaceholder('Lobby Settings...')
.addOptions([
{ label: 'Change Game', value: 'change_game', emoji: '🎮' },
{ label: 'Set Max Players', value: 'set_max_players', emoji: '👥' },
{ label: 'Invite Friends', value: 'invite_friends', emoji: '📨' },
{ label: 'Start Game', value: 'start_game', emoji: '🚀' }
]);
});
});
await interaction.reply({
components: [container.build()],
flags: MessageFlags.IsComponentsV2,
});
}
if (action === 'list') {
const container = new ContainerBuilder()
.addText(`${EMOJIS.LIST} **Active Game Lobbies**`)
.addText(`Found ${gameLobbies.size} active lobbies`)
.addSeparator({ spacing: SeparatorSpacingSize.Small, divider: true });
if (gameLobbies.size === 0) {
container
.addText(`${EMOJIS.INFO} No active lobbies found.`)
.addText('Create a new lobby to get started!')
.addActionRow((row) => {
row.addButton((btn) => btn.asPrimary('create_lobby', 'Create Lobby'))
.addButton((btn) => btn.asSecondary('refresh_lobbies', 'Refresh'));
});
} else {
// Display each lobby
Array.from(gameLobbies.values()).forEach((lobby, index) => {
const statusEmoji = lobby.status === 'waiting' ? '🟡' : lobby.status === 'playing' ? '🟢' : '🔴';
container
.addText(`${statusEmoji} **${lobby.game}** (${lobby.id})`)
.addText(`Host: ${lobby.host.displayName || lobby.host.username}`)
.addText(`Players: ${lobby.players.length}/${lobby.maxPlayers}`)
.addActionRow((row) => {
row.addButton((btn) => btn.asPrimary(`join_${lobby.id}`, 'Join'))
.addButton((btn) => btn.asSecondary(`view_${lobby.id}`, 'View Details'))
.addButton((btn) => btn.asSecondary(`spectate_${lobby.id}`, 'Spectate'));
});
if (index < gameLobbies.size - 1) {
container.addSeparator({ spacing: SeparatorSpacingSize.Small });
}
});
container
.addSeparator({ spacing: SeparatorSpacingSize.Medium, divider: true })
.addActionRow((row) => {
row.addButton((btn) => btn.asPrimary('create_new_lobby', 'Create New Lobby'))
.addButton((btn) => btn.asSecondary('refresh_lobbies', 'Refresh'))
.addButton((btn) => btn.asSecondary('filter_lobbies', 'Filter'));
});
}
await interaction.reply({
components: [container.build()],
flags: MessageFlags.IsComponentsV2,
});
}
}
// Tournament bracket system
if (interaction.commandName === 'tournament') {
const container = new ContainerBuilder()
.addText(`${EMOJIS.TROPHY} **Tournament Manager**`)
.addText("Create and manage competitive tournaments")
.addSeparator({ spacing: SeparatorSpacingSize.Medium, divider: true })
.addText(`${EMOJIS.CHART} **Current Tournaments:**`)
.addText('🏆 Summer Championship - 16 teams')
.addText('🥇 Weekly Ladder - 32 players')
.addText('🎮 Casual Cup - 8 teams')
.addSeparator({ spacing: SeparatorSpacingSize.Small, divider: true })
.addActionRow((row) => {
row.addSelectMenu((menu) => {
menu.setCustomId('tournament_action')
.setPlaceholder('Select tournament action...')
.addOptions([
{ label: 'Create Tournament', value: 'create_tournament', emoji: '🏆' },
{ label: 'Join Tournament', value: 'join_tournament', emoji: '👤' },
{ label: 'View Brackets', value: 'view_brackets', emoji: '📊' },
{ label: 'Tournament Rules', value: 'tournament_rules', emoji: '📋' }
]);
});
})
.addActionRow((row) => {
row.addButton((btn) => btn.asPrimary('quick_match', 'Quick Match'))
.addButton((btn) => btn.asSecondary('leaderboard', 'Leaderboard'))
.addButton((btn) => btn.asSecondary('match_history', 'Match History'));
});
await interaction.reply({
components: [container.build()],
flags: MessageFlags.IsComponentsV2,
});
}
});
// Handle lobby interactions
client.on('interactionCreate', async (interaction) => {
if (!interaction.isButton()) return;
// Join lobby functionality
if (interaction.customId.startsWith('join_')) {
const lobbyId = interaction.customId.replace('join_', '');
const lobby = gameLobbies.get(lobbyId);
if (!lobby) {
await interaction.reply({
content: 'This lobby no longer exists.',
ephemeral: true
});
return;
}
if (lobby.players.length >= lobby.maxPlayers) {
await interaction.reply({
content: 'This lobby is full!',
ephemeral: true
});
return;
}
if (lobby.players.some(p => p.id === interaction.user.id)) {
await interaction.reply({
content: 'You are already in this lobby!',
ephemeral: true
});
return;
}
lobby.players.push(interaction.user);
const container = new ContainerBuilder()
.addText(`${EMOJIS.SUCCESS} **Joined Lobby Successfully!**`)
.addText(`**Game:** ${lobby.game}`)
.addText(`**Host:** ${lobby.host.displayName || lobby.host.username}`)
.addText(`**Players:** ${lobby.players.length}/${lobby.maxPlayers}`)
.addSeparator({ spacing: SeparatorSpacingSize.Small, divider: true })
.addText(`${EMOJIS.USERS} **Current Players:**`)
.addText(lobby.players.map(p => `• ${p.displayName || p.username}`).join('\n'))
.addSeparator({ spacing: SeparatorSpacingSize.Medium });
if (lobby.players.length === lobby.maxPlayers) {
container
.addText(`${EMOJIS.PARTY} **Lobby is now full! Ready to start?**`)
.addActionRow((row) => {
row.addButton((btn) => btn.asSuccess(`start_game_${lobbyId}`, 'Start Game'))
.addButton((btn) => btn.asSecondary(`wait_more_${lobbyId}`, 'Wait for More'))
.addButton((btn) => btn.asDanger(`leave_${lobbyId}`, 'Leave Lobby'));
});
} else {
container.addActionRow((row) => {
row.addButton((btn) => btn.asPrimary(`invite_friends_${lobbyId}`, 'Invite Friends'))
.addButton((btn) => btn.asSecondary(`lobby_chat_${lobbyId}`, 'Lobby Chat'))
.addButton((btn) => btn.asDanger(`leave_${lobbyId}`, 'Leave Lobby'));
});
}
await interaction.update({
components: [container.build()],
flags: MessageFlags.IsComponentsV2,
});
}
// Start game functionality
if (interaction.customId.startsWith('start_game_')) {
const lobbyId = interaction.customId.replace('start_game_', '');
const lobby = gameLobbies.get(lobbyId);
if (lobby && lobby.host.id === interaction.user.id) {
lobby.status = 'playing';
const container = new ContainerBuilder()
.addText(`${EMOJIS.ROCKET} **Game Started!**`)
.addText(`**${lobby.game}** is now in progress`)
.addSeparator({ spacing: SeparatorSpacingSize.Small, divider: true })
.addText(`${EMOJIS.USERS} **Players:**`)
.addText(lobby.players.map(p => `🎮 ${p.displayName || p.username}`).join('\n'))
.addSeparator({ spacing: SeparatorSpacingSize.Medium })
.addText(`${EMOJIS.INFO} **Game Information:**`)
.addText(`Started: <t:${Math.floor(Date.now() / 1000)}:R>`)
.addText(`Duration: Estimated 30-45 minutes`)
.addActionRow((row) => {
row.addButton((btn) => btn.asSecondary('game_stats', 'Live Stats'))
.addButton((btn) => btn.asSecondary('spectate_mode', 'Spectate'))
.addButton((btn) => btn.asDanger('end_game', 'End Game'));
});
await interaction.update({
components: [container.build()],
flags: MessageFlags.IsComponentsV2,
});
} else {
await interaction.reply({
content: 'Only the lobby host can start the game.',
ephemeral: true
});
}
}
// Quick match system
if (interaction.customId === 'quick_match') {
const container = new ContainerBuilder()
.addText(`${EMOJIS.HOURGLASS} **Finding Match...**`)
.addText('Searching for players with similar skill level')
.addSeparator({ spacing: SeparatorSpacingSize.Small, divider: true })
.addText(`${EMOJIS.CHART} **Your Stats:**`)
.addText('Rank: Gold III')
.addText('Win Rate: 67%')
.addText('Recent Performance: 🔥 Win Streak (3)')
.addSeparator({ spacing: SeparatorSpacingSize.Medium })
.addActionRow((row) => {
row.addButton((btn) => btn.asDanger('cancel_search', 'Cancel Search'))
.addButton((btn) => btn.asSecondary('search_settings', 'Search Settings'));
});
await interaction.update({
components: [container.build()],
flags: MessageFlags.IsComponentsV2,
});
// Simulate finding a match
setTimeout(async () => {
try {
const matchFoundContainer = new ContainerBuilder()
.addText(`${EMOJIS.SUCCESS} **Match Found!**`)
.addText('Found 4 other players')
.addSeparator({ spacing: SeparatorSpacingSize.Small, divider: true })
.addText(`${EMOJIS.USERS} **Team Assignment:**`)
.addText('🔵 **Blue Team:**')
.addText(`• ${interaction.user.displayName || interaction.user.username} (You)`)
.addText('• PlayerTwo (Gold II)')
.addText('• PlayerThree (Gold I)')
.addText('')
.addText('🔴 **Red Team:**')
.addText('• PlayerFour (Gold III)')
.addText('• PlayerFive (Gold II)')
.addSeparator({ spacing: SeparatorSpacingSize.Medium })
.addActionRow((row) => {
row.addButton((btn) => btn.asSuccess('accept_match', 'Accept Match (30s)'))
.addButton((btn) => btn.asDanger('decline_match', 'Decline'));
});
await interaction.editReply({
components: [matchFoundContainer.build()],
flags: MessageFlags.IsComponentsV2,
});
} catch (error) {
console.log('Match update failed - user may have navigated away');
}
}, 3000);
}
});
// Handle select menu interactions
client.on('interactionCreate', async (interaction) => {
if (!interaction.isStringSelectMenu()) return;
if (interaction.customId === 'tournament_action') {
const action = interaction.values[0];
if (action === 'view_brackets') {
const container = new ContainerBuilder()
.addText(`${EMOJIS.CHART} **Tournament Brackets**`)
.addText('Summer Championship - Round of 16')
.addSeparator({ spacing: SeparatorSpacingSize.Small, divider: true })
.addText('🥇 **Quarter Finals:**')
.addText('Team Alpha vs Team Beta')
.addText('Team Gamma vs Team Delta')
.addText('Team Epsilon vs Team Zeta')
.addText('Team Eta vs Team Theta')
.addSeparator({ spacing: SeparatorSpacingSize.Small })
.addText('📅 **Next Matches:** Tomorrow 8:00 PM UTC')
.addActionRow((row) => {
row.addButton((btn) => btn.asPrimary('view_full_bracket', 'View Full Bracket'))
.addButton((btn) => btn.asSecondary('predict_winners', 'Make Predictions'))
.addButton((btn) => btn.asSecondary('tournament_schedule', 'Schedule'));
});
await interaction.update({
components: [container.build()],
flags: MessageFlags.IsComponentsV2,
});
}
if (action === 'create_tournament') {
const container = new ContainerBuilder()
.addText(`${EMOJIS.HAMMER} **Create New Tournament**`)
.addText('Set up a competitive tournament for your community')
.addSeparator({ spacing: SeparatorSpacingSize.Medium, divider: true })
.addActionRow((row) => {
row.addSelectMenu((menu) => {
menu.setCustomId('tournament_type')
.setPlaceholder('Select tournament type...')
.addOptions([
{ label: 'Single Elimination', value: 'single_elim', emoji: '🏆' },
{ label: 'Double Elimination', value: 'double_elim', emoji: '🥇' },
{ label: 'Round Robin', value: 'round_robin', emoji: '🔄' },
{ label: 'Swiss System', value: 'swiss', emoji: '🇨🇭' }
]);
});
})
.addActionRow((row) => {
row.addButton((btn) => btn.asPrimary('tournament_settings', 'Tournament Settings'))
.addButton((btn) => btn.asSecondary('tournament_rules', 'Set Rules'))
.addButton((btn) => btn.asSecondary('preview_tournament', 'Preview'));
});
await interaction.update({
components: [container.build()],
flags: MessageFlags.IsComponentsV2,
});
}
}
});
client.login(process.env.DISCORD_TOKEN);