Merge pull request #2325 from Bond-009/naming

Clean up Emby.Naming
pull/2384/head
dkanada 4 years ago committed by GitHub
commit df739b5b2f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -19,15 +19,13 @@ namespace Emby.Naming.Audio
_options = options;
}
public MultiPartResult ParseMultiPart(string path)
public bool IsMultiPart(string path)
{
var result = new MultiPartResult();
var filename = Path.GetFileName(path);
if (string.IsNullOrEmpty(filename))
{
return result;
return false;
}
// TODO: Move this logic into options object
@ -57,12 +55,11 @@ namespace Emby.Naming.Audio
if (int.TryParse(tmp, NumberStyles.Integer, CultureInfo.InvariantCulture, out _))
{
result.IsMultiPart = true;
break;
return true;
}
}
return result;
return false;
}
}
}

@ -1,26 +0,0 @@
#pragma warning disable CS1591
#pragma warning disable SA1600
namespace Emby.Naming.Audio
{
public class MultiPartResult
{
/// <summary>
/// Gets or sets the name.
/// </summary>
/// <value>The name.</value>
public string Name { get; set; }
/// <summary>
/// Gets or sets the part.
/// </summary>
/// <value>The part.</value>
public string Part { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this instance is multi part.
/// </summary>
/// <value><c>true</c> if this instance is multi part; otherwise, <c>false</c>.</value>
public bool IsMultiPart { get; set; }
}
}

@ -32,7 +32,7 @@ namespace Emby.Naming.AudioBook
public int? ChapterNumber { get; set; }
/// <summary>
/// Gets or sets the type.
/// Gets or sets a value indicating whether this instance is a directory.
/// </summary>
/// <value>The type.</value>
public bool IsDirectory { get; set; }

@ -39,9 +39,7 @@ namespace Emby.Naming.AudioBook
var stackResult = new StackResolver(_options)
.ResolveAudioBooks(metadata);
var list = new List<AudioBookInfo>();
foreach (var stack in stackResult.Stacks)
foreach (var stack in stackResult)
{
var stackFiles = stack.Files.Select(i => audioBookResolver.Resolve(i, stack.IsDirectoryStack)).ToList();
stackFiles.Sort();
@ -50,20 +48,9 @@ namespace Emby.Naming.AudioBook
Files = stackFiles,
Name = stack.Name
};
list.Add(info);
}
// Whatever files are left, just add them
/*list.AddRange(remainingFiles.Select(i => new AudioBookInfo
{
Files = new List<AudioBookFileInfo> { i },
Name = i.,
Year = i.Year
}));*/
var orderedList = list.OrderBy(i => i.Name);
return orderedList;
yield return info;
}
}
}
}

@ -11,6 +11,24 @@ namespace Emby.Naming.Common
private string _expression;
private Regex _regex;
public EpisodeExpression(string expression, bool byDate)
{
Expression = expression;
IsByDate = byDate;
DateTimeFormats = Array.Empty<string>();
SupportsAbsoluteEpisodeNumbers = true;
}
public EpisodeExpression(string expression)
: this(expression, false)
{
}
public EpisodeExpression()
: this(null)
{
}
public string Expression
{
get => _expression;
@ -32,23 +50,5 @@ namespace Emby.Naming.Common
public string[] DateTimeFormats { get; set; }
public Regex Regex => _regex ?? (_regex = new Regex(Expression, RegexOptions.IgnoreCase | RegexOptions.Compiled));
public EpisodeExpression(string expression, bool byDate)
{
Expression = expression;
IsByDate = byDate;
DateTimeFormats = Array.Empty<string>();
SupportsAbsoluteEpisodeNumbers = true;
}
public EpisodeExpression(string expression)
: this(expression, false)
{
}
public EpisodeExpression()
: this(null)
{
}
}
}

@ -11,46 +11,6 @@ namespace Emby.Naming.Common
{
public class NamingOptions
{
public string[] AudioFileExtensions { get; set; }
public string[] AlbumStackingPrefixes { get; set; }
public string[] SubtitleFileExtensions { get; set; }
public char[] SubtitleFlagDelimiters { get; set; }
public string[] SubtitleForcedFlags { get; set; }
public string[] SubtitleDefaultFlags { get; set; }
public EpisodeExpression[] EpisodeExpressions { get; set; }
public string[] EpisodeWithoutSeasonExpressions { get; set; }
public string[] EpisodeMultiPartExpressions { get; set; }
public string[] VideoFileExtensions { get; set; }
public string[] StubFileExtensions { get; set; }
public string[] AudioBookPartsExpressions { get; set; }
public StubTypeRule[] StubTypes { get; set; }
public char[] VideoFlagDelimiters { get; set; }
public Format3DRule[] Format3DRules { get; set; }
public string[] VideoFileStackingExpressions { get; set; }
public string[] CleanDateTimes { get; set; }
public string[] CleanStrings { get; set; }
public EpisodeExpression[] MultipleEpisodeExpressions { get; set; }
public ExtraRule[] VideoExtraRules { get; set; }
public NamingOptions()
{
VideoFileExtensions = new[]
@ -681,11 +641,54 @@ namespace Emby.Naming.Common
Compile();
}
public string[] AudioFileExtensions { get; set; }
public string[] AlbumStackingPrefixes { get; set; }
public string[] SubtitleFileExtensions { get; set; }
public char[] SubtitleFlagDelimiters { get; set; }
public string[] SubtitleForcedFlags { get; set; }
public string[] SubtitleDefaultFlags { get; set; }
public EpisodeExpression[] EpisodeExpressions { get; set; }
public string[] EpisodeWithoutSeasonExpressions { get; set; }
public string[] EpisodeMultiPartExpressions { get; set; }
public string[] VideoFileExtensions { get; set; }
public string[] StubFileExtensions { get; set; }
public string[] AudioBookPartsExpressions { get; set; }
public StubTypeRule[] StubTypes { get; set; }
public char[] VideoFlagDelimiters { get; set; }
public Format3DRule[] Format3DRules { get; set; }
public string[] VideoFileStackingExpressions { get; set; }
public string[] CleanDateTimes { get; set; }
public string[] CleanStrings { get; set; }
public EpisodeExpression[] MultipleEpisodeExpressions { get; set; }
public ExtraRule[] VideoExtraRules { get; set; }
public Regex[] VideoFileStackingRegexes { get; private set; }
public Regex[] CleanDateTimeRegexes { get; private set; }
public Regex[] CleanStringRegexes { get; private set; }
public Regex[] EpisodeWithoutSeasonRegexes { get; private set; }
public Regex[] EpisodeMultiPartRegexes { get; private set; }
public void Compile()

@ -4,7 +4,7 @@
<TargetFramework>netstandard2.1</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<TreatWarningsAsErrors Condition=" '$(Configuration)' == 'Release' " >true</TreatWarningsAsErrors>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
<ItemGroup>
@ -24,7 +24,7 @@
<!-- Code Analyzers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.8" PrivateAssets="All" />
<!-- TODO: <PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.8" PrivateAssets="All" /> -->
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />

@ -1,5 +1,6 @@
#pragma warning disable CS1591
#pragma warning disable SA1600
#nullable enable
using System;
using System.Collections.Generic;
@ -28,7 +29,7 @@ namespace Emby.Naming.TV
path += ".mp4";
}
EpisodePathParserResult result = null;
EpisodePathParserResult? result = null;
foreach (var expression in _options.EpisodeExpressions)
{
@ -136,7 +137,7 @@ namespace Emby.Naming.TV
// It avoids erroneous parsing of something like "series-s09e14-1080p.mkv" as a multi-episode from E14 to E108
int nextIndex = endingNumberGroup.Index + endingNumberGroup.Length;
if (nextIndex >= name.Length
|| "0123456789iIpP".IndexOf(name[nextIndex]) == -1)
|| !"0123456789iIpP".Contains(name[nextIndex], StringComparison.Ordinal))
{
if (int.TryParse(endingNumberGroup.Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out num))
{

@ -1,5 +1,6 @@
#pragma warning disable CS1591
#pragma warning disable SA1600
#nullable enable
using System;
using System.IO;
@ -18,7 +19,7 @@ namespace Emby.Naming.TV
_options = options;
}
public EpisodeInfo Resolve(
public EpisodeInfo? Resolve(
string path,
bool isDirectory,
bool? isNamed = null,
@ -26,14 +27,9 @@ namespace Emby.Naming.TV
bool? supportsAbsoluteNumbers = null,
bool fillExtendedInfo = true)
{
if (string.IsNullOrEmpty(path))
{
throw new ArgumentNullException(nameof(path));
}
bool isStub = false;
string container = null;
string stubType = null;
string? container = null;
string? stubType = null;
if (!isDirectory)
{
@ -41,17 +37,13 @@ namespace Emby.Naming.TV
// Check supported extensions
if (!_options.VideoFileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase))
{
var stubResult = StubResolver.ResolveFile(path, _options);
isStub = stubResult.IsStub;
// It's not supported. Check stub extensions
if (!isStub)
if (!StubResolver.TryResolveFile(path, _options, out stubType))
{
return null;
}
stubType = stubResult.StubType;
isStub = true;
}
container = extension.TrimStart('.');

@ -8,9 +8,24 @@ using System.Linq;
namespace Emby.Naming.TV
{
public class SeasonPathParser
public static class SeasonPathParser
{
public SeasonPathParserResult Parse(string path, bool supportSpecialAliases, bool supportNumericSeasonFolders)
/// <summary>
/// A season folder must contain one of these somewhere in the name.
/// </summary>
private static readonly string[] _seasonFolderNames =
{
"season",
"sæson",
"temporada",
"saison",
"staffel",
"series",
"сезон",
"stagione"
};
public static SeasonPathParserResult Parse(string path, bool supportSpecialAliases, bool supportNumericSeasonFolders)
{
var result = new SeasonPathParserResult();
@ -27,21 +42,6 @@ namespace Emby.Naming.TV
return result;
}
/// <summary>
/// A season folder must contain one of these somewhere in the name.
/// </summary>
private static readonly string[] _seasonFolderNames =
{
"season",
"sæson",
"temporada",
"saison",
"staffel",
"series",
"сезон",
"stagione"
};
/// <summary>
/// Gets the season number from path.
/// </summary>
@ -150,6 +150,7 @@ namespace Emby.Naming.TV
{
numericStart = i;
}
length++;
}
}
@ -161,11 +162,11 @@ namespace Emby.Naming.TV
}
var currentChar = path[i];
if (currentChar.Equals('('))
if (currentChar == '(')
{
hasOpenParenth = true;
}
else if (currentChar.Equals(')'))
else if (currentChar == ')')
{
hasOpenParenth = false;
}

@ -20,7 +20,7 @@ namespace Emby.Naming.Video
_options = options;
}
public StackResult ResolveDirectories(IEnumerable<string> files)
public IEnumerable<FileStack> ResolveDirectories(IEnumerable<string> files)
{
return Resolve(files.Select(i => new FileSystemMetadata
{
@ -29,7 +29,7 @@ namespace Emby.Naming.Video
}));
}
public StackResult ResolveFiles(IEnumerable<string> files)
public IEnumerable<FileStack> ResolveFiles(IEnumerable<string> files)
{
return Resolve(files.Select(i => new FileSystemMetadata
{
@ -38,9 +38,8 @@ namespace Emby.Naming.Video
}));
}
public StackResult ResolveAudioBooks(IEnumerable<FileSystemMetadata> files)
public IEnumerable<FileStack> ResolveAudioBooks(IEnumerable<FileSystemMetadata> files)
{
var result = new StackResult();
foreach (var directory in files.GroupBy(file => file.IsDirectory ? file.FullName : Path.GetDirectoryName(file.FullName)))
{
var stack = new FileStack()
@ -58,20 +57,16 @@ namespace Emby.Naming.Video
stack.Files.Add(file.FullName);
}
result.Stacks.Add(stack);
yield return stack;
}
return result;
}
public StackResult Resolve(IEnumerable<FileSystemMetadata> files)
public IEnumerable<FileStack> Resolve(IEnumerable<FileSystemMetadata> files)
{
var result = new StackResult();
var resolver = new VideoResolver(_options);
var list = files
.Where(i => i.IsDirectory || (resolver.IsVideoFile(i.FullName) || resolver.IsStubFile(i.FullName)))
.Where(i => i.IsDirectory || resolver.IsVideoFile(i.FullName) || resolver.IsStubFile(i.FullName))
.OrderBy(i => i.FullName)
.ToList();
@ -191,14 +186,12 @@ namespace Emby.Naming.Video
if (stack.Files.Count > 1)
{
result.Stacks.Add(stack);
yield return stack;
i += stack.Files.Count - 1;
break;
}
}
}
return result;
}
private string GetRegexInput(FileSystemMetadata file)

@ -1,17 +0,0 @@
#pragma warning disable CS1591
#pragma warning disable SA1600
using System.Collections.Generic;
namespace Emby.Naming.Video
{
public class StackResult
{
public List<FileStack> Stacks { get; set; }
public StackResult()
{
Stacks = new List<FileStack>();
}
}
}

@ -1,5 +1,6 @@
#pragma warning disable CS1591
#pragma warning disable SA1600
#nullable enable
using System;
using System.IO;
@ -10,25 +11,22 @@ namespace Emby.Naming.Video
{
public static class StubResolver
{
public static StubResult ResolveFile(string path, NamingOptions options)
public static bool TryResolveFile(string path, NamingOptions options, out string? stubType)
{
stubType = default;
if (path == null)
{
return default;
return false;
}
var extension = Path.GetExtension(path);
if (!options.StubFileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase))
{
return default;
return false;
}
var result = new StubResult()
{
IsStub = true
};
path = Path.GetFileNameWithoutExtension(path);
var token = Path.GetExtension(path).TrimStart('.');
@ -36,12 +34,12 @@ namespace Emby.Naming.Video
{
if (string.Equals(rule.Token, token, StringComparison.OrdinalIgnoreCase))
{
result.StubType = rule.StubType;
break;
stubType = rule.StubType;
return true;
}
}
return result;
return true;
}
}
}

@ -68,7 +68,7 @@ namespace Emby.Naming.Video
public string StubType { get; set; }
/// <summary>
/// Gets or sets the type.
/// Gets or sets a value indicating whether this instance is a directory.
/// </summary>
/// <value>The type.</value>
public bool IsDirectory { get; set; }

@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
namespace Emby.Naming.Video
@ -10,11 +11,14 @@ namespace Emby.Naming.Video
/// <summary>
/// Initializes a new instance of the <see cref="VideoInfo" /> class.
/// </summary>
public VideoInfo()
/// <param name="name">The name.</param>
public VideoInfo(string name)
{
Files = new List<VideoFileInfo>();
Extras = new List<VideoFileInfo>();
AlternateVersions = new List<VideoFileInfo>();
Name = name;
Files = Array.Empty<VideoFileInfo>();
Extras = Array.Empty<VideoFileInfo>();
AlternateVersions = Array.Empty<VideoFileInfo>();
}
/// <summary>
@ -33,18 +37,18 @@ namespace Emby.Naming.Video
/// Gets or sets the files.
/// </summary>
/// <value>The files.</value>
public List<VideoFileInfo> Files { get; set; }
public IReadOnlyList<VideoFileInfo> Files { get; set; }
/// <summary>
/// Gets or sets the extras.
/// </summary>
/// <value>The extras.</value>
public List<VideoFileInfo> Extras { get; set; }
public IReadOnlyList<VideoFileInfo> Extras { get; set; }
/// <summary>
/// Gets or sets the alternate versions.
/// </summary>
/// <value>The alternate versions.</value>
public List<VideoFileInfo> AlternateVersions { get; set; }
public IReadOnlyList<VideoFileInfo> AlternateVersions { get; set; }
}
}

@ -41,20 +41,19 @@ namespace Emby.Naming.Video
});
var stackResult = new StackResolver(_options)
.Resolve(nonExtras);
.Resolve(nonExtras).ToList();
var remainingFiles = videoInfos
.Where(i => !stackResult.Stacks.Any(s => s.ContainsFile(i.Path, i.IsDirectory)))
.Where(i => !stackResult.Any(s => s.ContainsFile(i.Path, i.IsDirectory)))
.ToList();
var list = new List<VideoInfo>();
foreach (var stack in stackResult.Stacks)
foreach (var stack in stackResult)
{
var info = new VideoInfo
var info = new VideoInfo(stack.Name)
{
Files = stack.Files.Select(i => videoResolver.Resolve(i, stack.IsDirectoryStack)).ToList(),
Name = stack.Name
Files = stack.Files.Select(i => videoResolver.Resolve(i, stack.IsDirectoryStack)).ToList()
};
info.Year = info.Files[0].Year;
@ -85,10 +84,9 @@ namespace Emby.Naming.Video
foreach (var media in standaloneMedia)
{
var info = new VideoInfo
var info = new VideoInfo(media.Name)
{
Files = new List<VideoFileInfo> { media },
Name = media.Name
Files = new List<VideoFileInfo> { media }
};
info.Year = info.Files[0].Year;
@ -128,7 +126,8 @@ namespace Emby.Naming.Video
.Except(extras)
.ToList();
info.Extras.AddRange(extras);
extras.AddRange(info.Extras);
info.Extras = extras;
}
}
@ -141,7 +140,8 @@ namespace Emby.Naming.Video
.Except(extrasByFileName)
.ToList();
info.Extras.AddRange(extrasByFileName);
extrasByFileName.AddRange(info.Extras);
info.Extras = extrasByFileName;
}
// If there's only one video, accept all trailers
@ -152,7 +152,8 @@ namespace Emby.Naming.Video
.Where(i => i.ExtraType == ExtraType.Trailer)
.ToList();
list[0].Extras.AddRange(trailers);
trailers.AddRange(list[0].Extras);
list[0].Extras = trailers;
remainingFiles = remainingFiles
.Except(trailers)
@ -160,14 +161,13 @@ namespace Emby.Naming.Video
}
// Whatever files are left, just add them
list.AddRange(remainingFiles.Select(i => new VideoInfo
list.AddRange(remainingFiles.Select(i => new VideoInfo(i.Name)
{
Files = new List<VideoFileInfo> { i },
Name = i.Name,
Year = i.Year
}));
return list.OrderBy(i => i.Name);
return list;
}
private IEnumerable<VideoInfo> GetVideosGroupedByVersion(List<VideoInfo> videos)
@ -191,9 +191,18 @@ namespace Emby.Naming.Video
list.Add(ordered[0]);
list[0].AlternateVersions = ordered.Skip(1).Select(i => i.Files[0]).ToList();
var alternateVersionsLen = ordered.Count - 1;
var alternateVersions = new VideoFileInfo[alternateVersionsLen];
for (int i = 0; i < alternateVersionsLen; i++)
{
alternateVersions[i] = ordered[i + 1].Files[0];
}
list[0].AlternateVersions = alternateVersions;
list[0].Name = folderName;
list[0].Extras.AddRange(ordered.Skip(1).SelectMany(i => i.Extras));
var extras = ordered.Skip(1).SelectMany(i => i.Extras).ToList();
extras.AddRange(list[0].Extras);
list[0].Extras = extras;
return list;
}

@ -1,5 +1,6 @@
#pragma warning disable CS1591
#pragma warning disable SA1600
#nullable enable
using System;
using System.IO;
@ -22,7 +23,7 @@ namespace Emby.Naming.Video
/// </summary>
/// <param name="path">The path.</param>
/// <returns>VideoFileInfo.</returns>
public VideoFileInfo ResolveDirectory(string path)
public VideoFileInfo? ResolveDirectory(string path)
{
return Resolve(path, true);
}
@ -32,7 +33,7 @@ namespace Emby.Naming.Video
/// </summary>
/// <param name="path">The path.</param>
/// <returns>VideoFileInfo.</returns>
public VideoFileInfo ResolveFile(string path)
public VideoFileInfo? ResolveFile(string path)
{
return Resolve(path, false);
}
@ -42,10 +43,10 @@ namespace Emby.Naming.Video
/// </summary>
/// <param name="path">The path.</param>
/// <param name="isDirectory">if set to <c>true</c> [is folder].</param>
/// <param name="parseName">Whether or not the name should be parsed for info</param>
/// <param name="parseName">Whether or not the name should be parsed for info.</param>
/// <returns>VideoFileInfo.</returns>
/// <exception cref="ArgumentNullException"><c>path</c> is <c>null</c>.</exception>
public VideoFileInfo Resolve(string path, bool isDirectory, bool parseName = true)
public VideoFileInfo? Resolve(string path, bool isDirectory, bool parseName = true)
{
if (string.IsNullOrEmpty(path))
{
@ -53,8 +54,8 @@ namespace Emby.Naming.Video
}
bool isStub = false;
string container = null;
string stubType = null;
string? container = null;
string? stubType = null;
if (!isDirectory)
{
@ -63,17 +64,13 @@ namespace Emby.Naming.Video
// Check supported extensions
if (!_options.VideoFileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase))
{
var stubResult = StubResolver.ResolveFile(path, _options);
isStub = stubResult.IsStub;
// It's not supported. Check stub extensions
if (!isStub)
if (!StubResolver.TryResolveFile(path, _options, out stubType))
{
return null;
}
stubType = stubResult.StubType;
isStub = true;
}
container = extension.TrimStart('.');

@ -2382,7 +2382,7 @@ namespace Emby.Server.Implementations.Library
public int? GetSeasonNumberFromPath(string path)
{
return new SeasonPathParser().Parse(path, true, true).SeasonNumber;
return SeasonPathParser.Parse(path, true, true).SeasonNumber;
}
public bool FillMissingEpisodeNumbersFromPath(Episode episode, bool forceRefresh)

@ -76,7 +76,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
}
/// <summary>
/// Determine if the supplied file data points to a music album
/// Determine if the supplied file data points to a music album.
/// </summary>
public bool IsMusicAlbum(string path, IDirectoryService directoryService, LibraryOptions libraryOptions)
{
@ -84,7 +84,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
}
/// <summary>
/// Determine if the supplied resolve args should be considered a music album
/// Determine if the supplied resolve args should be considered a music album.
/// </summary>
/// <param name="args">The args.</param>
/// <returns><c>true</c> if [is music album] [the specified args]; otherwise, <c>false</c>.</returns>
@ -104,7 +104,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
}
/// <summary>
/// Determine if the supplied list contains what we should consider music
/// Determine if the supplied list contains what we should consider music.
/// </summary>
private bool ContainsMusic(
IEnumerable<FileSystemMetadata> list,
@ -118,6 +118,8 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
var discSubfolderCount = 0;
var notMultiDisc = false;
var namingOptions = ((LibraryManager)_libraryManager).GetNamingOptions();
var parser = new AlbumParser(namingOptions);
foreach (var fileSystemInfo in list)
{
if (fileSystemInfo.IsDirectory)
@ -134,7 +136,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
if (hasMusic)
{
if (IsMultiDiscFolder(path, libraryOptions))
if (parser.IsMultiPart(path))
{
logger.LogDebug("Found multi-disc folder: " + path);
discSubfolderCount++;
@ -165,15 +167,5 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
return discSubfolderCount > 0;
}
private bool IsMultiDiscFolder(string path, LibraryOptions libraryOptions)
{
var namingOptions = ((LibraryManager)_libraryManager).GetNamingOptions();
var parser = new AlbumParser(namingOptions);
var result = parser.ParseMultiPart(path);
return result.IsMultiPart;
}
}
}

@ -21,6 +21,28 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
/// </summary>
public class MovieResolver : BaseVideoResolver<Video>, IMultiItemResolver
{
private string[] _validCollectionTypes = new[]
{
CollectionType.Movies,
CollectionType.HomeVideos,
CollectionType.MusicVideos,
CollectionType.Movies,
CollectionType.Photos
};
private readonly IImageProcessor _imageProcessor;
/// <summary>
/// Initializes a new instance of the <see cref="MovieResolver"/> class.
/// </summary>
/// <param name="libraryManager">The library manager.</param>
/// <param name="imageProcessor">The image processor.</param>
public MovieResolver(ILibraryManager libraryManager, IImageProcessor imageProcessor)
: base(libraryManager)
{
_imageProcessor = imageProcessor;
}
/// <summary>
/// Gets the priority.
/// </summary>
@ -144,7 +166,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
foreach (var video in resolverResult)
{
var firstVideo = video.Files.First();
var firstVideo = video.Files[0];
var videoItem = new T
{
@ -230,7 +252,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
// Owned items will be caught by the plain video resolver
if (args.Parent == null)
{
//return FindMovie<Video>(args.Path, args.Parent, files, args.DirectoryService, collectionType);
// return FindMovie<Video>(args.Path, args.Parent, files, args.DirectoryService, collectionType);
return null;
}
@ -275,7 +297,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
{
item = ResolveVideo<Movie>(args, true);
}
else if (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase) ||
string.Equals(collectionType, CollectionType.Photos, StringComparison.OrdinalIgnoreCase))
{
@ -319,7 +340,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
{
if (item is Movie || item is MusicVideo)
{
//we need to only look at the name of this actual item (not parents)
// We need to only look at the name of this actual item (not parents)
var justName = item.IsInMixedFolder ? Path.GetFileName(item.Path) : Path.GetFileName(item.ContainingFolderPath);
if (!string.IsNullOrEmpty(justName))
@ -347,9 +368,8 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
}
/// <summary>
/// Finds a movie based on a child file system entries
/// Finds a movie based on a child file system entries.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns>Movie.</returns>
private T FindMovie<T>(ItemResolveArgs args, string path, Folder parent, List<FileSystemMetadata> fileSystemEntries, IDirectoryService directoryService, string collectionType, bool parseName)
where T : Video, new()
@ -377,6 +397,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
Set3DFormat(movie);
return movie;
}
if (IsBluRayDirectory(child.FullName, filename, directoryService))
{
var movie = new T
@ -407,9 +428,9 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
}
// TODO: Allow GetMultiDiscMovie in here
const bool supportsMultiVersion = true;
const bool SupportsMultiVersion = true;
var result = ResolveVideos<T>(parent, fileSystemEntries, directoryService, supportsMultiVersion, collectionType, parseName) ??
var result = ResolveVideos<T>(parent, fileSystemEntries, directoryService, SupportsMultiVersion, collectionType, parseName) ??
new MultiItemResolverResult();
if (result.Items.Count == 1)
@ -437,7 +458,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
/// <summary>
/// Gets the multi disc movie.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="multiDiscFolders">The folders.</param>
/// <param name="directoryService">The directory service.</param>
/// <returns>``0.</returns>
@ -451,7 +471,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
var subFileEntries = directoryService.GetFileSystemEntries(i);
var subfolders = subFileEntries
.Where(e => e.IsDirectory)
.Where(e => e.IsDirectory)
.ToList();
if (subfolders.Any(s => IsDvdDirectory(s.FullName, s.Name, directoryService)))
@ -459,6 +479,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
videoTypes.Add(VideoType.Dvd);
return true;
}
if (subfolders.Any(s => IsBluRayDirectory(s.FullName, s.Name, directoryService)))
{
videoTypes.Add(VideoType.BluRay);
@ -476,7 +497,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
}
return false;
}).OrderBy(i => i).ToList();
// If different video types were found, don't allow this
@ -491,11 +511,10 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
}
var namingOptions = ((LibraryManager)LibraryManager).GetNamingOptions();
var resolver = new StackResolver(namingOptions);
var result = resolver.ResolveDirectories(folderPaths);
var result = new StackResolver(namingOptions).ResolveDirectories(folderPaths).ToList();
if (result.Stacks.Count != 1)
if (result.Count != 1)
{
return null;
}
@ -508,7 +527,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
VideoType = videoTypes[0],
Name = result.Stacks[0].Name
Name = result[0].Name
};
SetIsoType(returnVideo);
@ -516,15 +535,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
return returnVideo;
}
private string[] ValidCollectionTypes = new[]
{
CollectionType.Movies,
CollectionType.HomeVideos,
CollectionType.MusicVideos,
CollectionType.Movies,
CollectionType.Photos
};
private bool IsInvalid(Folder parent, string collectionType)
{
if (parent != null)
@ -540,20 +550,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
return false;
}
return !ValidCollectionTypes.Contains(collectionType, StringComparer.OrdinalIgnoreCase);
}
private IImageProcessor _imageProcessor;
/// <summary>
/// Initializes a new instance of the <see cref="MovieResolver"/> class.
/// </summary>
/// <param name="libraryManager">The library manager.</param>
/// <param name="imageProcessor">The image processor.</param>
public MovieResolver(ILibraryManager libraryManager, IImageProcessor imageProcessor)
: base(libraryManager)
{
_imageProcessor = imageProcessor;
return !_validCollectionTypes.Contains(collectionType, StringComparer.OrdinalIgnoreCase);
}
}
}

@ -9,17 +9,12 @@ using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.Library.Resolvers.TV
{
/// <summary>
/// Class SeasonResolver
/// Class SeasonResolver.
/// </summary>
public class SeasonResolver : FolderResolver<Season>
{
/// <summary>
/// The _config
/// </summary>
private readonly IServerConfigurationManager _config;
private readonly ILibraryManager _libraryManager;
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
private readonly ILocalizationManager _localization;
private readonly ILogger _logger;
@ -45,14 +40,13 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
/// <returns>Season.</returns>
protected override Season Resolve(ItemResolveArgs args)
{
if (args.Parent is Series && args.IsDirectory)
if (args.Parent is Series series && args.IsDirectory)
{
var namingOptions = ((LibraryManager)_libraryManager).GetNamingOptions();
var series = ((Series)args.Parent);
var path = args.Path;
var seasonParserResult = new SeasonPathParser().Parse(path, true, true);
var seasonParserResult = SeasonPathParser.Parse(path, true, true);
var season = new Season
{
@ -74,7 +68,8 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
{
if (episodeInfo.EpisodeNumber.HasValue && episodeInfo.SeasonNumber.HasValue)
{
_logger.LogDebug("Found folder underneath series with episode number: {0}. Season {1}. Episode {2}",
_logger.LogDebug(
"Found folder underneath series with episode number: {0}. Season {1}. Episode {2}",
path,
episodeInfo.SeasonNumber.Value,
episodeInfo.EpisodeNumber.Value);
@ -90,7 +85,11 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
season.Name = seasonNumber == 0 ?
args.LibraryOptions.SeasonZeroDisplayName :
string.Format(_localization.GetLocalizedString("NameSeasonNumber"), seasonNumber.ToString(UsCulture), args.GetLibraryOptions().PreferredMetadataLanguage);
string.Format(
CultureInfo.InvariantCulture,
_localization.GetLocalizedString("NameSeasonNumber"),
seasonNumber,
args.GetLibraryOptions().PreferredMetadataLanguage);
}

@ -203,7 +203,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
/// <returns><c>true</c> if [is season folder] [the specified path]; otherwise, <c>false</c>.</returns>
private static bool IsSeasonFolder(string path, bool isTvContentType, ILibraryManager libraryManager)
{
var seasonNumber = new SeasonPathParser().Parse(path, isTvContentType, isTvContentType).SeasonNumber;
var seasonNumber = SeasonPathParser.Parse(path, isTvContentType, isTvContentType).SeasonNumber;
return seasonNumber.HasValue;
}

@ -60,7 +60,7 @@ namespace Jellyfin.Naming.Tests.Music
{
var parser = new AlbumParser(new NamingOptions());
return parser.ParseMultiPart(path).IsMultiPart;
return parser.IsMultiPart(path);
}
}
}

@ -103,8 +103,7 @@ namespace Jellyfin.Naming.Tests.TV
private int? GetSeasonNumberFromPath(string path)
{
var result = new SeasonPathParser()
.Parse(path, true, true);
var result = SeasonPathParser.Parse(path, true, true);
return result.SeasonNumber;
}

@ -1,4 +1,5 @@
using Emby.Naming.Common;
using System.Linq;
using Emby.Naming.Common;
using Emby.Naming.Video;
using MediaBrowser.Model.IO;
using Xunit;
@ -21,10 +22,10 @@ namespace Jellyfin.Naming.Tests.Video
var resolver = GetResolver();
var result = resolver.ResolveFiles(files);
var result = resolver.ResolveFiles(files).ToList();
Assert.Single(result.Stacks);
TestStackInfo(result.Stacks[0], "Bad Boys (2006)", 4);
Assert.Single(result);
TestStackInfo(result[0], "Bad Boys (2006)", 4);
}
[Fact]
@ -38,9 +39,9 @@ namespace Jellyfin.Naming.Tests.Video
var resolver = GetResolver();
var result = resolver.ResolveFiles(files);
var result = resolver.ResolveFiles(files).ToList();
Assert.Empty(result.Stacks);
Assert.Empty(result);
}
[Fact]
@ -54,9 +55,9 @@ namespace Jellyfin.Naming.Tests.Video
var resolver = GetResolver();
var result = resolver.ResolveFiles(files);
var result = resolver.ResolveFiles(files).ToList();
Assert.Empty(result.Stacks);
Assert.Empty(result);
}
[Fact]
@ -70,9 +71,9 @@ namespace Jellyfin.Naming.Tests.Video
var resolver = GetResolver();
var result = resolver.ResolveFiles(files);
var result = resolver.ResolveFiles(files).ToList();
Assert.Empty(result.Stacks);
Assert.Empty(result);
}
[Fact]
@ -86,9 +87,9 @@ namespace Jellyfin.Naming.Tests.Video
var resolver = GetResolver();
var result = resolver.ResolveFiles(files);
var result = resolver.ResolveFiles(files).ToList();
Assert.Empty(result.Stacks);
Assert.Empty(result);
}
[Fact]
@ -102,9 +103,8 @@ namespace Jellyfin.Naming.Tests.Video
var resolver = GetResolver();
var result = resolver.ResolveFiles(files);
Assert.Empty(result.Stacks);
var result = resolver.ResolveFiles(files).ToList();
Assert.Empty(result);
}
[Fact]
@ -119,9 +119,9 @@ namespace Jellyfin.Naming.Tests.Video
var resolver = GetResolver();
var result = resolver.ResolveFiles(files);
var result = resolver.ResolveFiles(files).ToList();
Assert.Empty(result.Stacks);
Assert.Empty(result);
}
[Fact]
@ -135,10 +135,10 @@ namespace Jellyfin.Naming.Tests.Video
var resolver = GetResolver();
var result = resolver.ResolveFiles(files);
var result = resolver.ResolveFiles(files).ToList();
Assert.Single(result.Stacks);
TestStackInfo(result.Stacks[0], "300 2006", 2);
Assert.Single(result);
TestStackInfo(result[0], "300 2006", 2);
}
[Fact]
@ -155,10 +155,10 @@ namespace Jellyfin.Naming.Tests.Video
var resolver = GetResolver();
var result = resolver.ResolveFiles(files);
var result = resolver.ResolveFiles(files).ToList();
Assert.Single(result.Stacks);
TestStackInfo(result.Stacks[0], "Bad Boys (2006).stv.unrated.multi.1080p.bluray.x264-rough", 4);
Assert.Single(result);
TestStackInfo(result[0], "Bad Boys (2006).stv.unrated.multi.1080p.bluray.x264-rough", 4);
}
[Fact]
@ -175,9 +175,9 @@ namespace Jellyfin.Naming.Tests.Video
var resolver = GetResolver();
var result = resolver.ResolveFiles(files);
var result = resolver.ResolveFiles(files).ToList();
Assert.Empty(result.Stacks);
Assert.Empty(result);
}
[Fact]
@ -194,10 +194,10 @@ namespace Jellyfin.Naming.Tests.Video
var resolver = GetResolver();
var result = resolver.ResolveFiles(files);
var result = resolver.ResolveFiles(files).ToList();
Assert.Single(result.Stacks);
TestStackInfo(result.Stacks[0], "300 (2006)", 4);
Assert.Single(result);
TestStackInfo(result[0], "300 (2006)", 4);
}
[Fact]
@ -214,10 +214,10 @@ namespace Jellyfin.Naming.Tests.Video
var resolver = GetResolver();
var result = resolver.ResolveFiles(files);
var result = resolver.ResolveFiles(files).ToList();
Assert.Single(result.Stacks);
TestStackInfo(result.Stacks[0], "Bad Boys (2006)", 3);
Assert.Single(result);
TestStackInfo(result[0], "Bad Boys (2006)", 3);
}
[Fact]
@ -238,11 +238,11 @@ namespace Jellyfin.Naming.Tests.Video
var resolver = GetResolver();
var result = resolver.ResolveFiles(files);
var result = resolver.ResolveFiles(files).ToList();
Assert.Equal(2, result.Stacks.Count);
TestStackInfo(result.Stacks[1], "Bad Boys (2006)", 4);
TestStackInfo(result.Stacks[0], "300 (2006)", 3);
Assert.Equal(2, result.Count);
TestStackInfo(result[1], "Bad Boys (2006)", 4);
TestStackInfo(result[0], "300 (2006)", 3);
}
[Fact]
@ -256,10 +256,10 @@ namespace Jellyfin.Naming.Tests.Video
var resolver = GetResolver();
var result = resolver.ResolveDirectories(files);
var result = resolver.ResolveDirectories(files).ToList();
Assert.Single(result.Stacks);
TestStackInfo(result.Stacks[0], "blah blah", 2);
Assert.Single(result);
TestStackInfo(result[0], "blah blah", 2);
}
[Fact]
@ -275,11 +275,11 @@ namespace Jellyfin.Naming.Tests.Video
var resolver = GetResolver();
var result = resolver.ResolveFiles(files);
var result = resolver.ResolveFiles(files).ToList();
Assert.Single(result.Stacks);
Assert.Single(result);
TestStackInfo(result.Stacks[0], "300", 3);
TestStackInfo(result[0], "300", 3);
}
[Fact]
@ -297,12 +297,12 @@ namespace Jellyfin.Naming.Tests.Video
var resolver = GetResolver();
var result = resolver.ResolveFiles(files);
var result = resolver.ResolveFiles(files).ToList();
Assert.Equal(2, result.Stacks.Count);
Assert.Equal(2, result.Count);
TestStackInfo(result.Stacks[0], "300", 2);
TestStackInfo(result.Stacks[1], "Avengers", 3);
TestStackInfo(result[0], "300", 2);
TestStackInfo(result[1], "Avengers", 3);
}
[Fact]
@ -328,13 +328,13 @@ namespace Jellyfin.Naming.Tests.Video
var resolver = GetResolver();
var result = resolver.ResolveFiles(files);
var result = resolver.ResolveFiles(files).ToList();
Assert.Equal(3, result.Stacks.Count);
Assert.Equal(3, result.Count);
TestStackInfo(result.Stacks[0], "300 (2006)", 4);
TestStackInfo(result.Stacks[1], "300", 3);
TestStackInfo(result.Stacks[2], "Bad Boys (2006)", 4);
TestStackInfo(result[0], "300 (2006)", 4);
TestStackInfo(result[1], "300", 3);
TestStackInfo(result[2], "Bad Boys (2006)", 4);
}
[Fact]
@ -354,11 +354,11 @@ namespace Jellyfin.Naming.Tests.Video
var resolver = GetResolver();
var result = resolver.ResolveFiles(files);
var result = resolver.ResolveFiles(files).ToList();
Assert.Single(result.Stacks);
Assert.Single(result);
TestStackInfo(result.Stacks[0], "300 (2006)", 4);
TestStackInfo(result[0], "300 (2006)", 4);
}
[Fact]
@ -375,11 +375,11 @@ namespace Jellyfin.Naming.Tests.Video
var resolver = GetResolver();
var result = resolver.Resolve(files);
var result = resolver.Resolve(files).ToList();
Assert.Equal(2, result.Stacks.Count);
TestStackInfo(result.Stacks[0], "300 (2006)", 3);
TestStackInfo(result.Stacks[1], "Bad Boys (2006)", 2);
Assert.Equal(2, result.Count);
TestStackInfo(result[0], "300 (2006)", 3);
TestStackInfo(result[1], "Bad Boys (2006)", 2);
}
[Fact]
@ -397,9 +397,9 @@ namespace Jellyfin.Naming.Tests.Video
var resolver = GetResolver();
var result = resolver.ResolveFiles(files);
var result = resolver.ResolveFiles(files).ToList();
Assert.Empty(result.Stacks);
Assert.Empty(result);
}
[Fact]
@ -414,10 +414,10 @@ namespace Jellyfin.Naming.Tests.Video
var resolver = GetResolver();
var result = resolver.ResolveFiles(files);
var result = resolver.ResolveFiles(files).ToList();
Assert.Single(result.Stacks);
Assert.Equal(2, result.Stacks[0].Files.Count);
Assert.Single(result);
Assert.Equal(2, result[0].Files.Count);
}
[Fact]
@ -432,10 +432,10 @@ namespace Jellyfin.Naming.Tests.Video
var resolver = GetResolver();
var result = resolver.ResolveDirectories(files);
var result = resolver.ResolveDirectories(files).ToList();
Assert.Single(result.Stacks);
Assert.Equal(2, result.Stacks[0].Files.Count);
Assert.Single(result);
Assert.Equal(2, result[0].Files.Count);
}
private void TestStackInfo(FileStack stack, string name, int fileCount)

@ -36,17 +36,17 @@ namespace Jellyfin.Naming.Tests.Video
{
var options = new NamingOptions();
var resultStubType = StubResolver.ResolveFile(path, options);
var isStubResult = StubResolver.TryResolveFile(path, options, out var stubTypeResult);
Assert.Equal(isStub, resultStubType.IsStub);
Assert.Equal(isStub, isStubResult);
if (stubType == null)
if (isStub)
{
Assert.Null(resultStubType.StubType);
Assert.Equal(stubType, stubTypeResult);
}
else
{
Assert.Equal(stubType, resultStubType.StubType, true);
Assert.Null(stubTypeResult);
}
}
}

Loading…
Cancel
Save