Как заставить моего бота получать случайные сообщения, которые уже отправлены пользователями в канале, и отправлять это случайное сообщение при срабатывании автоответа - PullRequest
2 голосов
/ 21 ноября 2019

Как видно из заголовка, я пытался использовать fetchMessages для проверки сообщений, отправляемых определенным каналом, но когда я попытался возиться с этим, он просто выдает мне бесконечные блоки информации в консоли.

Я попытался прочитать его, но там, похоже, нет реального сообщения, и он просто дает мне информацию о сервере, такую ​​как идентификатор канала, идентификатор участника, их привилегии и т. Д.

Сначала яЯ подумал, что использование этого метода даст мне случайные сообщения, так что я могу просто заставить бота отправлять сообщения прямо на канал, но это дает мне ошибку, поэтому я просто использовал console.log для получения дополнительной информации. Но это не так, или я просто неправильно его использую ...

Вот код, который я пробую:

    bot.on('message', msg =>{

    if(msg.author.bot) return;
    lowerCase = msg.content.toLowerCase();

    if(lowerCase.includes ("fetch")){ 
        msg.channel.fetchMessages({limit: 1}).then(console.log);
    }
})

Также, очевидно, он не может отследитьстарые сообщения, поскольку, когда я пытался отфильтровать сообщения, используя идентификатор пользователя, это показывает, что они отправили 0 сообщений, даже если они отправляли сообщения раньше? Я пытаюсь добиться того, чтобы он все еще мог читать очень старые сообщения и отправлять их, когда я использую сообщение автоответчика.

1 Ответ

2 голосов
/ 21 ноября 2019

TextChannel.fetchMessages () может получать только до 100 сообщений одновременно

Краткий ответ:

Хотя этоне отображается в документах , если вы получите более 100, вы получите ошибку API:

DiscordAPIError: Invalid Form Body
limit: int value should be less than or equal to 100.

Консольное ведение журнала объекта Message действительно даст вамвся информация о Guild и обо всем остальном в нем. Вы, вероятно, захотите, чтобы консоль только регистрировала содержание сообщения и идентификатор автора / usertag

Так что если вы хотите искать за пределами последних 100 сообщений, вам придется непрерывно получать 100 сообщений, используя идентификатор самого старогосообщение в параметре ChannelLogsQueryOptions before в каждом последующем вызове TextChannel.fetchMessages(), а затем объединение каждого Collection вместе с использованием Collection.concat().


Длинный ответ:

Если вы хотите, например, получить последние 200 сообщений, вы можете написать что-нибудькак это:

// using .then()
await channel.fetchMessages({limit: 100})
.then(first100 => {
  let next100 = await channel.fetchMessages({limit: 100, before: first100.lastKey()})
  .then(next100 => {
    let all200 = first100.concat(next100);
  });
});
// in async function
let first100 = await channel.fetchMessages({limit: 100});
let next100 = await channel.fetchMessages({limit: 100, before: first100.last().id});
let all200 = first100.concat(next100);

Взгляните на этот ответ для асинхронной функции, которая хранит прошлые сообщения в массиве.

Я сделал свою собственную версиюкоторый даст вам Collection и вернет его как правильное Promise вместо:

const fetchManyMessages = (channel, limit = 200) => {
  return new Promise((resolve, reject) => {
    channel.fetchMessages({limit: limit < 100 ? limit : 100})
    .then(collection => {
      const nextBatch = () => {
        console.log(collection.size);
        let remaining = limit - collection.size;

        channel.fetchMessages({limit: remaining<100 ? remaining : 100, before: collection.lastKey()})
        .then(next => {
          let concatenated = collection.concat(next);

          // resolve when limit is met or when no new msgs were added (reached beginning of channel)
          if (collection.size >= limit || collection.size == concatenated.size) return resolve(concatenated);

          collection = concatenated;
          nextBatch();
        })
        .catch(error => reject(error));
      }

      nextBatch();
    })
    .catch(error => reject(error));
  });
}

Пример использования:

fetchManyMessages(message.channel, 1500)
.then(msgs => console.log(msgs.size))
.catch(err => console.log(err));

И здесь я также сделал prototype версию, которая, я думаю, отлично подходит для некоторой синтаксической удивительности:

Discord.TextChannel.prototype.fetchManyMessages = function (limit = 200) {
  return new Promise((resolve, reject) => {
    this.fetchMessages({limit: limit < 100 ? limit : 100})
    .then(collection => {
      const nextBatch = () => {
        console.log(collection.size);
        let remaining = limit - collection.size;

        this.fetchMessages({limit: remaining<100 ? remaining : 100, before: collection.lastKey()})
        .then(next => {
          let concatenated = collection.concat(next);

          // resolve when limit is met or when no new msgs were added (reached beginning of channel)
          if (collection.size >= limit || collection.size == concatenated.size) return resolve(concatenated);

          collection = concatenated;
          nextBatch();
        })
        .catch(error => reject(error));
      }

      nextBatch();
    })
    .catch(error => reject(error));
  });
}

Пример использования:

message.channel.fetchManyMessages(1500)
.then(msgs => console.log(msgs.size))
.catch(err => console.log(err));
...