mirror of
https://github.com/jellyfin/jellyfin.git
synced 2024-06-29 10:23:36 +02:00
Make sure episodes in series folder don't group as multiversion
Test for episodes in series folder Turn on multiple versions for episodes Support for multiversion episodes in mixed folders Update 2 failing test cases. These were for passing for unofficially supported filenames. Dashes with no spaces, which is not how JF docs say multiversion files are supposed to be named. Fix possible null fix null take 2 Don't ParseName when calling ResolveVideos<Episode> ParseName drops everything after year in a filename. This results in episode information being dropped if year is present. Update tests to set ParseName=false Additional test with Mixed folder with Year in filename Added case when calculating displayname for versions for mixed folders. Add StringComparison.Ordinal to LastIndexOf Was generating an error in recent build attempts. Clean the episode filename to set the grouper value This allows files like Name (2020) - S01E01 [BluRay-480p x264][AC3 2.0] - [ORIGINAL].mkv Name (2020) - S01E01 [BluRay-1080p x264][AC3 5.1]- [Remaster].mkv to be grouped on 'Name (2020) - S01E01' Fix false positive merging Only do cleanstring or " -" index cleaning, not both. Compatiblity fix when stacking episodes and multiple versions are present Fix linting problems
This commit is contained in:
parent
8677a17c3e
commit
9016fec892
|
@ -726,6 +726,12 @@ namespace Emby.Naming.Common
|
||||||
@"^\s*(?<name>[^ ].*?)\s*$"
|
@"^\s*(?<name>[^ ].*?)\s*$"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
VideoVersionExpressions = new[]
|
||||||
|
{
|
||||||
|
// get filename before final space-dash-space
|
||||||
|
@"^(?<filename>.*?)(?:\s-\s(?!.*\s-\s)(.*))?$"
|
||||||
|
};
|
||||||
|
|
||||||
MultipleEpisodeExpressions = new[]
|
MultipleEpisodeExpressions = new[]
|
||||||
{
|
{
|
||||||
@".*(\\|\/)[sS]?(?<seasonnumber>[0-9]{1,4})[xX](?<epnumber>[0-9]{1,3})((-| - )[0-9]{1,4}[eExX](?<endingepnumber>[0-9]{1,3}))+[^\\\/]*$",
|
@".*(\\|\/)[sS]?(?<seasonnumber>[0-9]{1,4})[xX](?<epnumber>[0-9]{1,3})((-| - )[0-9]{1,4}[eExX](?<endingepnumber>[0-9]{1,3}))+[^\\\/]*$",
|
||||||
|
@ -846,6 +852,11 @@ namespace Emby.Naming.Common
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string[] CleanStrings { get; set; }
|
public string[] CleanStrings { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets list of raw clean strings regular expressions strings.
|
||||||
|
/// </summary>
|
||||||
|
public string[] VideoVersionExpressions { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets list of multi-episode regular expressions.
|
/// Gets or sets list of multi-episode regular expressions.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -866,6 +877,11 @@ namespace Emby.Naming.Common
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Regex[] CleanStringRegexes { get; private set; } = Array.Empty<Regex>();
|
public Regex[] CleanStringRegexes { get; private set; } = Array.Empty<Regex>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets list of video version regular expressions.
|
||||||
|
/// </summary>
|
||||||
|
public Regex[] VideoVersionRegexes { get; private set; } = Array.Empty<Regex>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Compiles raw regex strings into regexes.
|
/// Compiles raw regex strings into regexes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -873,6 +889,7 @@ namespace Emby.Naming.Common
|
||||||
{
|
{
|
||||||
CleanDateTimeRegexes = CleanDateTimes.Select(Compile).ToArray();
|
CleanDateTimeRegexes = CleanDateTimes.Select(Compile).ToArray();
|
||||||
CleanStringRegexes = CleanStrings.Select(Compile).ToArray();
|
CleanStringRegexes = CleanStrings.Select(Compile).ToArray();
|
||||||
|
VideoVersionRegexes = VideoVersionExpressions.Select(Compile).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Regex Compile(string exp)
|
private Regex Compile(string exp)
|
||||||
|
|
|
@ -4,7 +4,9 @@ using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using Emby.Naming.Common;
|
using Emby.Naming.Common;
|
||||||
|
using Emby.Naming.TV;
|
||||||
using Jellyfin.Extensions;
|
using Jellyfin.Extensions;
|
||||||
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.IO;
|
using MediaBrowser.Model.IO;
|
||||||
|
|
||||||
namespace Emby.Naming.Video
|
namespace Emby.Naming.Video
|
||||||
|
@ -25,10 +27,16 @@ namespace Emby.Naming.Video
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="videoInfos">List of related video files.</param>
|
/// <param name="videoInfos">List of related video files.</param>
|
||||||
/// <param name="namingOptions">The naming options.</param>
|
/// <param name="namingOptions">The naming options.</param>
|
||||||
|
/// <param name="collectionType">Collection type of videos being resolved.</param>
|
||||||
/// <param name="supportMultiVersion">Indication we should consider multi-versions of content.</param>
|
/// <param name="supportMultiVersion">Indication we should consider multi-versions of content.</param>
|
||||||
/// <param name="parseName">Whether to parse the name or use the filename.</param>
|
/// <param name="parseName">Whether to parse the name or use the filename.</param>
|
||||||
/// <returns>Returns enumerable of <see cref="VideoInfo"/> which groups files together when related.</returns>
|
/// <returns>Returns enumerable of <see cref="VideoInfo"/> which groups files together when related.</returns>
|
||||||
public static IReadOnlyList<VideoInfo> Resolve(IReadOnlyList<VideoFileInfo> videoInfos, NamingOptions namingOptions, bool supportMultiVersion = true, bool parseName = true)
|
public static IReadOnlyList<VideoInfo> Resolve(
|
||||||
|
IReadOnlyList<VideoFileInfo> videoInfos,
|
||||||
|
NamingOptions namingOptions,
|
||||||
|
string collectionType,
|
||||||
|
bool supportMultiVersion = true,
|
||||||
|
bool parseName = true)
|
||||||
{
|
{
|
||||||
// Filter out all extras, otherwise they could cause stacks to not be resolved
|
// Filter out all extras, otherwise they could cause stacks to not be resolved
|
||||||
// See the unit test TestStackedWithTrailer
|
// See the unit test TestStackedWithTrailer
|
||||||
|
@ -79,12 +87,19 @@ namespace Emby.Naming.Video
|
||||||
var info = new VideoInfo(media.Name) { Files = new[] { media } };
|
var info = new VideoInfo(media.Name) { Files = new[] { media } };
|
||||||
|
|
||||||
info.Year = info.Files[0].Year;
|
info.Year = info.Files[0].Year;
|
||||||
|
if (info.Year is null)
|
||||||
|
{
|
||||||
|
// parse name for year info. Episodes don't get parsed up to this point for year info
|
||||||
|
var info2 = VideoResolver.Resolve(media.Path, media.IsDirectory, namingOptions, parseName);
|
||||||
|
info.Year = info2?.Year;
|
||||||
|
}
|
||||||
|
|
||||||
list.Add(info);
|
list.Add(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (supportMultiVersion)
|
if (supportMultiVersion)
|
||||||
{
|
{
|
||||||
list = GetVideosGroupedByVersion(list, namingOptions);
|
list = GetVideosGroupedByVersion(list, namingOptions, collectionType);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Whatever files are left, just add them
|
// Whatever files are left, just add them
|
||||||
|
@ -98,7 +113,7 @@ namespace Emby.Naming.Video
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<VideoInfo> GetVideosGroupedByVersion(List<VideoInfo> videos, NamingOptions namingOptions)
|
private static List<VideoInfo> GetVideosGroupedByVersion(List<VideoInfo> videos, NamingOptions namingOptions, string collectionType)
|
||||||
{
|
{
|
||||||
if (videos.Count == 0)
|
if (videos.Count == 0)
|
||||||
{
|
{
|
||||||
|
@ -112,6 +127,8 @@ namespace Emby.Naming.Video
|
||||||
return videos;
|
return videos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var mergeable = new List<VideoInfo>();
|
||||||
|
var notMergeable = new List<VideoInfo>();
|
||||||
// Cannot use Span inside local functions and delegates thus we cannot use LINQ here nor merge with the above [if]
|
// Cannot use Span inside local functions and delegates thus we cannot use LINQ here nor merge with the above [if]
|
||||||
VideoInfo? primary = null;
|
VideoInfo? primary = null;
|
||||||
for (var i = 0; i < videos.Count; i++)
|
for (var i = 0; i < videos.Count; i++)
|
||||||
|
@ -122,9 +139,14 @@ namespace Emby.Naming.Video
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsEligibleForMultiVersion(folderName, video.Files[0].FileNameWithoutExtension, namingOptions))
|
// don't merge stacked episodes
|
||||||
|
if (video.Files.Count() == 1 && IsEligibleForMultiVersion(folderName, video.Files[0].Path, namingOptions, collectionType))
|
||||||
{
|
{
|
||||||
return videos;
|
mergeable.Add(video);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
notMergeable.Add(video);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (folderName.Equals(video.Files[0].FileNameWithoutExtension, StringComparison.Ordinal))
|
if (folderName.Equals(video.Files[0].FileNameWithoutExtension, StringComparison.Ordinal))
|
||||||
|
@ -133,35 +155,59 @@ namespace Emby.Naming.Video
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (videos.Count > 1)
|
var list = new List<VideoInfo>();
|
||||||
|
if (collectionType.Equals(CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
var groups = videos.GroupBy(x => ResolutionRegex().IsMatch(x.Files[0].FileNameWithoutExtension)).ToList();
|
var groupedList = mergeable.GroupBy(x => EpisodeGrouper(x.Files[0].Path, namingOptions, collectionType));
|
||||||
videos.Clear();
|
foreach (var grouping in groupedList)
|
||||||
|
{
|
||||||
|
list.Add(OrganizeAlternateVersions(grouping.ToList(), grouping.Key.AsSpan(), primary));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (mergeable.Count() > 0)
|
||||||
|
{
|
||||||
|
list.Add(OrganizeAlternateVersions(mergeable, folderName, primary));
|
||||||
|
}
|
||||||
|
|
||||||
|
// add non mergeables back in
|
||||||
|
list.AddRange(notMergeable);
|
||||||
|
list.Sort((x, y) => string.Compare(x.Name, y.Name, StringComparison.Ordinal));
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static VideoInfo OrganizeAlternateVersions(List<VideoInfo> grouping, ReadOnlySpan<char> name, VideoInfo? primary)
|
||||||
|
{
|
||||||
|
VideoInfo? groupPrimary = null;
|
||||||
|
if (primary is not null && grouping.Contains(primary))
|
||||||
|
{
|
||||||
|
groupPrimary = primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
var alternateVersions = new List<VideoInfo>();
|
||||||
|
if (grouping.Count() > 1)
|
||||||
|
{
|
||||||
|
// groups resolution based into one, and all other names
|
||||||
|
var groups = grouping.GroupBy(x => ResolutionRegex().IsMatch(x.Files[0].FileNameWithoutExtension));
|
||||||
foreach (var group in groups)
|
foreach (var group in groups)
|
||||||
{
|
{
|
||||||
if (group.Key)
|
if (group.Key)
|
||||||
{
|
{
|
||||||
videos.InsertRange(0, group.OrderByDescending(x => x.Files[0].FileNameWithoutExtension.ToString(), new AlphanumericComparator()));
|
alternateVersions.InsertRange(0, group.OrderByDescending(x => x.Files[0].FileNameWithoutExtension.ToString(), new AlphanumericComparator()));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
videos.AddRange(group.OrderBy(x => x.Files[0].FileNameWithoutExtension.ToString(), new AlphanumericComparator()));
|
alternateVersions.AddRange(group.OrderBy(x => x.Files[0].FileNameWithoutExtension.ToString(), new AlphanumericComparator()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
primary ??= videos[0];
|
groupPrimary ??= alternateVersions.FirstOrDefault() ?? grouping.First();
|
||||||
videos.Remove(primary);
|
alternateVersions.Remove(groupPrimary);
|
||||||
|
groupPrimary.AlternateVersions = alternateVersions.Select(x => x.Files[0]).ToArray();
|
||||||
|
|
||||||
var list = new List<VideoInfo>
|
groupPrimary.Name = name.ToString();
|
||||||
{
|
return groupPrimary;
|
||||||
primary
|
|
||||||
};
|
|
||||||
|
|
||||||
list[0].AlternateVersions = videos.Select(x => x.Files[0]).ToArray();
|
|
||||||
list[0].Name = folderName.ToString();
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool HaveSameYear(IReadOnlyList<VideoInfo> videos)
|
private static bool HaveSameYear(IReadOnlyList<VideoInfo> videos)
|
||||||
|
@ -183,8 +229,16 @@ namespace Emby.Naming.Video
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsEligibleForMultiVersion(ReadOnlySpan<char> folderName, ReadOnlySpan<char> testFilename, NamingOptions namingOptions)
|
private static bool IsEligibleForMultiVersion(ReadOnlySpan<char> folderName, ReadOnlySpan<char> testFilePath, NamingOptions namingOptions, ReadOnlySpan<char> collectionType)
|
||||||
{
|
{
|
||||||
|
var testFilename = Path.GetFileNameWithoutExtension(testFilePath);
|
||||||
|
|
||||||
|
if (collectionType.Equals(CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
// episodes are always eligible to be grouped
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (!testFilename.StartsWith(folderName, StringComparison.OrdinalIgnoreCase))
|
if (!testFilename.StartsWith(folderName, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -207,5 +261,41 @@ namespace Emby.Naming.Video
|
||||||
|| testFilename[0] == '-'
|
|| testFilename[0] == '-'
|
||||||
|| CheckMultiVersionRegex().IsMatch(testFilename);
|
|| CheckMultiVersionRegex().IsMatch(testFilename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string EpisodeGrouper(string testFilePath, NamingOptions namingOptions, ReadOnlySpan<char> collectionType)
|
||||||
|
{
|
||||||
|
// grouper for tv shows/episodes should be everything before space-dash-space
|
||||||
|
var resolver = new EpisodeResolver(namingOptions);
|
||||||
|
EpisodeInfo? episodeInfo = resolver.Resolve(testFilePath, false);
|
||||||
|
ReadOnlySpan<char> seriesName = episodeInfo!.SeriesName;
|
||||||
|
|
||||||
|
var filename = Path.GetFileNameWithoutExtension(testFilePath);
|
||||||
|
// start with grouping by filename
|
||||||
|
string g = filename;
|
||||||
|
for (var i = 0; i < namingOptions.VideoVersionRegexes.Length; i++)
|
||||||
|
{
|
||||||
|
var rule = namingOptions.VideoVersionRegexes[i];
|
||||||
|
var match = rule.Match(filename);
|
||||||
|
if (!match.Success)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
g = match.Groups["filename"].Value;
|
||||||
|
// clean the filename
|
||||||
|
if (VideoResolver.TryCleanString(g, namingOptions, out string newName))
|
||||||
|
{
|
||||||
|
g = newName;
|
||||||
|
}
|
||||||
|
|
||||||
|
// never group episodes under series name
|
||||||
|
if (MemoryExtensions.Equals(g.AsSpan(), seriesName, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
g = filename;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return g;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -229,7 +229,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
|
||||||
|
|
||||||
if (string.Equals(collectionType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(collectionType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return ResolveVideos<Episode>(parent, files, false, collectionType, true);
|
return ResolveVideos<Episode>(parent, files, true, collectionType, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -275,7 +275,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
|
||||||
.Where(f => f is not null)
|
.Where(f => f is not null)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
var resolverResult = VideoListResolver.Resolve(videoInfos, NamingOptions, supportMultiEditions, parseName);
|
var resolverResult = VideoListResolver.Resolve(videoInfos, NamingOptions, collectionType, supportMultiEditions, parseName);
|
||||||
|
|
||||||
var result = new MultiItemResolverResult
|
var result = new MultiItemResolverResult
|
||||||
{
|
{
|
||||||
|
|
|
@ -1179,10 +1179,18 @@ namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
if (HasLocalAlternateVersions)
|
if (HasLocalAlternateVersions)
|
||||||
{
|
{
|
||||||
var displayName = System.IO.Path.GetFileNameWithoutExtension(path)
|
var fileName = System.IO.Path.GetFileNameWithoutExtension(path);
|
||||||
|
var displayName = fileName
|
||||||
.Replace(System.IO.Path.GetFileName(ContainingFolderPath), string.Empty, StringComparison.OrdinalIgnoreCase)
|
.Replace(System.IO.Path.GetFileName(ContainingFolderPath), string.Empty, StringComparison.OrdinalIgnoreCase)
|
||||||
.TrimStart(new char[] { ' ', '-' });
|
.TrimStart(new char[] { ' ', '-' });
|
||||||
|
|
||||||
|
if (fileName == displayName)
|
||||||
|
{
|
||||||
|
// file does not start with parent folder name. This must be an episode in a mixed directory
|
||||||
|
// get string after last dash - this is the version name
|
||||||
|
displayName = fileName.Substring(fileName.LastIndexOf('-') + 1).TrimStart(new char[] { ' ', '-' });
|
||||||
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(displayName))
|
if (!string.IsNullOrEmpty(displayName))
|
||||||
{
|
{
|
||||||
terms.Add(displayName);
|
terms.Add(displayName);
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Emby.Naming.Common;
|
using Emby.Naming.Common;
|
||||||
using Emby.Naming.Video;
|
using Emby.Naming.Video;
|
||||||
|
using MediaBrowser.Model.Entities;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Jellyfin.Naming.Tests.Video
|
namespace Jellyfin.Naming.Tests.Video
|
||||||
|
@ -23,7 +25,8 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
_namingOptions).ToList();
|
_namingOptions,
|
||||||
|
CollectionType.Movies).ToList();
|
||||||
|
|
||||||
Assert.Single(result.Where(v => v.ExtraType is null));
|
Assert.Single(result.Where(v => v.ExtraType is null));
|
||||||
Assert.Single(result.Where(v => v.ExtraType is not null));
|
Assert.Single(result.Where(v => v.ExtraType is not null));
|
||||||
|
@ -42,7 +45,8 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
_namingOptions).ToList();
|
_namingOptions,
|
||||||
|
CollectionType.Movies).ToList();
|
||||||
|
|
||||||
Assert.Single(result.Where(v => v.ExtraType is null));
|
Assert.Single(result.Where(v => v.ExtraType is null));
|
||||||
Assert.Single(result.Where(v => v.ExtraType is not null));
|
Assert.Single(result.Where(v => v.ExtraType is not null));
|
||||||
|
@ -60,7 +64,8 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
_namingOptions).ToList();
|
_namingOptions,
|
||||||
|
CollectionType.Movies).ToList();
|
||||||
|
|
||||||
Assert.Single(result);
|
Assert.Single(result);
|
||||||
Assert.Single(result[0].AlternateVersions);
|
Assert.Single(result[0].AlternateVersions);
|
||||||
|
@ -82,7 +87,8 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
_namingOptions).ToList();
|
_namingOptions,
|
||||||
|
CollectionType.Movies).ToList();
|
||||||
|
|
||||||
Assert.Equal(7, result.Count);
|
Assert.Equal(7, result.Count);
|
||||||
Assert.Empty(result[0].AlternateVersions);
|
Assert.Empty(result[0].AlternateVersions);
|
||||||
|
@ -105,7 +111,8 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
_namingOptions).ToList();
|
_namingOptions,
|
||||||
|
CollectionType.Movies).ToList();
|
||||||
|
|
||||||
Assert.Single(result);
|
Assert.Single(result);
|
||||||
Assert.Equal(7, result[0].AlternateVersions.Count);
|
Assert.Equal(7, result[0].AlternateVersions.Count);
|
||||||
|
@ -129,7 +136,8 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
_namingOptions).ToList();
|
_namingOptions,
|
||||||
|
CollectionType.Movies).ToList();
|
||||||
|
|
||||||
Assert.Equal(9, result.Count);
|
Assert.Equal(9, result.Count);
|
||||||
Assert.Empty(result[0].AlternateVersions);
|
Assert.Empty(result[0].AlternateVersions);
|
||||||
|
@ -149,7 +157,8 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
_namingOptions).ToList();
|
_namingOptions,
|
||||||
|
CollectionType.Movies).ToList();
|
||||||
|
|
||||||
Assert.Equal(5, result.Count);
|
Assert.Equal(5, result.Count);
|
||||||
Assert.Empty(result[0].AlternateVersions);
|
Assert.Empty(result[0].AlternateVersions);
|
||||||
|
@ -171,7 +180,8 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
_namingOptions).ToList();
|
_namingOptions,
|
||||||
|
CollectionType.Movies).ToList();
|
||||||
|
|
||||||
Assert.Equal(5, result.Count);
|
Assert.Equal(5, result.Count);
|
||||||
Assert.Empty(result[0].AlternateVersions);
|
Assert.Empty(result[0].AlternateVersions);
|
||||||
|
@ -193,7 +203,8 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
_namingOptions).ToList();
|
_namingOptions,
|
||||||
|
CollectionType.Movies).ToList();
|
||||||
|
|
||||||
Assert.Single(result);
|
Assert.Single(result);
|
||||||
Assert.Equal("/movies/Iron Man/Iron Man.mkv", result[0].Files[0].Path);
|
Assert.Equal("/movies/Iron Man/Iron Man.mkv", result[0].Files[0].Path);
|
||||||
|
@ -222,7 +233,8 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
_namingOptions).ToList();
|
_namingOptions,
|
||||||
|
CollectionType.Movies).ToList();
|
||||||
|
|
||||||
Assert.Single(result);
|
Assert.Single(result);
|
||||||
Assert.Equal("/movies/Iron Man/Iron Man.mkv", result[0].Files[0].Path);
|
Assert.Equal("/movies/Iron Man/Iron Man.mkv", result[0].Files[0].Path);
|
||||||
|
@ -246,7 +258,8 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
_namingOptions).ToList();
|
_namingOptions,
|
||||||
|
CollectionType.Movies).ToList();
|
||||||
|
|
||||||
Assert.Equal(2, result.Count);
|
Assert.Equal(2, result.Count);
|
||||||
}
|
}
|
||||||
|
@ -267,7 +280,8 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
_namingOptions).ToList();
|
_namingOptions,
|
||||||
|
CollectionType.Movies).ToList();
|
||||||
|
|
||||||
Assert.Equal(7, result.Count);
|
Assert.Equal(7, result.Count);
|
||||||
Assert.Empty(result[0].AlternateVersions);
|
Assert.Empty(result[0].AlternateVersions);
|
||||||
|
@ -289,7 +303,8 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
_namingOptions).ToList();
|
_namingOptions,
|
||||||
|
CollectionType.Movies).ToList();
|
||||||
|
|
||||||
Assert.Equal(5, result.Count);
|
Assert.Equal(5, result.Count);
|
||||||
Assert.Empty(result[0].AlternateVersions);
|
Assert.Empty(result[0].AlternateVersions);
|
||||||
|
@ -306,7 +321,8 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
_namingOptions).ToList();
|
_namingOptions,
|
||||||
|
CollectionType.Movies);
|
||||||
|
|
||||||
Assert.Single(result);
|
Assert.Single(result);
|
||||||
Assert.Single(result[0].AlternateVersions);
|
Assert.Single(result[0].AlternateVersions);
|
||||||
|
@ -323,7 +339,8 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
_namingOptions).ToList();
|
_namingOptions,
|
||||||
|
CollectionType.Movies);
|
||||||
|
|
||||||
Assert.Single(result);
|
Assert.Single(result);
|
||||||
Assert.Single(result[0].AlternateVersions);
|
Assert.Single(result[0].AlternateVersions);
|
||||||
|
@ -344,7 +361,8 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
_namingOptions).ToList();
|
_namingOptions,
|
||||||
|
CollectionType.Movies);
|
||||||
|
|
||||||
Assert.Single(result);
|
Assert.Single(result);
|
||||||
Assert.Equal("/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016).mkv", result[0].Files[0].Path);
|
Assert.Equal("/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016).mkv", result[0].Files[0].Path);
|
||||||
|
@ -367,7 +385,8 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
_namingOptions).ToList();
|
_namingOptions,
|
||||||
|
CollectionType.Movies);
|
||||||
|
|
||||||
Assert.Single(result);
|
Assert.Single(result);
|
||||||
Assert.Single(result[0].AlternateVersions);
|
Assert.Single(result[0].AlternateVersions);
|
||||||
|
@ -384,7 +403,8 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
_namingOptions).ToList();
|
_namingOptions,
|
||||||
|
CollectionType.Movies);
|
||||||
|
|
||||||
Assert.Equal(2, result.Count);
|
Assert.Equal(2, result.Count);
|
||||||
}
|
}
|
||||||
|
@ -392,9 +412,166 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
[Fact]
|
[Fact]
|
||||||
public void TestEmptyList()
|
public void TestEmptyList()
|
||||||
{
|
{
|
||||||
var result = VideoListResolver.Resolve(new List<VideoFileInfo>(), _namingOptions).ToList();
|
var result = VideoListResolver.Resolve(new List<VideoFileInfo>(), _namingOptions, string.Empty).ToList();
|
||||||
|
|
||||||
Assert.Empty(result);
|
Assert.Empty(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TestMultiVersionEpisodeDontCollapse()
|
||||||
|
{
|
||||||
|
// Test for false positive
|
||||||
|
|
||||||
|
var files = new[]
|
||||||
|
{
|
||||||
|
@"/TV/Dexter/Dexter - S01E01 - One.mkv",
|
||||||
|
@"/TV/Dexter/Dexter - S01E02 - Two.mkv",
|
||||||
|
@"/TV/Dexter/Dexter - S01E03 - Three.mkv",
|
||||||
|
@"/TV/Dexter/Dexter - S01E04 - Four.mkv",
|
||||||
|
@"/TV/Dexter/Dexter - S01E05 - Five.mkv",
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = VideoListResolver.Resolve(
|
||||||
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions, false)).OfType<VideoFileInfo>().ToList(),
|
||||||
|
_namingOptions,
|
||||||
|
CollectionType.TvShows);
|
||||||
|
|
||||||
|
Assert.Equal(5, result.Count);
|
||||||
|
Assert.Empty(result[0].AlternateVersions);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TestMultiVersionEpisodeDontCollapse2()
|
||||||
|
{
|
||||||
|
// Test for false positive
|
||||||
|
|
||||||
|
var files = new[]
|
||||||
|
{
|
||||||
|
@"/TV/Dexter/Dexter - S01E01 One.mkv",
|
||||||
|
@"/TV/Dexter/Dexter - S01E02 Two.mkv",
|
||||||
|
@"/TV/Dexter/Dexter - S01E03 Three.mkv",
|
||||||
|
@"/TV/Dexter/Dexter - S01E04 Four.mkv",
|
||||||
|
@"/TV/Dexter/Dexter - S01E05 Five.mkv",
|
||||||
|
@"/TV/Star Trek- Picard/Season 3/Star Trek - Picard 3x01 [WEBDL-720p Proper x264][EAC3 5.1] - Part One - The Next Generation.mkv",
|
||||||
|
@"/TV/Star Trek- Picard/Season 3/Star Trek - Picard 3x02 [WEBDL-720p Proper x264][EAC3 5.1] - Part Two - Disengage.mkv",
|
||||||
|
@"/TV/Star Trek- Picard/Season 3/Star Trek - Picard 3x03 [WEBDL-720p x264][EAC3 5.1] - Part Three - Seventeen Seconds.mkv",
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = VideoListResolver.Resolve(
|
||||||
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions, false)).OfType<VideoFileInfo>().ToList(),
|
||||||
|
_namingOptions,
|
||||||
|
CollectionType.TvShows);
|
||||||
|
|
||||||
|
Assert.Equal(8, result.Count);
|
||||||
|
Assert.Empty(result[0].AlternateVersions);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TestMultiVersionEpisode()
|
||||||
|
{
|
||||||
|
var files = new[]
|
||||||
|
{
|
||||||
|
@"/TV/Dexter/Dexter - S01E01/Dexter - S01E01 - One.mkv",
|
||||||
|
@"/TV/Dexter/Dexter - S01E01/Dexter - S01E01 - Two.mkv",
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = VideoListResolver.Resolve(
|
||||||
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions, false)).OfType<VideoFileInfo>().ToList(),
|
||||||
|
_namingOptions,
|
||||||
|
CollectionType.TvShows);
|
||||||
|
|
||||||
|
Assert.Single(result);
|
||||||
|
Assert.Single(result[0].AlternateVersions);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TestMultiVersionEpisodeMixedSeriesFolder()
|
||||||
|
{
|
||||||
|
var files = new[]
|
||||||
|
{
|
||||||
|
@"/TV/Dexter/Dexter - S01E01.mkv",
|
||||||
|
@"/TV/Dexter/Dexter - S01E01 - Unaired.mkv",
|
||||||
|
@"/TV/Dexter/Dexter - S01E02 - Two.mkv",
|
||||||
|
@"/TV/Dexter/Dexter - S01E03 - Three.mkv",
|
||||||
|
@"/TV/Dexter/Dexter S02E01 - Ia.mkv",
|
||||||
|
@"/TV/Dexter/Dexter S02E01 - I.mkv",
|
||||||
|
@"/TV/Dexter/Dexter - S02E02.mkv",
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = VideoListResolver.Resolve(
|
||||||
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions, false)).OfType<VideoFileInfo>().ToList(),
|
||||||
|
_namingOptions,
|
||||||
|
CollectionType.TvShows);
|
||||||
|
|
||||||
|
Assert.Equal(5, result.Count);
|
||||||
|
Assert.Single(result[0].AlternateVersions);
|
||||||
|
Assert.Empty(result[1].AlternateVersions);
|
||||||
|
Assert.Empty(result[2].AlternateVersions);
|
||||||
|
Assert.Empty(result[3].AlternateVersions);
|
||||||
|
|
||||||
|
var s02e01 = result.FirstOrDefault(x => string.Equals(x.Name, "Dexter S02E01", StringComparison.Ordinal));
|
||||||
|
Assert.NotNull(s02e01);
|
||||||
|
Assert.Single(s02e01!.AlternateVersions);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TestMultiVersionEpisodeMixedSeasonFolder()
|
||||||
|
{
|
||||||
|
var files = new[]
|
||||||
|
{
|
||||||
|
@"/TV/Dexter/Season 2/Dexter - S02E01 - Ia.mkv",
|
||||||
|
@"/TV/Dexter/Season 2/Dexter - S02E01 - I.mkv",
|
||||||
|
@"/TV/Dexter/Season 2/Dexter - S02E02.mkv",
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = VideoListResolver.Resolve(
|
||||||
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions, false)).OfType<VideoFileInfo>().ToList(),
|
||||||
|
_namingOptions,
|
||||||
|
CollectionType.TvShows);
|
||||||
|
|
||||||
|
Assert.Equal(2, result.Count);
|
||||||
|
Assert.Single(result[0].AlternateVersions);
|
||||||
|
Assert.Empty(result[1].AlternateVersions);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TestMultiVersionEpisodeMixedSeasonFolderWithYear()
|
||||||
|
{
|
||||||
|
var files = new[]
|
||||||
|
{
|
||||||
|
@"/TV/Name (2020)/Season 1/Name (2020) - S01E01 - [ORIGINAL].mkv",
|
||||||
|
@"/TV/Name (2020)/Season 1/Name (2020) - S01E01 - [VERSION].mkv",
|
||||||
|
@"/TV/Name (2020)/Season 1/Name (2020) - S01E02 - [ORIGINAL].mkv",
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = VideoListResolver.Resolve(
|
||||||
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions, false)).OfType<VideoFileInfo>().ToList(),
|
||||||
|
_namingOptions,
|
||||||
|
CollectionType.TvShows);
|
||||||
|
|
||||||
|
Assert.Equal(2, result.Count);
|
||||||
|
Assert.Single(result[0].AlternateVersions);
|
||||||
|
Assert.Empty(result[1].AlternateVersions);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TestMultiVersionEpisodeMixedSeasonFolderWithYearAndDirtyNames()
|
||||||
|
{
|
||||||
|
var files = new[]
|
||||||
|
{
|
||||||
|
@"/TV/Name (2020)/Season 1/Name (2020) - S01E01 [BluRay-480p x264][AC3 2.0] - [ORIGINAL].mkv",
|
||||||
|
@"/TV/Name (2020)/Season 1/Name (2020) - S01E01 [BluRay-1080p x264][AC3 5.1] - [Remaster].mkv",
|
||||||
|
@"/TV/Name (2020)/Season 1/Name (2020) - S01E02 - [ORIGINAL].mkv",
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = VideoListResolver.Resolve(
|
||||||
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions, false)).OfType<VideoFileInfo>().ToList(),
|
||||||
|
_namingOptions,
|
||||||
|
CollectionType.TvShows);
|
||||||
|
|
||||||
|
Assert.Equal(2, result.Count);
|
||||||
|
Assert.Single(result[0].AlternateVersions);
|
||||||
|
Assert.Empty(result[1].AlternateVersions);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,8 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
_namingOptions).ToList();
|
_namingOptions,
|
||||||
|
CollectionType.Movies).ToList();
|
||||||
|
|
||||||
Assert.Equal(11, result.Count);
|
Assert.Equal(11, result.Count);
|
||||||
var batman = result.FirstOrDefault(x => string.Equals(x.Name, "Batman", StringComparison.Ordinal));
|
var batman = result.FirstOrDefault(x => string.Equals(x.Name, "Batman", StringComparison.Ordinal));
|
||||||
|
@ -65,6 +66,90 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
Assert.Equal(ExtraType.Trailer, result[10].ExtraType);
|
Assert.Equal(ExtraType.Trailer, result[10].ExtraType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TestTVStackAndVersions()
|
||||||
|
{
|
||||||
|
// No stacking here because there is no part/disc/etc
|
||||||
|
var files = new[]
|
||||||
|
{
|
||||||
|
@"/TV/Grey's Anatomy (2005)/Grey's Anatomy (2005) - s01e01 CD1.avi",
|
||||||
|
@"/TV/Grey's Anatomy (2005)/Grey's Anatomy (2005) - s01e01 CD2.avi",
|
||||||
|
@"/TV/Grey's Anatomy (2005)/Grey's Anatomy (2005) - s01e02 - The First Cut is the Deepest.avi",
|
||||||
|
@"/TV/Grey's Anatomy (2005)/Grey's Anatomy (2005) - s01e03.mp4",
|
||||||
|
@"/TV/Grey's Anatomy (2005)/Grey's Anatomy (2005) - s01e04 - Aired Version.mp4",
|
||||||
|
@"/TV/Grey's Anatomy (2005)/Grey's Anatomy (2005) - s01e04 - Uncensored Version.mp4"
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = VideoListResolver.Resolve(
|
||||||
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions, false)).OfType<VideoFileInfo>().ToList(),
|
||||||
|
_namingOptions,
|
||||||
|
CollectionType.TvShows).ToList();
|
||||||
|
|
||||||
|
Assert.Equal(4, result.Count);
|
||||||
|
|
||||||
|
var s01e01 = result.FirstOrDefault(x => string.Equals(x.Name, "Grey's Anatomy (2005) - s01e01", StringComparison.Ordinal));
|
||||||
|
Assert.NotNull(s01e01);
|
||||||
|
Assert.Equal(2, s01e01!.Files.Count);
|
||||||
|
|
||||||
|
var s01e04 = result.FirstOrDefault(x => string.Equals(x.Name, "Grey's Anatomy (2005) - s01e04", StringComparison.Ordinal));
|
||||||
|
Assert.NotNull(s01e04);
|
||||||
|
Assert.Equal(1, s01e04!.AlternateVersions.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TestTVStackAndVersionsNoFirstDash()
|
||||||
|
{
|
||||||
|
// No stacking here because there is no part/disc/etc
|
||||||
|
var files = new[]
|
||||||
|
{
|
||||||
|
@"/TV/Grey's Anatomy (2005)/Grey's Anatomy (2005) s01e01 - pt1.avi",
|
||||||
|
@"/TV/Grey's Anatomy (2005)/Grey's Anatomy (2005) s01e01 - pt2.avi",
|
||||||
|
@"/TV/Grey's Anatomy (2005)/Grey's Anatomy (2005) s01e02 - The First Cut is the Deepest.avi",
|
||||||
|
@"/TV/Grey's Anatomy (2005)/Grey's Anatomy (2005) s01e03.mp4",
|
||||||
|
@"/TV/Grey's Anatomy (2005)/Grey's Anatomy (2005) s01e04 - Aired Version.mp4",
|
||||||
|
@"/TV/Grey's Anatomy (2005)/Grey's Anatomy (2005) s01e04 - Uncensored Version.mp4"
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = VideoListResolver.Resolve(
|
||||||
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions, false)).OfType<VideoFileInfo>().ToList(),
|
||||||
|
_namingOptions,
|
||||||
|
CollectionType.TvShows).ToList();
|
||||||
|
|
||||||
|
Assert.Equal(4, result.Count);
|
||||||
|
|
||||||
|
var s01e01 = result.FirstOrDefault(x => string.Equals(x.Name, "Grey's Anatomy (2005) s01e01", StringComparison.Ordinal));
|
||||||
|
Assert.NotNull(s01e01);
|
||||||
|
Assert.Equal(2, s01e01!.Files.Count);
|
||||||
|
|
||||||
|
var s01e04 = result.FirstOrDefault(x => string.Equals(x.Name, "Grey's Anatomy (2005) s01e04", StringComparison.Ordinal));
|
||||||
|
Assert.NotNull(s01e04);
|
||||||
|
Assert.Equal(1, s01e04!.AlternateVersions.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TestTVStack()
|
||||||
|
{
|
||||||
|
// No stacking here because there is no part/disc/etc
|
||||||
|
var files = new[]
|
||||||
|
{
|
||||||
|
@"/TV/Doctor Who/Season 21/Doctor Who 21x11 - Resurrection of the Daleks - Part 1.mkv",
|
||||||
|
@"/TV/Doctor Who/Season 21/Doctor Who 21x11 - Resurrection of the Daleks - Part 2.mkv",
|
||||||
|
@"/TV/Doctor Who/Season 21/Doctor Who 21x12 - Resurrection of the Daleks - Part 3.mkv",
|
||||||
|
@"/TV/Doctor Who/Season 21/Doctor Who 21x12 - Resurrection of the Daleks - Part 4.mkv"
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = VideoListResolver.Resolve(
|
||||||
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions, false)).OfType<VideoFileInfo>().ToList(),
|
||||||
|
_namingOptions,
|
||||||
|
CollectionType.TvShows).ToList();
|
||||||
|
|
||||||
|
Assert.Equal(2, result.Count);
|
||||||
|
|
||||||
|
var s21e12 = result.FirstOrDefault(x => string.Equals(x.Name, "Doctor Who 21x12 - Resurrection of the Daleks", StringComparison.Ordinal));
|
||||||
|
Assert.NotNull(s21e12);
|
||||||
|
Assert.Equal(2, s21e12!.Files.Count);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void TestWithMetadata()
|
public void TestWithMetadata()
|
||||||
{
|
{
|
||||||
|
@ -76,7 +161,8 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
_namingOptions).ToList();
|
_namingOptions,
|
||||||
|
CollectionType.Movies).ToList();
|
||||||
|
|
||||||
Assert.Single(result);
|
Assert.Single(result);
|
||||||
}
|
}
|
||||||
|
@ -92,7 +178,8 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
_namingOptions).ToList();
|
_namingOptions,
|
||||||
|
CollectionType.Movies).ToList();
|
||||||
|
|
||||||
Assert.Equal(2, result.Count);
|
Assert.Equal(2, result.Count);
|
||||||
Assert.False(result[0].ExtraType.HasValue);
|
Assert.False(result[0].ExtraType.HasValue);
|
||||||
|
@ -110,7 +197,8 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
_namingOptions).ToList();
|
_namingOptions,
|
||||||
|
CollectionType.Movies).ToList();
|
||||||
|
|
||||||
Assert.Equal(2, result.Count);
|
Assert.Equal(2, result.Count);
|
||||||
Assert.False(result[0].ExtraType.HasValue);
|
Assert.False(result[0].ExtraType.HasValue);
|
||||||
|
@ -129,7 +217,8 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
_namingOptions).ToList();
|
_namingOptions,
|
||||||
|
CollectionType.Movies).ToList();
|
||||||
|
|
||||||
Assert.Equal(3, result.Count);
|
Assert.Equal(3, result.Count);
|
||||||
Assert.False(result[0].ExtraType.HasValue);
|
Assert.False(result[0].ExtraType.HasValue);
|
||||||
|
@ -149,7 +238,8 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
_namingOptions).ToList();
|
_namingOptions,
|
||||||
|
CollectionType.Movies).ToList();
|
||||||
|
|
||||||
Assert.Equal(3, result.Count);
|
Assert.Equal(3, result.Count);
|
||||||
Assert.False(result[0].ExtraType.HasValue);
|
Assert.False(result[0].ExtraType.HasValue);
|
||||||
|
@ -168,7 +258,8 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
_namingOptions).ToList();
|
_namingOptions,
|
||||||
|
CollectionType.Movies).ToList();
|
||||||
|
|
||||||
Assert.Equal(2, result.Count);
|
Assert.Equal(2, result.Count);
|
||||||
Assert.False(result[0].ExtraType.HasValue);
|
Assert.False(result[0].ExtraType.HasValue);
|
||||||
|
@ -190,7 +281,8 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
_namingOptions).ToList();
|
_namingOptions,
|
||||||
|
string.Empty).ToList();
|
||||||
|
|
||||||
Assert.Equal(5, result.Count);
|
Assert.Equal(5, result.Count);
|
||||||
}
|
}
|
||||||
|
@ -206,7 +298,8 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => VideoResolver.Resolve(i, true, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
files.Select(i => VideoResolver.Resolve(i, true, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
_namingOptions).ToList();
|
_namingOptions,
|
||||||
|
CollectionType.Movies).ToList();
|
||||||
|
|
||||||
Assert.Single(result);
|
Assert.Single(result);
|
||||||
}
|
}
|
||||||
|
@ -223,7 +316,8 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => VideoResolver.Resolve(i, true, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
files.Select(i => VideoResolver.Resolve(i, true, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
_namingOptions).ToList();
|
_namingOptions,
|
||||||
|
CollectionType.Movies).ToList();
|
||||||
|
|
||||||
Assert.Equal(2, result.Count);
|
Assert.Equal(2, result.Count);
|
||||||
}
|
}
|
||||||
|
@ -241,7 +335,8 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
_namingOptions).ToList();
|
_namingOptions,
|
||||||
|
CollectionType.Movies).ToList();
|
||||||
|
|
||||||
Assert.Equal(3, result.Count);
|
Assert.Equal(3, result.Count);
|
||||||
Assert.False(result[0].ExtraType.HasValue);
|
Assert.False(result[0].ExtraType.HasValue);
|
||||||
|
@ -262,7 +357,8 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
_namingOptions).ToList();
|
_namingOptions,
|
||||||
|
CollectionType.Movies).ToList();
|
||||||
|
|
||||||
Assert.Equal(4, result.Count);
|
Assert.Equal(4, result.Count);
|
||||||
Assert.False(result[0].ExtraType.HasValue);
|
Assert.False(result[0].ExtraType.HasValue);
|
||||||
|
@ -284,7 +380,8 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
_namingOptions).ToList();
|
_namingOptions,
|
||||||
|
string.Empty).ToList();
|
||||||
|
|
||||||
Assert.Equal(2, result.Count);
|
Assert.Equal(2, result.Count);
|
||||||
}
|
}
|
||||||
|
@ -299,7 +396,8 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
_namingOptions).ToList();
|
_namingOptions,
|
||||||
|
CollectionType.Movies).ToList();
|
||||||
|
|
||||||
Assert.Single(result);
|
Assert.Single(result);
|
||||||
}
|
}
|
||||||
|
@ -314,7 +412,8 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
_namingOptions).ToList();
|
_namingOptions,
|
||||||
|
CollectionType.Movies).ToList();
|
||||||
|
|
||||||
Assert.Single(result);
|
Assert.Single(result);
|
||||||
}
|
}
|
||||||
|
@ -330,7 +429,8 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
_namingOptions).ToList();
|
_namingOptions,
|
||||||
|
CollectionType.Movies).ToList();
|
||||||
|
|
||||||
// The result should contain two individual movies
|
// The result should contain two individual movies
|
||||||
// Version grouping should not work here, because the files are not in a directory with the name 'Four Sisters and a Wedding'
|
// Version grouping should not work here, because the files are not in a directory with the name 'Four Sisters and a Wedding'
|
||||||
|
@ -348,7 +448,8 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
_namingOptions).ToList();
|
_namingOptions,
|
||||||
|
CollectionType.Movies).ToList();
|
||||||
|
|
||||||
Assert.Equal(2, result.Count);
|
Assert.Equal(2, result.Count);
|
||||||
}
|
}
|
||||||
|
@ -364,7 +465,8 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
_namingOptions).ToList();
|
_namingOptions,
|
||||||
|
CollectionType.Movies).ToList();
|
||||||
|
|
||||||
Assert.Equal(2, result.Count);
|
Assert.Equal(2, result.Count);
|
||||||
Assert.False(result[0].ExtraType.HasValue);
|
Assert.False(result[0].ExtraType.HasValue);
|
||||||
|
@ -382,7 +484,8 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
_namingOptions).ToList();
|
_namingOptions,
|
||||||
|
CollectionType.Movies).ToList();
|
||||||
|
|
||||||
Assert.Equal(2, result.Count);
|
Assert.Equal(2, result.Count);
|
||||||
Assert.False(result[0].ExtraType.HasValue);
|
Assert.False(result[0].ExtraType.HasValue);
|
||||||
|
@ -400,7 +503,8 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
_namingOptions).ToList();
|
_namingOptions,
|
||||||
|
CollectionType.Movies).ToList();
|
||||||
|
|
||||||
Assert.Equal(2, result.Count);
|
Assert.Equal(2, result.Count);
|
||||||
Assert.False(result[0].ExtraType.HasValue);
|
Assert.False(result[0].ExtraType.HasValue);
|
||||||
|
|
Loading…
Reference in a new issue