简体   繁体   中英

Detecting failure to update a message

I'm working on a discord bot where a specifc message should be updated or created if it doesn't exist. A problem arises if the message has been deleted by someone with access... A dangling reference is created and when it's time to update an exception is raised. How do I detect if a message with a specific ID does not exist in the current channel?

This is a the current code:

    TextChannel scoreChannel = channel.getGuild().getTextChannelsByName(gameType + "-ladder", true).get(0);
    String id = ScoreboardController.getScoreboardMessageId(gameType);
    if (id == null)
        scoreChannel.sendMessage(eb.build()).queue();
    else {
        scoreChannel.editMessageById(id, eb.build()).queue(); // this part can fail
    }

Note that getScoreboardMessageId fetches the previously stored id from the database.

Either I need to query for the message by title or by other means find if it's missing.


I tried retrieving the embeded messages like so, but without success:

    List<Message> messages = scoreChannel.getHistory().getRetrievedHistory();

After some more searching I managed to do this which works but is not Async:

 TextChannel scoreChannel = channel.getGuild().getTextChannelsByName(gameType + "-ladder", true).get(0);
        List<Message> messages = new MessageHistory(scoreChannel).retrievePast(10).complete();
        boolean wasUpdated = false;
        for (Message msg : messages) {
            if (msg.getEmbeds().get(0).getTitle().equals(content[0])) {
                scoreChannel.editMessageById(msg.getId(), eb.build()).queue();
                wasUpdated = true;
            }
        }
        if (!wasUpdated)
            scoreChannel.sendMessage(eb.build()).queue();

You can use the failure callback of queue:

channel.editMessageById(messageId, embed).queue(
    (success) -> {
        System.out.printf("[%#s] %s (edited)\n",
                   success.getAuthor(), success.getContentDisplay()); // its a Message
    },
    (failure) -> {
        failure.printStackTrace(); // its a throwable
    }
);

The failure callback being called implies the edit has failed. This can happen if the message no longer exists or some connection issue occurred. Note that you can pass null for either of these callbacks to simplify the cases at which only the failure or only the success should be handled.

As the docs suggests the getRetrievedHistory() method returns an empty list unless you previously used retrievePast or retrieveFuture which are both returning RestAction<List<Message>> . This means you have to use:

history.retrievePast(amount).queue((messages) -> {
    /* use messages here */
});

The amount is limited to a maximum of 100 messages per call. An easier API without this limitation is offered by channel.getIterableHistory().takeAsync(amount) which returns a CompletableFuture and can be combined with thenAccept .

Even better would be using channel.retrieveMessageById(messageId) which only retrieves the message and fails if the message doesn't exist. This however is not needed in your case since you edit the message by id and can just use the failure response of that rather than running into a TOCTOU Problem .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM