diff --git a/.gitignore b/.gitignore index ef8150c0e..d967f8b06 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ # User-specific files .vs/ +.vscode/ .idea/ *.suo *.user @@ -9,4 +10,4 @@ bin/ obj/ # Test results -TestResults/ \ No newline at end of file +TestResults/ diff --git a/DiscordChatExporter.Core/Exporting/ExportRequest.cs b/DiscordChatExporter.Core/Exporting/ExportRequest.cs index 30a7cb285..411379e92 100644 --- a/DiscordChatExporter.Core/Exporting/ExportRequest.cs +++ b/DiscordChatExporter.Core/Exporting/ExportRequest.cs @@ -154,27 +154,39 @@ private static string FormatPath( Channel channel, Snowflake? after, Snowflake? before - ) => - Regex.Replace( + ) + { + string preFormattedPath = Regex.Replace( path, "%.", m => PathEx.EscapeFileName( m.Value switch { + // On %T and %P, we have to make sure that we still get name and position of the category if the channel is a thread "%g" => guild.Id.ToString(), "%G" => guild.Name, "%t" => channel.Parent?.Id.ToString() ?? "", - "%T" => channel.Parent?.Name ?? "", + "%T" + => channel.IsThread + ? (channel.Parent?.Parent?.Name ?? "") + : channel.Parent?.Name ?? "", "%c" => channel.Id.ToString(), "%C" => channel.Name, "%p" => channel.Position?.ToString(CultureInfo.InvariantCulture) ?? "0", "%P" - => channel.Parent?.Position?.ToString(CultureInfo.InvariantCulture) - ?? "0", + => channel.IsThread + ? ( + channel + .Parent?.Parent + ?.Position + ?.ToString(CultureInfo.InvariantCulture) ?? "" + ) + : channel.Parent?.Position?.ToString(CultureInfo.InvariantCulture) + ?? "0", "%a" => after?.ToDate().ToString("yyyy-MM-dd", CultureInfo.InvariantCulture) @@ -194,6 +206,32 @@ private static string FormatPath( ) ); + // We are looking for any structure in the path which contains either %y or %z. If the channel is a thread, we can resolve the placeholders, otherwise, that whole structure needs to be removed. + string formattedPath = Regex.Replace( + preFormattedPath, + @"\\[^\\]*%[xyz][^\\]*\\", + m => + channel.IsThread + ? Regex.Replace( + m.Value, + "%[xyz]", + n => + n.Value switch + { + "%x" => channel.Parent?.Id.ToString() ?? "", + "%y" + => channel + .Parent?.Position + ?.ToString(CultureInfo.InvariantCulture) ?? "", + "%z" => channel.Parent?.Name ?? "", + _ => n.Value + } + ) + : "\\" + ); + return formattedPath; + } + private static string GetOutputBaseFilePath( Guild guild, Channel channel,