Редактирование сообщения разногласия бота через цепочку обещаний в javascript - PullRequest
0 голосов
/ 03 ноября 2019

В настоящее время я работаю над ботом-нарушителем, и одна из команд, которые я хотел бы реализовать, - это редактирование сообщения, которое бот ранее отправил с помощью команды edit - я использую discord.js чтобы сделать это и из документации, похоже, мне нужно будет использовать цепочку обещаний, чтобы достичь того, чего я хочу, но я немного запутался в некоторых маленьких кусочках. Мой текущий код выглядит следующим образом:

module.exports = {
    name: 'edit',
    description: 'Edit one of the bot\'s messages',
    args: true, // does the command have arguments?
    guildOnly: true, // can this command be used outside of the discord channel?
    execute(message, args) {
        if (args.length < 2) {
            console.log("Insufficient arguments provided");
            return;
        }
        const server = message.guild;
        let id = args.shift();
        let newMessage = args.join(' ');

        let channels = server.channels;
        for (let [, channel] of channels) {
            if(channel.type === 'text') {
                channel.fetchMessage(id)
                .then(response => {
                    return response;
                }, _reason => {
                    console.log("still looking");
                })
                .then(function (message) {
                    message.edit(newMessage)
                    .then(editedMessage => {
                        console.log(`new message content: ${editedMessage}`);
                    })
                    .catch(console.error);
                })

            }
        }
    },
};

По сути, мой мыслительный процесс заключается в следующем: команду можно использовать в любом канале для редактирования любых сообщений бота в любом другом канале - чтобы добиться этого, япотребовалось бы перебрать все каналы сервера и проверить соответствующий идентификатор сообщения (как показано выше с помощью цикла for) - здесь я запутался, команда fetchMessage, замеченная здесь возвращает обещание, но моя главная проблема в том, что если сообщение не в канале, я хочу, чтобы бот продолжал искать, пока не найдет его. Как только это произойдет, я попытаюсь связать другое обещание, чтобы отредактировать сообщение ;в этот момент я отправлю сообщение на дискотеку о том, что процесс успешно завершен - так как он стоит сейчас, мой код в настоящее время выдает ошибку, когда проверяет первый канал и не находит сообщение, возможно, из-за моего условия отклонения в fetchMessage блок. У меня вопрос: как заставить программу не выдавать ошибку, если она не находит сообщение с первой попытки и если оно находит правильное сообщение, как я могу получить обещание правильно отредактировать его?

Ответы [ 2 ]

0 голосов
/ 04 ноября 2019

Предполагая, что это массив (или его можно преобразовать в массив) message.guild.channels можно сканировать асинхронно, сначала сформировав цепочку .catch(), построенную ниже с шаблоном, основанным на Array.prototype.reduce () .

module.exports = {
    'name': 'edit',
    'description': 'Edit one of the bot\'s messages',
    'args': true,
    'guildOnly': true,
    execute(message, args) {
        if (args.length < 2) {
            return Promise.reject(new RangeError('Insufficient arguments provided')); // ensure that execute() returns a Promise
        }
        let id = args.shift();
        let newMessage = args.join(' ');
        return message.guild.channels.reduce((rejetedPromise, [, channel]) => { // assuming `message.guild.channels` to be Array
            return rejetedPromise.catch(error => {
                if (channel.type === 'text') {
                    return channel.fetchMessage(id); // will resolve to `msg` if found and drop through to the then() below,
                                                     // otherwise will reject and flow will keep going to the next catch formed by the reduction.
                } else {
                    throw new Error('channel(s) searched but message not found'); // keep going to next catch
                }
            });
        }, Promise.reject('no channels')) // starter Promise for the reduction. If `message.guild.channels.length === 0`, this promise will fall straight through to the .catch() below
        .then(msg => msg.edit(newMessage)) // execution will arrive here only if a `channel.fetchMessage(id)` above succeeds.
        .then(editedMessage => { // this whole clause is optional.
            console.log(`new message content: ${editedMessage}`);
            return editedMessage; // return whatever is of interest to execute()'s caller.
        })
        .catch(error => { // this whole clause is optional.
            console.error(error);
            throw error; // rethrow error to inform execute()'s caller of the error.
        });
    }
};

Блок message.guild.channels.reduce(...) не нуждается в пояснениях.

Он создает цепочку перехвата, которая при сборке вручную будет иметь вид:

Promise.reject().catch(...).catch(...).catch(...).catch(...).then(...);

Сравните это с более знакомой (и более понятной) цепочкой:

Promise.resolve().then(...).then(...).then(...).catch(...);

Природа цепочки перехвата заключается в том, что ее расчет:

  • будет выполняться из обратного вызова перехватачтобы перехватить обратный вызов до тех пор, пока эти обратные вызовы либо сгенерируют, либо вернут Обещание, которое / будет отклонено.
  • перейдет к окончательному .then(), как только любой из обратных вызовов catch вернет значение или Обещаниеэто / будет решено.

Таким образом, вы получаете именно то, что вы хотите - чтобы бот продолжал искать канал за каналом, пока не найдет нужное сообщение.

0 голосов
/ 03 ноября 2019

Я бы предложил вам добавить аргумент channel, но если вы действительно хотите сделать это по-своему, вам нужно только перехватить fetchMessage(). Кроме того, я не понимаю цель вашего первого .then(). Вот как бы я это сделал:

if (args.length < 2) {
  console.log("Insufficient arguments provided");
  return;
}
const server = message.guild;
let id = args.shift();
let newMessage = args.join(" ");

let channels = server.channels;
for (let [, channel] of channels) {
  if (channel.type === "text") {
    channel
      .fetchMessage(id)
      .then(message => {
        message.edit(newMessage).then(editedMessage => {
          console.log(`new message content: ${editedMessage}`);
        });
      })
      .catch(e => console.log("Not this channel"););
  }
}
...