I am trying to refactor the code that I am using to generate embeds (user input makes an API call for info, which I display through the embed) with my bot in Discord. I have both a slash command and prefix command version of the code (so that people can either ask the bot with a prefix command or use the slash commands) and I am trying to pull the duplicated code for both those requests into a helper file.
The helper file: (/utils/itemHelper.js)
const { MessageEmbed } = require('discord.js');
const { request } = require('undici');
const { ITEM_URL, BASE_URL } = require('./utils');
const { itemAliases } =require('./itemAliases')
async function getItem( itemName ){
if (itemName in itemAliases){ itemName = itemAliases[itemName] };
const { body } = await request(ITEM_URL + encodeURIComponent(itemName));
const { items } = await body.json();
const [itemAnswer] = items;
const itemEmbed = new MessageEmbed()
.setTitle(itemAnswer.name)
.setDescription('Mentor notes will go here.')
.setImage(BASE_URL + itemAnswer.screenshot)
console.log(itemEmbed);
}
module.exports = { getItem }
At this point, the console.log(itemEmbed) gives me what I want:
MessageEmbed {
type: 'rich',
title: 'Frost Brand',
description: 'Mentor notes will go here.',
url: null,
color: null,
timestamp: null,
fields: [],
thumbnail: null,
image: { url: 'https://dom5api.illwiki.com/items/14/screenshot' },
video: null,
author: null,
provider: null,
footer: null
}
But by the time I call the function within the file were I create the slash command, I get an error message (which is discord telling me that the embed I want to send is lacking the description field):
data.embeds[0].description: This field is required.
The slash command file where I call the async function: (/commands/item.js)
const { SlashCommandBuilder } = require('@discordjs/builders');
const { MessageEmbed } = require('discord.js');
const { getItem } = require('../utils/itemHelper')
module.exports = {
data: new SlashCommandBuilder()
.setName('item')
.setDescription('Replies with information about an item')
.addStringOption(option => option.setName('item_name').setDescription('Enter the name of the item').setRequired(true)),
async execute(interaction) {
let itemName = interaction.options.getString('item_name');
const itemEmbed = getItem( itemName );
console.log(`itemEmbed:`+ itemEmbed);
await interaction.reply({ embeds: [itemEmbed] });
},
};
The console.log output is
itemEmbed:[object Promise]
My hunch is that I am somehow misunderstanding/misapplying how async functions and promises work (and that the information I need is hidden somewhere inside [object Promise]). I have tried to do ‘return itemEmbed’ at the end of the helper file, but that didn’t solve the issue. I have also considered if I might be missing a param in my async function, but I don’t think I need another param, or if I did need one what role it would fill.
Thanks for any/all help in advance!
Advertisement
Answer
In your getItem function, there’s two problems:
- You made it
async. When a function is asynchronous, it is considered as aPromisethat you have to use theawaitkeyword onawait getItem(..)So that it will wait for the fetch to finish to finally continue executing your code. - You don’t
returnanything on your function. You log the embed in your console. Try using it like so :
const { MessageEmbed } = require('discord.js');
const { request } = require('undici');
const { ITEM_URL, BASE_URL } = require('./utils');
const { itemAliases } =require('./itemAliases')
function getItem( itemName ){
if (itemName in itemAliases){ itemName = itemAliases[itemName] };
const { body } = await request(ITEM_URL + encodeURIComponent(itemName));
const { items } = await body.json();
const [itemAnswer] = items;
const itemEmbed = new MessageEmbed()
.setTitle(itemAnswer.name)
.setDescription('Mentor notes will go here.')
.setImage(BASE_URL + itemAnswer.screenshot)
return itemEmbed
}
module.exports = { getItem }
const itemEmbed = await getItem(itemName);