From dfc36b45811de8245be7bfaca00148af7465f3db Mon Sep 17 00:00:00 2001 From: Jason Dove Date: Mon, 6 Mar 2023 18:21:34 -0600 Subject: [PATCH] case-insensitive file extensions in local scanner (#1197) --- CHANGELOG.md | 4 ++ .../Core/Metadata/MovieFolderScannerTests.cs | 45 +++++++++++++++++++ .../Core/Metadata/LocalFolderScanner.cs | 10 ++--- 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2cd5e849a..d21ba7824 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Note that these subtitles are not currently supported in ETV, but they did cause a playback issue - Fix Jellyfin, Emby and Plex library scans that wouldn't work in certain timezones +### Changed +- Ignore case of video and audio file extensions in local folder scanner + - For example, the scanner will now find `movie.MKV` as well as `movie.mkv` on case-sensitive filesystems + ## [0.7.5-beta] - 2023-03-05 ### Added - Use AV1 hardware-accelerated decoder with VAAPI, QSV, NVIDIA when available diff --git a/ErsatzTV.Scanner.Tests/Core/Metadata/MovieFolderScannerTests.cs b/ErsatzTV.Scanner.Tests/Core/Metadata/MovieFolderScannerTests.cs index 794a87b01..f2797505c 100644 --- a/ErsatzTV.Scanner.Tests/Core/Metadata/MovieFolderScannerTests.cs +++ b/ErsatzTV.Scanner.Tests/Core/Metadata/MovieFolderScannerTests.cs @@ -121,6 +121,51 @@ public class MovieFolderScannerTests It.Is(i => i.MediaVersions.Head().MediaFiles.Head().Path == moviePath)), Times.Once); } + + [Test] + public async Task NewMovie_Statistics_And_FallbackMetadata_MixedCase( + [ValueSource(typeof(LocalFolderScanner), nameof(LocalFolderScanner.VideoFileExtensions))] + string videoExtension) + { + char[] mixedCaseExtension = videoExtension.ToLowerInvariant().ToArray(); + mixedCaseExtension[2] = char.ToUpper(mixedCaseExtension[2]); + videoExtension = new string(mixedCaseExtension); + + string moviePath = Path.Combine( + FakeRoot, + Path.Combine("Movie (2020)", $"Movie (2020){videoExtension}")); + + MovieFolderScanner service = GetService( + new FakeFileEntry(moviePath) { LastWriteTime = DateTime.Now } + ); + var libraryPath = new LibraryPath + { Id = 1, Path = FakeRoot, LibraryFolders = new List() }; + + Either result = await service.ScanFolder( + libraryPath, + FFmpegPath, + FFprobePath, + 0, + 1, + CancellationToken.None); + + result.IsRight.Should().BeTrue(); + + _movieRepository.Verify(x => x.GetOrAdd(It.IsAny(), It.IsAny()), Times.Once); + _movieRepository.Verify(x => x.GetOrAdd(libraryPath, moviePath), Times.Once); + + _localStatisticsProvider.Verify( + x => x.RefreshStatistics( + FFmpegPath, + FFprobePath, + It.Is(i => i.MediaVersions.Head().MediaFiles.Head().Path == moviePath)), + Times.Once); + + _localMetadataProvider.Verify( + x => x.RefreshFallbackMetadata( + It.Is(i => i.MediaVersions.Head().MediaFiles.Head().Path == moviePath)), + Times.Once); + } [Test] public async Task NewMovie_Statistics_And_SidecarMetadata_MovieNameNfo( diff --git a/ErsatzTV.Scanner/Core/Metadata/LocalFolderScanner.cs b/ErsatzTV.Scanner/Core/Metadata/LocalFolderScanner.cs index 26404e792..1eab8be88 100644 --- a/ErsatzTV.Scanner/Core/Metadata/LocalFolderScanner.cs +++ b/ErsatzTV.Scanner/Core/Metadata/LocalFolderScanner.cs @@ -22,24 +22,24 @@ public abstract class LocalFolderScanner { ".mpg", ".mp2", ".mpeg", ".mpe", ".mpv", ".ogg", ".mp4", ".m4p", ".m4v", ".avi", ".wmv", ".mov", ".mkv", ".ts", ".webm" - }.ToImmutableHashSet(); + }.ToImmutableHashSet(StringComparer.OrdinalIgnoreCase); public static readonly ImmutableHashSet AudioFileExtensions = new[] { ".aac", ".alac", ".dff", ".dsf", ".flac", ".mp3", ".m4a", ".ogg", ".opus", ".oga", ".ogx", ".spx", ".wav", ".wma" - }.ToImmutableHashSet(); + }.ToImmutableHashSet(StringComparer.OrdinalIgnoreCase); public static readonly ImmutableHashSet ImageFileExtensions = new[] { "jpg", "jpeg", "png", "gif", "tbn" - }.ToImmutableHashSet(); + }.ToImmutableHashSet(StringComparer.OrdinalIgnoreCase); public static readonly ImmutableHashSet ExtraFiles = new[] { "behindthescenes", "deleted", "featurette", "interview", "scene", "short", "trailer", "other" - }.ToImmutableHashSet(); + }.ToImmutableHashSet(StringComparer.OrdinalIgnoreCase); public static readonly ImmutableHashSet ExtraDirectories = new List { @@ -48,7 +48,7 @@ public abstract class LocalFolderScanner "extras", "specials" } .Map(s => $"{Path.DirectorySeparatorChar}{s}{Path.DirectorySeparatorChar}") - .ToImmutableHashSet(); + .ToImmutableHashSet(StringComparer.OrdinalIgnoreCase); private readonly IClient _client; private readonly IFFmpegPngService _ffmpegPngService;