Ragnar Lothbrok
Ragnar Lothbrok

Reputation: 306

Displaying leaderboard in embed

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: Curent Output: Desired Output: Desired Output

Upvotes: 0

Views: 4988

Answers (2)

solonovamax
solonovamax

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

Cipher
Cipher

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

Related Questions