From f32b8d3b843fab86c011dc9bc44ebc63c142e1a8 Mon Sep 17 00:00:00 2001 From: panko Date: Sun, 27 Sep 2026 16:30:31 -0400 Subject: Backport pull request #17964 from jellyfin/release-12.z Ignore Sample subfolders when resolving movie folders Original-merge: 40c7e44953d262bdc48437f8083a8c83417ef4c7 Merged-by: crobibero Backported-by: Cody Robibero --- Emby.Naming/Common/NamingOptions.cs | 6 ++ .../Library/MovieResolverTests.cs | 89 ++++++++++++++++++++++ 2 files changed, 95 insertions(+) diff --git a/Emby.Naming/Common/NamingOptions.cs b/Emby.Naming/Common/NamingOptions.cs index 9ecefb4c7b..58d6e012f9 100644 --- a/Emby.Naming/Common/NamingOptions.cs +++ b/Emby.Naming/Common/NamingOptions.cs @@ -542,6 +542,12 @@ namespace Emby.Naming.Common "samples", MediaType.Video), + new ExtraRule( + ExtraType.Sample, + ExtraRuleType.DirectoryName, + "sample", + MediaType.Video), + new ExtraRule( ExtraType.Short, ExtraRuleType.DirectoryName, diff --git a/tests/Jellyfin.Server.Implementations.Tests/Library/MovieResolverTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Library/MovieResolverTests.cs index e1346a8436..3aac3cdc43 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Library/MovieResolverTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Library/MovieResolverTests.cs @@ -10,6 +10,7 @@ using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Configuration; using MediaBrowser.Model.IO; using Microsoft.Extensions.Logging; using Moq; @@ -89,4 +90,92 @@ public class MovieResolverTests Assert.All(result.Items, item => Assert.IsType(item)); Assert.Single(((Video)result.Items[0]).LocalAlternateVersions); } + + [Fact] + public void AllExtrasTypesFolderNames_ContainsSampleSingularAndPlural() + { + Assert.True(_namingOptions.AllExtrasTypesFolderNames.ContainsKey("sample")); + Assert.True(_namingOptions.AllExtrasTypesFolderNames.ContainsKey("Sample")); + Assert.True(_namingOptions.AllExtrasTypesFolderNames.ContainsKey("samples")); + } + + [Theory] + [InlineData("Sample")] + [InlineData("sample")] + [InlineData("SAMPLE")] + [InlineData("samples")] + public void ResolvePath_MovieFolderWithSampleSubfolder_ResolvesToMovie(string sampleDirName) + { + var libraryManager = new Mock(); + libraryManager.Setup(m => m.GetLibraryOptions(It.IsAny())).Returns(new LibraryOptions()); + libraryManager.Setup(m => m.IgnoreFile(It.IsAny(), It.IsAny())).Returns(false); + + var resolver = new MovieResolver(Mock.Of(), Mock.Of>(), _namingOptions, Mock.Of(), _videoListResolver); + var args = new ItemResolveArgs( + Mock.Of(), + libraryManager.Object) + { + Parent = new Folder(), + CollectionType = CollectionType.movies, + FileInfo = new FileSystemMetadata + { + FullName = "/media/Outer Colony (2026)", + IsDirectory = true + }, + FileSystemChildren = new[] + { + new FileSystemMetadata + { + FullName = "/media/Outer Colony (2026)/Outer Colony (2026).mkv", + Name = "Outer Colony (2026).mkv" + }, + new FileSystemMetadata + { + FullName = "/media/Outer Colony (2026)/" + sampleDirName, + Name = sampleDirName, + IsDirectory = true + } + } + }; + + Assert.IsType(resolver.ResolvePath(args)); + } + + [Fact] + public void ResolvePath_MovieFolderWithRealSubfolder_DoesNotResolveToSingleMovie() + { + var libraryManager = new Mock(); + libraryManager.Setup(m => m.GetLibraryOptions(It.IsAny())).Returns(new LibraryOptions()); + libraryManager.Setup(m => m.IgnoreFile(It.IsAny(), It.IsAny())).Returns(false); + + var resolver = new MovieResolver(Mock.Of(), Mock.Of>(), _namingOptions, Mock.Of(), _videoListResolver); + var args = new ItemResolveArgs( + Mock.Of(), + libraryManager.Object) + { + Parent = new Folder(), + CollectionType = CollectionType.movies, + FileInfo = new FileSystemMetadata + { + FullName = "/media/Outer Colony (2026)", + IsDirectory = true + }, + FileSystemChildren = new[] + { + new FileSystemMetadata + { + FullName = "/media/Outer Colony (2026)/Outer Colony (2026).mkv", + Name = "Outer Colony (2026).mkv" + }, + new FileSystemMetadata + { + FullName = "/media/Outer Colony (2026)/Feature", + Name = "Feature", + IsDirectory = true + } + } + }; + + Assert.Null(resolver.ResolvePath(args)); + } } -- cgit v1.2.3