Home > Software engineering >  Cannot read properties of undefined error in discord.js node js
Cannot read properties of undefined error in discord.js node js

Time:10-27

const { SlashCommandBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder } = require('discord.js');
const fetch = require('node-fetch');

module.exports = {
    data: new SlashCommandBuilder()
        .setName('quiz')
        .setDescription('Starts a Quiz!')
        .addStringOption(option =>
            option.setName('category')
                .setDescription('Category of questions.')
                .setRequired(true)
                .addChoices(
                    { name: 'History', value: '23' },
                    { name: 'Arts', value: '25' },
                    { name: 'Comics', value: '29' },
                    { name: 'Computer', value: '18' },
                    { name: 'Animals', value: '27' },
                    { name: 'Films', value: '11' },
                ))
        .addStringOption(option =>
            option.setName('difficulty')
                .setDescription('The difficulty of questions.')
                .setRequired(true)
                .addChoices(
                    { name: 'Easy', value: 'easy' },
                    { name: 'Medium', value: 'medium' },
                    { name: 'Hard', value: 'hard' },
                ))
        .addStringOption(option =>
            option.setName('type')
                .setDescription('Type of questions.')
                .setRequired(true)
                .addChoices(
                    { name: 'Multiple Choice', value: 'multiple' },
                    { name: 'True / False', value: 'boolean' },
                )),

    async execute(interaction) {
        const category = interaction.options.getString('category');
        const difficulty = interaction.options.getString('difficulty');
        const type = interaction.options.getString('type');

        const response = await fetch(`https://opentdb.com/api.php?amount=12&category=${category}&difficulty=${difficulty}&type=${type}`);
        const data = await response.json()
        
        var length = data.results.length;
        var random = Math.floor(Math.random() * length);

        let randomQuestion = data.results[random];

        console.log(randomQuestion);

        let question = randomQuestion.question;
        const correctAnswer = randomQuestion.correct_answer;

        const questionEmbed = new EmbedBuilder()
            .setDescription(question)

        const multipleAnswersRow = new ActionRowBuilder()
            .addComponents(
                new ButtonBuilder()
                    .setCustomId('first')
                    .setLabel('Click me!')
                    .setStyle(ButtonStyle.Primary),
                new ButtonBuilder()
                    .setCustomId('second')
                    .setLabel('Click me!')
                    .setStyle(ButtonStyle.Primary),
                new ButtonBuilder()
                    .setCustomId('third')
                    .setLabel('Click me!')
                    .setStyle(ButtonStyle.Primary),
                new ButtonBuilder()
                    .setCustomId('fourth')
                    .setLabel('Click me!')
                    .setStyle(ButtonStyle.Primary),
                new ButtonBuilder()
                    .setCustomId('last')
                    .setLabel('Stop')
                    .setStyle(ButtonStyle.Danger),
            );
        const booleanAnswersRow = new ActionRowBuilder()
            .addComponents(
                new ButtonBuilder()
                    .setCustomId('first')
                    .setLabel('Click me!')
                    .setStyle(ButtonStyle.Primary),
                new ButtonBuilder()
                    .setCustomId('second')
                    .setLabel('Click me!')
                    .setStyle(ButtonStyle.Primary),
                new ButtonBuilder()
                    .setCustomId('third')
                    .setLabel('Click me!')
                    .setStyle(ButtonStyle.Danger)
            );

        if(type == 'multiple'){
            interaction.reply({embeds: [questionEmbed], components: [multipleAnswersRow]});
        }
        else if(type == 'boolean'){
            interaction.reply({embeds: [questionEmbed], components: [booleanAnswersRow]});
        }
    },
};

Error -

undefined
Error executing quiz
TypeError: Cannot read properties of undefined (reading 'question')
    at Object.execute (C:\Projects\Work Projects\Programmers Bot\commands\quiz.js:53:39)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async Object.execute (C:\Projects\Work Projects\Programmers Bot\events\interactionCreate.js:16:4)

I as trying to make a quiz command and it had an option to choose if you want to get questions as true/false or multiple choice based, when running the commands if i run the multiple choice question, it's working perfectly and when i try true/false it gives me this error,

i have used same question variable for both type of questions.

I hope someone can help me resolve this issue.

CodePudding user response:

OpenTDB categories start from 9 (General Knowledge). Supplying a category of 8 or less may lead to the following response:

{ response_code: 1, results: [] }

Where response code 1 means:

Code 1: No Results Could not return results. The API doesn't have enough questions for your query. (Ex. Asking for 50 Questions in a Category that only has 20.)

Ensure you supply a category id of 9 or higher and check for the response code

// Change category accordingly
const response = await fetch(`https://opentdb.com/api.php?amount=12&category=9&difficulty=easy`);
const data = await response.json()
if (data.response_code !== 0) throw `Error Code: ${data.response_code}`;

if (!data.results.length) throw "No Questions!";
  
const random = Math.floor(Math.random() * data.results.length);
const randomQuestion = data.results[random];
  
const { question } = randomQuestion;
const correctAnswer = randomQuestion.correct_answer;

Consider using my package "open-trivia-db" to make working with OpenTDB alot faster:

import { Category, getQuestions } from 'open-trivia-db';

const questions = await getQuestions({
  amount: 50, // 1 - 50
  difficulty: 'easy', // or 'medium' or 'hard'
  type: 'multiple', // or 'boolean (true/false)
  category: Category.allNames.SCIENCE_COMPUTERS
});

// questions[0].value and questions[0].correctAnswer

If you want to make an entire trivia game with points and leaderboards, I've also written discord-trivia

import { TriviaCommandBuilder, TriviaManager } from 'discord-trivia';

const cmd = new TriviaCommandBuilder();

const trivia = new TriviaManager({
  theme: 'Red'
});

module.exports = {
    data: cmd.toBuilder(),
    async execute(interaction) {
      const game = trivia.createGame(interaction, cmd.getOptions(interaction));

      game
        .start()
        .catch(console.error);
    },
};

For both libraries, you may need to swap the import/export syntax for require() depending on your environment setup

  • Related