检测更新消息失败

Detecting failure to update a message

我正在开发一个 discord 机器人,其中应该更新或创建不存在的特定消息。如果消息已被具有访问权限的人删除,则会出现问题...创建了一个悬空引用,并且在需要更新时引发异常。如何检测当前频道不存在特定ID的消息?

这是当前代码:

    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
    }

请注意,getScoreboardMessageId 从数据库中获取先前存储的 ID。

我需要按标题或其他方式查询邮件是否丢失。


我尝试像这样检索嵌入的消息,但没有成功:

    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();

可以使用队列的失败回调:

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
    }
);

调用失败回调意味着编辑失败。如果消息不再存在或发生某些连接问题,则可能会发生这种情况。请注意,您可以为这些回调中的任何一个传递 null 以简化仅应处理失败或仅应处理成功的情况。

正如文档所建议的那样 getRetrievedHistory() 方法 returns 一个 空列表 除非你之前使用过 retrievePastretrieveFuture 都返回 RestAction<List<Message>>。这意味着您必须使用:

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

每次通话最多可发送 100 条消息。 channel.getIterableHistory().takeAsync(amount) 提供了一个没有此限制的更简单的 API,其中 returns 和 CompletableFuture 可以与 thenAccept.

结合使用

更好的方法是使用 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.