Can you assist with my Discord blackjack Code

523 views Asked by At

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)

1

There are 1 answers

1
Bobosky On

Explanation

On line 55, the filter declaration, this is where the error pops out.

In your code, you are passing interaction to the playBlackjack function and you store it as message. There is no option of author in interaction in discord.js. You would have to replace it with user if you want to filter for the interaction author.

Solution

Simply change the code to the following on line 55

const filter = i => i.user.id === message.user.id;

References

Discord.js Documentation (Interaction Properties)