Невозможно обновить предыдущие сообщения после переподключения - PullRequest
0 голосов
/ 09 июля 2019

Я создал бота с помощью команды, которая позволяет пользователю настраивать своего рода «канал» для своего канала.

Этот канал предназначен для отправки сообщения, сохранения гильдии, канала и идентификатора сообщения.И в автономном цикле обновления попробуйте обновить сообщение новой информацией.

Все это работает довольно хорошо, если оно находится в пределах одного сеанса.

Скажите, что бот теряет соединение из-за разрыва диска, и повторно подключается через некоторое время,кажется, что бот больше не может найти, и, следовательно, больше не обновляет сообщение.

В частности, кажется, что он не может получить сообщение по id
var message = await channel.GetMessageAsync(playtimeFeed.MessageId) as SocketUserMessage;

Стоит отметить, что я использую _settings, который сохраняется в формате json и снова загружается при перезагрузке бота.

Я также подтвердил, что сообщение все еще существует на сервере в канале с тем же идентификатором сообщения.И что у бота есть права на просмотр истории сообщений канала.

Таким образом, мой вопрос, почему 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();
    });
}

1 Ответ

1 голос
/ 10 июля 2019

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

Метод GetMessageAsync пытается извлечь сообщение из кэша как SocketUserMessage, если, однако, сообщение не найдено в кэше, выполняется запрос на отдых, который возвращает RestUserMessge. Выполнив мягкое приведение к результату GetMessageAsync, вы можете получить значение NULL, если / когда возвращается RestUserMessage.

Если существует вероятность того, что сообщение, с которым вы имеете дело, может быть либо объектом Socket, либо объектом Rest, просто используйте интерфейс для взаимодействия с ним - IUserMessage.

...