0

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

Ragnar Lothbrok
  • 306
  • 1
  • 4
  • 22

2 Answers2

1

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;
solonovamax
  • 138
  • 5
  • @Ranar Lothbrok You will got an error on `bot.users.cache.get(data.user).tag` for unchached users, so it`s not right solution.... – Cipher Mar 09 '20 at 21:00
  • Sorry, I am not used to discord.js, so I forgot about that. Instead, you should use `const user = (await bot.users.fetch(data.user)).tag;` This will get the user if it is in the cache and update it if it isn't. Docs here: https://discord.js.org/#/docs/main/master/class/UserManager?scrollTo=fetch – solonovamax Mar 10 '20 at 18:58
0

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);
Cipher
  • 2,702
  • 1
  • 6
  • 17