重新连接后无法更新以前的消息
Unable to update previous messages after reconnection
我创建了一个带有命令的机器人,允许用户为他们的频道配置某种 'feed'。
此提要应该发送一条消息,保存公会、频道和消息 ID。并在独立的更新周期中,尝试用新信息更新消息。
只要在同一个会话中,这一切都很好。
假设机器人由于不和谐中断而失去连接,并在 x 时间后重新连接,机器人似乎不再能够找到,因此不再更新消息。
特别是好像无法通过id取回消息
var message = await channel.GetMessageAsync(playtimeFeed.MessageId) as SocketUserMessage;
值得注意的是,我使用了 _settings
,它以 json 格式保存,并在 bot 重启时再次加载。
我也确认了该消息仍然存在于该频道的服务器中,具有相同的消息ID。并且该机器人有权查看该频道的消息历史记录。
所以我的问题是,为什么 GetMessageAsync
在重新连接后无法检索以前发布的消息?
最初调用的命令
public async Task BindPlaytimeFeedAsync(ICommandContext context)
{
var builder = await _scumService.GetTop25PlaytimeByDate(new DateTime(), DateTime.Now);
var message = await context.Channel.SendMessageAsync(null, false, builder.Build());
_settings.PlaytimeFeed = new MessageInfo()
{
GuildId = context.Guild.Id,
ChannelId = context.Channel.Id,
MessageId = message.Id,
};
var ptFeedMessage = await context.Channel.SendMessageAsync("Playtime feed is now bound to this channel (this message self-destructs in 5 seconds)");
await Task.Delay(5000);
await ptFeedMessage.DeleteAsync();
}
提要的刷新间隔是使用计时器与机器人本身一起定义的,如下所示。
...
_client = new DiscordSocketClient(
new DiscordSocketConfig
{
LogLevel = LogSeverity.Verbose,
AlwaysDownloadUsers = true, // Start the cache off with updated information.
MessageCacheSize = 1000
}
);
_service = ConfigureServices();
_feedInterval = new Timer(async (e) =>
{
Console.WriteLine("doing feed stuff");
await HandleFeedsAsync();
}, null, 15000, 300000);
CmdHandler = new CommandHandler(_service, state);
...
private async Task HandleFeedsAsync()
{
var botSettings = _service.GetService<ISettings>() as BotSettings;
await HandleKdFeedAsync(botSettings.KdFeed);
await HandlePlaytimeFeedAsync(botSettings.PlaytimeFeed);
await HandleWeeklyPlaytimeFeed(botSettings.WeeklyPlaytimeFeed);
await HandleAdminFeed(botSettings);
}
最终使用以下代码段覆盖消息。
private async Task HandlePlaytimeFeedAsync(MessageInfo playtimeFeed)
{
if (playtimeFeed == null)
return;
var scumService = _service.GetService<ScumService>();
var guild = _client.GetGuild(playtimeFeed.GuildId);
var channel = guild.GetTextChannel(playtimeFeed.ChannelId);
var message = await channel.GetMessageAsync(playtimeFeed.MessageId) as SocketUserMessage;
if (message == null)
return;
var builder = await scumService.GetTop25PlaytimeByDate(new DateTime(), DateTime.Now);
await message.ModifyAsync(prop =>
{
prop.Embed = builder.Build();
});
}
var message = await channel.GetMessageAsync(playtimeFeed.MessageId) as SocketUserMessage;
GetMessageAsync
方法尝试从缓存中检索消息作为 SocketUserMessage
,但是如果在缓存中找不到该消息,则会执行休息请求,这将 return RestUserMessge
。通过对 GetMessageAsync
的结果执行软转换,您可以获得 null if/when a RestUserMessage
是 returned。
当您处理的消息可能是 Socket 实体或 Rest 实体时,只需使用接口与之交互 -- IUserMessage
。
我创建了一个带有命令的机器人,允许用户为他们的频道配置某种 'feed'。
此提要应该发送一条消息,保存公会、频道和消息 ID。并在独立的更新周期中,尝试用新信息更新消息。
只要在同一个会话中,这一切都很好。
假设机器人由于不和谐中断而失去连接,并在 x 时间后重新连接,机器人似乎不再能够找到,因此不再更新消息。
特别是好像无法通过id取回消息
var message = await channel.GetMessageAsync(playtimeFeed.MessageId) as SocketUserMessage;
值得注意的是,我使用了 _settings
,它以 json 格式保存,并在 bot 重启时再次加载。
我也确认了该消息仍然存在于该频道的服务器中,具有相同的消息ID。并且该机器人有权查看该频道的消息历史记录。
所以我的问题是,为什么 GetMessageAsync
在重新连接后无法检索以前发布的消息?
最初调用的命令
public async Task BindPlaytimeFeedAsync(ICommandContext context)
{
var builder = await _scumService.GetTop25PlaytimeByDate(new DateTime(), DateTime.Now);
var message = await context.Channel.SendMessageAsync(null, false, builder.Build());
_settings.PlaytimeFeed = new MessageInfo()
{
GuildId = context.Guild.Id,
ChannelId = context.Channel.Id,
MessageId = message.Id,
};
var ptFeedMessage = await context.Channel.SendMessageAsync("Playtime feed is now bound to this channel (this message self-destructs in 5 seconds)");
await Task.Delay(5000);
await ptFeedMessage.DeleteAsync();
}
提要的刷新间隔是使用计时器与机器人本身一起定义的,如下所示。
...
_client = new DiscordSocketClient(
new DiscordSocketConfig
{
LogLevel = LogSeverity.Verbose,
AlwaysDownloadUsers = true, // Start the cache off with updated information.
MessageCacheSize = 1000
}
);
_service = ConfigureServices();
_feedInterval = new Timer(async (e) =>
{
Console.WriteLine("doing feed stuff");
await HandleFeedsAsync();
}, null, 15000, 300000);
CmdHandler = new CommandHandler(_service, state);
...
private async Task HandleFeedsAsync()
{
var botSettings = _service.GetService<ISettings>() as BotSettings;
await HandleKdFeedAsync(botSettings.KdFeed);
await HandlePlaytimeFeedAsync(botSettings.PlaytimeFeed);
await HandleWeeklyPlaytimeFeed(botSettings.WeeklyPlaytimeFeed);
await HandleAdminFeed(botSettings);
}
最终使用以下代码段覆盖消息。
private async Task HandlePlaytimeFeedAsync(MessageInfo playtimeFeed)
{
if (playtimeFeed == null)
return;
var scumService = _service.GetService<ScumService>();
var guild = _client.GetGuild(playtimeFeed.GuildId);
var channel = guild.GetTextChannel(playtimeFeed.ChannelId);
var message = await channel.GetMessageAsync(playtimeFeed.MessageId) as SocketUserMessage;
if (message == null)
return;
var builder = await scumService.GetTop25PlaytimeByDate(new DateTime(), DateTime.Now);
await message.ModifyAsync(prop =>
{
prop.Embed = builder.Build();
});
}
var message = await channel.GetMessageAsync(playtimeFeed.MessageId) as SocketUserMessage;
GetMessageAsync
方法尝试从缓存中检索消息作为 SocketUserMessage
,但是如果在缓存中找不到该消息,则会执行休息请求,这将 return RestUserMessge
。通过对 GetMessageAsync
的结果执行软转换,您可以获得 null if/when a RestUserMessage
是 returned。
当您处理的消息可能是 Socket 实体或 Rest 实体时,只需使用接口与之交互 -- IUserMessage
。