Discord.js Кэш Ролей Ботов Не Синхронизирован

#javascript #node.js #discord #discord.js

Вопрос:

У меня только что начались проблемы с моим discord.js бот для управления ролями. Бот успешно добавит роль после события реакции. Если пользователь затем удалит реакцию, роль должна исчезнуть.

У меня есть вспомогательный метод, который рано возвращается, если у пользователя нет роли (чтобы избежать ненужной работы и поддерживать чистоту ведения журнала). Этот метод предотвращает удаление роли при первом событии удаления реакции. Последовательность выглядит следующим образом:

  1. Пользователь добавляет реакцию, бот дает пользователю новую роль
  2. Пользователь удаляет реакцию, бот рано возвращается, потому guild.members.cache.get(user.id).roles.cache.has(role.id) что возвращает false.
  3. Пользователь снова добавляет реакцию, бот рано возвращается, но теперь роль появляется в кэше ролей пользователя.
  4. Пользователь снова удаляет реакцию, бот удаляет роль у пользователя.

Роль правильно отображается в discord правильно в первый раз, однако я провел некоторое расследование и добавил следующий код в бота:

  guild.members.cache.get(member.id).roles.add(role.id)
    .then(() => guild.members.cache.get(author.id))
    .then(user => console.log(user._roles));
 

Вывод не включает новую роль, несмотря на то, что пользователь продвигается в клиенте, поэтому, похоже, кэш обновляется не сразу. Как я могу быть уверен, что получаю самую актуальную информацию?

Правка: В итоге я решил обойти это, создав свой собственный кэш для хранения ролей, но для потомков вот несколько дополнительных кодов, чтобы попытаться изолировать причину:

 let guild;
const messageId = //some value
const roleId = //some value
const channelId = //some value
const emojiName = //some value

client.on('messageReactionAdd', async (reaction, user) => {
  handleReactionAdded(reaction, user)
});

client.on('messageReactionRemove', async (reaction, user) => {
  handleReactionRemoval(reaction, user)
});

const handleReactionAdded = async (reaction, user) => {
  if (reaction.message.partial) await reaction.message.fetch();
  if (reaction.partial) await reaction.fetch();
  if (user.bot || !reaction.message.guild) return;
  if (reaction.message.id == messageId amp;amp; reaction.message.channel.id == channelId amp;amp; reaction.emoji.name === emojiName) {

    guild = reaction.message.guild
    if (_hasRole(user)) return;
    guild.members.cache
        .get(user.id)
        .roles
        .add(roleId)
}

const handleReactionAdded = async (reaction, user) => {
  if (reaction.message.partial) await reaction.message.fetch();
  if (reaction.partial) await reaction.fetch();
  if (user.bot || !reaction.message.guild) return;
  if (reaction.message.id == messageId amp;amp; reaction.message.channel.id == channelId amp;amp; reaction.emoji.name === emojiName) {

    guild = reaction.message.guild
    if (!_hasRole(user)) return;
    guild.members.cache
        .get(user.id)
        .roles
        .remove(roleId)
}

const _hasRole = user => {
  return guild.members.cache.get(user.id).roles.has(roleId);
}
 

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

1. Предоставленных вами строк кода недостаточно. Вам нужно показать следующее: Как вы удаляете роли; Как вы добавляете роли; события и условия, которые, возможно, приведут к раннему возвращению функции

2. Основная проблема полностью инкапсулирована в предоставленном мной фрагменте: после member.roles.add(role.id) вызова member._roles должна включать эту роль, но это не так (по крайней мере, не сразу). Я структурировал его в обещания, чтобы попытаться убедиться, что он был выполнен асинхронно.

Ответ №1:

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

 await guild.members.fetch({user, force: true})