Как опубликовать таблицу лидеров в embed [discord.js ]

#javascript #node.js #discord.js

#javascript #node.js #discord.js

Вопрос:

У меня есть discord.js система выравнивания, которая хранит уровни людей в файле json database.json следующим образом: {"626916199783071750":{"xp":54,"level":14} я сортирую уровни каждого, используя этот код:

 members.sort(function(a, b) {
  const keyA = a[Object.keys(a)[0]].level,
        keyB = b[Object.keys(a)[0]].level;
  // Compare
  // (swap -1 and 1 to change sort order)
  if(keyA < keyB) return -1;
  if(keyA > keyB) return 1;
  return 0;
});
console.log(members);
 

(члены определяются с const members = [require("./database.json")]; помощью )
Я могу нормально зарегистрировать его, и он находится в правильном порядке, но мне было интересно, как я отправлю это в виде вставки, поскольку этот код не работал:

       let embed = new Discord.RichEmbed()
      .setColor(0x4286f4)
      .addField('Level:', members)
      member.channel.send(embed);
 

Это давало мне вставку с просто неопределенным как поле.
Для справки я использую discord.js v12

Комментарии:

1. Это должно быть new Discord.MessageEmbed() потому, что вы используете v12 из Discord.js

2. теперь я получаю TypeError: Cannot read property 'client' of undefined

3. я думаю, что это вызвано где-то в другом месте, пожалуйста, проверьте номер строки, в которой вызвана ошибка.

4. Я не верю discord.js позволяет напрямую устанавливать поля для встраивания или содержимое сообщения в массивы / объекты. Вам нужно будет преобразовать массив в строку, прежде чем добавлять его в поле вставки. Что касается Cannot read property 'client' of undefined , эта ошибка не связана с этой проблемой и находится где-то еще в вашем коде полностью.

5. В нем говорится, что это происходит в строке кода, которая let embed = new Discord.RichEmbed()

Ответ №1:

После многократного редактирования и обсуждения с вами ниже я позволяю себе внести некоторые изменения в способ работы вашего бота.

Хранение данных

Прежде всего, способ хранения данных довольно плохой. JSON — плохой выбор, и его очень раздражает использование в качестве базы данных, но он остается вариантом. Вы должны проверить Quick.db , что отлично подходит для начинающих! С другой стороны, вы всегда, всегда хотите хранить документы в массиве. Массивы буквально созданы для этого. Вот некоторый код для переключения ваших текущих данных на новую модель. Не забудьте также обновить другие части вашего бота, которые хранят данные, чтобы они соответствовали новой форме. Я не хочу вносить слишком много изменений, но я хотел бы добавить, что хранение level — плохая идея, поскольку это зависит от xp . Вы должны написать функцию xp , которая преобразует level и использует ее вместо сохранения level .

 // const fs = require("fs")
// const oldDb = JSON.parse(fs.readFileSync("database.json"))
const oldDb = {
  "626916199783071750": {
    "xp": 69,
    "level": 14
  },
  "579776588732956674": {
    "xp": 2,
    "level": 13
  },
  "784566696244674621": {
    "xp": 99,
    "level": 1
  },
  "495304082769051660": {
    "xp": 6,
    "level": 1
  },
  "752987763573391411": {
    "xp": 1,
    "level": 0
  }
}

let newDb = Object.keys(oldDb).map((id) =>
  ({
    id,
    xp: oldDb[id].xp,
    level: oldDb[id].level
  })
)

console.log(newDb)
// fs.writeFile("database.json", JSON.stringify(newDb), 'utf8') 

Сортировка по уровню

С этого момента вы сможете работать гораздо эффективнее. Поскольку мы изменили модель данных бота, я помогу вам преобразовать метод сортировки в тот, который действительно работает.

 // const users = require("./database.json"), with the new data model this time
const users = [{
  id: "626916199783071750",
  level: 14,
  xp: 69
}, {
  id: "579776588732956674",
  level: 13,
  xp: 2
}, {
  id: "784566696244674621",
  level: 1,
  xp: 99
}, {
  id: "495304082769051660",
  level: 1,
  xp: 6
}, {
  id: "752987763573391411",
  level: 0,
  xp: 1
}]

const sortedUsers = users.sort((a, b) => (a.level > b.level) ? 1 : -1) // ternary operation, it's basically just a 'if'
console.log(sortedUsers) 

Опубликовать таблицу лидеров

Ах, ты сделал это! Теперь, вот мой первоначальный ответ… как отправить все эти данные. Вам нужно будет добавить поле для каждого элемента. MessageEmbed#addFields() здесь идеально подходит. Приведенный ниже код не тестировался.

 const maxNumberOfUsersToDisplay = 10;

const embed = new Discord.MessageEmbed().setColor(0x4286f4).addFields(
  sortedUsers.flatMap((userDoc, i) => {
    // flatMap will map and delete all the [] of the array
    if (!(i < maxNumberOfUsersToDisplay amp;amp; i < 25)) return [];

    return {
      name: user.id, // Feel free to mess with the code and replace this with a mention/tag
      value: `Level ${user.level}`,
      inline: false, // default value, just to show you you can adjust this param to change the embed layout
    };
  })
);

message.channel.send(embed);
 

Array#flatMap() действует как a .map() и a .flat() , это неясный метод, который следует использовать чаще: его также можно использовать как a .map() и a .filter() , как показано выше.

Комментарии:

1. вот ссылка на мою базу данных, должно ли то, что вы отправляете, все еще работать? sourceb.in/x4hsyLxeaf

2. Почему вы используете sort тогда? Это объект… Не могли бы вы сообщить мне, какие console.log(members) результаты?

3. журнал дает мне ссылку на изображение

4. Хорошо. Почему вы используете [require('database-file')] ? Какова цель [] ? В нем всего 1 элемент, поэтому sort метод ничего не делает.

5. если я этого не сделаю, это даст мне TypeError: members.sort is not a function