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}`
);
};