diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Caching/ImageCache.cs b/src/Snap.Hutao/Snap.Hutao/Core/Caching/ImageCache.cs index ec25bf9e..af792574 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Caching/ImageCache.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Caching/ImageCache.cs @@ -1,6 +1,7 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. +using Microsoft.Extensions.Caching.Memory; using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient; using Snap.Hutao.Core.IO; using Snap.Hutao.Core.IO.Hashing; @@ -28,6 +29,7 @@ namespace Snap.Hutao.Core.Caching; internal sealed partial class ImageCache : IImageCache, IImageCacheFilePathOperation { private const string CacheFolderName = nameof(ImageCache); + private const string CacheFailedDownloadTasksName = $"{nameof(ImageCache)}.FailedDownloadTasks"; private readonly FrozenDictionary retryCountToDelay = FrozenDictionary.ToFrozenDictionary( [ @@ -38,10 +40,11 @@ internal sealed partial class ImageCache : IImageCache, IImageCacheFilePathOpera private readonly ConcurrentDictionary concurrentTasks = new(); - private readonly IHttpClientFactory httpClientFactory; private readonly IHttpRequestMessageBuilderFactory httpRequestMessageBuilderFactory; + private readonly IHttpClientFactory httpClientFactory; private readonly IServiceProvider serviceProvider; private readonly ILogger logger; + private readonly IMemoryCache memoryCache; private string? baseFolder; private string? cacheFolder; @@ -192,6 +195,16 @@ internal sealed partial class ImageCache : IImageCache, IImageCacheFilePathOpera if (responseMessage.IsSuccessStatusCode) { + if (responseMessage.Content.Headers.ContentType?.MediaType is "application/json") + { +#if DEBUG + DebugTrack(uri); +#endif + string raw = await responseMessage.Content.ReadAsStringAsync().ConfigureAwait(false); + logger.LogColorizedCritical("Failed to download '{Uri}' with unexpected body '{Raw}'", (uri, ConsoleColor.Red), (raw, ConsoleColor.DarkYellow)); + return; + } + using (Stream httpStream = await responseMessage.Content.ReadAsStreamAsync().ConfigureAwait(false)) { using (FileStream fileStream = File.Create(baseFile)) @@ -214,10 +227,25 @@ internal sealed partial class ImageCache : IImageCache, IImageCacheFilePathOpera } default: +#if DEBUG + DebugTrack(uri); +#endif + logger.LogColorizedCritical("Failed to download '{Uri}' with status code '{StatusCode}'", (uri, ConsoleColor.Red), (responseMessage.StatusCode, ConsoleColor.DarkYellow)); return; } } } } } -} \ No newline at end of file +} + +#if DEBUG +internal partial class ImageCache +{ + private void DebugTrack(Uri uri) + { + HashSet? set = memoryCache.GetOrCreate(CacheFailedDownloadTasksName, entry => entry.Value ??= new HashSet()) as HashSet; + set?.Add(uri.ToString()); + } +} +#endif \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Logging/LoggerExtension.cs b/src/Snap.Hutao/Snap.Hutao/Core/Logging/LoggerExtension.cs index 199194dd..747a3471 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Logging/LoggerExtension.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Logging/LoggerExtension.cs @@ -151,7 +151,7 @@ internal static class LoggerExtension } else { - resultMessageBuilder.Append(ConsoleVirtualTerminalSequences.Default); + resultMessageBuilder.Append(ConsoleVirtualTerminalSequences.ForegroundWhite); } } } @@ -164,7 +164,7 @@ internal static class LoggerExtension // Restore default colors if (message.ForegroundColor.HasValue || message.BackgroundColor.HasValue) { - resultMessageBuilder.Append(ConsoleVirtualTerminalSequences.Default); + resultMessageBuilder.Append(ConsoleVirtualTerminalSequences.ForegroundWhite); } return resultMessageBuilder.ToString(); diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/TestPage.xaml b/src/Snap.Hutao/Snap.Hutao/View/Page/TestPage.xaml index 581fe913..d0229615 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Page/TestPage.xaml +++ b/src/Snap.Hutao/Snap.Hutao/View/Page/TestPage.xaml @@ -91,6 +91,13 @@ Style="{ThemeResource SettingButtonStyle}"/> + +