From c69211797ff04e361d32d87d106641739e0fe8b1 Mon Sep 17 00:00:00 2001 From: Tyrrrz <1935960+Tyrrrz@users.noreply.github.com> Date: Mon, 3 Jul 2023 18:35:28 +0300 Subject: [PATCH] Clean up --- .../Infra/ExportWrapper.cs | 27 ++++--- .../Exporting/ExportAssetDownloader.cs | 71 +++++++++---------- .../Exporting/ExportContext.cs | 34 ++++----- 3 files changed, 60 insertions(+), 72 deletions(-) diff --git a/DiscordChatExporter.Cli.Tests/Infra/ExportWrapper.cs b/DiscordChatExporter.Cli.Tests/Infra/ExportWrapper.cs index 76b877f..5433909 100644 --- a/DiscordChatExporter.Cli.Tests/Infra/ExportWrapper.cs +++ b/DiscordChatExporter.Cli.Tests/Infra/ExportWrapper.cs @@ -48,23 +48,22 @@ public static class ExportWrapper var fileName = channelId.ToString() + '.' + format.GetFileExtension(); var filePath = Path.Combine(DirPath, fileName); - // Lock separately for each channel and format - using (await Locker.LockAsync(filePath)) + using var _ = await Locker.LockAsync(filePath); + using var console = new FakeConsole(); + + // Perform the export only if it hasn't been done before + if (!File.Exists(filePath)) { - // Perform the export only if it hasn't been done before - if (!File.Exists(filePath)) + await new ExportChannelsCommand { - await new ExportChannelsCommand - { - Token = Secrets.DiscordToken, - ChannelIds = new[] { channelId }, - ExportFormat = format, - OutputPath = filePath - }.ExecuteAsync(new FakeConsole()); - } - - return await File.ReadAllTextAsync(filePath); + Token = Secrets.DiscordToken, + ChannelIds = new[] { channelId }, + ExportFormat = format, + OutputPath = filePath + }.ExecuteAsync(console); } + + return await File.ReadAllTextAsync(filePath); } public static async ValueTask ExportAsHtmlAsync(Snowflake channelId) => Html.Parse( diff --git a/DiscordChatExporter.Core/Exporting/ExportAssetDownloader.cs b/DiscordChatExporter.Core/Exporting/ExportAssetDownloader.cs index 2a0ed91..77ab32e 100644 --- a/DiscordChatExporter.Core/Exporting/ExportAssetDownloader.cs +++ b/DiscordChatExporter.Core/Exporting/ExportAssetDownloader.cs @@ -38,50 +38,49 @@ internal partial class ExportAssetDownloader var fileName = GetFileNameFromUrl(url); var filePath = Path.Combine(_workingDirPath, fileName); - using (await Locker.LockAsync(filePath, cancellationToken)) - { - if (_pathCache.TryGetValue(url, out var cachedFilePath)) - return cachedFilePath; + using var _ = await Locker.LockAsync(filePath, cancellationToken); + + if (_pathCache.TryGetValue(url, out var cachedFilePath)) + return cachedFilePath; - // Reuse existing files if we're allowed to - if (_reuse && File.Exists(filePath)) - return _pathCache[url] = filePath; + // Reuse existing files if we're allowed to + if (_reuse && File.Exists(filePath)) + return _pathCache[url] = filePath; - Directory.CreateDirectory(_workingDirPath); + Directory.CreateDirectory(_workingDirPath); + + await Http.ResiliencePolicy.ExecuteAsync(async () => + { + // Download the file + using var response = await Http.Client.GetAsync(url, cancellationToken); + await using (var output = File.Create(filePath)) + await response.Content.CopyToAsync(output, cancellationToken); - await Http.ResiliencePolicy.ExecuteAsync(async () => + // Try to set the file date according to the last-modified header + try { - // Download the file - using var response = await Http.Client.GetAsync(url, cancellationToken); - await using (var output = File.Create(filePath)) - await response.Content.CopyToAsync(output, cancellationToken); + var lastModified = response.Content.Headers.TryGetValue("Last-Modified")?.Pipe(s => + DateTimeOffset.TryParse(s, CultureInfo.InvariantCulture, DateTimeStyles.None, out var instant) + ? instant + : (DateTimeOffset?)null + ); - // Try to set the file date according to the last-modified header - try + if (lastModified is not null) { - var lastModified = response.Content.Headers.TryGetValue("Last-Modified")?.Pipe(s => - DateTimeOffset.TryParse(s, CultureInfo.InvariantCulture, DateTimeStyles.None, out var instant) - ? instant - : (DateTimeOffset?)null - ); - - if (lastModified is not null) - { - File.SetCreationTimeUtc(filePath, lastModified.Value.UtcDateTime); - File.SetLastWriteTimeUtc(filePath, lastModified.Value.UtcDateTime); - File.SetLastAccessTimeUtc(filePath, lastModified.Value.UtcDateTime); - } + File.SetCreationTimeUtc(filePath, lastModified.Value.UtcDateTime); + File.SetLastWriteTimeUtc(filePath, lastModified.Value.UtcDateTime); + File.SetLastAccessTimeUtc(filePath, lastModified.Value.UtcDateTime); } - catch - { - // This can apparently fail for some reason. - // Updating the file date is not a critical task, so we'll just ignore exceptions thrown here. - // https://github.com/Tyrrrz/DiscordChatExporter/issues/585 - } - }); + } + catch + { + // This can apparently fail for some reason. + // Updating the file date is not a critical task, so we'll just ignore exceptions thrown here. + // https://github.com/Tyrrrz/DiscordChatExporter/issues/585 + } + }); - return _pathCache[url] = filePath; - } + return _pathCache[url] = filePath; } } diff --git a/DiscordChatExporter.Core/Exporting/ExportContext.cs b/DiscordChatExporter.Core/Exporting/ExportContext.cs index 7309df6..1700992 100644 --- a/DiscordChatExporter.Core/Exporting/ExportContext.cs +++ b/DiscordChatExporter.Core/Exporting/ExportContext.cs @@ -89,27 +89,17 @@ internal class ExportContext public Role? TryGetRole(Snowflake id) => _roles.GetValueOrDefault(id); - public Color? TryGetUserColor(Snowflake id) - { - var memberRoles = GetUserRoles(id); - - return memberRoles? - .Where(r => r.Color is not null) - .Select(r => r.Color) - .FirstOrDefault(); - } - - public IReadOnlyList GetUserRoles(Snowflake id) - { - var member = TryGetMember(id); - - return member? - .RoleIds - .Select(TryGetRole) - .WhereNotNull() - .OrderByDescending(r => r.Position) - .ToArray() ?? Array.Empty(); - } + public IReadOnlyList GetUserRoles(Snowflake id) => TryGetMember(id)? + .RoleIds + .Select(TryGetRole) + .WhereNotNull() + .OrderByDescending(r => r.Position) + .ToArray() ?? Array.Empty(); + + public Color? TryGetUserColor(Snowflake id) => GetUserRoles(id) + .Where(r => r.Color is not null) + .Select(r => r.Color) + .FirstOrDefault(); public async ValueTask ResolveAssetUrlAsync(string url, CancellationToken cancellationToken = default) { @@ -122,7 +112,7 @@ internal class ExportContext var relativeFilePath = Path.GetRelativePath(Request.OutputDirPath, filePath); // Prefer relative paths so that the output files can be copied around without breaking references. - // If the assets path is outside of the export directory, use an absolute path instead. + // If the asset directory is outside of the export directory, use an absolute path instead. var optimalFilePath = relativeFilePath.StartsWith(".." + Path.DirectorySeparatorChar, StringComparison.Ordinal) || relativeFilePath.StartsWith(".." + Path.AltDirectorySeparatorChar, StringComparison.Ordinal)