重新连接后无法更新以前的消息

时间:2019-07-09 15:07:00

标签: c# discord.net

我使用命令创建了一个漫游器,该漫游器允许用户为自己的频道配置某种“馈送”。

该Feed应该发送一条消息,并保存行会,频道和消息ID。并且在独立的更新周期中,尝试使用新信息更新消息。

只要它在同一会话中,这一切都很好。

假设机器人由于不正常的中断而失去了连接,并在x时间后重新连接,机器人似乎不再能够找到并因此更新了消息。

尤其是,它似乎无法通过id检索消息
var message = await channel.GetMessageAsync(playtimeFeed.MessageId) as SocketUserMessage;

值得注意的是,我使用的是_settings,它以json格式保存,并在机器人重启时再次加载。

我还确认了该消息仍在通道中的服务器中,并且具有相同的消息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();
}

Feed的刷新间隔是在机器人本身旁边使用计时器定义的,如下所示。

...
_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();
    });
}

1 个答案:

答案 0 :(得分:1)

var message = await channel.GetMessageAsync(playtimeFeed.MessageId) as SocketUserMessage;

GetMessageAsync方法尝试以SocketUserMessage的形式从缓存中检索消息,但是,如果在缓存中找不到该消息,则会执行一个休息请求,该请求将返回RestUserMessge。通过对GetMessageAsync的结果执行软转换,如果/当返回RestUserMessage时,您可以得到null。

当您处理的消息有可能是Socket实体或Rest实体时,只需使用该接口与之交互-IUserMessage