检测更新消息失败

Posted

技术标签:

【中文标题】检测更新消息失败【英文标题】:Detecting failure to update a message 【发布时间】:2019-12-28 03:15:53 【问题描述】:

我正在开发一个不和谐的机器人,如果特定消息不存在,则应该在其中更新或创建它。如果消息已被具有访问权限的人删除,则会出现问题... 创建一个悬空引用,并在需要更新时引发异常。如何检测当前频道中是否不存在具有特定 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();

【问题讨论】:

阅读queue的文档 【参考方案1】:

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

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() 方法返回一个 空列表,除非您之前使用了 retrievePastretrieveFuture,它们都返回 RestAction&lt;List&lt;Message&gt;&gt;。这意味着您必须使用:

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

每次通话最多只能发送 100 条消息。 channel.getIterableHistory().takeAsync(amount) 提供了一个没有此限制的更简单的 API,它返回一个 CompletableFuture 并且可以与 thenAccept 结合使用。

更好的是使用channel.retrieveMessageById(messageId),它只检索消息并在消息不存在时失败。但是,在您的情况下不需要这样做,因为您通过 id 编辑消息并且可以只使用该消息的失败响应而不是遇到TOCTOU Problem。

【讨论】:

以上是关于检测更新消息失败的主要内容,如果未能解决你的问题,请参考以下文章

Symfony Messenger / RabbitMQ 检测请求消息

Dapper.SimpleCRUD 插入/更新/获取失败并显示消息“实体必须具有至少一个 [Key] 属性”

检测传入的 SMS 消息

如果在jsp中删除记录失败,则显示错误消息

Rabbit-MQ 2

Java小程序加载失败时如何显示消息?