diff --git a/PluralKit.Bot/Services/WebhookCacheService.cs b/PluralKit.Bot/Services/WebhookCacheService.cs index 5844252d..cf107d56 100644 --- a/PluralKit.Bot/Services/WebhookCacheService.cs +++ b/PluralKit.Bot/Services/WebhookCacheService.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Concurrent; using System.Linq; +using System.Net.Http; using System.Threading.Tasks; using Discord; using Discord.Webhook; @@ -54,13 +55,26 @@ namespace PluralKit.Bot return await GetWebhook(webhook.Channel); } - private async Task GetOrCreateWebhook(ITextChannel channel) => - await FindExistingWebhook(channel) ?? await DoCreateWebhook(channel); + private async Task GetOrCreateWebhook(ITextChannel channel) + { + _logger.Debug("Webhook for channel {Channel} not found in cache, trying to fetch", channel.Id); + return await FindExistingWebhook(channel) ?? await DoCreateWebhook(channel); + } private async Task FindExistingWebhook(ITextChannel channel) { _logger.Debug("Finding webhook for channel {Channel}", channel.Id); - return (await channel.GetWebhooksAsync()).FirstOrDefault(IsWebhookMine); + try + { + return (await channel.GetWebhooksAsync()).FirstOrDefault(IsWebhookMine); + } + catch (HttpRequestException e) + { + _logger.Warning(e, "Error occurred while fetching webhook list"); + // This happens sometimes when Discord returns a malformed request for the webhook list + // Nothing we can do than just assume that none exist and return null. + return null; + } } private Task DoCreateWebhook(ITextChannel channel) diff --git a/PluralKit.Bot/Services/WebhookExecutorService.cs b/PluralKit.Bot/Services/WebhookExecutorService.cs index e0604079..f8b17468 100644 --- a/PluralKit.Bot/Services/WebhookExecutorService.cs +++ b/PluralKit.Bot/Services/WebhookExecutorService.cs @@ -96,7 +96,22 @@ namespace PluralKit.Bot // DiscordWebhookClient has a sync network call in its constructor (!!!) // and we want to punt that onto a task queue, so we do that. - return Task.Run(() => new DiscordWebhookClient(webhook)); + return Task.Run(async () => + { + try + { + return new DiscordWebhookClient(webhook); + } + catch (InvalidOperationException) + { + // TODO: does this leak stuff inside the DiscordWebhookClient created above? + + // Webhook itself was found in cache, but has been deleted on the channel + // We request a new webhook instead + return new DiscordWebhookClient(await _webhookCache.InvalidateAndRefreshWebhook(webhook)); + } + + }); } private string FixClyde(string name)