I am trying to program blackjack for my discord bot. The following code sends three embeds, one that is the players hand, one that is the dealers hand, and another that asks if the player would like to hit or stand. My first issue is that it sends three hit or stand embeds then continues to send them. I only need one embed sent and for it not to repeat. Second when I hit the buttons, either hit or stand, I get an error code. I execute the command using the interactions method.
It appears my collector/filter is not able to properly read the id of the user, and I cannot figure out why!
Here is my Code:
const Discord = require('discord.js');
const { EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle } = Discord
const createDeck = require('../functions/deck')
const shuffleDeck = require('../functions/shuffleDeck')
const getHandValue = require('../functions/getHandValue')
async function playBlackjack(message) {
const deck = createDeck();
const shuffledDeck = shuffleDeck(deck);
const playerHand = [shuffledDeck.pop(), shuffledDeck.pop()];
const dealerHand = [shuffledDeck.pop(), shuffledDeck.pop()];
const playerEmbed = new EmbedBuilder()
.setTitle('Blackjack')
.setDescription(`Your hand: ${playerHand.join(', ')}`)
.setColor('#FFA500')
.setTimestamp();
const dealerEmbed = new EmbedBuilder()
.setTitle('Blackjack')
.setDescription(`Dealer hand: ${dealerHand[0]}, *hidden*`)
.setColor('#FFA500')
.setTimestamp();
const playerMsg = await message.channel.send({ embeds: [playerEmbed] });
const dealerMsg = await message.channel.send({ embeds: [dealerEmbed] });
let playerScore = getHandValue(playerHand);
let dealerScore = getHandValue(dealerHand.slice(0, 1));
const hitButton = new ButtonBuilder()
.setCustomId('hit')
.setLabel('Hit')
.setStyle(ButtonStyle.Primary);
const standButton = new ButtonBuilder()
.setCustomId('stand')
.setLabel('Stand')
.setStyle(ButtonStyle.Primary);
const buttonRow = new ActionRowBuilder()
.addComponents(hitButton, standButton);
let ongoing = true;
while (ongoing) {
const hitOrStandEmbed = new EmbedBuilder()
.setTitle('Blackjack')
.setDescription('Do you want to hit or stand?')
.setColor('#FFA500')
.setTimestamp();
const hitOrStandMsg = await message.channel.send({ embeds: [hitOrStandEmbed], components: [buttonRow] });
const filter = i => i.user.id === message.author.id;
const collector = hitOrStandMsg.createMessageComponentCollector({ filter, time: 60000 });
collector.on('collect', async i => {
if (i.customId === 'hit') {
const newCard = shuffledDeck.pop();
playerHand.push(newCard);
playerScore = getHandValue(playerHand);
playerEmbed.setDescription(`Your hand: ${playerHand.join(', ')}`);
if (playerScore > 21) {
playerEmbed.setDescription(`Your hand: ${playerHand.join(', ')}\nBust! Dealer wins.`);
playerEmbed.setColor('#FF0000');
await playerMsg.edit({ embeds: [playerEmbed] });
await hitOrStandMsg.delete();
ongoing = false;
collector.stop();
} else {
playerEmbed.setDescription(`Your hand: ${playerHand.join(', ')}`);
await playerMsg.edit({ embeds: [playerEmbed] });
await hitOrStandMsg.delete();
}
} else if (i.customId === 'stand') {
while (dealerScore < 17) {
const newCard = shuffledDeck.pop();
dealerHand.push(newCard);
dealerScore = getHandValue(dealerHand);
dealerEmbed.setDescription(`Dealer hand: ${dealerHand.join(', ')}`);
await dealerMsg.edit({ embeds: [dealerEmbed] });
}
dealerEmbed.setDescription(`Dealer hand: ${dealerHand.join(', ')}\nDealer score: ${dealerScore}`);
await dealerMsg.edit({ embeds: [dealerEmbed]
});
if (dealerScore > 21) {
playerEmbed.setDescription(`Your hand: ${playerHand.join(', ')}\n Dealer hand: ${dealerHand.join(', ')}\nDealer score: ${dealerScore}\nDealer busts! You win!`);
playerEmbed.setColor('#00FF00');
await playerMsg.edit({ embeds: [playerEmbed] });
} else if (playerScore > dealerScore) { playerEmbed.setDescription(`Your hand: ${playerHand.join(', ')}\nDealer hand: ${dealerHand.join(', ')}\nDealer score: ${dealerScore}\nYou win!`);
playerEmbed.setColor('#00FF00');
await playerMsg.edit({ embeds: [playerEmbed] });
} else if (dealerScore > playerScore) { playerEmbed.setDescription(`Your hand: ${playerHand.join(', ')}\nDealer hand: ${dealerHand.join(', ')}\nDealer score: ${dealerScore}\nDealer wins!`);
playerEmbed.setColor('#FF0000'); await playerMsg.edit({ embeds: [playerEmbed] });
} else { playerEmbed.setDescription(`Your hand: ${playerHand.join(', ')}\nDealer hand: ${dealerHand.join(', ')}\nDealer score: ${dealerScore}\nIt's a tie!`);
playerEmbed.setColor('#FFFF00');
await playerMsg.edit({ embeds: [playerEmbed] });
}
await hitOrStandMsg.delete();
collector.stop();
}
});
collector.on('end', async collected => {
if (collected.size === 0) {
await hitOrStandMsg.delete();
playerEmbed.setDescription(`Your hand: ${playerHand.join(', ')}\nYou took too long to make a decision. Game over.`);
playerEmbed.setColor('#FF0000');
await playerMsg.edit({ embeds: [playerEmbed] });
}
});
if (playerScore > 21 || dealerScore > 21) {
break;
}
}
}
module.exports = {
playBlackjack,
};
and the execute file:
const { SlashCommandBuilder, MessageCollector, Message, MessageContextMenuCommandInteraction } = require('discord.js');
const { playBlackjack } = require('../functions/playBlackjack');
module.exports = {
data: new SlashCommandBuilder()
.setName('blackjack')
.setDescription('Play a Game of Blackjack'),
async execute(interaction) {
playBlackjack(interaction);
}
}
Any help or tips would be appreciated!!
I got this error when executing my code:
node:events:491 throw er; // Unhandled 'error' event ^
TypeError: Cannot read properties of undefined (reading 'id') at InteractionCollector.filter (C:\Users\Sauce\Desktop\FrontierEconomyBot\functions\playBlackjack.js:55:42) at InteractionCollector.handleCollect (C:\Users\Sauce\Desktop\FrontierEconomyBot\node_modules\discord.js\src\structures\interfaces\Collector.js:110:39) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) Emitted 'error' event on Client instance at: at emitUnhandledRejectionOrErr (node:events:394:10) at process.processTicksAndRejections (node:internal/process/task_queues:84:21)
Explanation
On line 55, the filter declaration, this is where the error pops out.
In your code, you are passing
interactionto theplayBlackjackfunction and you store it asmessage. There is no option ofauthorin interaction in discord.js. You would have to replace it withuserif you want to filter for the interaction author.Solution
Simply change the code to the following on line 55
References
Discord.js Documentation (Interaction Properties)