From c259dd2af1f2a6fe178726597d38034efc344260 Mon Sep 17 00:00:00 2001 From: Scrub <72096833+ScrubN@users.noreply.github.com> Date: Sat, 15 Jun 2024 00:13:02 -0400 Subject: [PATCH] Fix WPF crash when getting filename for streams with missing info (#1098) * Fix ReplaceInvalidFilenameChars throwing on null input & add some null annotations * Update tests * Use underscores instead of dashes --- .../ToolTests/FilenameServiceTests.cs | 25 +++++++++++++++++-- TwitchDownloaderCore/Tools/FilenameService.cs | 11 ++++++-- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/TwitchDownloaderCore.Tests/ToolTests/FilenameServiceTests.cs b/TwitchDownloaderCore.Tests/ToolTests/FilenameServiceTests.cs index 078607d8..2a6a02cc 100644 --- a/TwitchDownloaderCore.Tests/ToolTests/FilenameServiceTests.cs +++ b/TwitchDownloaderCore.Tests/ToolTests/FilenameServiceTests.cs @@ -1,5 +1,4 @@ -using TwitchDownloaderCore.Extensions; -using TwitchDownloaderCore.Tools; +using TwitchDownloaderCore.Tools; namespace TwitchDownloaderCore.Tests.ToolTests { @@ -148,6 +147,17 @@ public void DoesNotInterpretBogusTemplateParameter() Assert.Equal(EXPECTED, result); } + [Fact] + public void GetFilenameDoesNotThrow_WhenNullOrDefaultInput() + { + const string TEMPLATE = "{title}_{id}_{date}_{channel}_{trim_start}_{trim_end}_{length}_{views}_{game}_{date_custom=\"s\"}_{trim_start_custom=\"hh\\-mm\\-ss\"}_{trim_end_custom=\"hh\\-mm\\-ss\"}_{length_custom=\"hh\\-mm\\-ss\"}"; + const string EXPECTED = "__1-1-01__00-00-00_00-00-00_00-00-00_0__0001-01-01T00_00_00_00-00-00_00-00-00_00-00-00"; + + var result = FilenameService.GetFilename(TEMPLATE, default, default, default, default, default, default, default, default); + + Assert.Equal(EXPECTED, result); + } + [Theory] [InlineData("\"", """)] [InlineData("*", "*")] @@ -166,6 +176,17 @@ public void CorrectlyReplacesInvalidFilenameCharacters(string str, string expect Assert.Equal(expected, actual); } + [Fact] + public void ReplaceInvalidFilenameCharactersDoesNotThrow_WhenNullInput() + { + const string? STR = null; + const string? EXPECTED = null; + + var actual = FilenameService.ReplaceInvalidFilenameChars(STR); + + Assert.Equal(EXPECTED, actual); + } + [Fact] public void GetNonCollidingNameWorks_WhenNoCollisionExists() { diff --git a/TwitchDownloaderCore/Tools/FilenameService.cs b/TwitchDownloaderCore/Tools/FilenameService.cs index 8f73faeb..8ae0ddf2 100644 --- a/TwitchDownloaderCore/Tools/FilenameService.cs +++ b/TwitchDownloaderCore/Tools/FilenameService.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.Text; @@ -9,7 +10,7 @@ namespace TwitchDownloaderCore.Tools { public static class FilenameService { - public static string GetFilename(string template, string title, string id, DateTime date, string channel, TimeSpan trimStart, TimeSpan trimEnd, long viewCount, string game) + public static string GetFilename(string template, [AllowNull] string title, [AllowNull] string id, DateTime date, [AllowNull] string channel, TimeSpan trimStart, TimeSpan trimEnd, long viewCount, [AllowNull] string game) { var videoLength = trimEnd - trimStart; @@ -86,8 +87,14 @@ private static string[] GetTemplateSubfolders(ref string fullPath) private static readonly char[] FilenameInvalidChars = Path.GetInvalidFileNameChars(); - public static string ReplaceInvalidFilenameChars(string filename) + [return: NotNullIfNotNull(nameof(filename))] + public static string ReplaceInvalidFilenameChars([AllowNull] string filename) { + if (string.IsNullOrEmpty(filename)) + { + return filename; + } + const string TIMESTAMP_PATTERN = /*lang=regex*/ @"(?<=\d):(?=\d\d)"; var newName = Regex.Replace(filename, TIMESTAMP_PATTERN, "_");