Reputation: 306
I am trying to create a leaderboard command for my Discord bot and having some trouble getting the data to display, my current code only displays the top user, you can see in the image there are 4 lines, this is because there are 4 entries in the database, so it's getting the information but not displaying all the data. Could someone point out what I am doing wrong/what I would need to change to fix this. (The blocked out bits in the photos is my username) Code:
const top10 = db
.prepare(
'SELECT * FROM scores WHERE guild = ? ORDER BY points DESC LIMIT 10;',
)
.all(message.guild.id);
if (!top10) {
return;
}
for (const data of top10) {
let userNames = '';
for (let i = 0; i < top10.length; i++) {
const user = bot.users.cache.get(data.user).tag;
userNames += `\`${i + 1}\` ${user}\n`;
}
const level = `\`${data.level}\`\n`;
const xp = `\`${data.points.toLocaleString('en')}\`\n`;
const embed = new MessageEmbed()
.setAuthor(`Leaderboard for ${message.guild.name}`, message.guild.iconURL({ dynamic: true }))
.setColor(0x51267)
.addFields({ name: 'Top 10', value: userNames, inline: true },
{ name: 'Level', value: level, inline: true },
{ name: 'XP', value: xp, inline: true });
message.channel.send(embed);
return;
}
Current Output:
Desired Output:
Upvotes: 0
Views: 4988
Reputation: 138
From reading your code, I believe you made a mistake in the structuring of your code. From what it seems, your code gets the first item in top10
, then adds that to the string as many times as the length of the top10 array. It then gets the level and xp for the first user, adds it to a string, then constructs this into an embed.
Here is the code revised so it should work as you intended:
let userNames = '';
let levels = '';
let xp = '';
for (let i = 0; i < top10.length; i++) {
const data = top10[i];
const user = (await bot.users.fetch(data.user)).tag;
userNames += `\`${i + 1}\` ${user}\n`;
levels += `\`${data.level}\`\n`;
xp += `\`${data.points.toLocaleString('en')}\`\n`;
}
const embed = new MessageEmbed()
.setAuthor(`Leaderboard for ${message.guild.name}`, message.guild.iconURL({ dynamic: true }))
.setColor(0x51267)
.addFields({ name: 'Top 10', value: userNames, inline: true },
{ name: 'Level', value: levels, inline: true },
{ name: 'XP', value: xp, inline: true });
message.channel.send(embed);
return;
Upvotes: 1
Reputation: 2722
You problem is, you just add \n
to js object, so its no work.
As varian you can create 3 arrs with data, then, map db result push information to data.
And better use message.guild.members.chache.get
for check if user on server, because, bot.users.cache.get(data.user).tag
will return undined, after bot restart, if user don`t send any messages in handled bot channels.
const top10 = db.prepare('SELECT * FROM scores WHERE guild = ? ORDER BY points DESC LIMIT 10;').all(message.guild.id);
if (!top10) {
return;
}
let usersArr = [];
let levelArr = [];
let xpArr = [];
top10.forEach(dataUser, index => {
let findUser = message.guild.members.cache.get(dataUser.user);
if (findUser) {
usersArr.push(`\`${index + 1}\` ${user.tag}`);
levelArr.push(dataUser.level);
xpArr.push(dataUser.points.toLocaleString('en'));
}
});
const embed = new MessageEmbed()
.setAuthor(`Leaderboard for ${message.guild.name}`, message.guild.iconURL({ dynamic: true }))
.setColor(0x51267)
.addFields({ name: 'Top 10', value: usersArr.join('\n'), inline: true }, { name: 'Level', value: levelArr.join('\n'), inline: true }, { name: 'XP', value: xpArr.join('\n'), inline: true });
message.channel.send(embed);
Upvotes: 0