Home > Blockchain >  Passing multiple Embeds through a helper function for Discord Bot
Passing multiple Embeds through a helper function for Discord Bot

Time:08-03

I have refactored my code to remove some redundancy, part of which was making helper functions for the generation of embeds that my bot sends as a reply. For one of the slash commands, the bot is supposed to send back multiple embeds.

mercHelper.js (Houses the helper function inside the utils folder)

const { MessageEmbed } = require('discord.js');
const { request } = require('undici');
const { MERC_URL, BASE_URL } = require('./utils');
const { mercAliases } =require('./mercAliases')

async function getMerc( mercName ){
    if (mercName in mercAliases){ mercName = mercAliases[mercName] };
    const { body } = await request(MERC_URL   encodeURIComponent(mercName));
    const { mercs } = await body.json();

    const [mercAnswer] = mercs;
    const mercEmbed = new MessageEmbed()
        .setTitle(mercAnswer.name)
        .setDescription('Mentor notes will go here.')
        .setImage(BASE_URL   mercAnswer.screenshot)
    const mercLeaderEmbed = new MessageEmbed()
        .setImage(BASE_URL '/commanders/'  mercAnswer.commander_id '/screenshot')
        .setDescription('Name of mercenary group leader: '  mercAnswer.bossname)
    const mercTroopEmbed = new MessageEmbed()
        .setImage(BASE_URL '/commanders/'  mercAnswer.unit_id '/screenshot')
        .setDescription('Number of units: '  mercAnswer.nrunits)
    return [mercEmbed, mercLeaderEmbed, mercTroopEmbed];
    
}

module.exports = { getMerc }

merc.js (slash command file)

const { SlashCommandBuilder } = require('@discordjs/builders');
const { getMerc } = require('../utils/mercHelper');


module.exports = {
    data: new SlashCommandBuilder()
        .setName('merc')
        .setDescription('Replies with information about a merc')
        .addStringOption(option => option.setName('merc_name').setDescription('Enter the name of the mercenary').setRequired(true)),

    async execute(interaction) {
        let mercName = interaction.options.getString('merc_name');
        const mercEmbed = await getMerc( mercName );
        const mercLeaderEmbed = await getMerc( mercName );
        console.log('mercLeaderEmbed' mercLeaderEmbed)
        const mercTroopEmbed = await getMerc( mercName );
        console.log('mercTroopEmbed' mercTroopEmbed)
        await interaction.reply({ embeds: [mercEmbed, mercLeaderEmbed, mercTroopEmbed] });
    },
};

When I run the code I have currently, I get the following error message: DiscordAPIError: Invalid Form Body and then empty data.embeds.

I assume this is happening because when I 'return' embeds from the helper function, it is now going through somehow. I added console.logs to the helper file - all the information was present.

When I tried to do the same in the slash command file (merc.js), I get mercLeaderEmbed[object Object],[object Object],[object Object] and the same for the second console.log.

Maybe the return is working properly, but I am not calling the information correctly, which is resulting in the return of [object Object], but I am not sure on how to solve that issue/how to rewrite the code to avoid this.

CodePudding user response:

You're calling await getMerc(mercName) three times and assign the same value to three different variables (mercEmbed, mercLeaderEmbed, and mercTroopEmbed). If you return an array of the three embeds ([mercEmbed, mercLeaderEmbed, mercTroopEmbed]) from getMerc, you don't need to call it more than once.

When you log 'mercLeaderEmbed' mercLeaderEmbed, you receive mercLeaderEmbed[object Object],[object Object],[object Object] because mercLeaderEmbed is already an array of the three objects (and they get stringified because you concatenate the array with a string).

I think what you want is either destructuring the returned array like this:

async execute(interaction) {
  let mercName = interaction.options.getString('merc_name');
  let [mercEmbed, mercLeaderEmbed, mercTroopEmbed] = await getMerc(mercName);

  await interaction.reply({
    embeds: [mercEmbed, mercLeaderEmbed, mercTroopEmbed],
  });
}

Or just sending the returned array of embeds like this:

async execute(interaction) {
  let mercName = interaction.options.getString('merc_name');
  let embeds = await getMerc(mercName);

  await interaction.reply({ embeds });
}
  • Related