From d9c06bacda73cfe5d750564ef4b4d55cfefa1332 Mon Sep 17 00:00:00 2001 From: Tyrrrz <1935960+Tyrrrz@users.noreply.github.com> Date: Tue, 3 Jan 2023 10:34:53 +0200 Subject: [PATCH] Trim dots at the end of filenames on Windows Closes #977 --- .../Exporting/ExportRequest.cs | 82 ++++++++++--------- DiscordChatExporter.Core/Utils/PathEx.cs | 9 ++ 2 files changed, 52 insertions(+), 39 deletions(-) diff --git a/DiscordChatExporter.Core/Exporting/ExportRequest.cs b/DiscordChatExporter.Core/Exporting/ExportRequest.cs index 7d1b1a9..f7e251c 100644 --- a/DiscordChatExporter.Core/Exporting/ExportRequest.cs +++ b/DiscordChatExporter.Core/Exporting/ExportRequest.cs @@ -40,45 +40,6 @@ public partial record ExportRequest( public partial record ExportRequest { - private static string GetOutputBaseFilePath( - Guild guild, - Channel channel, - string outputPath, - ExportFormat format, - Snowflake? after = null, - Snowflake? before = null) - { - // Formats path - outputPath = Regex.Replace(outputPath, "%.", m => - PathEx.EscapeFileName(m.Value switch - { - "%g" => guild.Id.ToString(), - "%G" => guild.Name, - "%t" => channel.Category.Id.ToString(), - "%T" => channel.Category.Name, - "%c" => channel.Id.ToString(), - "%C" => channel.Name, - "%p" => channel.Position?.ToString() ?? "0", - "%P" => channel.Category.Position?.ToString() ?? "0", - "%a" => after?.ToDate().ToString("yyyy-MM-dd") ?? "", - "%b" => before?.ToDate().ToString("yyyy-MM-dd") ?? "", - "%d" => DateTimeOffset.Now.ToString("yyyy-MM-dd"), - "%%" => "%", - _ => m.Value - }) - ); - - // Output is a directory - if (Directory.Exists(outputPath) || string.IsNullOrWhiteSpace(Path.GetExtension(outputPath))) - { - var fileName = GetDefaultOutputFileName(guild, channel, format, after, before); - return Path.Combine(outputPath, fileName); - } - - // Output is a file - return outputPath; - } - public static string GetDefaultOutputFileName( Guild guild, Channel channel, @@ -120,4 +81,47 @@ public partial record ExportRequest return PathEx.EscapeFileName(buffer.ToString()); } + + private static string GetOutputBaseFilePath( + Guild guild, + Channel channel, + string outputPath, + ExportFormat format, + Snowflake? after = null, + Snowflake? before = null) + { + // Format path + var actualOutputPath = PathEx.EscapeFileName( + Regex.Replace( + outputPath, + "%.", + m => m.Value switch + { + "%g" => guild.Id.ToString(), + "%G" => guild.Name, + "%t" => channel.Category.Id.ToString(), + "%T" => channel.Category.Name, + "%c" => channel.Id.ToString(), + "%C" => channel.Name, + "%p" => channel.Position?.ToString() ?? "0", + "%P" => channel.Category.Position?.ToString() ?? "0", + "%a" => after?.ToDate().ToString("yyyy-MM-dd") ?? "", + "%b" => before?.ToDate().ToString("yyyy-MM-dd") ?? "", + "%d" => DateTimeOffset.Now.ToString("yyyy-MM-dd"), + "%%" => "%", + _ => m.Value + } + ) + ); + + // Output is a directory + if (Directory.Exists(actualOutputPath) || string.IsNullOrWhiteSpace(Path.GetExtension(actualOutputPath))) + { + var fileName = GetDefaultOutputFileName(guild, channel, format, after, before); + return Path.Combine(actualOutputPath, fileName); + } + + // Output is a file + return actualOutputPath; + } } \ No newline at end of file diff --git a/DiscordChatExporter.Core/Utils/PathEx.cs b/DiscordChatExporter.Core/Utils/PathEx.cs index 65469b7..237e83b 100644 --- a/DiscordChatExporter.Core/Utils/PathEx.cs +++ b/DiscordChatExporter.Core/Utils/PathEx.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.IO; +using System.Runtime.InteropServices; using System.Text; namespace DiscordChatExporter.Core.Utils; @@ -15,6 +16,14 @@ public static class PathEx foreach (var c in path) buffer.Append(!InvalidFileNameChars.Contains(c) ? c : '_'); + // File names cannot end with a dot on Windows + // https://github.com/Tyrrrz/DiscordChatExporter/issues/977 + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + while (buffer.Length > 0 && buffer[^1] == '.') + buffer.Remove(buffer.Length - 1, 1); + } + return buffer.ToString(); }