简体   繁体   English

检测更新消息失败

[英]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?如何检测当前频道中是否不存在具有特定 ID 的消息?

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.请注意, getScoreboardMessageId 从数据库中获取先前存储的 id。

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.请注意,您可以为这些回调中的任何一个传递 null 以简化仅应处理失败或仅应处理成功的情况。

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>> .正如文档所建议的那样, getRetrievedHistory()方法返回一个空列表,除非您之前使用过retrievePastretrieveFuture ,它们都返回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.该数量限制为每次呼叫最多 100 条消息。 An easier API without this limitation is offered by channel.getIterableHistory().takeAsync(amount) which returns a CompletableFuture and can be combined with thenAccept . channel.getIterableHistory().takeAsync(amount)提供了一个没有这个限制的更简单的 API,它返回一个CompletableFuture并且可以与thenAccept结合使用。

Even better would be using channel.retrieveMessageById(messageId) which only retrieves the message and fails if the message doesn't exist.更好的是使用channel.retrieveMessageById(messageId) ,它只检索消息,如果消息不存在则失败。 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 .然而,这在您的情况下是不需要的,因为您通过 id 编辑消息并且可以只使用它的失败响应而不是遇到TOCTOU Problem

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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