检测更新消息失败
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()
方法返回一个 空列表,除非您之前使用了 retrievePast 或 retrieveFuture,它们都返回 RestAction<List<Message>>
。这意味着您必须使用:
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 检测请求消息