diff --git a/Emby.Naming/Common/NamingOptions.cs b/Emby.Naming/Common/NamingOptions.cs index 69e68660d4..f3f70d3fed 100644 --- a/Emby.Naming/Common/NamingOptions.cs +++ b/Emby.Naming/Common/NamingOptions.cs @@ -5,6 +5,7 @@ using System; using System.Linq; using System.Text.RegularExpressions; using Emby.Naming.Video; +using MediaBrowser.Model.Entities; namespace Emby.Naming.Common { @@ -176,7 +177,7 @@ namespace Emby.Naming.Common CleanDateTimes = new[] { - @"(.+[^ _\,\.\(\)\[\]\-])[ _\.\(\)\[\]\-]+(19[0-9][0-9]|20[0-1][0-9])([ _\,\.\(\)\[\]\-][^0-9]|$)" + @"(.+[^_\,\.\(\)\[\]\-])[_\.\(\)\[\]\-](19[0-9][0-9]|20[0-1][0-9])([ _\,\.\(\)\[\]\-][^0-9]|).*(19[0-9][0-9]|20[0-1][0-9])*" }; CleanStrings = new[] @@ -423,126 +424,126 @@ namespace Emby.Naming.Common { new ExtraRule { - ExtraType = "trailer", + ExtraType = ExtraType.Trailer, RuleType = ExtraRuleType.Filename, Token = "trailer", MediaType = MediaType.Video }, new ExtraRule { - ExtraType = "trailer", + ExtraType = ExtraType.Trailer, RuleType = ExtraRuleType.Suffix, Token = "-trailer", MediaType = MediaType.Video }, new ExtraRule { - ExtraType = "trailer", + ExtraType = ExtraType.Trailer, RuleType = ExtraRuleType.Suffix, Token = ".trailer", MediaType = MediaType.Video }, new ExtraRule { - ExtraType = "trailer", + ExtraType = ExtraType.Trailer, RuleType = ExtraRuleType.Suffix, Token = "_trailer", MediaType = MediaType.Video }, new ExtraRule { - ExtraType = "trailer", + ExtraType = ExtraType.Trailer, RuleType = ExtraRuleType.Suffix, Token = " trailer", MediaType = MediaType.Video }, new ExtraRule { - ExtraType = "sample", + ExtraType = ExtraType.Sample, RuleType = ExtraRuleType.Filename, Token = "sample", MediaType = MediaType.Video }, new ExtraRule { - ExtraType = "sample", + ExtraType = ExtraType.Sample, RuleType = ExtraRuleType.Suffix, Token = "-sample", MediaType = MediaType.Video }, new ExtraRule { - ExtraType = "sample", + ExtraType = ExtraType.Sample, RuleType = ExtraRuleType.Suffix, Token = ".sample", MediaType = MediaType.Video }, new ExtraRule { - ExtraType = "sample", + ExtraType = ExtraType.Sample, RuleType = ExtraRuleType.Suffix, Token = "_sample", MediaType = MediaType.Video }, new ExtraRule { - ExtraType = "sample", + ExtraType = ExtraType.Sample, RuleType = ExtraRuleType.Suffix, Token = " sample", MediaType = MediaType.Video }, new ExtraRule { - ExtraType = "themesong", + ExtraType = ExtraType.ThemeSong, RuleType = ExtraRuleType.Filename, Token = "theme", MediaType = MediaType.Audio }, new ExtraRule { - ExtraType = "scene", + ExtraType = ExtraType.Scene, RuleType = ExtraRuleType.Suffix, Token = "-scene", MediaType = MediaType.Video }, new ExtraRule { - ExtraType = "clip", + ExtraType = ExtraType.Clip, RuleType = ExtraRuleType.Suffix, Token = "-clip", MediaType = MediaType.Video }, new ExtraRule { - ExtraType = "interview", + ExtraType = ExtraType.Interview, RuleType = ExtraRuleType.Suffix, Token = "-interview", MediaType = MediaType.Video }, new ExtraRule { - ExtraType = "behindthescenes", + ExtraType = ExtraType.BehindTheScenes, RuleType = ExtraRuleType.Suffix, Token = "-behindthescenes", MediaType = MediaType.Video }, new ExtraRule { - ExtraType = "deletedscene", + ExtraType = ExtraType.DeletedScene, RuleType = ExtraRuleType.Suffix, Token = "-deleted", MediaType = MediaType.Video }, new ExtraRule { - ExtraType = "featurette", + ExtraType = ExtraType.Clip, RuleType = ExtraRuleType.Suffix, Token = "-featurette", MediaType = MediaType.Video }, new ExtraRule { - ExtraType = "short", + ExtraType = ExtraType.Clip, RuleType = ExtraRuleType.Suffix, Token = "-short", MediaType = MediaType.Video diff --git a/Emby.Naming/Video/CleanStringParser.cs b/Emby.Naming/Video/CleanStringParser.cs index be028c662e..fcd4b65c75 100644 --- a/Emby.Naming/Video/CleanStringParser.cs +++ b/Emby.Naming/Video/CleanStringParser.cs @@ -7,7 +7,7 @@ using System.Text.RegularExpressions; namespace Emby.Naming.Video { /// - /// http://kodi.wiki/view/Advancedsettings.xml#video + /// . /// public class CleanStringParser { diff --git a/Emby.Naming/Video/ExtraResolver.cs b/Emby.Naming/Video/ExtraResolver.cs index 989ede206e..ea9a6d6c2a 100644 --- a/Emby.Naming/Video/ExtraResolver.cs +++ b/Emby.Naming/Video/ExtraResolver.cs @@ -23,7 +23,7 @@ namespace Emby.Naming.Video { return _options.VideoExtraRules .Select(i => GetExtraInfo(path, i)) - .FirstOrDefault(i => !string.IsNullOrEmpty(i.ExtraType)) ?? new ExtraResult(); + .FirstOrDefault(i => i.ExtraType != null) ?? new ExtraResult(); } private ExtraResult GetExtraInfo(string path, ExtraRule rule) diff --git a/Emby.Naming/Video/ExtraResult.cs b/Emby.Naming/Video/ExtraResult.cs index 6081a44942..4e991d685d 100644 --- a/Emby.Naming/Video/ExtraResult.cs +++ b/Emby.Naming/Video/ExtraResult.cs @@ -1,6 +1,8 @@ #pragma warning disable CS1591 #pragma warning disable SA1600 +using MediaBrowser.Model.Entities; + namespace Emby.Naming.Video { public class ExtraResult @@ -9,7 +11,7 @@ namespace Emby.Naming.Video /// Gets or sets the type of the extra. /// /// The type of the extra. - public string ExtraType { get; set; } + public ExtraType? ExtraType { get; set; } /// /// Gets or sets the rule. diff --git a/Emby.Naming/Video/ExtraRule.cs b/Emby.Naming/Video/ExtraRule.cs index cfce79fd08..cfaa84ed6b 100644 --- a/Emby.Naming/Video/ExtraRule.cs +++ b/Emby.Naming/Video/ExtraRule.cs @@ -1,7 +1,8 @@ #pragma warning disable CS1591 #pragma warning disable SA1600 -using Emby.Naming.Common; +using MediaBrowser.Model.Entities; +using MediaType = Emby.Naming.Common.MediaType; namespace Emby.Naming.Video { @@ -17,7 +18,7 @@ namespace Emby.Naming.Video /// Gets or sets the type of the extra. /// /// The type of the extra. - public string ExtraType { get; set; } + public ExtraType ExtraType { get; set; } /// /// Gets or sets the type of the rule. diff --git a/Emby.Naming/Video/StubResolver.cs b/Emby.Naming/Video/StubResolver.cs index bbf399677d..95868e89d2 100644 --- a/Emby.Naming/Video/StubResolver.cs +++ b/Emby.Naming/Video/StubResolver.cs @@ -14,14 +14,14 @@ namespace Emby.Naming.Video { if (path == null) { - return default(StubResult); + return default; } var extension = Path.GetExtension(path); if (!options.StubFileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase)) { - return default(StubResult); + return default; } var result = new StubResult() diff --git a/Emby.Naming/Video/VideoFileInfo.cs b/Emby.Naming/Video/VideoFileInfo.cs index 250a1ec45d..90c798da10 100644 --- a/Emby.Naming/Video/VideoFileInfo.cs +++ b/Emby.Naming/Video/VideoFileInfo.cs @@ -1,3 +1,5 @@ +using MediaBrowser.Model.Entities; + namespace Emby.Naming.Video { /// @@ -30,10 +32,10 @@ namespace Emby.Naming.Video public int? Year { get; set; } /// - /// Gets or sets the type of the extra, e.g. trailer, theme song, behing the scenes, etc. + /// Gets or sets the type of the extra, e.g. trailer, theme song, behind the scenes, etc. /// /// The type of the extra. - public string ExtraType { get; set; } + public ExtraType? ExtraType { get; set; } /// /// Gets or sets the extra rule. diff --git a/Emby.Naming/Video/VideoListResolver.cs b/Emby.Naming/Video/VideoListResolver.cs index 5a32846bf3..87498000ce 100644 --- a/Emby.Naming/Video/VideoListResolver.cs +++ b/Emby.Naming/Video/VideoListResolver.cs @@ -7,6 +7,7 @@ using System.IO; using System.Linq; using System.Text.RegularExpressions; using Emby.Naming.Common; +using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; namespace Emby.Naming.Video @@ -32,7 +33,7 @@ namespace Emby.Naming.Video // Filter out all extras, otherwise they could cause stacks to not be resolved // See the unit test TestStackedWithTrailer var nonExtras = videoInfos - .Where(i => string.IsNullOrEmpty(i.ExtraType)) + .Where(i => i.ExtraType == null) .Select(i => new FileSystemMetadata { FullName = i.Path, @@ -79,7 +80,7 @@ namespace Emby.Naming.Video } var standaloneMedia = remainingFiles - .Where(i => string.IsNullOrEmpty(i.ExtraType)) + .Where(i => i.ExtraType == null) .ToList(); foreach (var media in standaloneMedia) @@ -148,7 +149,7 @@ namespace Emby.Naming.Video if (list.Count == 1) { var trailers = remainingFiles - .Where(i => string.Equals(i.ExtraType, "trailer", StringComparison.OrdinalIgnoreCase)) + .Where(i => i.ExtraType == ExtraType.Trailer) .ToList(); list[0].Extras.AddRange(trailers); @@ -229,7 +230,7 @@ namespace Emby.Naming.Video } return remainingFiles - .Where(i => !string.IsNullOrEmpty(i.ExtraType)) + .Where(i => i.ExtraType == null) .Where(i => baseNames.Any(b => i.FileNameWithoutExtension.StartsWith(b, StringComparison.OrdinalIgnoreCase))) .ToList(); } diff --git a/Emby.Naming/Video/VideoResolver.cs b/Emby.Naming/Video/VideoResolver.cs index 5a93e1eafe..41b79697cc 100644 --- a/Emby.Naming/Video/VideoResolver.cs +++ b/Emby.Naming/Video/VideoResolver.cs @@ -94,7 +94,7 @@ namespace Emby.Naming.Video { var cleanDateTimeResult = CleanDateTime(name); - if (string.IsNullOrEmpty(extraResult.ExtraType)) + if (extraResult.ExtraType == null) { name = CleanString(cleanDateTimeResult.Name).Name; } diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 9be4e13ec5..ae3cdece91 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -2559,7 +2559,7 @@ namespace Emby.Server.Implementations.Library if (currentVideo != null) { - files.AddRange(currentVideo.Extras.Where(i => string.Equals(i.ExtraType, "trailer", StringComparison.OrdinalIgnoreCase)).Select(i => _fileSystem.GetFileInfo(i.Path))); + files.AddRange(currentVideo.Extras.Where(i => i.ExtraType == ExtraType.Trailer).Select(i => _fileSystem.GetFileInfo(i.Path))); } var resolvers = new IItemResolver[] @@ -2609,7 +2609,7 @@ namespace Emby.Server.Implementations.Library if (currentVideo != null) { - files.AddRange(currentVideo.Extras.Where(i => !string.Equals(i.ExtraType, "trailer", StringComparison.OrdinalIgnoreCase)).Select(i => _fileSystem.GetFileInfo(i.Path))); + files.AddRange(currentVideo.Extras.Where(i => i.ExtraType != ExtraType.Trailer).Select(i => _fileSystem.GetFileInfo(i.Path))); } return ResolvePaths(files, directoryService, null, new LibraryOptions(), null) @@ -2713,7 +2713,7 @@ namespace Emby.Server.Implementations.Library if (!string.Equals(newPath, path, StringComparison.Ordinal)) { - if (to.IndexOf('/') != -1) + if (to.IndexOf('/', StringComparison.Ordinal) != -1) { newPath = newPath.Replace('\\', '/'); } @@ -2734,30 +2734,7 @@ namespace Emby.Server.Implementations.Library var result = resolver.GetExtraInfo(item.Path); - if (string.Equals(result.ExtraType, "deletedscene", StringComparison.OrdinalIgnoreCase)) - { - item.ExtraType = ExtraType.DeletedScene; - } - else if (string.Equals(result.ExtraType, "behindthescenes", StringComparison.OrdinalIgnoreCase)) - { - item.ExtraType = ExtraType.BehindTheScenes; - } - else if (string.Equals(result.ExtraType, "interview", StringComparison.OrdinalIgnoreCase)) - { - item.ExtraType = ExtraType.Interview; - } - else if (string.Equals(result.ExtraType, "scene", StringComparison.OrdinalIgnoreCase)) - { - item.ExtraType = ExtraType.Scene; - } - else if (string.Equals(result.ExtraType, "sample", StringComparison.OrdinalIgnoreCase)) - { - item.ExtraType = ExtraType.Sample; - } - else - { - item.ExtraType = ExtraType.Clip; - } + item.ExtraType = result.ExtraType; } public List GetPeople(InternalPeopleQuery query) diff --git a/MediaBrowser.Model/Entities/MediaType.cs b/MediaBrowser.Model/Entities/MediaType.cs index c56c8f8f22..d8b02c9eae 100644 --- a/MediaBrowser.Model/Entities/MediaType.cs +++ b/MediaBrowser.Model/Entities/MediaType.cs @@ -3,20 +3,23 @@ namespace MediaBrowser.Model.Entities /// /// Class MediaType /// - public class MediaType + public static class MediaType { /// /// The video /// public const string Video = "Video"; + /// /// The audio /// public const string Audio = "Audio"; + /// /// The photo /// public const string Photo = "Photo"; + /// /// The book /// diff --git a/jellyfin.ruleset b/jellyfin.ruleset index b6f5cf01b0..92b7a03fdd 100644 --- a/jellyfin.ruleset +++ b/jellyfin.ruleset @@ -24,6 +24,8 @@ + + diff --git a/tests/Jellyfin.Naming.Tests/Music/MultiDiscAlbumTests.cs b/tests/Jellyfin.Naming.Tests/Music/MultiDiscAlbumTests.cs new file mode 100644 index 0000000000..eb69d915ca --- /dev/null +++ b/tests/Jellyfin.Naming.Tests/Music/MultiDiscAlbumTests.cs @@ -0,0 +1,57 @@ +using Emby.Naming.Audio; +using Emby.Naming.Common; +using Xunit; + +namespace Jellyfin.Naming.Tests.Music +{ + public class MultiDiscAlbumTests + { + [Fact] + public void TestMultiDiscAlbums() + { + Assert.False(IsMultiDiscAlbumFolder(@"blah blah")); + Assert.False(IsMultiDiscAlbumFolder(@"d:/music\weezer/03 Pinkerton")); + Assert.False(IsMultiDiscAlbumFolder(@"d:/music/michael jackson/Bad (2012 Remaster)")); + + Assert.True(IsMultiDiscAlbumFolder(@"cd1")); + Assert.True(IsMultiDiscAlbumFolder(@"disc1")); + Assert.True(IsMultiDiscAlbumFolder(@"disk1")); + + // Add a space + Assert.True(IsMultiDiscAlbumFolder(@"cd 1")); + Assert.True(IsMultiDiscAlbumFolder(@"disc 1")); + Assert.True(IsMultiDiscAlbumFolder(@"disk 1")); + + Assert.True(IsMultiDiscAlbumFolder(@"cd - 1")); + Assert.True(IsMultiDiscAlbumFolder(@"disc- 1")); + Assert.True(IsMultiDiscAlbumFolder(@"disk - 1")); + + Assert.True(IsMultiDiscAlbumFolder(@"Disc 01 (Hugo Wolf · 24 Lieder)")); + Assert.True(IsMultiDiscAlbumFolder(@"Disc 04 (Encores and Folk Songs)")); + Assert.True(IsMultiDiscAlbumFolder(@"Disc04 (Encores and Folk Songs)")); + Assert.True(IsMultiDiscAlbumFolder(@"Disc 04(Encores and Folk Songs)")); + Assert.True(IsMultiDiscAlbumFolder(@"Disc04(Encores and Folk Songs)")); + + Assert.True(IsMultiDiscAlbumFolder(@"D:/Video/MBTestLibrary/VideoTest/music/.38 special/anth/Disc 2")); + } + + [Fact] + public void TestMultiDiscAlbums1() + { + Assert.False(IsMultiDiscAlbumFolder(@"[1985] Oppurtunities (Let's make lots of money) (1985)")); + } + + [Fact] + public void TestMultiDiscAlbums2() + { + Assert.False(IsMultiDiscAlbumFolder(@"Blah 04(Encores and Folk Songs)")); + } + + private bool IsMultiDiscAlbumFolder(string path) + { + var parser = new AlbumParser(new NamingOptions()); + + return parser.ParseMultiPart(path).IsMultiPart; + } + } +} diff --git a/tests/Jellyfin.Naming.Tests/Subtitles/SubtitleParserTests.cs b/tests/Jellyfin.Naming.Tests/Subtitles/SubtitleParserTests.cs new file mode 100644 index 0000000000..e8f14cdc45 --- /dev/null +++ b/tests/Jellyfin.Naming.Tests/Subtitles/SubtitleParserTests.cs @@ -0,0 +1,40 @@ +using Emby.Naming.Common; +using Emby.Naming.Subtitles; +using Xunit; + +namespace Jellyfin.Naming.Tests.Subtitles +{ + public class SubtitleParserTests + { + private SubtitleParser GetParser() + { + var options = new NamingOptions(); + + return new SubtitleParser(options); + } + + [Fact] + public void TestSubtitles() + { + Test("The Skin I Live In (2011).srt", null, false, false); + Test("The Skin I Live In (2011).eng.srt", "eng", false, false); + Test("The Skin I Live In (2011).eng.default.srt", "eng", true, false); + Test("The Skin I Live In (2011).eng.forced.srt", "eng", false, true); + Test("The Skin I Live In (2011).eng.foreign.srt", "eng", false, true); + Test("The Skin I Live In (2011).eng.default.foreign.srt", "eng", true, true); + + Test("The Skin I Live In (2011).default.foreign.eng.srt", "eng", true, true); + } + + private void Test(string input, string language, bool isDefault, bool isForced) + { + var parser = GetParser(); + + var result = parser.ParseFile(input); + + Assert.Equal(language, result.Language, true); + Assert.Equal(isDefault, result.IsDefault); + Assert.Equal(isForced, result.IsForced); + } + } +} diff --git a/tests/Jellyfin.Naming.Tests/TV/AbsoluteEpisodeNumberTests.cs b/tests/Jellyfin.Naming.Tests/TV/AbsoluteEpisodeNumberTests.cs new file mode 100644 index 0000000000..9abbcc7bf0 --- /dev/null +++ b/tests/Jellyfin.Naming.Tests/TV/AbsoluteEpisodeNumberTests.cs @@ -0,0 +1,61 @@ +using Emby.Naming.Common; +using Emby.Naming.TV; +using Xunit; + +namespace Jellyfin.Naming.Tests.TV +{ + public class AbsoluteEpisodeNumberTests + { + [Fact] + public void TestAbsoluteEpisodeNumber1() + { + Assert.Equal(12, GetEpisodeNumberFromFile(@"The Simpsons/12.avi")); + } + + [Fact] + public void TestAbsoluteEpisodeNumber2() + { + Assert.Equal(12, GetEpisodeNumberFromFile(@"The Simpsons/The Simpsons 12.avi")); + } + + [Fact] + public void TestAbsoluteEpisodeNumber3() + { + Assert.Equal(82, GetEpisodeNumberFromFile(@"The Simpsons/The Simpsons 82.avi")); + } + + [Fact] + public void TestAbsoluteEpisodeNumber4() + { + Assert.Equal(112, GetEpisodeNumberFromFile(@"The Simpsons/The Simpsons 112.avi")); + } + + [Fact] + public void TestAbsoluteEpisodeNumber5() + { + Assert.Equal(2, GetEpisodeNumberFromFile(@"The Simpsons/Foo_ep_02.avi")); + } + + [Fact] + public void TestAbsoluteEpisodeNumber6() + { + Assert.Equal(889, GetEpisodeNumberFromFile(@"The Simpsons/The Simpsons 889.avi")); + } + + [Fact] + public void TestAbsoluteEpisodeNumber7() + { + Assert.Equal(101, GetEpisodeNumberFromFile(@"The Simpsons/The Simpsons 101.avi")); + } + + private int? GetEpisodeNumberFromFile(string path) + { + var options = new NamingOptions(); + + var result = new EpisodeResolver(options) + .Resolve(path, false, null, null, true); + + return result.EpisodeNumber; + } + } +} diff --git a/tests/Jellyfin.Naming.Tests/TV/DailyEpisodeTests.cs b/tests/Jellyfin.Naming.Tests/TV/DailyEpisodeTests.cs new file mode 100644 index 0000000000..29daf8cc37 --- /dev/null +++ b/tests/Jellyfin.Naming.Tests/TV/DailyEpisodeTests.cs @@ -0,0 +1,69 @@ +using Emby.Naming.Common; +using Emby.Naming.TV; +using Xunit; + +namespace Jellyfin.Naming.Tests.TV +{ + public class DailyEpisodeTests + { + [Fact] + public void TestDailyEpisode1() + { + Test(@"/server/anything_1996.11.14.mp4", "anything", 1996, 11, 14); + } + + [Fact] + public void TestDailyEpisode2() + { + Test(@"/server/anything_1996-11-14.mp4", "anything", 1996, 11, 14); + } + + // FIXME + // [Fact] + public void TestDailyEpisode3() + { + Test(@"/server/anything_14.11.1996.mp4", "anything", 1996, 11, 14); + } + + // FIXME + // [Fact] + public void TestDailyEpisode4() + { + Test(@"/server/A Daily Show - (2015-01-15) - Episode Name - [720p].mkv", "A Daily Show", 2015, 01, 15); + } + + [Fact] + public void TestDailyEpisode5() + { + Test(@"/server/james.corden.2017.04.20.anne.hathaway.720p.hdtv.x264-crooks.mkv", "james.corden", 2017, 04, 20); + } + + [Fact] + public void TestDailyEpisode6() + { + Test(@"/server/ABC News 2018_03_24_19_00_00.mkv", "ABC News", 2018, 03, 24); + } + + // FIXME + // [Fact] + public void TestDailyEpisode7() + { + Test(@"/server/Last Man Standing_KTLADT_2018_05_25_01_28_00.wtv", "Last Man Standing", 2018, 05, 25); + } + + private void Test(string path, string seriesName, int? year, int? month, int? day) + { + var options = new NamingOptions(); + + var result = new EpisodeResolver(options) + .Resolve(path, false); + + Assert.Null(result.SeasonNumber); + Assert.Null(result.EpisodeNumber); + Assert.Equal(year, result.Year); + Assert.Equal(month, result.Month); + Assert.Equal(day, result.Day); + Assert.Equal(seriesName, result.SeriesName, true); + } + } +} diff --git a/tests/Jellyfin.Naming.Tests/TV/EpisodeNumberTests.cs b/tests/Jellyfin.Naming.Tests/TV/EpisodeNumberTests.cs new file mode 100644 index 0000000000..1ae6372817 --- /dev/null +++ b/tests/Jellyfin.Naming.Tests/TV/EpisodeNumberTests.cs @@ -0,0 +1,424 @@ +using Emby.Naming.Common; +using Emby.Naming.TV; +using Xunit; + +namespace Jellyfin.Naming.Tests.TV +{ + public class EpisodeNumberTests + { + [Fact] + public void TestEpisodeNumber1() + { + Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 02/S02E03 blah.avi")); + } + + [Fact] + public void TestEpisodeNumber40() + { + Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 2/02x03 - 02x04 - 02x15 - Ep Name.mp4")); + } + + [Fact] + public void TestEpisodeNumber41() + { + Assert.Equal(02, GetEpisodeNumberFromFile(@"Season 1/01x02 blah.avi")); + } + + [Fact] + public void TestEpisodeNumber42() + { + Assert.Equal(02, GetEpisodeNumberFromFile(@"Season 1/S01x02 blah.avi")); + } + + [Fact] + public void TestEpisodeNumber43() + { + Assert.Equal(02, GetEpisodeNumberFromFile(@"Season 1/S01E02 blah.avi")); + } + + [Fact] + public void TestEpisodeNumber44() + { + Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 2/Elementary - 02x03-04-15 - Ep Name.mp4")); + } + + [Fact] + public void TestEpisodeNumber45() + { + Assert.Equal(02, GetEpisodeNumberFromFile(@"Season 1/S01xE02 blah.avi")); + } + + [Fact] + public void TestEpisodeNumber46() + { + Assert.Equal(02, GetEpisodeNumberFromFile(@"Season 1/seriesname S01E02 blah.avi")); + } + + [Fact] + public void TestEpisodeNumber47() + { + Assert.Equal(36, GetEpisodeNumberFromFile(@"Season 2/[HorribleSubs] Hunter X Hunter - 136 [720p].mkv")); + } + + [Fact] + public void TestEpisodeNumber50() + { + // This convention is not currently supported, just adding in case we want to look at it in the future + Assert.Equal(1, GetEpisodeNumberFromFile(@"2016/Season s2016e1.mp4")); + } + + // FIXME + // [Fact] + public void TestEpisodeNumber51() + { + // This convention is not currently supported, just adding in case we want to look at it in the future + Assert.Equal(1, GetEpisodeNumberFromFile(@"2016/Season 2016x1.mp4")); + } + + [Fact] + public void TestEpisodeNumber52() + { + Assert.Equal(16, GetEpisodeNumberFromFile(@"Season 2/Episode - 16.avi")); + } + + [Fact] + public void TestEpisodeNumber53() + { + // This is not supported. Expected to fail, although it would be a good one to add support for. + Assert.Equal(16, GetEpisodeNumberFromFile(@"Season 2/Episode 16.avi")); + } + + [Fact] + public void TestEpisodeNumber54() + { + // This is not supported. Expected to fail, although it would be a good one to add support for. + Assert.Equal(16, GetEpisodeNumberFromFile(@"Season 2/Episode 16 - Some Title.avi")); + } + + // [Fact] + public void TestEpisodeNumber55() + { + // This is not supported. Expected to fail, although it would be a good one to add support for. + Assert.Equal(16, GetEpisodeNumberFromFile(@"Season 2/Season 3 Episode 16.avi")); + } + + // [Fact] + public void TestEpisodeNumber56() + { + // This is not supported. Expected to fail, although it would be a good one to add support for. + Assert.Equal(16, GetEpisodeNumberFromFile(@"Season 2/Season 3 Episode 16 - Some Title.avi")); + } + + [Fact] + public void TestEpisodeNumber57() + { + Assert.Equal(16, GetEpisodeNumberFromFile(@"Season 2/16 Some Title.avi")); + } + + [Fact] + public void TestEpisodeNumber58() + { + Assert.Equal(16, GetEpisodeNumberFromFile(@"Season 2/16 - 12 Some Title.avi")); + } + + [Fact] + public void TestEpisodeNumber59() + { + Assert.Equal(7, GetEpisodeNumberFromFile(@"Season 2/7 - 12 Angry Men.avi")); + } + + // FIXME + // [Fact] + public void TestEpisodeNumber60() + { + Assert.Equal(16, GetEpisodeNumberFromFile(@"Season 2/16 12 Some Title.avi")); + } + + // FIXME + // [Fact] + public void TestEpisodeNumber61() + { + Assert.Equal(7, GetEpisodeNumberFromFile(@"Season 2/7 12 Angry Men.avi")); + } + + // FIXME + // [Fact] + public void TestEpisodeNumber62() + { + // This is not supported. Expected to fail, although it would be a good one to add support for. + Assert.Equal(3, GetEpisodeNumberFromFile(@"Season 4/Uchuu.Senkan.Yamato.2199.E03.avi")); + } + + [Fact] + public void TestEpisodeNumber63() + { + Assert.Equal(3, GetEpisodeNumberFromFile(@"Season 4/Uchuu.Senkan.Yamato.2199.S04E03.avi")); + } + + [Fact] + public void TestEpisodeNumber64() + { + Assert.Equal(368, GetEpisodeNumberFromFile(@"Running Man/Running Man S2017E368.mkv")); + } + + // FIXME + // [Fact] + public void TestEpisodeNumber65() + { + // Not supported yet + Assert.Equal(7, GetEpisodeNumberFromFile(@"/The.Legend.of.Condor.Heroes.2017.V2.web-dl.1080p.h264.aac-hdctv/The.Legend.of.Condor.Heroes.2017.E07.V2.web-dl.1080p.h264.aac-hdctv.mkv")); + } + + [Fact] + public void TestEpisodeNumber30() + { + Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 2/02x03 - 02x04 - 02x15 - Ep Name.mp4")); + } + + // FIXME + // [Fact] + public void TestEpisodeNumber31() + { + Assert.Equal(02, GetEpisodeNumberFromFile(@"Season 1/seriesname 01x02 blah.avi")); + } + + [Fact] + public void TestEpisodeNumber32() + { + Assert.Equal(9, GetEpisodeNumberFromFile(@"Season 25/The Simpsons.S25E09.Steal this episode.mp4")); + } + + [Fact] + public void TestEpisodeNumber33() + { + Assert.Equal(02, GetEpisodeNumberFromFile(@"Season 1/seriesname S01x02 blah.avi")); + } + + [Fact] + public void TestEpisodeNumber34() + { + Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 2/Elementary - 02x03 - 02x04 - 02x15 - Ep Name.mp4")); + } + + [Fact] + public void TestEpisodeNumber35() + { + Assert.Equal(02, GetEpisodeNumberFromFile(@"Season 1/seriesname S01xE02 blah.avi")); + } + + [Fact] + public void TestEpisodeNumber36() + { + Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 02/02x03 - x04 - x15 - Ep Name.mp4")); + } + + [Fact] + public void TestEpisodeNumber37() + { + Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 02/Elementary - 02x03 - x04 - x15 - Ep Name.mp4")); + } + + [Fact] + public void TestEpisodeNumber38() + { + Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 02/02x03x04x15 - Ep Name.mp4")); + } + + [Fact] + public void TestEpisodeNumber39() + { + Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 02/Elementary - 02x03x04x15 - Ep Name.mp4")); + } + + [Fact] + public void TestEpisodeNumber20() + { + Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 2/02x03-04-15 - Ep Name.mp4")); + } + + [Fact] + public void TestEpisodeNumber21() + { + Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 02/02x03-E15 - Ep Name.mp4")); + } + + [Fact] + public void TestEpisodeNumber22() + { + Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 02/Elementary - 02x03-E15 - Ep Name.mp4")); + } + + [Fact] + public void TestEpisodeNumber23() + { + Assert.Equal(23, GetEpisodeNumberFromFile(@"Season 1/Elementary - S01E23-E24-E26 - The Woman.mp4")); + } + + [Fact] + public void TestEpisodeNumber24() + { + Assert.Equal(23, GetEpisodeNumberFromFile(@"Season 2009/S2009E23-E24-E26 - The Woman.mp4")); + } + + [Fact] + public void TestEpisodeNumber25() + { + Assert.Equal(02, GetEpisodeNumberFromFile(@"Season 2009/2009x02 blah.avi")); + } + + [Fact] + public void TestEpisodeNumber26() + { + Assert.Equal(02, GetEpisodeNumberFromFile(@"Season 2009/S2009x02 blah.avi")); + } + + [Fact] + public void TestEpisodeNumber27() + { + Assert.Equal(02, GetEpisodeNumberFromFile(@"Season 2009/S2009E02 blah.avi")); + } + + // FIXME + // [Fact] + public void TestEpisodeNumber28() + { + Assert.Equal(02, GetEpisodeNumberFromFile(@"Season 2009/seriesname 2009x02 blah.avi")); + } + + [Fact] + public void TestEpisodeNumber29() + { + Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 2009/Elementary - 2009x03x04x15 - Ep Name.mp4")); + } + + [Fact] + public void TestEpisodeNumber11() + { + Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 2009/2009x03x04x15 - Ep Name.mp4")); + } + + [Fact] + public void TestEpisodeNumber12() + { + Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 2009/Elementary - 2009x03-E15 - Ep Name.mp4")); + } + + [Fact] + public void TestEpisodeNumber13() + { + Assert.Equal(02, GetEpisodeNumberFromFile(@"Season 2009/S2009xE02 blah.avi")); + } + + [Fact] + public void TestEpisodeNumber14() + { + Assert.Equal(23, GetEpisodeNumberFromFile(@"Season 2009/Elementary - S2009E23-E24-E26 - The Woman.mp4")); + } + + [Fact] + public void TestEpisodeNumber15() + { + Assert.Equal(02, GetEpisodeNumberFromFile(@"Season 2009/seriesname S2009xE02 blah.avi")); + } + + [Fact] + public void TestEpisodeNumber16() + { + Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 2009/2009x03-E15 - Ep Name.mp4")); + } + + [Fact] + public void TestEpisodeNumber17() + { + Assert.Equal(02, GetEpisodeNumberFromFile(@"Season 2009/seriesname S2009E02 blah.avi")); + } + + [Fact] + public void TestEpisodeNumber18() + { + Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 2009/2009x03 - 2009x04 - 2009x15 - Ep Name.mp4")); + } + + [Fact] + public void TestEpisodeNumber19() + { + Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 2009/2009x03 - x04 - x15 - Ep Name.mp4")); + } + + [Fact] + public void TestEpisodeNumber2() + { + Assert.Equal(02, GetEpisodeNumberFromFile(@"Season 2009/seriesname S2009x02 blah.avi")); + } + + [Fact] + public void TestEpisodeNumber3() + { + Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 2009/Elementary - 2009x03 - 2009x04 - 2009x15 - Ep Name.mp4")); + } + + [Fact] + public void TestEpisodeNumber4() + { + Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 2009/Elementary - 2009x03-04-15 - Ep Name.mp4")); + } + + [Fact] + public void TestEpisodeNumber5() + { + Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 2009/2009x03-04-15 - Ep Name.mp4")); + } + + [Fact] + public void TestEpisodeNumber6() + { + Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 2009/Elementary - 2009x03 - x04 - x15 - Ep Name.mp4")); + } + + [Fact] + public void TestEpisodeNumber7() + { + Assert.Equal(02, GetEpisodeNumberFromFile(@"Season 1/02 - blah-02 a.avi")); + } + + [Fact] + public void TestEpisodeNumber8() + { + Assert.Equal(02, GetEpisodeNumberFromFile(@"Season 1/02 - blah.avi")); + } + + [Fact] + public void TestEpisodeNumber9() + { + Assert.Equal(02, GetEpisodeNumberFromFile(@"Season 2/02 - blah 14 blah.avi")); + } + + [Fact] + public void TestEpisodeNumber10() + { + Assert.Equal(02, GetEpisodeNumberFromFile(@"Season 2/02.avi")); + } + + [Fact] + public void TestEpisodeNumber48() + { + Assert.Equal(02, GetEpisodeNumberFromFile(@"Season 2/2. Infestation.avi")); + } + + [Fact] + public void TestEpisodeNumber49() + { + Assert.Equal(7, GetEpisodeNumberFromFile(@"The Wonder Years/The.Wonder.Years.S04.PDTV.x264-JCH/The Wonder Years s04e07 Christmas Party NTSC PDTV.avi")); + } + + private int? GetEpisodeNumberFromFile(string path) + { + var options = new NamingOptions(); + + var result = new EpisodePathParser(options) + .Parse(path, false); + + return result.EpisodeNumber; + } + } +} diff --git a/tests/Jellyfin.Naming.Tests/TV/EpisodeNumberWithoutSeasonTests.cs b/tests/Jellyfin.Naming.Tests/TV/EpisodeNumberWithoutSeasonTests.cs new file mode 100644 index 0000000000..00aa9ee7c2 --- /dev/null +++ b/tests/Jellyfin.Naming.Tests/TV/EpisodeNumberWithoutSeasonTests.cs @@ -0,0 +1,127 @@ +using Emby.Naming.Common; +using Emby.Naming.TV; +using Xunit; + +namespace Jellyfin.Naming.Tests.TV +{ + public class EpisodeNumberWithoutSeasonTests + { + [Fact] + public void TestEpisodeNumberWithoutSeason1() + { + Assert.Equal(8, GetEpisodeNumberFromFile(@"The Simpsons/The Simpsons.S25E08.Steal this episode.mp4")); + } + + [Fact] + public void TestEpisodeNumberWithoutSeason2() + { + Assert.Equal(2, GetEpisodeNumberFromFile(@"The Simpsons/The Simpsons - 02 - Ep Name.avi")); + } + + [Fact] + public void TestEpisodeNumberWithoutSeason3() + { + Assert.Equal(2, GetEpisodeNumberFromFile(@"The Simpsons/02.avi")); + } + + [Fact] + public void TestEpisodeNumberWithoutSeason4() + { + Assert.Equal(2, GetEpisodeNumberFromFile(@"The Simpsons/02 - Ep Name.avi")); + } + + [Fact] + public void TestEpisodeNumberWithoutSeason5() + { + Assert.Equal(2, GetEpisodeNumberFromFile(@"The Simpsons/02-Ep Name.avi")); + } + + [Fact] + public void TestEpisodeNumberWithoutSeason6() + { + Assert.Equal(2, GetEpisodeNumberFromFile(@"The Simpsons/02.EpName.avi")); + } + + [Fact] + public void TestEpisodeNumberWithoutSeason7() + { + Assert.Equal(2, GetEpisodeNumberFromFile(@"The Simpsons/The Simpsons - 02.avi")); + } + + [Fact] + public void TestEpisodeNumberWithoutSeason8() + { + Assert.Equal(2, GetEpisodeNumberFromFile(@"The Simpsons/The Simpsons - 02 Ep Name.avi")); + } + + // FIXME + // [Fact] + public void TestEpisodeNumberWithoutSeason9() + { + Assert.Equal(2, GetEpisodeNumberFromFile(@"The Simpsons/The Simpsons 5 - 02 - Ep Name.avi")); + } + + // FIXME + // [Fact] + public void TestEpisodeNumberWithoutSeason10() + { + Assert.Equal(2, GetEpisodeNumberFromFile(@"The Simpsons/The Simpsons 5 - 02 Ep Name.avi")); + } + + // FIXME + // [Fact] + public void TestEpisodeNumberWithoutSeason11() + { + Assert.Equal(7, GetEpisodeNumberFromFile(@"Seinfeld/Seinfeld 0807 The Checks.avi")); + Assert.Equal(8, GetSeasonNumberFromFile(@"Seinfeld/Seinfeld 0807 The Checks.avi")); + } + + [Fact] + public void TestEpisodeNumberWithoutSeason12() + { + Assert.Equal(7, GetEpisodeNumberFromFile(@"GJ Club (2013)/GJ Club - 07.mkv")); + } + + // FIXME + // [Fact] + public void TestEpisodeNumberWithoutSeason13() + { + // This is not supported anymore after removing the episode number 365+ hack from EpisodePathParser + Assert.Equal(13, GetEpisodeNumberFromFile(@"Case Closed (1996-2007)/Case Closed - 13.mkv")); + } + + [Fact] + public void TestEpisodeNumberWithoutSeason14() + { + Assert.Equal(3, GetSeasonNumberFromFile(@"Case Closed (1996-2007)/Case Closed - 317.mkv")); + Assert.Equal(17, GetEpisodeNumberFromFile(@"Case Closed (1996-2007)/Case Closed - 317.mkv")); + } + + [Fact] + public void TestEpisodeNumberWithoutSeason15() + { + Assert.Equal(2017, GetSeasonNumberFromFile(@"Running Man/Running Man S2017E368.mkv")); + } + + private int? GetEpisodeNumberFromFile(string path) + { + var options = new NamingOptions(); + + var result = new EpisodeResolver(options) + .Resolve(path, false); + + return result.EpisodeNumber; + } + + private int? GetSeasonNumberFromFile(string path) + { + var options = new NamingOptions(); + + var result = new EpisodeResolver(options) + .Resolve(path, false); + + return result.SeasonNumber; + } + + } +} diff --git a/tests/Jellyfin.Naming.Tests/EpisodePathParserTest.cs b/tests/Jellyfin.Naming.Tests/TV/EpisodePathParserTest.cs similarity index 69% rename from tests/Jellyfin.Naming.Tests/EpisodePathParserTest.cs rename to tests/Jellyfin.Naming.Tests/TV/EpisodePathParserTest.cs index dd1e042155..da6e993100 100644 --- a/tests/Jellyfin.Naming.Tests/EpisodePathParserTest.cs +++ b/tests/Jellyfin.Naming.Tests/TV/EpisodePathParserTest.cs @@ -2,7 +2,7 @@ using Emby.Naming.Common; using Emby.Naming.TV; using Xunit; -namespace Jellyfin.Naming.Tests +namespace Jellyfin.Naming.Tests.TV { public class EpisodePathParserTest { @@ -11,6 +11,10 @@ namespace Jellyfin.Naming.Tests [InlineData("/media/Foo - S04E011", "Foo", 4, 11)] [InlineData("/media/Foo/Foo s01x01", "Foo", 1, 1)] [InlineData("/media/Foo (2019)/Season 4/Foo (2019).S04E03", "Foo (2019)", 4, 3)] + [InlineData("D:\\media\\Foo\\Foo-S01E01", "Foo", 1, 1)] + [InlineData("D:\\media\\Foo - S04E011", "Foo", 4, 11)] + [InlineData("D:\\media\\Foo\\Foo s01x01", "Foo", 1, 1)] + [InlineData("D:\\media\\Foo (2019)\\Season 4\\Foo (2019).S04E03", "Foo (2019)", 4, 3)] public void ParseEpisodesCorrectly(string path, string name, int season, int episode) { NamingOptions o = new NamingOptions(); @@ -21,18 +25,13 @@ namespace Jellyfin.Naming.Tests Assert.Equal(name, res.SeriesName); Assert.Equal(season, res.SeasonNumber); Assert.Equal(episode, res.EpisodeNumber); - - // testing other paths delimeter - var res2 = p.Parse(path.Replace('/', '\\'), false); - Assert.True(res2.Success); - Assert.Equal(name, res2.SeriesName); - Assert.Equal(season, res2.SeasonNumber); - Assert.Equal(episode, res2.EpisodeNumber); } [Theory] [InlineData("/media/Foo/Foo 889", "Foo", 889)] [InlineData("/media/Foo/[Bar] Foo Baz - 11 [1080p]", "Foo Baz", 11)] + [InlineData("D:\\media\\Foo\\Foo 889", "Foo", 889)] + [InlineData("D:\\media\\Foo\\[Bar] Foo Baz - 11 [1080p]", "Foo Baz", 11)] public void ParseEpisodeWithoutSeason(string path, string name, int episode) { NamingOptions o = new NamingOptions(); @@ -43,13 +42,6 @@ namespace Jellyfin.Naming.Tests Assert.Equal(name, res.SeriesName); Assert.Null(res.SeasonNumber); Assert.Equal(episode, res.EpisodeNumber); - - // testing other paths delimeter - var res2 = p.Parse(path.Replace('/', '\\'), false, fillExtendedInfo: false); - Assert.True(res2.Success); - Assert.Equal(name, res2.SeriesName); - Assert.Null(res2.SeasonNumber); - Assert.Equal(episode, res2.EpisodeNumber); } } } diff --git a/tests/Jellyfin.Naming.Tests/TV/EpisodeWithoutSeasonTests.cs b/tests/Jellyfin.Naming.Tests/TV/EpisodeWithoutSeasonTests.cs new file mode 100644 index 0000000000..c2851ccdb1 --- /dev/null +++ b/tests/Jellyfin.Naming.Tests/TV/EpisodeWithoutSeasonTests.cs @@ -0,0 +1,56 @@ +using Emby.Naming.Common; +using Emby.Naming.TV; +using Xunit; + +namespace Jellyfin.Naming.Tests.TV +{ + public class EpisodeWithoutSeasonTests + { + // FIXME + // [Fact] + public void TestWithoutSeason1() + { + Test(@"/server/anything_ep02.mp4", "anything", null, 2); + } + + // FIXME + // [Fact] + public void TestWithoutSeason2() + { + Test(@"/server/anything_ep_02.mp4", "anything", null, 2); + } + + // FIXME + // [Fact] + public void TestWithoutSeason3() + { + Test(@"/server/anything_part.II.mp4", "anything", null, null); + } + + // FIXME + // [Fact] + public void TestWithoutSeason4() + { + Test(@"/server/anything_pt.II.mp4", "anything", null, null); + } + + // FIXME + // [Fact] + public void TestWithoutSeason5() + { + Test(@"/server/anything_pt_II.mp4", "anything", null, null); + } + + private void Test(string path, string seriesName, int? seasonNumber, int? episodeNumber) + { + var options = new NamingOptions(); + + var result = new EpisodeResolver(options) + .Resolve(path, false); + + Assert.Equal(seasonNumber, result.SeasonNumber); + Assert.Equal(episodeNumber, result.EpisodeNumber); + Assert.Equal(seriesName, result.SeriesName, true); + } + } +} diff --git a/tests/Jellyfin.Naming.Tests/TV/MultiEpisodeTests.cs b/tests/Jellyfin.Naming.Tests/TV/MultiEpisodeTests.cs new file mode 100644 index 0000000000..b15dd6b74c --- /dev/null +++ b/tests/Jellyfin.Naming.Tests/TV/MultiEpisodeTests.cs @@ -0,0 +1,105 @@ +using Emby.Naming.Common; +using Emby.Naming.TV; +using Xunit; + +namespace Jellyfin.Naming.Tests.TV +{ + public class MultiEpisodeTests + { + [Fact] + public void TestGetEndingEpisodeNumberFromFile() + { + Assert.Null(GetEndingEpisodeNumberFromFile(@"Season 1/4x01 – 20 Hours in America (1).mkv")); + + Assert.Null(GetEndingEpisodeNumberFromFile(@"Season 1/01x02 blah.avi")); + Assert.Null(GetEndingEpisodeNumberFromFile(@"Season 1/S01x02 blah.avi")); + Assert.Null(GetEndingEpisodeNumberFromFile(@"Season 1/S01E02 blah.avi")); + Assert.Null(GetEndingEpisodeNumberFromFile(@"Season 1/S01xE02 blah.avi")); + Assert.Null(GetEndingEpisodeNumberFromFile(@"Season 1/seriesname 01x02 blah.avi")); + Assert.Null(GetEndingEpisodeNumberFromFile(@"Season 1/seriesname S01x02 blah.avi")); + Assert.Null(GetEndingEpisodeNumberFromFile(@"Season 1/seriesname S01E02 blah.avi")); + Assert.Null(GetEndingEpisodeNumberFromFile(@"Season 1/seriesname S01xE02 blah.avi")); + Assert.Null(GetEndingEpisodeNumberFromFile(@"Season 2/02x03 - 04 Ep Name.mp4")); + Assert.Null(GetEndingEpisodeNumberFromFile(@"Season 2/My show name 02x03 - 04 Ep Name.mp4")); + Assert.Equal(15, GetEndingEpisodeNumberFromFile(@"Season 2/Elementary - 02x03 - 02x04 - 02x15 - Ep Name.mp4")); + Assert.Equal(15, GetEndingEpisodeNumberFromFile(@"Season 2/02x03 - 02x04 - 02x15 - Ep Name.mp4")); + Assert.Equal(15, GetEndingEpisodeNumberFromFile(@"Season 2/02x03-04-15 - Ep Name.mp4")); + Assert.Equal(15, GetEndingEpisodeNumberFromFile(@"Season 2/Elementary - 02x03-04-15 - Ep Name.mp4")); + Assert.Equal(15, GetEndingEpisodeNumberFromFile(@"Season 02/02x03-E15 - Ep Name.mp4")); + Assert.Equal(15, GetEndingEpisodeNumberFromFile(@"Season 02/Elementary - 02x03-E15 - Ep Name.mp4")); + Assert.Equal(15, GetEndingEpisodeNumberFromFile(@"Season 02/02x03 - x04 - x15 - Ep Name.mp4")); + Assert.Equal(15, GetEndingEpisodeNumberFromFile(@"Season 02/Elementary - 02x03 - x04 - x15 - Ep Name.mp4")); + Assert.Equal(15, GetEndingEpisodeNumberFromFile(@"Season 02/02x03x04x15 - Ep Name.mp4")); + Assert.Equal(15, GetEndingEpisodeNumberFromFile(@"Season 02/Elementary - 02x03x04x15 - Ep Name.mp4")); + Assert.Equal(26, GetEndingEpisodeNumberFromFile(@"Season 1/Elementary - S01E23-E24-E26 - The Woman.mp4")); + Assert.Equal(26, GetEndingEpisodeNumberFromFile(@"Season 1/S01E23-E24-E26 - The Woman.mp4")); + + + // Four Digits seasons + Assert.Null(GetEndingEpisodeNumberFromFile(@"Season 2009/2009x02 blah.avi")); + Assert.Null(GetEndingEpisodeNumberFromFile(@"Season 2009/S2009x02 blah.avi")); + Assert.Null(GetEndingEpisodeNumberFromFile(@"Season 2009/S2009E02 blah.avi")); + Assert.Null(GetEndingEpisodeNumberFromFile(@"Season 2009/S2009xE02 blah.avi")); + Assert.Null(GetEndingEpisodeNumberFromFile(@"Season 2009/seriesname 2009x02 blah.avi")); + Assert.Null(GetEndingEpisodeNumberFromFile(@"Season 2009/seriesname S2009x02 blah.avi")); + Assert.Null(GetEndingEpisodeNumberFromFile(@"Season 2009/seriesname S2009E02 blah.avi")); + Assert.Null(GetEndingEpisodeNumberFromFile(@"Season 2009/seriesname S2009xE02 blah.avi")); + Assert.Equal(15, GetEndingEpisodeNumberFromFile(@"Season 2009/Elementary - 2009x03 - 2009x04 - 2009x15 - Ep Name.mp4")); + Assert.Equal(15, GetEndingEpisodeNumberFromFile(@"Season 2009/2009x03 - 2009x04 - 2009x15 - Ep Name.mp4")); + Assert.Equal(15, GetEndingEpisodeNumberFromFile(@"Season 2009/2009x03-04-15 - Ep Name.mp4")); + Assert.Equal(15, GetEndingEpisodeNumberFromFile(@"Season 2009/Elementary - 2009x03-04-15 - Ep Name.mp4")); + Assert.Equal(15, GetEndingEpisodeNumberFromFile(@"Season 2009/2009x03-E15 - Ep Name.mp4")); + Assert.Equal(15, GetEndingEpisodeNumberFromFile(@"Season 2009/Elementary - 2009x03-E15 - Ep Name.mp4")); + Assert.Equal(15, GetEndingEpisodeNumberFromFile(@"Season 2009/2009x03 - x04 - x15 - Ep Name.mp4")); + Assert.Equal(15, GetEndingEpisodeNumberFromFile(@"Season 2009/Elementary - 2009x03 - x04 - x15 - Ep Name.mp4")); + Assert.Equal(15, GetEndingEpisodeNumberFromFile(@"Season 2009/2009x03x04x15 - Ep Name.mp4")); + Assert.Equal(15, GetEndingEpisodeNumberFromFile(@"Season 2009/Elementary - 2009x03x04x15 - Ep Name.mp4")); + Assert.Equal(26, GetEndingEpisodeNumberFromFile(@"Season 2009/Elementary - S2009E23-E24-E26 - The Woman.mp4")); + Assert.Equal(26, GetEndingEpisodeNumberFromFile(@"Season 2009/S2009E23-E24-E26 - The Woman.mp4")); + + // Without season number + Assert.Null(GetEndingEpisodeNumberFromFile(@"Season 1/02 - blah.avi")); + Assert.Null(GetEndingEpisodeNumberFromFile(@"Season 2/02 - blah 14 blah.avi")); + Assert.Null(GetEndingEpisodeNumberFromFile(@"Season 1/02 - blah-02 a.avi")); + Assert.Null(GetEndingEpisodeNumberFromFile(@"Season 2/02.avi")); + + Assert.Equal(3, GetEndingEpisodeNumberFromFile(@"Season 1/02-03 - blah.avi")); + Assert.Equal(4, GetEndingEpisodeNumberFromFile(@"Season 2/02-04 - blah 14 blah.avi")); + Assert.Equal(5, GetEndingEpisodeNumberFromFile(@"Season 1/02-05 - blah-02 a.avi")); + Assert.Equal(4, GetEndingEpisodeNumberFromFile(@"Season 2/02-04.avi")); + Assert.Null(GetEndingEpisodeNumberFromFile(@"Season 2/[HorribleSubs] Hunter X Hunter - 136 [720p].mkv")); + + // With format specification that must not be detected as ending episode number + Assert.Null(GetEndingEpisodeNumberFromFile(@"Season 1/series-s09e14-1080p.mkv")); + Assert.Null(GetEndingEpisodeNumberFromFile(@"Season 1/series-s09e14-720p.mkv")); + Assert.Null(GetEndingEpisodeNumberFromFile(@"Season 1/series-s09e14-720i.mkv")); + Assert.Equal(4, GetEndingEpisodeNumberFromFile(@"Season 1/MOONLIGHTING_s01e01-e04.mkv")); + } + + [Fact] + public void TestGetEndingEpisodeNumberFromFolder() + { + Assert.Equal(4, GetEndingEpisodeNumberFromFolder(@"Season 1/MOONLIGHTING_s01e01-e04")); + } + + private int? GetEndingEpisodeNumberFromFolder(string path) + { + var options = new NamingOptions(); + + var result = new EpisodePathParser(options) + .Parse(path, true); + + return result.EndingEpsiodeNumber; + } + + private int? GetEndingEpisodeNumberFromFile(string path) + { + var options = new NamingOptions(); + + var result = new EpisodePathParser(options) + .Parse(path, false); + + return result.EndingEpsiodeNumber; + } + } +} diff --git a/tests/Jellyfin.Naming.Tests/TV/SeasonFolderTests.cs b/tests/Jellyfin.Naming.Tests/TV/SeasonFolderTests.cs new file mode 100644 index 0000000000..ffa8d34838 --- /dev/null +++ b/tests/Jellyfin.Naming.Tests/TV/SeasonFolderTests.cs @@ -0,0 +1,112 @@ +using Emby.Naming.TV; +using Xunit; + +namespace Jellyfin.Naming.Tests.TV +{ + public class SeasonFolderTests + { + [Fact] + public void TestGetSeasonNumberFromPath1() + { + Assert.Equal(1, GetSeasonNumberFromPath(@"/Drive/Season 1")); + } + + [Fact] + public void TestGetSeasonNumberFromPath2() + { + Assert.Equal(2, GetSeasonNumberFromPath(@"/Drive/Season 2")); + } + + [Fact] + public void TestGetSeasonNumberFromPath3() + { + Assert.Equal(2, GetSeasonNumberFromPath(@"/Drive/Season 02")); + } + + [Fact] + public void TestGetSeasonNumberFromPath4() + { + Assert.Equal(1, GetSeasonNumberFromPath(@"/Drive/Season 1")); + } + + [Fact] + public void TestGetSeasonNumberFromPath5() + { + Assert.Equal(2, GetSeasonNumberFromPath(@"/Drive/Seinfeld/S02")); + } + + [Fact] + public void TestGetSeasonNumberFromPath6() + { + Assert.Equal(2, GetSeasonNumberFromPath(@"/Drive/Seinfeld/2")); + } + + [Fact] + public void TestGetSeasonNumberFromPath7() + { + Assert.Equal(2009, GetSeasonNumberFromPath(@"/Drive/Season 2009")); + } + + [Fact] + public void TestGetSeasonNumberFromPath8() + { + Assert.Equal(1, GetSeasonNumberFromPath(@"/Drive/Season1")); + } + + [Fact] + public void TestGetSeasonNumberFromPath9() + { + Assert.Equal(4, GetSeasonNumberFromPath(@"The Wonder Years/The.Wonder.Years.S04.PDTV.x264-JCH")); + } + + [Fact] + public void TestGetSeasonNumberFromPath10() + { + Assert.Equal(7, GetSeasonNumberFromPath(@"/Drive/Season 7 (2016)")); + } + + [Fact] + public void TestGetSeasonNumberFromPath11() + { + Assert.Equal(7, GetSeasonNumberFromPath(@"/Drive/Staffel 7 (2016)")); + } + + [Fact] + public void TestGetSeasonNumberFromPath12() + { + Assert.Equal(7, GetSeasonNumberFromPath(@"/Drive/Stagione 7 (2016)")); + } + + [Fact] + public void TestGetSeasonNumberFromPath14() + { + Assert.Null(GetSeasonNumberFromPath(@"/Drive/Season (8)")); + } + + [Fact] + public void TestGetSeasonNumberFromPath13() + { + Assert.Equal(3, GetSeasonNumberFromPath(@"/Drive/3.Staffel")); + } + + [Fact] + public void TestGetSeasonNumberFromPath15() + { + Assert.Null(GetSeasonNumberFromPath(@"/Drive/s06e05")); + } + + [Fact] + public void TestGetSeasonNumberFromPath16() + { + Assert.Null(GetSeasonNumberFromPath(@"/Drive/The.Legend.of.Condor.Heroes.2017.V2.web-dl.1080p.h264.aac-hdctv")); + } + + private int? GetSeasonNumberFromPath(string path) + { + var result = new SeasonPathParser() + .Parse(path, true, true); + + return result.SeasonNumber; + } + } +} diff --git a/tests/Jellyfin.Naming.Tests/TV/SeasonNumberTests.cs b/tests/Jellyfin.Naming.Tests/TV/SeasonNumberTests.cs new file mode 100644 index 0000000000..ba3c5ecac9 --- /dev/null +++ b/tests/Jellyfin.Naming.Tests/TV/SeasonNumberTests.cs @@ -0,0 +1,305 @@ +using Emby.Naming.Common; +using Emby.Naming.TV; +using Xunit; + +namespace Jellyfin.Naming.Tests.TV +{ + public class SeasonNumberTests + { + private int? GetSeasonNumberFromEpisodeFile(string path) + { + var options = new NamingOptions(); + + var result = new EpisodeResolver(options) + .Resolve(path, false); + + return result.SeasonNumber; + } + + [Fact] + public void TestSeasonNumber1() + { + Assert.Equal(2, GetSeasonNumberFromEpisodeFile(@"/Show/Season 02/S02E03 blah.avi")); + } + + [Fact] + public void TestSeasonNumber2() + { + Assert.Equal(1, GetSeasonNumberFromEpisodeFile(@"Season 1/seriesname S01x02 blah.avi")); + } + + [Fact] + public void TestSeasonNumber3() + { + Assert.Equal(1, GetSeasonNumberFromEpisodeFile(@"Season 1/S01x02 blah.avi")); + } + + [Fact] + public void TestSeasonNumber4() + { + Assert.Equal(1, GetSeasonNumberFromEpisodeFile(@"Season 1/seriesname S01xE02 blah.avi")); + } + + [Fact] + public void TestSeasonNumber5() + { + Assert.Equal(1, GetSeasonNumberFromEpisodeFile(@"Season 1/01x02 blah.avi")); + } + + [Fact] + public void TestSeasonNumber6() + { + Assert.Equal(1, GetSeasonNumberFromEpisodeFile(@"Season 1/S01E02 blah.avi")); + } + + [Fact] + public void TestSeasonNumber7() + { + Assert.Equal(1, GetSeasonNumberFromEpisodeFile(@"Season 1/S01xE02 blah.avi")); + } + + // FIXME + // [Fact] + public void TestSeasonNumber8() + { + Assert.Equal(1, GetSeasonNumberFromEpisodeFile(@"Season 1/seriesname 01x02 blah.avi")); + } + + [Fact] + public void TestSeasonNumber9() + { + Assert.Equal(1, GetSeasonNumberFromEpisodeFile(@"Season 1/seriesname S01x02 blah.avi")); + } + + [Fact] + public void TestSeasonNumber10() + { + Assert.Equal(1, GetSeasonNumberFromEpisodeFile(@"Season 1/seriesname S01E02 blah.avi")); + } + + [Fact] + public void TestSeasonNumber11() + { + Assert.Equal(2, GetSeasonNumberFromEpisodeFile(@"Season 2/Elementary - 02x03 - 02x04 - 02x15 - Ep Name.mp4")); + } + + [Fact] + public void TestSeasonNumber12() + { + Assert.Equal(2, GetSeasonNumberFromEpisodeFile(@"Season 2/02x03 - 02x04 - 02x15 - Ep Name.mp4")); + } + + [Fact] + public void TestSeasonNumber13() + { + Assert.Equal(2, GetSeasonNumberFromEpisodeFile(@"Season 2/02x03-04-15 - Ep Name.mp4")); + } + + [Fact] + public void TestSeasonNumber14() + { + Assert.Equal(2, GetSeasonNumberFromEpisodeFile(@"Season 2/Elementary - 02x03-04-15 - Ep Name.mp4")); + } + + [Fact] + public void TestSeasonNumber15() + { + Assert.Equal(2, GetSeasonNumberFromEpisodeFile(@"Season 02/02x03-E15 - Ep Name.mp4")); + } + + [Fact] + public void TestSeasonNumber16() + { + Assert.Equal(2, GetSeasonNumberFromEpisodeFile(@"Season 02/Elementary - 02x03-E15 - Ep Name.mp4")); + } + + [Fact] + public void TestSeasonNumber17() + { + Assert.Equal(2, GetSeasonNumberFromEpisodeFile(@"Season 02/02x03 - x04 - x15 - Ep Name.mp4")); + } + + [Fact] + public void TestSeasonNumber18() + { + Assert.Equal(2, GetSeasonNumberFromEpisodeFile(@"Season 02/Elementary - 02x03 - x04 - x15 - Ep Name.mp4")); + } + + [Fact] + public void TestSeasonNumber19() + { + Assert.Equal(2, GetSeasonNumberFromEpisodeFile(@"Season 02/02x03x04x15 - Ep Name.mp4")); + } + + [Fact] + public void TestSeasonNumber20() + { + Assert.Equal(2, GetSeasonNumberFromEpisodeFile(@"Season 02/Elementary - 02x03x04x15 - Ep Name.mp4")); + } + + [Fact] + public void TestSeasonNumber21() + { + Assert.Equal(1, GetSeasonNumberFromEpisodeFile(@"Season 1/Elementary - S01E23-E24-E26 - The Woman.mp4")); + } + + [Fact] + public void TestSeasonNumber22() + { + Assert.Equal(1, GetSeasonNumberFromEpisodeFile(@"Season 1/S01E23-E24-E26 - The Woman.mp4")); + } + + [Fact] + public void TestSeasonNumber23() + { + Assert.Equal(25, GetSeasonNumberFromEpisodeFile(@"Season 25/The Simpsons.S25E09.Steal this episode.mp4")); + } + + [Fact] + public void TestSeasonNumber24() + { + Assert.Equal(25, GetSeasonNumberFromEpisodeFile(@"The Simpsons/The Simpsons.S25E09.Steal this episode.mp4")); + } + + [Fact] + public void TestSeasonNumber25() + { + Assert.Equal(2016, GetSeasonNumberFromEpisodeFile(@"2016/Season s2016e1.mp4")); + } + + // FIXME + // [Fact] + public void TestSeasonNumber26() + { + // This convention is not currently supported, just adding in case we want to look at it in the future + Assert.Equal(2016, GetSeasonNumberFromEpisodeFile(@"2016/Season 2016x1.mp4")); + } + + [Fact] + public void TestFourDigitSeasonNumber1() + { + Assert.Equal(2009, GetSeasonNumberFromEpisodeFile(@"Season 2009/2009x02 blah.avi")); + } + + [Fact] + public void TestFourDigitSeasonNumber2() + { + Assert.Equal(2009, GetSeasonNumberFromEpisodeFile(@"Season 2009/S2009x02 blah.avi")); + } + + [Fact] + public void TestFourDigitSeasonNumber3() + { + Assert.Equal(2009, GetSeasonNumberFromEpisodeFile(@"Season 2009/S2009E02 blah.avi")); + } + + [Fact] + public void TestFourDigitSeasonNumber4() + { + Assert.Equal(2009, GetSeasonNumberFromEpisodeFile(@"Season 2009/S2009xE02 blah.avi")); + } + + // FIXME + // [Fact] + public void TestFourDigitSeasonNumber5() + { + Assert.Equal(2009, GetSeasonNumberFromEpisodeFile(@"Season 2009/seriesname 2009x02 blah.avi")); + } + + [Fact] + public void TestFourDigitSeasonNumber6() + { + Assert.Equal(2009, GetSeasonNumberFromEpisodeFile(@"Season 2009/seriesname S2009x02 blah.avi")); + } + + [Fact] + public void TestFourDigitSeasonNumber7() + { + Assert.Equal(2009, GetSeasonNumberFromEpisodeFile(@"Season 2009/seriesname S2009E02 blah.avi")); + } + + [Fact] + public void TestFourDigitSeasonNumber8() + { + Assert.Equal(2009, GetSeasonNumberFromEpisodeFile(@"Season 2009/Elementary - 2009x03 - 2009x04 - 2009x15 - Ep Name.mp4")); + } + + [Fact] + public void TestFourDigitSeasonNumber9() + { + Assert.Equal(2009, GetSeasonNumberFromEpisodeFile(@"Season 2009/2009x03 - 2009x04 - 2009x15 - Ep Name.mp4")); + } + + [Fact] + public void TestFourDigitSeasonNumber10() + { + Assert.Equal(2009, GetSeasonNumberFromEpisodeFile(@"Season 2009/2009x03-04-15 - Ep Name.mp4")); + } + + [Fact] + public void TestFourDigitSeasonNumber11() + { + Assert.Equal(2009, GetSeasonNumberFromEpisodeFile(@"Season 2009/Elementary - 2009x03 - x04 - x15 - Ep Name.mp4")); + } + + [Fact] + public void TestFourDigitSeasonNumber12() + { + Assert.Equal(2009, GetSeasonNumberFromEpisodeFile(@"Season 2009/2009x03x04x15 - Ep Name.mp4")); + } + + [Fact] + public void TestFourDigitSeasonNumber13() + { + Assert.Equal(2009, GetSeasonNumberFromEpisodeFile(@"Season 2009/Elementary - 2009x03x04x15 - Ep Name.mp4")); + } + + [Fact] + public void TestFourDigitSeasonNumber14() + { + Assert.Equal(2009, GetSeasonNumberFromEpisodeFile(@"Season 2009/Elementary - S2009E23-E24-E26 - The Woman.mp4")); + } + + [Fact] + public void TestFourDigitSeasonNumber15() + { + Assert.Equal(2009, GetSeasonNumberFromEpisodeFile(@"Season 2009/S2009E23-E24-E26 - The Woman.mp4")); + } + + [Fact] + public void TestFourDigitSeasonNumber16() + { + Assert.Equal(2009, GetSeasonNumberFromEpisodeFile(@"Season 2009/Elementary - 2009x03 - x04 - x15 - Ep Name.mp4")); + } + + [Fact] + public void TestFourDigitSeasonNumber17() + { + Assert.Equal(2009, GetSeasonNumberFromEpisodeFile(@"Season 2009/2009x03x04x15 - Ep Name.mp4")); + } + + [Fact] + public void TestFourDigitSeasonNumber18() + { + Assert.Equal(2009, GetSeasonNumberFromEpisodeFile(@"Season 2009/Elementary - 2009x03x04x15 - Ep Name.mp4")); + } + + [Fact] + public void TestFourDigitSeasonNumber19() + { + Assert.Equal(2009, GetSeasonNumberFromEpisodeFile(@"Season 2009/Elementary - S2009E23-E24-E26 - The Woman.mp4")); + } + + [Fact] + public void TestFourDigitSeasonNumber20() + { + Assert.Equal(2009, GetSeasonNumberFromEpisodeFile(@"Season 2009/S2009E23-E24-E26 - The Woman.mp4")); + } + + [Fact] + public void TestNoSeriesFolder() + { + Assert.Equal(1, GetSeasonNumberFromEpisodeFile(@"Series/1-12 - The Woman.mp4")); + } + } +} diff --git a/tests/Jellyfin.Naming.Tests/TV/SimpleEpisodeTests.cs b/tests/Jellyfin.Naming.Tests/TV/SimpleEpisodeTests.cs new file mode 100644 index 0000000000..c9323c218e --- /dev/null +++ b/tests/Jellyfin.Naming.Tests/TV/SimpleEpisodeTests.cs @@ -0,0 +1,95 @@ +using Emby.Naming.Common; +using Emby.Naming.TV; +using Xunit; + +namespace Jellyfin.Naming.Tests.TV +{ + public class SimpleEpisodeTests + { + [Fact] + public void TestSimpleEpisodePath1() + { + Test(@"/server/anything_s01e02.mp4", "anything", 1, 2); + } + + [Fact] + public void TestSimpleEpisodePath2() + { + Test(@"/server/anything_s1e2.mp4", "anything", 1, 2); + } + + [Fact] + public void TestSimpleEpisodePath3() + { + Test(@"/server/anything_s01.e02.mp4", "anything", 1, 2); + } + + [Fact] + public void TestSimpleEpisodePath4() + { + Test(@"/server/anything_s01_e02.mp4", "anything", 1, 2); + } + + [Fact] + public void TestSimpleEpisodePath5() + { + Test(@"/server/anything_102.mp4", "anything", 1, 2); + } + + [Fact] + public void TestSimpleEpisodePath6() + { + Test(@"/server/anything_1x02.mp4", "anything", 1, 2); + } + + // FIXME + // [Fact] + public void TestSimpleEpisodePath7() + { + Test(@"/server/The Walking Dead 4x01.mp4", "The Walking Dead", 4, 1); + } + + [Fact] + public void TestSimpleEpisodePath8() + { + Test(@"/server/the_simpsons-s02e01_18536.mp4", "the_simpsons", 2, 1); + } + + + [Fact] + public void TestSimpleEpisodePath9() + { + Test(@"/server/Temp/S01E02 foo.mp4", string.Empty, 1, 2); + } + + [Fact] + public void TestSimpleEpisodePath10() + { + Test(@"Series/4-12 - The Woman.mp4", string.Empty, 4, 12); + } + + [Fact] + public void TestSimpleEpisodePath11() + { + Test(@"Series/4x12 - The Woman.mp4", string.Empty, 4, 12); + } + + [Fact] + public void TestSimpleEpisodePath12() + { + Test(@"Series/LA X, Pt. 1_s06e32.mp4", "LA X, Pt. 1", 6, 32); + } + + private void Test(string path, string seriesName, int? seasonNumber, int? episodeNumber) + { + var options = new NamingOptions(); + + var result = new EpisodeResolver(options) + .Resolve(path, false); + + Assert.Equal(seasonNumber, result.SeasonNumber); + Assert.Equal(episodeNumber, result.EpisodeNumber); + Assert.Equal(seriesName, result.SeriesName, true); + } + } +} diff --git a/tests/Jellyfin.Naming.Tests/Video/BaseVideoTest.cs b/tests/Jellyfin.Naming.Tests/Video/BaseVideoTest.cs new file mode 100644 index 0000000000..b993e241c0 --- /dev/null +++ b/tests/Jellyfin.Naming.Tests/Video/BaseVideoTest.cs @@ -0,0 +1,15 @@ +using Emby.Naming.Common; +using Emby.Naming.Video; + +namespace Jellyfin.Naming.Tests.Video +{ + public abstract class BaseVideoTest + { + protected VideoResolver GetParser() + { + var options = new NamingOptions(); + + return new VideoResolver(options); + } + } +} diff --git a/tests/Jellyfin.Naming.Tests/Video/CleanDateTimeTests.cs b/tests/Jellyfin.Naming.Tests/Video/CleanDateTimeTests.cs new file mode 100644 index 0000000000..bba73ad918 --- /dev/null +++ b/tests/Jellyfin.Naming.Tests/Video/CleanDateTimeTests.cs @@ -0,0 +1,143 @@ +using System.IO; +using Xunit; + +namespace Jellyfin.Naming.Tests.Video +{ + public class CleanDateTimeTests : BaseVideoTest + { + // FIXME + // [Fact] + public void TestCleanDateTime() + { + Test(@"The Wolf of Wall Street (2013).mkv", "The Wolf of Wall Street", 2013); + Test(@"The Wolf of Wall Street 2 (2013).mkv", "The Wolf of Wall Street 2", 2013); + Test(@"The Wolf of Wall Street - 2 (2013).mkv", "The Wolf of Wall Street - 2", 2013); + Test(@"The Wolf of Wall Street 2001 (2013).mkv", "The Wolf of Wall Street 2001", 2013); + + Test(@"300 (2006).mkv", "300", 2006); + Test(@"d:/movies/300 (2006).mkv", "300", 2006); + Test(@"300 2 (2006).mkv", "300 2", 2006); + Test(@"300 - 2 (2006).mkv", "300 - 2", 2006); + Test(@"300 2001 (2006).mkv", "300 2001", 2006); + + Test(@"curse.of.chucky.2013.stv.unrated.multi.1080p.bluray.x264-rough", "curse.of.chucky", 2013); + Test(@"curse.of.chucky.2013.stv.unrated.multi.2160p.bluray.x264-rough", "curse.of.chucky", 2013); + + Test(@"/server/Movies/300 (2007)/300 (2006).bluray.disc", "300", 2006); + } + + // FIXME + // [Fact] + public void TestCleanDateTime1() + { + Test(@"Arrival.2016.2160p.Blu-Ray.HEVC.mkv", "Arrival", 2016); + } + + // FIXME + // [Fact] + public void TestCleanDateTimeWithoutFileExtension() + { + Test(@"The Wolf of Wall Street (2013)", "The Wolf of Wall Street", 2013); + Test(@"The Wolf of Wall Street 2 (2013)", "The Wolf of Wall Street 2", 2013); + Test(@"The Wolf of Wall Street - 2 (2013)", "The Wolf of Wall Street - 2", 2013); + Test(@"The Wolf of Wall Street 2001 (2013)", "The Wolf of Wall Street 2001", 2013); + + Test(@"300 (2006)", "300", 2006); + Test(@"d:/movies/300 (2006)", "300", 2006); + Test(@"300 2 (2006)", "300 2", 2006); + Test(@"300 - 2 (2006)", "300 - 2", 2006); + Test(@"300 2001 (2006)", "300 2001", 2006); + + Test(@"/server/Movies/300 (2007)/300 (2006)", "300", 2006); + Test(@"/server/Movies/300 (2007)/300 (2006).mkv", "300", 2006); + } + + [Fact] + public void TestCleanDateTimeWithoutDate() + { + Test(@"American.Psycho.mkv", "American.Psycho.mkv", null); + Test(@"American Psycho.mkv", "American Psycho.mkv", null); + } + + [Fact] + public void TestCleanDateTimeWithBracketedName() + { + Test(@"[rec].mkv", "[rec].mkv", null); + } + + // FIXME + // [Fact] + public void TestCleanDateTimeWithoutExtension() + { + Test(@"St. Vincent (2014)", "St. Vincent", 2014); + } + + // FIXME + // [Fact] + public void TestCleanDateTimeWithoutDate1() + { + Test("Super movie(2009).mp4", "Super movie", 2009); + } + + // FIXME + // [Fact] + public void TestCleanDateTimeWithoutParenthesis() + { + Test("Drug War 2013.mp4", "Drug War", 2013); + } + + // FIXME + // [Fact] + public void TestCleanDateTimeWithMultipleYears() + { + Test("My Movie (1997) - GreatestReleaseGroup 2019.mp4", "My Movie", 1997); + } + + // FIXME + // [Fact] + public void TestCleanDateTimeWithYearAndResolution() + { + Test("First Man 2018 1080p.mkv", "First Man", 2018); + } + + // FIXME + // [Fact] + public void TestCleanDateTimeWithYearAndResolution1() + { + Test("First Man (2018) 1080p.mkv", "First Man", 2018); + } + + // FIXME + // [Fact] + public void TestCleanDateTimeWithSceneRelease() + { + Test("Maximum Ride - 2016 - WEBDL-1080p - x264 AC3.mkv", "Maximum Ride", 2016); + } + + // FIXME + // [Fact] + public void TestYearInBrackets() + { + Test("Robin Hood [Multi-Subs] [2018].mkv", "Robin Hood", 2018); + } + + private void Test(string input, string expectedName, int? expectedYear) + { + input = Path.GetFileName(input); + + var result = GetParser().CleanDateTime(input); + + Assert.Equal(expectedName, result.Name, true); + Assert.Equal(expectedYear, result.Year); + } + + // FIXME + // [Fact] + public void TestCleanDateAndStringsSequence() + { + // In this test case, running CleanDateTime first produces no date, so it will attempt to run CleanString first and then CleanDateTime again + + Test(@"3.Days.to.Kill.2014.720p.BluRay.x264.YIFY.mkv", "3.Days.to.Kill", 2014); + } + } +} diff --git a/tests/Jellyfin.Naming.Tests/Video/CleanStringTests.cs b/tests/Jellyfin.Naming.Tests/Video/CleanStringTests.cs new file mode 100644 index 0000000000..cd90ac236c --- /dev/null +++ b/tests/Jellyfin.Naming.Tests/Video/CleanStringTests.cs @@ -0,0 +1,133 @@ +using System; +using System.Globalization; +using Xunit; + +namespace Jellyfin.Naming.Tests.Video +{ + public class CleanStringTests : BaseVideoTest + { + // FIXME + // [Fact] + public void TestCleanString() + { + Test("Super movie 480p.mp4", "Super movie"); + Test("Super movie 480p 2001.mp4", "Super movie"); + Test("Super movie [480p].mp4", "Super movie"); + Test("480 Super movie [tmdbid=12345].mp4", "480 Super movie"); + } + + // FIXME + // [Fact] + public void TestCleanString1() + { + Test("Super movie(2009).mp4", "Super movie(2009).mp4"); + } + + // FIXME + // [Fact] + public void TestCleanString2() + { + Test("Run lola run (lola rennt) (2009).mp4", "Run lola run (lola rennt) (2009).mp4"); + } + + // FIXME + // [Fact] + public void TestStringWithoutDate() + { + Test(@"American.Psycho.mkv", "American.Psycho.mkv"); + Test(@"American Psycho.mkv", "American Psycho.mkv"); + } + + // FIXME + // [Fact] + public void TestNameWithBrackets() + { + Test(@"[rec].mkv", "[rec].mkv"); + } + + // FIXME + // [Fact] + public void Test4k() + { + Test("Crouching.Tiger.Hidden.Dragon.4k.mkv", "Crouching.Tiger.Hidden.Dragon"); + } + + // FIXME + // [Fact] + public void TestUltraHd() + { + Test("Crouching.Tiger.Hidden.Dragon.UltraHD.mkv", "Crouching.Tiger.Hidden.Dragon"); + } + + // FIXME + // [Fact] + public void TestUHd() + { + Test("Crouching.Tiger.Hidden.Dragon.UHD.mkv", "Crouching.Tiger.Hidden.Dragon"); + } + + // FIXME + // [Fact] + public void TestHDR() + { + Test("Crouching.Tiger.Hidden.Dragon.HDR.mkv", "Crouching.Tiger.Hidden.Dragon"); + } + + // FIXME + // [Fact] + public void TestHDC() + { + Test("Crouching.Tiger.Hidden.Dragon.HDC.mkv", "Crouching.Tiger.Hidden.Dragon"); + } + + // FIXME + // [Fact] + public void TestHDC1() + { + Test("Crouching.Tiger.Hidden.Dragon-HDC.mkv", "Crouching.Tiger.Hidden.Dragon"); + } + + // FIXME + // [Fact] + public void TestBDrip() + { + Test("Crouching.Tiger.Hidden.Dragon.BDrip.mkv", "Crouching.Tiger.Hidden.Dragon"); + } + + // FIXME + // [Fact] + public void TestBDripHDC() + { + Test("Crouching.Tiger.Hidden.Dragon.BDrip-HDC.mkv", "Crouching.Tiger.Hidden.Dragon"); + } + + // FIXME + // [Fact] + public void TestMulti() + { + Test("Crouching.Tiger.Hidden.Dragon.4K.UltraHD.HDR.BDrip-HDC.mkv", "Crouching.Tiger.Hidden.Dragon"); + } + + // FIXME + // [Fact] + public void TestLeadingBraces() + { + // Not actually supported, just reported by a user + Test("[0004] - After The Sunset.el.mkv", "After The Sunset"); + } + + // FIXME + // [Fact] + public void TestTrailingBraces() + { + Test("After The Sunset - [0004].mkv", "After The Sunset"); + } + + private void Test(string input, string expectedName) + { + var result = GetParser().CleanString(input).ToString(); + + Assert.Equal(expectedName, result, true); + } + } +} diff --git a/tests/Jellyfin.Naming.Tests/Video/ExtraTests.cs b/tests/Jellyfin.Naming.Tests/Video/ExtraTests.cs new file mode 100644 index 0000000000..1646237a0e --- /dev/null +++ b/tests/Jellyfin.Naming.Tests/Video/ExtraTests.cs @@ -0,0 +1,77 @@ +using Emby.Naming.Common; +using Emby.Naming.Video; +using MediaBrowser.Model.Entities; +using Xunit; + +namespace Jellyfin.Naming.Tests.Video +{ + public class ExtraTests : BaseVideoTest + { + // Requirements + // movie-deleted = ExtraType deletedscene + + // All of the above rules should be configurable through the options objects (ideally, even the ExtraTypes) + + [Fact] + public void TestKodiExtras() + { + var videoOptions = new NamingOptions(); + + Test("trailer.mp4", ExtraType.Trailer, videoOptions); + Test("300-trailer.mp4", ExtraType.Trailer, videoOptions); + + Test("theme.mp3", ExtraType.ThemeSong, videoOptions); + } + + [Fact] + public void TestExpandedExtras() + { + var videoOptions = new NamingOptions(); + + Test("trailer.mp4", ExtraType.Trailer, videoOptions); + Test("trailer.mp3", null, videoOptions); + Test("300-trailer.mp4", ExtraType.Trailer, videoOptions); + + Test("theme.mp3", ExtraType.ThemeSong, videoOptions); + Test("theme.mkv", null, videoOptions); + + Test("300-scene.mp4", ExtraType.Scene, videoOptions); + Test("300-scene2.mp4", ExtraType.Scene, videoOptions); + Test("300-clip.mp4", ExtraType.Clip, videoOptions); + + Test("300-deleted.mp4", ExtraType.DeletedScene, videoOptions); + Test("300-deletedscene.mp4", ExtraType.DeletedScene, videoOptions); + Test("300-interview.mp4", ExtraType.Interview, videoOptions); + Test("300-behindthescenes.mp4", ExtraType.BehindTheScenes, videoOptions); + } + + [Fact] + public void TestSample() + { + var videoOptions = new NamingOptions(); + + Test("300-sample.mp4", ExtraType.Sample, videoOptions); + } + + private void Test(string input, ExtraType? expectedType, NamingOptions videoOptions) + { + var parser = GetExtraTypeParser(videoOptions); + + var extraType = parser.GetExtraInfo(input).ExtraType; + + if (expectedType == null) + { + Assert.Null(extraType); + } + else + { + Assert.Equal(expectedType, extraType); + } + } + + private ExtraResolver GetExtraTypeParser(NamingOptions videoOptions) + { + return new ExtraResolver(videoOptions); + } + } +} diff --git a/tests/Jellyfin.Naming.Tests/Video/Format3DTests.cs b/tests/Jellyfin.Naming.Tests/Video/Format3DTests.cs new file mode 100644 index 0000000000..ed3112936d --- /dev/null +++ b/tests/Jellyfin.Naming.Tests/Video/Format3DTests.cs @@ -0,0 +1,78 @@ +using Emby.Naming.Common; +using Emby.Naming.Video; +using Xunit; + +namespace Jellyfin.Naming.Tests.Video +{ + public class Format3DTests : BaseVideoTest + { + [Fact] + public void TestKodiFormat3D() + { + var options = new NamingOptions(); + + Test("Super movie.3d.mp4", false, null, options); + Test("Super movie.3d.hsbs.mp4", true, "hsbs", options); + Test("Super movie.3d.sbs.mp4", true, "sbs", options); + Test("Super movie.3d.htab.mp4", true, "htab", options); + Test("Super movie.3d.tab.mp4", true, "tab", options); + Test("Super movie 3d hsbs.mp4", true, "hsbs", options); + } + + [Fact] + public void Test3DName() + { + var result = + GetParser().ResolveFile(@"C:/Users/media/Desktop/Video Test/Movies/Oblivion/Oblivion.3d.hsbs.mkv"); + + Assert.Equal("hsbs", result.Format3D); + Assert.Equal("Oblivion", result.Name); + } + + [Fact] + public void TestExpandedFormat3D() + { + // These were introduced for Media Browser 3 + // Kodi conventions are preferred but these still need to be supported + var options = new NamingOptions(); + + Test("Super movie.3d.mp4", false, null, options); + Test("Super movie.3d.hsbs.mp4", true, "hsbs", options); + Test("Super movie.3d.sbs.mp4", true, "sbs", options); + Test("Super movie.3d.htab.mp4", true, "htab", options); + Test("Super movie.3d.tab.mp4", true, "tab", options); + + Test("Super movie.hsbs.mp4", true, "hsbs", options); + Test("Super movie.sbs.mp4", true, "sbs", options); + Test("Super movie.htab.mp4", true, "htab", options); + Test("Super movie.tab.mp4", true, "tab", options); + Test("Super movie.sbs3d.mp4", true, "sbs3d", options); + Test("Super movie.3d.mvc.mp4", true, "mvc", options); + + Test("Super movie [3d].mp4", false, null, options); + Test("Super movie [hsbs].mp4", true, "hsbs", options); + Test("Super movie [fsbs].mp4", true, "fsbs", options); + Test("Super movie [ftab].mp4", true, "ftab", options); + Test("Super movie [htab].mp4", true, "htab", options); + Test("Super movie [sbs3d].mp4", true, "sbs3d", options); + } + + private void Test(string input, bool is3D, string format3D, NamingOptions options) + { + var parser = new Format3DParser(options); + + var result = parser.Parse(input); + + Assert.Equal(is3D, result.Is3D); + + if (format3D == null) + { + Assert.Null(result.Format3D); + } + else + { + Assert.Equal(format3D, result.Format3D, true); + } + } + } +} diff --git a/tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs b/tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs new file mode 100644 index 0000000000..b8674ec495 --- /dev/null +++ b/tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs @@ -0,0 +1,438 @@ +using System.Linq; +using Emby.Naming.Common; +using Emby.Naming.Video; +using MediaBrowser.Model.IO; +using Xunit; + +namespace Jellyfin.Naming.Tests.Video +{ + public class MultiVersionTests + { + // FIXME + // [Fact] + public void TestMultiEdition1() + { + var files = new[] + { + @"/movies/X-Men Days of Future Past/X-Men Days of Future Past - 1080p.mkv", + @"/movies/X-Men Days of Future Past/X-Men Days of Future Past-trailer.mp4", + @"/movies/X-Men Days of Future Past/X-Men Days of Future Past - [hsbs].mkv", + @"/movies/X-Men Days of Future Past/X-Men Days of Future Past [hsbs].mkv" + }; + + var resolver = GetResolver(); + + var result = resolver.Resolve(files.Select(i => new FileSystemMetadata + { + IsDirectory = false, + FullName = i + + }).ToList()).ToList(); + + Assert.Single(result); + Assert.Single(result[0].Extras); + } + + // FIXME + // [Fact] + public void TestMultiEdition2() + { + var files = new[] + { + @"/movies/X-Men Days of Future Past/X-Men Days of Future Past - apple.mkv", + @"/movies/X-Men Days of Future Past/X-Men Days of Future Past-trailer.mp4", + @"/movies/X-Men Days of Future Past/X-Men Days of Future Past - banana.mkv", + @"/movies/X-Men Days of Future Past/X-Men Days of Future Past [banana].mp4" + }; + + var resolver = GetResolver(); + + var result = resolver.Resolve(files.Select(i => new FileSystemMetadata + { + IsDirectory = false, + FullName = i + + }).ToList()).ToList(); + + Assert.Single(result); + Assert.Single(result[0].Extras); + Assert.Equal(2, result[0].AlternateVersions.Count); + } + + [Fact] + public void TestMultiEdition3() + { + // This is currently not supported and will fail, but we should try to figure it out + var files = new[] + { + @"/movies/The Phantom of the Opera (1925)/The Phantom of the Opera (1925) - 1925 version.mkv", + @"/movies/The Phantom of the Opera (1925)/The Phantom of the Opera (1925) - 1929 version.mkv" + }; + + var resolver = GetResolver(); + + var result = resolver.Resolve(files.Select(i => new FileSystemMetadata + { + IsDirectory = false, + FullName = i + + }).ToList()).ToList(); + + Assert.Single(result); + Assert.Single(result[0].AlternateVersions); + } + + // FIXME + // [Fact] + public void TestLetterFolders() + { + var files = new[] + { + @"/movies/M/Movie 1.mkv", + @"/movies/M/Movie 2.mkv", + @"/movies/M/Movie 3.mkv", + @"/movies/M/Movie 4.mkv", + @"/movies/M/Movie 5.mkv", + @"/movies/M/Movie 6.mkv", + @"/movies/M/Movie 7.mkv" + }; + + var resolver = GetResolver(); + + var result = resolver.Resolve(files.Select(i => new FileSystemMetadata + { + IsDirectory = false, + FullName = i + + }).ToList()).ToList(); + + Assert.Equal(7, result.Count); + Assert.Empty(result[0].Extras); + Assert.Empty(result[0].AlternateVersions); + } + + // FIXME + // [Fact] + public void TestMultiVersionLimit() + { + var files = new[] + { + @"/movies/Movie/Movie.mkv", + @"/movies/Movie/Movie-2.mkv", + @"/movies/Movie/Movie-3.mkv", + @"/movies/Movie/Movie-4.mkv", + @"/movies/Movie/Movie-5.mkv", + @"/movies/Movie/Movie-6.mkv", + @"/movies/Movie/Movie-7.mkv", + @"/movies/Movie/Movie-8.mkv" + }; + + var resolver = GetResolver(); + + var result = resolver.Resolve(files.Select(i => new FileSystemMetadata + { + IsDirectory = false, + FullName = i + + }).ToList()).ToList(); + + Assert.Single(result); + Assert.Empty(result[0].Extras); + Assert.Equal(7, result[0].AlternateVersions.Count); + } + + // FIXME + // [Fact] + public void TestMultiVersionLimit2() + { + var files = new[] + { + @"/movies/Mo/Movie 1.mkv", + @"/movies/Mo/Movie 2.mkv", + @"/movies/Mo/Movie 3.mkv", + @"/movies/Mo/Movie 4.mkv", + @"/movies/Mo/Movie 5.mkv", + @"/movies/Mo/Movie 6.mkv", + @"/movies/Mo/Movie 7.mkv", + @"/movies/Mo/Movie 8.mkv", + @"/movies/Mo/Movie 9.mkv" + }; + + var resolver = GetResolver(); + + var result = resolver.Resolve(files.Select(i => new FileSystemMetadata + { + IsDirectory = false, + FullName = i + + }).ToList()).ToList(); + + Assert.Equal(9, result.Count); + Assert.Empty(result[0].Extras); + Assert.Empty(result[0].AlternateVersions); + } + + // FIXME + // [Fact] + public void TestMultiVersion3() + { + var files = new[] + { + @"/movies/Movie/Movie 1.mkv", + @"/movies/Movie/Movie 2.mkv", + @"/movies/Movie/Movie 3.mkv", + @"/movies/Movie/Movie 4.mkv", + @"/movies/Movie/Movie 5.mkv" + }; + + var resolver = GetResolver(); + + var result = resolver.Resolve(files.Select(i => new FileSystemMetadata + { + IsDirectory = false, + FullName = i + + }).ToList()).ToList(); + + Assert.Equal(5, result.Count); + Assert.Empty(result[0].Extras); + Assert.Empty(result[0].AlternateVersions); + } + + // FIXME + // [Fact] + public void TestMultiVersion4() + { + // Test for false positive + + var files = new[] + { + @"/movies/Iron Man/Iron Man.mkv", + @"/movies/Iron Man/Iron Man (2008).mkv", + @"/movies/Iron Man/Iron Man (2009).mkv", + @"/movies/Iron Man/Iron Man (2010).mkv", + @"/movies/Iron Man/Iron Man (2011).mkv" + }; + + var resolver = GetResolver(); + + var result = resolver.Resolve(files.Select(i => new FileSystemMetadata + { + IsDirectory = false, + FullName = i + + }).ToList()).ToList(); + + Assert.Equal(5, result.Count); + Assert.Empty(result[0].Extras); + Assert.Empty(result[0].AlternateVersions); + } + + // FIXME + // [Fact] + public void TestMultiVersion5() + { + var files = new[] + { + @"/movies/Iron Man/Iron Man.mkv", + @"/movies/Iron Man/Iron Man-720p.mkv", + @"/movies/Iron Man/Iron Man-test.mkv", + @"/movies/Iron Man/Iron Man-bluray.mkv", + @"/movies/Iron Man/Iron Man-3d.mkv", + @"/movies/Iron Man/Iron Man-3d-hsbs.mkv", + @"/movies/Iron Man/Iron Man-3d.hsbs.mkv", + @"/movies/Iron Man/Iron Man[test].mkv", + }; + + var resolver = GetResolver(); + + var result = resolver.Resolve(files.Select(i => new FileSystemMetadata + { + IsDirectory = false, + FullName = i + + }).ToList()).ToList(); + + Assert.Single(result); + Assert.Empty(result[0].Extras); + Assert.Equal(7, result[0].AlternateVersions.Count); + Assert.False(result[0].AlternateVersions[2].Is3D); + Assert.True(result[0].AlternateVersions[3].Is3D); + Assert.True(result[0].AlternateVersions[4].Is3D); + } + + // FIXME + // [Fact] + public void TestMultiVersion6() + { + var files = new[] + { + @"/movies/Iron Man/Iron Man.mkv", + @"/movies/Iron Man/Iron Man - 720p.mkv", + @"/movies/Iron Man/Iron Man - test.mkv", + @"/movies/Iron Man/Iron Man - bluray.mkv", + @"/movies/Iron Man/Iron Man - 3d.mkv", + @"/movies/Iron Man/Iron Man - 3d-hsbs.mkv", + @"/movies/Iron Man/Iron Man - 3d.hsbs.mkv", + @"/movies/Iron Man/Iron Man [test].mkv" + }; + + var resolver = GetResolver(); + + var result = resolver.Resolve(files.Select(i => new FileSystemMetadata + { + IsDirectory = false, + FullName = i + + }).ToList()).ToList(); + + Assert.Single(result); + Assert.Empty(result[0].Extras); + Assert.Equal(7, result[0].AlternateVersions.Count); + Assert.False(result[0].AlternateVersions[3].Is3D); + Assert.True(result[0].AlternateVersions[4].Is3D); + Assert.True(result[0].AlternateVersions[5].Is3D); + } + + // FIXME + // [Fact] + public void TestMultiVersion7() + { + var files = new[] + { + @"/movies/Iron Man/Iron Man - B (2006).mkv", + @"/movies/Iron Man/Iron Man - C (2007).mkv" + }; + + var resolver = GetResolver(); + + var result = resolver.Resolve(files.Select(i => new FileSystemMetadata + { + IsDirectory = false, + FullName = i + + }).ToList()).ToList(); + + Assert.Equal(2, result.Count); + } + + // FIXME + // [Fact] + public void TestMultiVersion8() + { + // This is not actually supported yet + + var files = new[] + { + @"/movies/Iron Man/Iron Man.mkv", + @"/movies/Iron Man/Iron Man_720p.mkv", + @"/movies/Iron Man/Iron Man_test.mkv", + @"/movies/Iron Man/Iron Man_bluray.mkv", + @"/movies/Iron Man/Iron Man_3d.mkv", + @"/movies/Iron Man/Iron Man_3d-hsbs.mkv", + @"/movies/Iron Man/Iron Man_3d.hsbs.mkv" + }; + + var resolver = GetResolver(); + + var result = resolver.Resolve(files.Select(i => new FileSystemMetadata + { + IsDirectory = false, + FullName = i + + }).ToList()).ToList(); + + Assert.Single(result); + Assert.Empty(result[0].Extras); + Assert.Equal(6, result[0].AlternateVersions.Count); + Assert.False(result[0].AlternateVersions[2].Is3D); + Assert.True(result[0].AlternateVersions[3].Is3D); + Assert.True(result[0].AlternateVersions[4].Is3D); + } + + // FIXME + // [Fact] + public void TestMultiVersion9() + { + // Test for false positive + + var files = new[] + { + @"/movies/Iron Man/Iron Man (2007).mkv", + @"/movies/Iron Man/Iron Man (2008).mkv", + @"/movies/Iron Man/Iron Man (2009).mkv", + @"/movies/Iron Man/Iron Man (2010).mkv", + @"/movies/Iron Man/Iron Man (2011).mkv" + }; + + var resolver = GetResolver(); + + var result = resolver.Resolve(files.Select(i => new FileSystemMetadata + { + IsDirectory = false, + FullName = i + + }).ToList()).ToList(); + + Assert.Equal(5, result.Count); + Assert.Empty(result[0].Extras); + Assert.Empty(result[0].AlternateVersions); + } + + // FIXME + // [Fact] + public void TestMultiVersion10() + { + var files = new[] + { + @"/movies/Blade Runner (1982)/Blade Runner (1982) [Final Cut] [1080p HEVC AAC].mkv", + @"/movies/Blade Runner (1982)/Blade Runner (1982) [EE by ADM] [480p HEVC AAC,AAC,AAC].mkv" + }; + + var resolver = GetResolver(); + + var result = resolver.Resolve(files.Select(i => new FileSystemMetadata + { + IsDirectory = false, + FullName = i + + }).ToList()).ToList(); + + Assert.Single(result); + Assert.Empty(result[0].Extras); + Assert.Single(result[0].AlternateVersions); + } + + // FIXME + // [Fact] + public void TestMultiVersion11() + { + // Currently not supported but we should probably handle this. + + var files = new[] + { + @"/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016) [1080p] Blu-ray.x264.DTS.mkv", + @"/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016) [2160p] Blu-ray.x265.AAC.mkv" + }; + + var resolver = GetResolver(); + + var result = resolver.Resolve(files.Select(i => new FileSystemMetadata + { + IsDirectory = false, + FullName = i + + }).ToList()).ToList(); + + Assert.Single(result); + Assert.Empty(result[0].Extras); + Assert.Single(result[0].AlternateVersions); + } + + private VideoListResolver GetResolver() + { + var options = new NamingOptions(); + return new VideoListResolver(options); + } + } +} diff --git a/tests/Jellyfin.Naming.Tests/Video/StackTests.cs b/tests/Jellyfin.Naming.Tests/Video/StackTests.cs new file mode 100644 index 0000000000..5faef0e3db --- /dev/null +++ b/tests/Jellyfin.Naming.Tests/Video/StackTests.cs @@ -0,0 +1,478 @@ +using Emby.Naming.Common; +using Emby.Naming.Video; +using MediaBrowser.Model.IO; +using Xunit; + +namespace Jellyfin.Naming.Tests.Video +{ + public class StackTests : BaseVideoTest + { + [Fact] + public void TestSimpleStack() + { + var files = new[] + { + "Bad Boys (2006) part1.mkv", + "Bad Boys (2006) part2.mkv", + "Bad Boys (2006) part3.mkv", + "Bad Boys (2006) part4.mkv", + "Bad Boys (2006)-trailer.mkv" + }; + + var resolver = GetResolver(); + + var result = resolver.ResolveFiles(files); + + Assert.Single(result.Stacks); + TestStackInfo(result.Stacks[0], "Bad Boys (2006)", 4); + } + + [Fact] + public void TestFalsePositives() + { + var files = new[] + { + "Bad Boys (2006).mkv", + "Bad Boys (2007).mkv" + }; + + var resolver = GetResolver(); + + var result = resolver.ResolveFiles(files); + + Assert.Empty(result.Stacks); + } + + [Fact] + public void TestFalsePositives2() + { + var files = new[] + { + "Bad Boys 2006.mkv", + "Bad Boys 2007.mkv" + }; + + var resolver = GetResolver(); + + var result = resolver.ResolveFiles(files); + + Assert.Empty(result.Stacks); + } + + [Fact] + public void TestFalsePositives3() + { + var files = new[] + { + "300 (2006).mkv", + "300 (2007).mkv" + }; + + var resolver = GetResolver(); + + var result = resolver.ResolveFiles(files); + + Assert.Empty(result.Stacks); + } + + [Fact] + public void TestFalsePositives4() + { + var files = new[] + { + "300 2006.mkv", + "300 2007.mkv" + }; + + var resolver = GetResolver(); + + var result = resolver.ResolveFiles(files); + + Assert.Empty(result.Stacks); + } + + [Fact] + public void TestFalsePositives5() + { + var files = new[] + { + "Star Trek 1 - The motion picture.mkv", + "Star Trek 2- The wrath of khan.mkv" + }; + + var resolver = GetResolver(); + + var result = resolver.ResolveFiles(files); + + Assert.Empty(result.Stacks); + } + + [Fact] + public void TestFalsePositives6() + { + var files = new[] + { + "Red Riding in the Year of Our Lord 1983 (2009).mkv", + "Red Riding in the Year of Our Lord 1980 (2009).mkv", + "Red Riding in the Year of Our Lord 1974 (2009).mkv" + }; + + var resolver = GetResolver(); + + var result = resolver.ResolveFiles(files); + + Assert.Empty(result.Stacks); + } + + [Fact] + public void TestStackName() + { + var files = new[] + { + "d:/movies/300 2006 part1.mkv", + "d:/movies/300 2006 part2.mkv" + }; + + var resolver = GetResolver(); + + var result = resolver.ResolveFiles(files); + + Assert.Single(result.Stacks); + TestStackInfo(result.Stacks[0], "300 2006", 2); + } + + [Fact] + public void TestDirtyNames() + { + var files = new[] + { + "Bad Boys (2006).part1.stv.unrated.multi.1080p.bluray.x264-rough.mkv", + "Bad Boys (2006).part2.stv.unrated.multi.1080p.bluray.x264-rough.mkv", + "Bad Boys (2006).part3.stv.unrated.multi.1080p.bluray.x264-rough.mkv", + "Bad Boys (2006).part4.stv.unrated.multi.1080p.bluray.x264-rough.mkv", + "Bad Boys (2006)-trailer.mkv" + }; + + var resolver = GetResolver(); + + var result = resolver.ResolveFiles(files); + + Assert.Single(result.Stacks); + TestStackInfo(result.Stacks[0], "Bad Boys (2006).stv.unrated.multi.1080p.bluray.x264-rough", 4); + } + + [Fact] + public void TestNumberedFiles() + { + var files = new[] + { + "Bad Boys (2006).mkv", + "Bad Boys (2006) 1.mkv", + "Bad Boys (2006) 2.mkv", + "Bad Boys (2006) 3.mkv", + "Bad Boys (2006)-trailer.mkv" + }; + + var resolver = GetResolver(); + + var result = resolver.ResolveFiles(files); + + Assert.Empty(result.Stacks); + } + + [Fact] + public void TestSimpleStackWithNumericName() + { + var files = new[] + { + "300 (2006) part1.mkv", + "300 (2006) part2.mkv", + "300 (2006) part3.mkv", + "300 (2006) part4.mkv", + "300 (2006)-trailer.mkv" + }; + + var resolver = GetResolver(); + + var result = resolver.ResolveFiles(files); + + Assert.Single(result.Stacks); + TestStackInfo(result.Stacks[0], "300 (2006)", 4); + } + + [Fact] + public void TestMixedExpressionsNotAllowed() + { + var files = new[] + { + "Bad Boys (2006) part1.mkv", + "Bad Boys (2006) part2.mkv", + "Bad Boys (2006) part3.mkv", + "Bad Boys (2006) parta.mkv", + "Bad Boys (2006)-trailer.mkv" + }; + + var resolver = GetResolver(); + + var result = resolver.ResolveFiles(files); + + Assert.Single(result.Stacks); + TestStackInfo(result.Stacks[0], "Bad Boys (2006)", 3); + } + + [Fact] + public void TestDualStacks() + { + var files = new[] + { + "Bad Boys (2006) part1.mkv", + "Bad Boys (2006) part2.mkv", + "Bad Boys (2006) part3.mkv", + "Bad Boys (2006) part4.mkv", + "Bad Boys (2006)-trailer.mkv", + "300 (2006) part1.mkv", + "300 (2006) part2.mkv", + "300 (2006) part3.mkv", + "300 (2006)-trailer.mkv" + }; + + var resolver = GetResolver(); + + var result = resolver.ResolveFiles(files); + + Assert.Equal(2, result.Stacks.Count); + TestStackInfo(result.Stacks[1], "Bad Boys (2006)", 4); + TestStackInfo(result.Stacks[0], "300 (2006)", 3); + } + + [Fact] + public void TestDirectories() + { + var files = new[] + { + "blah blah - cd 1", + "blah blah - cd 2" + }; + + var resolver = GetResolver(); + + var result = resolver.ResolveDirectories(files); + + Assert.Single(result.Stacks); + TestStackInfo(result.Stacks[0], "blah blah", 2); + } + + [Fact] + public void TestFalsePositive() + { + var files = new[] + { + "300a.mkv", + "300b.mkv", + "300c.mkv", + "300-trailer.mkv" + }; + + var resolver = GetResolver(); + + var result = resolver.ResolveFiles(files); + + Assert.Single(result.Stacks); + + TestStackInfo(result.Stacks[0], "300", 3); + } + + [Fact] + public void TestFailSequence() + { + var files = new[] + { + "300 part1.mkv", + "300 part2.mkv", + "Avatar", + "Avengers part1.mkv", + "Avengers part2.mkv", + "Avengers part3.mkv" + }; + + var resolver = GetResolver(); + + var result = resolver.ResolveFiles(files); + + Assert.Equal(2, result.Stacks.Count); + + TestStackInfo(result.Stacks[0], "300", 2); + TestStackInfo(result.Stacks[1], "Avengers", 3); + } + + [Fact] + public void TestMixedExpressions() + { + var files = new[] + { + "Bad Boys (2006) part1.mkv", + "Bad Boys (2006) part2.mkv", + "Bad Boys (2006) part3.mkv", + "Bad Boys (2006) part4.mkv", + "Bad Boys (2006)-trailer.mkv", + "300 (2006) parta.mkv", + "300 (2006) partb.mkv", + "300 (2006) partc.mkv", + "300 (2006) partd.mkv", + "300 (2006)-trailer.mkv", + "300a.mkv", + "300b.mkv", + "300c.mkv", + "300-trailer.mkv" + }; + + var resolver = GetResolver(); + + var result = resolver.ResolveFiles(files); + + Assert.Equal(3, result.Stacks.Count); + + TestStackInfo(result.Stacks[0], "300 (2006)", 4); + TestStackInfo(result.Stacks[1], "300", 3); + TestStackInfo(result.Stacks[2], "Bad Boys (2006)", 4); + } + + [Fact] + public void TestAlphaLimitOfFour() + { + var files = new[] + { + "300 (2006) parta.mkv", + "300 (2006) partb.mkv", + "300 (2006) partc.mkv", + "300 (2006) partd.mkv", + "300 (2006) parte.mkv", + "300 (2006) partf.mkv", + "300 (2006) partg.mkv", + "300 (2006)-trailer.mkv" + }; + + var resolver = GetResolver(); + + var result = resolver.ResolveFiles(files); + + Assert.Single(result.Stacks); + + TestStackInfo(result.Stacks[0], "300 (2006)", 4); + } + + [Fact] + public void TestMixed() + { + var files = new[] + { + new FileSystemMetadata{FullName = "Bad Boys (2006) part1.mkv", IsDirectory = false}, + new FileSystemMetadata{FullName = "Bad Boys (2006) part2.mkv", IsDirectory = false}, + new FileSystemMetadata{FullName = "300 (2006) part2", IsDirectory = true}, + new FileSystemMetadata{FullName = "300 (2006) part3", IsDirectory = true}, + new FileSystemMetadata{FullName = "300 (2006) part1", IsDirectory = true} + }; + + var resolver = GetResolver(); + + var result = resolver.Resolve(files); + + Assert.Equal(2, result.Stacks.Count); + TestStackInfo(result.Stacks[0], "300 (2006)", 3); + TestStackInfo(result.Stacks[1], "Bad Boys (2006)", 2); + } + + [Fact] + public void TestDirectories2() + { + //TestDirectory(@"blah blah", false, @"blah blah"); + //TestDirectory(@"d:/music/weezer/03 Pinkerton", false, "03 Pinkerton"); + //TestDirectory(@"d:/music/michael jackson/Bad (2012 Remaster)", false, "Bad (2012 Remaster)"); + + //TestDirectory(@"blah blah - cd1", true, "blah blah"); + //TestDirectory(@"blah blah - disc1", true, "blah blah"); + //TestDirectory(@"blah blah - disk1", true, "blah blah"); + //TestDirectory(@"blah blah - pt1", true, "blah blah"); + //TestDirectory(@"blah blah - part1", true, "blah blah"); + //TestDirectory(@"blah blah - dvd1", true, "blah blah"); + + //// Add a space + //TestDirectory(@"blah blah - cd 1", true, "blah blah"); + //TestDirectory(@"blah blah - disc 1", true, "blah blah"); + //TestDirectory(@"blah blah - disk 1", true, "blah blah"); + //TestDirectory(@"blah blah - pt 1", true, "blah blah"); + //TestDirectory(@"blah blah - part 1", true, "blah blah"); + //TestDirectory(@"blah blah - dvd 1", true, "blah blah"); + + //// Not case sensitive + //TestDirectory(@"blah blah - Disc1", true, "blah blah"); + } + + [Fact] + public void TestNamesWithoutParts() + { + // No stacking here because there is no part/disc/etc + var files = new[] + { + "Harry Potter and the Deathly Hallows.mkv", + "Harry Potter and the Deathly Hallows 1.mkv", + "Harry Potter and the Deathly Hallows 2.mkv", + "Harry Potter and the Deathly Hallows 3.mkv", + "Harry Potter and the Deathly Hallows 4.mkv" + }; + + var resolver = GetResolver(); + + var result = resolver.ResolveFiles(files); + + Assert.Empty(result.Stacks); + } + + [Fact] + public void TestNumbersAppearingBeforePartNumber() + { + // No stacking here because there is no part/disc/etc + var files = new[] + { + "Neverland (2011)[720p][PG][Voted 6.5][Family-Fantasy]part1.mkv", + "Neverland (2011)[720p][PG][Voted 6.5][Family-Fantasy]part2.mkv" + }; + + var resolver = GetResolver(); + + var result = resolver.ResolveFiles(files); + + Assert.Single(result.Stacks); + Assert.Equal(2, result.Stacks[0].Files.Count); + } + + [Fact] + public void TestMultiDiscs() + { + // No stacking here because there is no part/disc/etc + var files = new[] + { + @"M:/Movies (DVD)/Movies (Musical)/The Sound of Music/The Sound of Music (1965) (Disc 01)", + @"M:/Movies (DVD)/Movies (Musical)/The Sound of Music/The Sound of Music (1965) (Disc 02)" + }; + + var resolver = GetResolver(); + + var result = resolver.ResolveDirectories(files); + + Assert.Single(result.Stacks); + Assert.Equal(2, result.Stacks[0].Files.Count); + } + + private void TestStackInfo(FileStack stack, string name, int fileCount) + { + Assert.Equal(fileCount, stack.Files.Count); + Assert.Equal(name, stack.Name); + } + + private StackResolver GetResolver() + { + return new StackResolver(new NamingOptions()); + } + } +} diff --git a/tests/Jellyfin.Naming.Tests/Video/StubTests.cs b/tests/Jellyfin.Naming.Tests/Video/StubTests.cs new file mode 100644 index 0000000000..96fa8c5a55 --- /dev/null +++ b/tests/Jellyfin.Naming.Tests/Video/StubTests.cs @@ -0,0 +1,55 @@ +using System; +using System.Globalization; +using Emby.Naming.Common; +using Emby.Naming.Video; +using Xunit; + +namespace Jellyfin.Naming.Tests.Video +{ + public class StubTests : BaseVideoTest + { + [Fact] + public void TestStubs() + { + Test("video.mkv", false, null); + Test("video.disc", true, null); + Test("video.dvd.disc", true, "dvd"); + Test("video.hddvd.disc", true, "hddvd"); + Test("video.bluray.disc", true, "bluray"); + Test("video.brrip.disc", true, "bluray"); + Test("video.bd25.disc", true, "bluray"); + Test("video.bd50.disc", true, "bluray"); + Test("video.vhs.disc", true, "vhs"); + Test("video.hdtv.disc", true, "tv"); + Test("video.pdtv.disc", true, "tv"); + Test("video.dsr.disc", true, "tv"); + } + + [Fact] + public void TestStubName() + { + var result = + GetParser().ResolveFile(@"C:/Users/media/Desktop/Video Test/Movies/Oblivion/Oblivion.dvd.disc"); + + Assert.Equal("Oblivion", result.Name); + } + + private void Test(string path, bool isStub, string stubType) + { + var options = new NamingOptions(); + + var resultStubType = StubResolver.ResolveFile(path, options); + + Assert.Equal(isStub, resultStubType.IsStub); + + if (stubType == null) + { + Assert.Null(resultStubType.StubType); + } + else + { + Assert.Equal(stubType, resultStubType.StubType, true); + } + } + } +} diff --git a/tests/Jellyfin.Naming.Tests/Video/VideoListResolverTests.cs b/tests/Jellyfin.Naming.Tests/Video/VideoListResolverTests.cs new file mode 100644 index 0000000000..ef8a178989 --- /dev/null +++ b/tests/Jellyfin.Naming.Tests/Video/VideoListResolverTests.cs @@ -0,0 +1,457 @@ +using System.Linq; +using Emby.Naming.Common; +using Emby.Naming.Video; +using MediaBrowser.Model.IO; +using Xunit; + +namespace Jellyfin.Naming.Tests.Video +{ + public class VideoListResolverTests + { + // FIXME + // [Fact] + public void TestStackAndExtras() + { + // No stacking here because there is no part/disc/etc + var files = new[] + { + "Harry Potter and the Deathly Hallows-trailer.mkv", + "Harry Potter and the Deathly Hallows.trailer.mkv", + "Harry Potter and the Deathly Hallows part1.mkv", + "Harry Potter and the Deathly Hallows part2.mkv", + "Harry Potter and the Deathly Hallows part3.mkv", + "Harry Potter and the Deathly Hallows part4.mkv", + "Batman-deleted.mkv", + "Batman-sample.mkv", + "Batman-trailer.mkv", + "Batman part1.mkv", + "Batman part2.mkv", + "Batman part3.mkv", + "Avengers.mkv", + "Avengers-trailer.mkv", + + // Despite having a keyword in the name that will return an ExtraType, there's no original video to match it to + // So this is just a standalone video + "trailer.mkv", + + // Same as above + "WillyWonka-trailer.mkv" + }; + + var resolver = GetResolver(); + + var result = resolver.Resolve(files.Select(i => new FileSystemMetadata + { + IsDirectory = false, + FullName = i + + }).ToList()).ToList(); + + Assert.Equal(5, result.Count); + + Assert.Equal(3, result[1].Files.Count); + Assert.Equal(3, result[1].Extras.Count); + Assert.Equal("Batman", result[1].Name); + + Assert.Equal(4, result[2].Files.Count); + Assert.Equal(2, result[2].Extras.Count); + Assert.Equal("Harry Potter and the Deathly Hallows", result[2].Name); + } + + [Fact] + public void TestWithMetadata() + { + var files = new[] + { + "300.mkv", + "300.nfo" + }; + + var resolver = GetResolver(); + + var result = resolver.Resolve(files.Select(i => new FileSystemMetadata + { + IsDirectory = false, + FullName = i + + }).ToList()).ToList(); + + Assert.Single(result); + } + + [Fact] + public void TestWithExtra() + { + var files = new[] + { + "300.mkv", + "300 trailer.mkv" + }; + + var resolver = GetResolver(); + + var result = resolver.Resolve(files.Select(i => new FileSystemMetadata + { + IsDirectory = false, + FullName = i + + }).ToList()).ToList(); + + Assert.Single(result); + } + + [Fact] + public void TestVariationWithFolderName() + { + var files = new[] + { + "X-Men Days of Future Past - 1080p.mkv", + "X-Men Days of Future Past-trailer.mp4" + }; + + var resolver = GetResolver(); + + var result = resolver.Resolve(files.Select(i => new FileSystemMetadata + { + IsDirectory = false, + FullName = i + + }).ToList()).ToList(); + + Assert.Single(result); + } + + [Fact] + public void TestTrailer2() + { + var files = new[] + { + "X-Men Days of Future Past - 1080p.mkv", + "X-Men Days of Future Past-trailer.mp4", + "X-Men Days of Future Past-trailer2.mp4" + }; + + var resolver = GetResolver(); + + var result = resolver.Resolve(files.Select(i => new FileSystemMetadata + { + IsDirectory = false, + FullName = i + + }).ToList()).ToList(); + + Assert.Single(result); + } + + [Fact] + public void TestDifferentNames() + { + var files = new[] + { + "Looper (2012)-trailer.mkv", + "Looper.2012.bluray.720p.x264.mkv" + }; + + var resolver = GetResolver(); + + var result = resolver.Resolve(files.Select(i => new FileSystemMetadata + { + IsDirectory = false, + FullName = i + + }).ToList()).ToList(); + + Assert.Single(result); + } + + [Fact] + public void TestSeparateFiles() + { + // These should be considered separate, unrelated videos + var files = new[] + { + "My video 1.mkv", + "My video 2.mkv", + "My video 3.mkv", + "My video 4.mkv", + "My video 5.mkv" + }; + + var resolver = GetResolver(); + + var result = resolver.Resolve(files.Select(i => new FileSystemMetadata + { + IsDirectory = false, + FullName = i + + }).ToList()).ToList(); + + Assert.Equal(5, result.Count); + } + + [Fact] + public void TestMultiDisc() + { + var files = new[] + { + @"M:/Movies (DVD)/Movies (Musical)/Sound of Music (1965)/Sound of Music Disc 1", + @"M:/Movies (DVD)/Movies (Musical)/Sound of Music (1965)/Sound of Music Disc 2" + }; + + var resolver = GetResolver(); + + var result = resolver.Resolve(files.Select(i => new FileSystemMetadata + { + IsDirectory = true, + FullName = i + + }).ToList()).ToList(); + + Assert.Single(result); + } + + [Fact] + public void TestPoundSign() + { + // These should be considered separate, unrelated videos + var files = new[] + { + @"My movie #1.mp4", + @"My movie #2.mp4" + }; + + var resolver = GetResolver(); + + var result = resolver.Resolve(files.Select(i => new FileSystemMetadata + { + IsDirectory = true, + FullName = i + + }).ToList()).ToList(); + + Assert.Equal(2, result.Count); + } + + [Fact] + public void TestStackedWithTrailer() + { + var files = new[] + { + @"No (2012) part1.mp4", + @"No (2012) part2.mp4", + @"No (2012) part1-trailer.mp4" + }; + + var resolver = GetResolver(); + + var result = resolver.Resolve(files.Select(i => new FileSystemMetadata + { + IsDirectory = false, + FullName = i + + }).ToList()).ToList(); + + Assert.Single(result); + } + + [Fact] + public void TestStackedWithTrailer2() + { + var files = new[] + { + @"No (2012) part1.mp4", + @"No (2012) part2.mp4", + @"No (2012)-trailer.mp4" + }; + + var resolver = GetResolver(); + + var result = resolver.Resolve(files.Select(i => new FileSystemMetadata + { + IsDirectory = false, + FullName = i + + }).ToList()).ToList(); + + Assert.Single(result); + } + + [Fact] + public void TestExtrasByFolderName() + { + var files = new[] + { + @"/Movies/Top Gun (1984)/movie.mp4", + @"/Movies/Top Gun (1984)/Top Gun (1984)-trailer.mp4", + @"/Movies/Top Gun (1984)/Top Gun (1984)-trailer2.mp4", + @"trailer.mp4" + }; + + var resolver = GetResolver(); + + var result = resolver.Resolve(files.Select(i => new FileSystemMetadata + { + IsDirectory = false, + FullName = i + + }).ToList()).ToList(); + + Assert.Single(result); + } + + [Fact] + public void TestDoubleTags() + { + var files = new[] + { + @"/MCFAMILY-PC/Private3$/Heterosexual/Breast In Class 2 Counterfeit Racks (2011)/Breast In Class 2 Counterfeit Racks (2011) Disc 1 cd1.avi", + @"/MCFAMILY-PC/Private3$/Heterosexual/Breast In Class 2 Counterfeit Racks (2011)/Breast In Class 2 Counterfeit Racks (2011) Disc 1 cd2.avi", + @"/MCFAMILY-PC/Private3$/Heterosexual/Breast In Class 2 Counterfeit Racks (2011)/Breast In Class 2 Disc 2 cd1.avi", + @"/MCFAMILY-PC/Private3$/Heterosexual/Breast In Class 2 Counterfeit Racks (2011)/Breast In Class 2 Disc 2 cd2.avi" + }; + + var resolver = GetResolver(); + + var result = resolver.Resolve(files.Select(i => new FileSystemMetadata + { + IsDirectory = false, + FullName = i + + }).ToList()).ToList(); + + Assert.Equal(2, result.Count); + } + + [Fact] + public void TestArgumentOutOfRangeException() + { + var files = new[] + { + @"/nas-markrobbo78/Videos/INDEX HTPC/Movies/Watched/3 - ACTION/Argo (2012)/movie.mkv" + }; + + var resolver = GetResolver(); + + var result = resolver.Resolve(files.Select(i => new FileSystemMetadata + { + IsDirectory = false, + FullName = i + + }).ToList()).ToList(); + + Assert.Single(result); + } + + [Fact] + public void TestColony() + { + var files = new[] + { + @"The Colony.mkv" + }; + + var resolver = GetResolver(); + + var result = resolver.Resolve(files.Select(i => new FileSystemMetadata + { + IsDirectory = false, + FullName = i + + }).ToList()).ToList(); + + Assert.Single(result); + } + + [Fact] + public void TestFourSisters() + { + var files = new[] + { + @"Four Sisters and a Wedding - A.avi", + @"Four Sisters and a Wedding - B.avi" + }; + + var resolver = GetResolver(); + + var result = resolver.Resolve(files.Select(i => new FileSystemMetadata + { + IsDirectory = false, + FullName = i + + }).ToList()).ToList(); + + Assert.Single(result); + } + + [Fact] + public void TestMovieTrailer() + { + var files = new[] + { + @"/Server/Despicable Me/Despicable Me (2010).mkv", + @"/Server/Despicable Me/movie-trailer.mkv" + }; + + var resolver = GetResolver(); + + var result = resolver.Resolve(files.Select(i => new FileSystemMetadata + { + IsDirectory = false, + FullName = i + + }).ToList()).ToList(); + + Assert.Single(result); + } + + [Fact] + public void TestTrailerFalsePositives() + { + var files = new[] + { + @"/Server/Despicable Me/Skyscraper (2018) - Big Game Spot.mkv", + @"/Server/Despicable Me/Skyscraper (2018) - Trailer.mkv", + @"/Server/Despicable Me/Baywatch (2017) - Big Game Spot.mkv", + @"/Server/Despicable Me/Baywatch (2017) - Trailer.mkv" + }; + + var resolver = GetResolver(); + + var result = resolver.Resolve(files.Select(i => new FileSystemMetadata + { + IsDirectory = false, + FullName = i + + }).ToList()).ToList(); + + Assert.Equal(4, result.Count); + } + + [Fact] + public void TestSubfolders() + { + var files = new[] + { + @"/Movies/Despicable Me/Despicable Me.mkv", + @"/Movies/Despicable Me/trailers/trailer.mkv" + }; + + var resolver = GetResolver(); + + var result = resolver.Resolve(files.Select(i => new FileSystemMetadata + { + IsDirectory = false, + FullName = i + + }).ToList()).ToList(); + + Assert.Single(result); + } + + private VideoListResolver GetResolver() + { + var options = new NamingOptions(); + return new VideoListResolver(options); + } + } +} diff --git a/tests/Jellyfin.Naming.Tests/Video/VideoResolverTests.cs b/tests/Jellyfin.Naming.Tests/Video/VideoResolverTests.cs new file mode 100644 index 0000000000..5a3ce88869 --- /dev/null +++ b/tests/Jellyfin.Naming.Tests/Video/VideoResolverTests.cs @@ -0,0 +1,275 @@ +using MediaBrowser.Model.Entities; +using Xunit; + +namespace Jellyfin.Naming.Tests.Video +{ + public class VideoResolverTests : BaseVideoTest + { + // FIXME + // [Fact] + public void TestSimpleFile() + { + var parser = GetParser(); + + var result = + parser.ResolveFile(@"/server/Movies/Brave (2007)/Brave (2006).mkv"); + + Assert.Equal(2006, result.Year); + Assert.False(result.IsStub); + Assert.False(result.Is3D); + Assert.Equal("Brave", result.Name); + Assert.Null(result.ExtraType); + } + + // FIXME + // [Fact] + public void TestSimpleFile2() + { + var parser = GetParser(); + + var result = + parser.ResolveFile(@"/server/Movies/Bad Boys (1995)/Bad Boys (1995).mkv"); + + Assert.Equal(1995, result.Year); + Assert.False(result.IsStub); + Assert.False(result.Is3D); + Assert.Equal("Bad Boys", result.Name); + Assert.Null(result.ExtraType); + } + + // FIXME + // [Fact] + public void TestSimpleFileWithNumericName() + { + var parser = GetParser(); + + var result = + parser.ResolveFile(@"/server/Movies/300 (2007)/300 (2006).mkv"); + + Assert.Equal(2006, result.Year); + Assert.False(result.IsStub); + Assert.False(result.Is3D); + Assert.Equal("300", result.Name); + Assert.Null(result.ExtraType); + } + + // FIXME + // [Fact] + public void TestExtra() + { + var parser = GetParser(); + + var result = + parser.ResolveFile(@"/server/Movies/Brave (2007)/Brave (2006)-trailer.mkv"); + + Assert.Equal(2006, result.Year); + Assert.False(result.IsStub); + Assert.False(result.Is3D); + Assert.Equal(ExtraType.Trailer, result.ExtraType); + Assert.Equal("Brave (2006)-trailer", result.Name); + } + + // FIXME + // [Fact] + public void TestExtraWithNumericName() + { + var parser = GetParser(); + + var result = + parser.ResolveFile(@"/server/Movies/300 (2007)/300 (2006)-trailer.mkv"); + + Assert.Equal(2006, result.Year); + Assert.False(result.IsStub); + Assert.False(result.Is3D); + Assert.Equal("300 (2006)-trailer", result.Name); + Assert.Equal(ExtraType.Trailer, result.ExtraType); + } + + // FIXME + // [Fact] + public void TestStubFileWithNumericName() + { + var parser = GetParser(); + + var result = + parser.ResolveFile(@"/server/Movies/300 (2007)/300 (2006).bluray.disc"); + + Assert.Equal(2006, result.Year); + Assert.True(result.IsStub); + Assert.Equal("bluray", result.StubType); + Assert.False(result.Is3D); + Assert.Equal("300", result.Name); + Assert.Null(result.ExtraType); + } + + // FIXME + // [Fact] + public void TestStubFile() + { + var parser = GetParser(); + + var result = + parser.ResolveFile(@"/server/Movies/Brave (2007)/Brave (2006).bluray.disc"); + + Assert.Equal(2006, result.Year); + Assert.True(result.IsStub); + Assert.Equal("bluray", result.StubType); + Assert.False(result.Is3D); + Assert.Equal("Brave", result.Name); + Assert.Null(result.ExtraType); + } + + // FIXME + // [Fact] + public void TestExtraStubWithNumericNameNotSupported() + { + var parser = GetParser(); + + var result = + parser.ResolveFile(@"/server/Movies/300 (2007)/300 (2006)-trailer.bluray.disc"); + + Assert.Equal(2006, result.Year); + Assert.True(result.IsStub); + Assert.Equal("bluray", result.StubType); + Assert.False(result.Is3D); + Assert.Equal("300", result.Name); + Assert.Null(result.ExtraType); + } + + // FIXME + // [Fact] + public void TestExtraStubNotSupported() + { + // Using a stub for an extra is currently not supported + var parser = GetParser(); + + var result = + parser.ResolveFile(@"/server/Movies/brave (2007)/brave (2006)-trailer.bluray.disc"); + + Assert.Equal(2006, result.Year); + Assert.True(result.IsStub); + Assert.Equal("bluray", result.StubType); + Assert.False(result.Is3D); + Assert.Equal("brave", result.Name); + Assert.Null(result.ExtraType); + } + + // FIXME + // [Fact] + public void Test3DFileWithNumericName() + { + var parser = GetParser(); + + var result = + parser.ResolveFile(@"/server/Movies/300 (2007)/300 (2006).3d.sbs.mkv"); + + Assert.Equal(2006, result.Year); + Assert.False(result.IsStub); + Assert.True(result.Is3D); + Assert.Equal("sbs", result.Format3D); + Assert.Equal("300", result.Name); + Assert.Null(result.ExtraType); + } + + // FIXME + // [Fact] + public void TestBad3DFileWithNumericName() + { + var parser = GetParser(); + + var result = + parser.ResolveFile(@"/server/Movies/300 (2007)/300 (2006).3d1.sbas.mkv"); + + Assert.Equal(2006, result.Year); + Assert.False(result.IsStub); + Assert.False(result.Is3D); + Assert.Equal("300", result.Name); + Assert.Null(result.ExtraType); + Assert.Null(result.Format3D); + } + + // FIXME + // [Fact] + public void Test3DFile() + { + var parser = GetParser(); + + var result = + parser.ResolveFile(@"/server/Movies/brave (2007)/brave (2006).3d.sbs.mkv"); + + Assert.Equal(2006, result.Year); + Assert.False(result.IsStub); + Assert.True(result.Is3D); + Assert.Equal("sbs", result.Format3D); + Assert.Equal("brave", result.Name); + Assert.Null(result.ExtraType); + } + + [Fact] + public void TestNameWithoutDate() + { + var parser = GetParser(); + + var result = + parser.ResolveFile(@"/server/Movies/American Psycho/American.Psycho.mkv"); + + Assert.Null(result.Year); + Assert.False(result.IsStub); + Assert.False(result.Is3D); + Assert.Null(result.Format3D); + Assert.Equal("American.Psycho", result.Name); + Assert.Null(result.ExtraType); + } + + // FIXME + // [Fact] + public void TestCleanDateAndStringsSequence() + { + var parser = GetParser(); + + // In this test case, running CleanDateTime first produces no date, so it will attempt to run CleanString first and then CleanDateTime again + var result = + parser.ResolveFile(@"/server/Movies/3.Days.to.Kill/3.Days.to.Kill.2014.720p.BluRay.x264.YIFY.mkv"); + + Assert.Equal(2014, result.Year); + Assert.False(result.IsStub); + Assert.False(result.Is3D); + Assert.Null(result.Format3D); + Assert.Equal("3.Days.to.Kill", result.Name); + Assert.Null(result.ExtraType); + } + + // FIXME + // [Fact] + public void TestCleanDateAndStringsSequence1() + { + var parser = GetParser(); + + // In this test case, running CleanDateTime first produces no date, so it will attempt to run CleanString first and then CleanDateTime again + var result = + parser.ResolveFile(@"/server/Movies/3 days to kill (2005)/3 days to kill (2005).mkv"); + + Assert.Equal(2005, result.Year); + Assert.False(result.IsStub); + Assert.False(result.Is3D); + Assert.Null(result.Format3D); + Assert.Equal("3 days to kill", result.Name); + Assert.Null(result.ExtraType); + } + + [Fact] + public void TestFolderNameWithExtension() + { + var parser = GetParser(); + + var result = + parser.ResolveFile(@"/server/Movies/7 Psychos.mkv/7 Psychos.mkv"); + + Assert.Null(result.Year); + Assert.False(result.IsStub); + Assert.False(result.Is3D); + Assert.Equal("7 Psychos", result.Name); + Assert.Null(result.ExtraType); + } + } +}