I’m trying to make a horse race command for my discord bot (TypeScript).
The code itself works fine, but I have to update an embed which contains the race and the participants. The thing is that for it to properly update, I have to set its description every time that collector.on("collect")
fires. I want to ask if there’s a better, more efficient and cleaner way to update it. Thank you!
code:
const bet = interaction.options.get("bet").value; class Horse { name: string; owner: User; speed: number; position: Array<string>; constructor(name: string) { this.name = name; this.owner = null; this.speed = 0; this.position = ["🐴"]; } } const horses = [ new Horse(aimless.pick(names, { remove: true })), new Horse(aimless.pick(names, { remove: true })), new Horse(aimless.pick(names, { remove: true })), new Horse(aimless.pick(names, { remove: false })), ]; const hasJoined: Array<Horse["owner"]> = []; const row = new MessageActionRow(); for (const horse of horses) { row.addComponents( new MessageButton() .setCustomId(horse.name) .setLabel(horse.name) .setStyle("SECONDARY") ); } const embed = new MessageEmbed() .setTitle("Place your bets!") .setDescription( `**${horses[0].name} - ${ horses[0].owner !== null ? horses[0].owner.username : "Nobody" } ${horses[0].position} ${horses[1].name} - ${ horses[1].owner !== null ? horses[1].owner.username : "Nobody" } ${horses[1].position} ${horses[2].name} - ${ horses[2].owner !== null ? horses[2].owner.username : "Nobody" } ${horses[2].position} ${horses[3].name} - ${ horses[3].owner !== null ? horses[3].owner.username : "Nobody" } ${horses[3].position}**` ); await interaction.editReply({ embeds: , components: [row], }); const filter = async (i: MessageComponentInteraction) => { let profile: any; try { profile = await profileModel.findOne({ userID: i.user.id }); if (!profile) { await profileModel.create({ userID: i.user.id, serverID: i.guild?.id, username: i.user.username, bananas: 100, deposit: 0, }); profile.save(); } } catch (e) { await i.editReply("Something went wrong! :( Please retry."); } finally { if (hasJoined.includes(i.user)) { return false; } if (profile.bananas < bet) { interaction.editReply(`${i.user} you don't have enough bananas!`); } return profile.bananas >= bet; } }; const collector = interaction.channel.createMessageComponentCollector({ filter, time: 60000, }); collector.on("collect", async (int) => { await int.deferUpdate(); for (const btn of row.components) { if (btn.customId === (int.component as MessageButton).customId) { (btn as MessageButton).setDisabled(true).setStyle("SUCCESS"); hasJoined.push(int.user); horses.find((h) => h.name === btn.customId).owner = int.user; console.log(horses); } } embed.setDescription( `**${horses[0].name} - ${ horses[0].owner !== null ? horses[0].owner.username : "Nobody" } ${horses[0].position} ${horses[1].name} - ${ horses[1].owner !== null ? horses[1].owner.username : "Nobody" } ${horses[1].position} ${horses[2].name} - ${ horses[2].owner !== null ? horses[2].owner.username : "Nobody" } ${horses[2].position} ${horses[3].name} - ${ horses[3].owner !== null ? horses[3].owner.username : "Nobody" } ${horses[3].position}**` ); await int.editReply({ embeds: , components: [row], }); }); }, });`
Advertisement
Answer
You could make it into a function:
const displayHorses = (horses: Array<Horse>) => { return `**${horses[0].name} - ${ horses[0].owner !== null ? horses[0].owner.username : "Nobody" } ${horses[0].position} ${horses[1].name} - ${ horses[1].owner !== null ? horses[1].owner.username : "Nobody" } ${horses[1].position} ${horses[2].name} - ${ horses[2].owner !== null ? horses[2].owner.username : "Nobody" } ${horses[2].position} ${horses[3].name} - ${ horses[3].owner !== null ? horses[3].owner.username : "Nobody" } ${horses[3].position}**`; };
And then every time:
embed.setDescription(displayHorses(horses));
If you want to compact it even further, you could map the horse array.
const displayHorses = (horses: Array<Horse>) => { return horses.map( ({ name, owner, position }) => `**${name}** - ${owner !== null ? owner.username : "Nobody"} ${position}` ); };
Lastly, as a tip, if you’re using 14+, you could compact it even further to:
const displayHorses = (horses: Array<Horse>) => { return horses.map( ({ name, owner, position }) => `**${name}** - ${owner?.username ?? "Nobody"} ${position}` ); };