Răsfoiți Sursa

Fix more warnings

Bond-009 6 ani în urmă
părinte
comite
a6f9ceedd8
41 a modificat fișierele cu 339 adăugiri și 237 ștergeri
  1. 14 12
      Emby.Naming/Audio/AlbumParser.cs
  2. 2 0
      Emby.Naming/Audio/MultiPartResult.cs
  3. 25 4
      Emby.Naming/AudioBook/AudioBookFileInfo.cs
  4. 7 6
      Emby.Naming/AudioBook/AudioBookFilePathParser.cs
  5. 2 0
      Emby.Naming/AudioBook/AudioBookFilePathParserResult.cs
  6. 14 7
      Emby.Naming/AudioBook/AudioBookInfo.cs
  7. 1 1
      Emby.Naming/AudioBook/AudioBookListResolver.cs
  8. 6 5
      Emby.Naming/AudioBook/AudioBookResolver.cs
  9. 14 3
      Emby.Naming/Common/EpisodeExpression.cs
  10. 2 0
      Emby.Naming/Common/MediaType.cs
  11. 39 36
      Emby.Naming/Common/NamingOptions.cs
  12. 17 1
      Emby.Naming/Emby.Naming.csproj
  13. 1 0
      Emby.Naming/Extensions/StringExtensions.cs
  14. 0 30
      Emby.Naming/StringExtensions.cs
  15. 3 0
      Emby.Naming/Subtitles/SubtitleInfo.cs
  16. 11 0
      Emby.Naming/TV/EpisodeInfo.cs
  17. 24 28
      Emby.Naming/TV/EpisodePathParser.cs
  18. 7 0
      Emby.Naming/TV/EpisodePathParserResult.cs
  19. 9 3
      Emby.Naming/TV/EpisodeResolver.cs
  20. 20 22
      Emby.Naming/TV/SeasonPathParser.cs
  21. 2 0
      Emby.Naming/TV/SeasonPathParserResult.cs
  22. 10 10
      Emby.Naming/Video/CleanDateTimeParser.cs
  23. 0 2
      Emby.Naming/Video/ExtraResolver.cs
  24. 2 2
      Emby.Naming/Video/FileStack.cs
  25. 7 3
      Emby.Naming/Video/Format3DParser.cs
  26. 7 5
      Emby.Naming/Video/Format3DResult.cs
  27. 13 6
      Emby.Naming/Video/StackResolver.cs
  28. 20 12
      Emby.Naming/Video/StubResolver.cs
  29. 1 0
      Emby.Naming/Video/StubResult.cs
  30. 1 0
      Emby.Naming/Video/StubTypeRule.cs
  31. 11 1
      Emby.Naming/Video/VideoFileInfo.cs
  32. 4 0
      Emby.Naming/Video/VideoInfo.cs
  33. 18 22
      Emby.Naming/Video/VideoListResolver.cs
  34. 7 5
      Emby.Naming/Video/VideoResolver.cs
  35. 2 2
      Emby.Server.Implementations/Emby.Server.Implementations.csproj
  36. 1 1
      Emby.Server.Implementations/Library/LibraryManager.cs
  37. 1 1
      Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs
  38. 1 3
      Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs
  39. 3 3
      Jellyfin.Server/Jellyfin.Server.csproj
  40. 5 1
      Jellyfin.Server/Program.cs
  41. 5 0
      jellyfin.ruleset

+ 14 - 12
Emby.Naming/Audio/AlbumParser.cs

@@ -33,27 +33,29 @@ namespace Emby.Naming.Audio
 
             // Normalize
             // Remove whitespace
-            filename = filename.Replace("-", " ");
-            filename = filename.Replace(".", " ");
-            filename = filename.Replace("(", " ");
-            filename = filename.Replace(")", " ");
+            filename = filename.Replace('-', ' ');
+            filename = filename.Replace('.', ' ');
+            filename = filename.Replace('(', ' ');
+            filename = filename.Replace(')', ' ');
             filename = Regex.Replace(filename, @"\s+", " ");
 
             filename = filename.TrimStart();
 
             foreach (var prefix in _options.AlbumStackingPrefixes)
             {
-                if (filename.IndexOf(prefix, StringComparison.OrdinalIgnoreCase) == 0)
+                if (filename.IndexOf(prefix, StringComparison.OrdinalIgnoreCase) != 0)
                 {
-                    var tmp = filename.Substring(prefix.Length);
+                    continue;
+                }
+
+                var tmp = filename.Substring(prefix.Length);
 
-                    tmp = tmp.Trim().Split(' ').FirstOrDefault() ?? string.Empty;
+                tmp = tmp.Trim().Split(' ').FirstOrDefault() ?? string.Empty;
 
-                    if (int.TryParse(tmp, NumberStyles.Integer, CultureInfo.InvariantCulture, out var val))
-                    {
-                        result.IsMultiPart = true;
-                        break;
-                    }
+                if (int.TryParse(tmp, NumberStyles.Integer, CultureInfo.InvariantCulture, out _))
+                {
+                    result.IsMultiPart = true;
+                    break;
                 }
             }
 

+ 2 - 0
Emby.Naming/Audio/MultiPartResult.cs

@@ -7,11 +7,13 @@ namespace Emby.Naming.Audio
         /// </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>

+ 25 - 4
Emby.Naming/AudioBook/AudioBookFileInfo.cs

@@ -12,35 +12,56 @@ namespace Emby.Naming.AudioBook
         /// </summary>
         /// <value>The path.</value>
         public string Path { get; set; }
+
         /// <summary>
         /// Gets or sets the container.
         /// </summary>
         /// <value>The container.</value>
         public string Container { get; set; }
+
         /// <summary>
         /// Gets or sets the part number.
         /// </summary>
         /// <value>The part number.</value>
         public int? PartNumber { get; set; }
+
         /// <summary>
         /// Gets or sets the chapter number.
         /// </summary>
         /// <value>The chapter number.</value>
         public int? ChapterNumber { get; set; }
+
         /// <summary>
         /// Gets or sets the type.
         /// </summary>
         /// <value>The type.</value>
         public bool IsDirectory { get; set; }
 
+        /// <inheritdoc/>
         public int CompareTo(AudioBookFileInfo other)
         {
-            if (ReferenceEquals(this, other)) return 0;
-            if (ReferenceEquals(null, other)) return 1;
+            if (ReferenceEquals(this, other))
+            {
+                return 0;
+            }
+
+            if (ReferenceEquals(null, other))
+            {
+                return 1;
+            }
+
             var chapterNumberComparison = Nullable.Compare(ChapterNumber, other.ChapterNumber);
-            if (chapterNumberComparison != 0) return chapterNumberComparison;
+            if (chapterNumberComparison != 0)
+            {
+                return chapterNumberComparison;
+            }
+
             var partNumberComparison = Nullable.Compare(PartNumber, other.PartNumber);
-            if (partNumberComparison != 0) return partNumberComparison;
+            if (partNumberComparison != 0)
+            {
+                return partNumberComparison;
+            }
+
             return string.Compare(Path, other.Path, StringComparison.Ordinal);
         }
     }

+ 7 - 6
Emby.Naming/AudioBook/AudioBookFilePathParser.cs

@@ -1,3 +1,4 @@
+using System;
 using System.Globalization;
 using System.IO;
 using System.Text.RegularExpressions;
@@ -14,14 +15,13 @@ namespace Emby.Naming.AudioBook
             _options = options;
         }
 
-        public AudioBookFilePathParserResult Parse(string path, bool IsDirectory)
+        public AudioBookFilePathParserResult Parse(string path)
         {
-            var result = Parse(path);
-            return !result.Success ? new AudioBookFilePathParserResult() : result;
-        }
+            if (path == null)
+            {
+                throw new ArgumentNullException(nameof(path));
+            }
 
-        private AudioBookFilePathParserResult Parse(string path)
-        {
             var result = new AudioBookFilePathParserResult();
             var fileName = Path.GetFileNameWithoutExtension(path);
             foreach (var expression in _options.AudioBookPartsExpressions)
@@ -40,6 +40,7 @@ namespace Emby.Naming.AudioBook
                             }
                         }
                     }
+
                     if (!result.PartNumber.HasValue)
                     {
                         var value = match.Groups["part"];

+ 2 - 0
Emby.Naming/AudioBook/AudioBookFilePathParserResult.cs

@@ -3,7 +3,9 @@ namespace Emby.Naming.AudioBook
     public class AudioBookFilePathParserResult
     {
         public int? PartNumber { get; set; }
+
         public int? ChapterNumber { get; set; }
+
         public bool Success { get; set; }
     }
 }

+ 14 - 7
Emby.Naming/AudioBook/AudioBookInfo.cs

@@ -7,33 +7,40 @@ namespace Emby.Naming.AudioBook
     /// </summary>
     public class AudioBookInfo
     {
+        public AudioBookInfo()
+        {
+            Files = new List<AudioBookFileInfo>();
+            Extras = new List<AudioBookFileInfo>();
+            AlternateVersions = new List<AudioBookFileInfo>();
+        }
+
         /// <summary>
         /// Gets or sets the name.
         /// </summary>
         /// <value>The name.</value>
         public string Name { get; set; }
+
+        /// <summary>
+        /// Gets or sets the year.
+        /// </summary>
         public int? Year { get; set; }
+
         /// <summary>
         /// Gets or sets the files.
         /// </summary>
         /// <value>The files.</value>
         public List<AudioBookFileInfo> Files { get; set; }
+
         /// <summary>
         /// Gets or sets the extras.
         /// </summary>
         /// <value>The extras.</value>
         public List<AudioBookFileInfo> Extras { get; set; }
+
         /// <summary>
         /// Gets or sets the alternate versions.
         /// </summary>
         /// <value>The alternate versions.</value>
         public List<AudioBookFileInfo> AlternateVersions { get; set; }
-
-        public AudioBookInfo()
-        {
-            Files = new List<AudioBookFileInfo>();
-            Extras = new List<AudioBookFileInfo>();
-            AlternateVersions = new List<AudioBookFileInfo>();
-        }
     }
 }

+ 1 - 1
Emby.Naming/AudioBook/AudioBookListResolver.cs

@@ -15,7 +15,7 @@ namespace Emby.Naming.AudioBook
             _options = options;
         }
 
-        public IEnumerable<AudioBookInfo> Resolve(List<FileSystemMetadata> files)
+        public IEnumerable<AudioBookInfo> Resolve(IEnumerable<FileSystemMetadata> files)
         {
             var audioBookResolver = new AudioBookResolver(_options);
 

+ 6 - 5
Emby.Naming/AudioBook/AudioBookResolver.cs

@@ -24,19 +24,21 @@ namespace Emby.Naming.AudioBook
             return Resolve(path, true);
         }
 
-        public AudioBookFileInfo Resolve(string path, bool IsDirectory = false)
+        public AudioBookFileInfo Resolve(string path, bool isDirectory = false)
         {
             if (string.IsNullOrEmpty(path))
             {
                 throw new ArgumentNullException(nameof(path));
             }
 
-            if (IsDirectory) // TODO
+            // TODO
+            if (isDirectory)
             {
                 return null;
             }
 
             var extension = Path.GetExtension(path);
+
             // Check supported extensions
             if (!_options.AudioFileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase))
             {
@@ -45,8 +47,7 @@ namespace Emby.Naming.AudioBook
 
             var container = extension.TrimStart('.');
 
-            var parsingResult = new AudioBookFilePathParser(_options)
-                .Parse(path, IsDirectory);
+            var parsingResult = new AudioBookFilePathParser(_options).Parse(path);
 
             return new AudioBookFileInfo
             {
@@ -54,7 +55,7 @@ namespace Emby.Naming.AudioBook
                 Container = container,
                 PartNumber = parsingResult.PartNumber,
                 ChapterNumber = parsingResult.ChapterNumber,
-                IsDirectory = IsDirectory
+                IsDirectory = isDirectory
             };
         }
     }

+ 14 - 3
Emby.Naming/Common/EpisodeExpression.cs

@@ -6,17 +6,28 @@ namespace Emby.Naming.Common
     public class EpisodeExpression
     {
         private string _expression;
-        public string Expression { get => _expression;
-            set { _expression = value; _regex = null; } }
+        private Regex _regex;
+
+        public string Expression
+        {
+            get => _expression;
+            set
+            {
+                _expression = value;
+                _regex = null;
+            }
+        }
 
         public bool IsByDate { get; set; }
+
         public bool IsOptimistic { get; set; }
+
         public bool IsNamed { get; set; }
+
         public bool SupportsAbsoluteEpisodeNumbers { get; set; }
 
         public string[] DateTimeFormats { get; set; }
 
-        private Regex _regex;
         public Regex Regex => _regex ?? (_regex = new Regex(Expression, RegexOptions.IgnoreCase | RegexOptions.Compiled));
 
         public EpisodeExpression(string expression, bool byDate)

+ 2 - 0
Emby.Naming/Common/MediaType.cs

@@ -6,10 +6,12 @@ namespace Emby.Naming.Common
         /// The audio
         /// </summary>
         Audio = 0,
+
         /// <summary>
         /// The photo
         /// </summary>
         Photo = 1,
+
         /// <summary>
         /// The video
         /// </summary>

+ 39 - 36
Emby.Naming/Common/NamingOptions.cs

@@ -8,19 +8,25 @@ 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; }
@@ -28,12 +34,14 @@ namespace Emby.Naming.Common
         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 string[] CleanStrings { get; set; }
 
         public EpisodeExpression[] MultipleEpisodeExpressions { get; set; }
 
@@ -41,7 +49,7 @@ namespace Emby.Naming.Common
 
         public NamingOptions()
         {
-            VideoFileExtensions = new string[]
+            VideoFileExtensions = new[]
             {
                 ".m4v",
                 ".3gp",
@@ -106,53 +114,53 @@ namespace Emby.Naming.Common
             {
                 new StubTypeRule
                 {
-                     StubType = "dvd",
-                     Token = "dvd"
+                    StubType = "dvd",
+                    Token = "dvd"
                 },
                 new StubTypeRule
                 {
-                     StubType = "hddvd",
-                     Token = "hddvd"
+                    StubType = "hddvd",
+                    Token = "hddvd"
                 },
                 new StubTypeRule
                 {
-                     StubType = "bluray",
-                     Token = "bluray"
+                    StubType = "bluray",
+                    Token = "bluray"
                 },
                 new StubTypeRule
                 {
-                     StubType = "bluray",
-                     Token = "brrip"
+                    StubType = "bluray",
+                    Token = "brrip"
                 },
                 new StubTypeRule
                 {
-                     StubType = "bluray",
-                     Token = "bd25"
+                    StubType = "bluray",
+                    Token = "bd25"
                 },
                 new StubTypeRule
                 {
-                     StubType = "bluray",
-                     Token = "bd50"
+                    StubType = "bluray",
+                    Token = "bd50"
                 },
                 new StubTypeRule
                 {
-                     StubType = "vhs",
-                     Token = "vhs"
+                    StubType = "vhs",
+                    Token = "vhs"
                 },
                 new StubTypeRule
                 {
-                     StubType = "tv",
-                     Token = "HDTV"
+                    StubType = "tv",
+                    Token = "HDTV"
                 },
                 new StubTypeRule
                 {
-                     StubType = "tv",
-                     Token = "PDTV"
+                    StubType = "tv",
+                    Token = "PDTV"
                 },
                 new StubTypeRule
                 {
-                     StubType = "tv",
-                     Token = "DSR"
+                    StubType = "tv",
+                    Token = "DSR"
                 }
             };
 
@@ -286,7 +294,7 @@ namespace Emby.Naming.Common
                 new EpisodeExpression(@"[\._ -]()[Ee][Pp]_?([0-9]+)([^\\/]*)$"),
                 new EpisodeExpression("([0-9]{4})[\\.-]([0-9]{2})[\\.-]([0-9]{2})", true)
                 {
-                    DateTimeFormats = new []
+                    DateTimeFormats = new[]
                     {
                         "yyyy.MM.dd",
                         "yyyy-MM-dd",
@@ -295,7 +303,7 @@ namespace Emby.Naming.Common
                 },
                 new EpisodeExpression("([0-9]{2})[\\.-]([0-9]{2})[\\.-]([0-9]{4})", true)
                 {
-                    DateTimeFormats = new []
+                    DateTimeFormats = new[]
                     {
                         "dd.MM.yyyy",
                         "dd-MM-yyyy",
@@ -348,9 +356,7 @@ namespace Emby.Naming.Common
                 },
 
                 // "1-12 episode title"
-                new EpisodeExpression(@"([0-9]+)-([0-9]+)")
-                {
-                },
+                new EpisodeExpression(@"([0-9]+)-([0-9]+)"),
 
                 // "01 - blah.avi", "01-blah.avi"
                 new EpisodeExpression(@".*(\\|\/)(?<epnumber>\d{1,3})(-(?<endingepnumber>\d{2,3}))*\s?-\s?[^\\\/]*$")
@@ -427,7 +433,7 @@ namespace Emby.Naming.Common
                     Token = "_trailer",
                     MediaType = MediaType.Video
                 },
-                 new ExtraRule
+                new ExtraRule
                 {
                     ExtraType = "trailer",
                     RuleType = ExtraRuleType.Suffix,
@@ -462,7 +468,7 @@ namespace Emby.Naming.Common
                     Token = "_sample",
                     MediaType = MediaType.Video
                 },
-                 new ExtraRule
+                new ExtraRule
                 {
                     ExtraType = "sample",
                     RuleType = ExtraRuleType.Suffix,
@@ -476,7 +482,6 @@ namespace Emby.Naming.Common
                     Token = "theme",
                     MediaType = MediaType.Audio
                 },
-
                 new ExtraRule
                 {
                     ExtraType = "scene",
@@ -526,8 +531,8 @@ namespace Emby.Naming.Common
                     Token = "-short",
                     MediaType = MediaType.Video
                 }
-
             };
+
             Format3DRules = new[]
             {
                 // Kodi rules:
@@ -648,12 +653,10 @@ namespace Emby.Naming.Common
                 @".*(\\|\/)(?<seriesname>((?![sS]?\d{1,4}[xX]\d{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3}))(-[xX]?[eE]?(?<endingepnumber>\d{1,3}))+[^\\\/]*$",
                 @".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>\d{1,4})[xX\.]?[eE](?<epnumber>\d{1,3})((-| - )?[xXeE](?<endingepnumber>\d{1,3}))+[^\\\/]*$",
                 @".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>\d{1,4})[xX\.]?[eE](?<epnumber>\d{1,3})(-[xX]?[eE]?(?<endingepnumber>\d{1,3}))+[^\\\/]*$"
-
             }.Select(i => new EpisodeExpression(i)
-            {
-                IsNamed = true
-
-            }).ToArray();
+                {
+                    IsNamed = true
+                }).ToArray();
 
             VideoFileExtensions = extensions
                 .Distinct(StringComparer.OrdinalIgnoreCase)

+ 17 - 1
Emby.Naming/Emby.Naming.csproj

@@ -1,4 +1,4 @@
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
     <TargetFramework>netstandard2.0</TargetFramework>
@@ -18,6 +18,22 @@
     <PackageId>Jellyfin.Naming</PackageId>
     <PackageLicenseUrl>https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt</PackageLicenseUrl>
     <RepositoryUrl>https://github.com/jellyfin/jellyfin</RepositoryUrl>
+    <GenerateDocumentationFile>true</GenerateDocumentationFile>
+  </PropertyGroup>
+
+  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
+    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+  </PropertyGroup>
+
+  <!-- Code analysers-->
+  <ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+    <PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.2" />
+    <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" />
+    <PackageReference Include="SerilogAnalyzer" Version="0.15.0" />
+  </ItemGroup>
+
+  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
+    <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet>
   </PropertyGroup>
 
 </Project>

+ 1 - 0
Emby.Naming/Extensions/StringExtensions.cs

@@ -5,6 +5,7 @@ namespace Emby.Naming.Extensions
 {
     public static class StringExtensions
     {
+        // TODO: @bond remove this when moving to netstandard2.1
         public static string Replace(this string str, string oldValue, string newValue, StringComparison comparison)
         {
             var sb = new StringBuilder();

+ 0 - 30
Emby.Naming/StringExtensions.cs

@@ -1,30 +0,0 @@
-using System;
-using System.Text;
-
-namespace Emby.Naming
-{
-    internal static class StringExtensions
-    {
-        public static string Replace(this string str, string oldValue, string newValue, StringComparison comparison)
-        {
-            var sb = new StringBuilder();
-
-            var previousIndex = 0;
-            var index = str.IndexOf(oldValue, comparison);
-
-            while (index != -1)
-            {
-                sb.Append(str.Substring(previousIndex, index - previousIndex));
-                sb.Append(newValue);
-                index += oldValue.Length;
-
-                previousIndex = index;
-                index = str.IndexOf(oldValue, index, comparison);
-            }
-
-            sb.Append(str.Substring(previousIndex));
-
-            return sb.ToString();
-        }
-    }
-}

+ 3 - 0
Emby.Naming/Subtitles/SubtitleInfo.cs

@@ -7,16 +7,19 @@ namespace Emby.Naming.Subtitles
         /// </summary>
         /// <value>The path.</value>
         public string Path { get; set; }
+
         /// <summary>
         /// Gets or sets the language.
         /// </summary>
         /// <value>The language.</value>
         public string Language { get; set; }
+
         /// <summary>
         /// Gets or sets a value indicating whether this instance is default.
         /// </summary>
         /// <value><c>true</c> if this instance is default; otherwise, <c>false</c>.</value>
         public bool IsDefault { get; set; }
+
         /// <summary>
         /// Gets or sets a value indicating whether this instance is forced.
         /// </summary>

+ 11 - 0
Emby.Naming/TV/EpisodeInfo.cs

@@ -7,31 +7,37 @@ namespace Emby.Naming.TV
         /// </summary>
         /// <value>The path.</value>
         public string Path { get; set; }
+
         /// <summary>
         /// Gets or sets the container.
         /// </summary>
         /// <value>The container.</value>
         public string Container { get; set; }
+
         /// <summary>
         /// Gets or sets the name of the series.
         /// </summary>
         /// <value>The name of the series.</value>
         public string SeriesName { get; set; }
+
         /// <summary>
         /// Gets or sets the format3 d.
         /// </summary>
         /// <value>The format3 d.</value>
         public string Format3D { get; set; }
+
         /// <summary>
         /// Gets or sets a value indicating whether [is3 d].
         /// </summary>
         /// <value><c>true</c> if [is3 d]; otherwise, <c>false</c>.</value>
         public bool Is3D { get; set; }
+
         /// <summary>
         /// Gets or sets a value indicating whether this instance is stub.
         /// </summary>
         /// <value><c>true</c> if this instance is stub; otherwise, <c>false</c>.</value>
         public bool IsStub { get; set; }
+
         /// <summary>
         /// Gets or sets the type of the stub.
         /// </summary>
@@ -39,12 +45,17 @@ namespace Emby.Naming.TV
         public string StubType { get; set; }
 
         public int? SeasonNumber { get; set; }
+
         public int? EpisodeNumber { get; set; }
+
         public int? EndingEpsiodeNumber { get; set; }
 
         public int? Year { get; set; }
+
         public int? Month { get; set; }
+
         public int? Day { get; set; }
+
         public bool IsByDate { get; set; }
     }
 }

+ 24 - 28
Emby.Naming/TV/EpisodePathParser.cs

@@ -15,12 +15,12 @@ namespace Emby.Naming.TV
             _options = options;
         }
 
-        public EpisodePathParserResult Parse(string path, bool IsDirectory, bool? isNamed = null, bool? isOptimistic = null, bool? supportsAbsoluteNumbers = null, bool fillExtendedInfo = true)
+        public EpisodePathParserResult Parse(string path, bool isDirectory, bool? isNamed = null, bool? isOptimistic = null, bool? supportsAbsoluteNumbers = null, bool fillExtendedInfo = true)
         {
             // Added to be able to use regex patterns which require a file extension.
             // There were no failed tests without this block, but to be safe, we can keep it until
             // the regex which require file extensions are modified so that they don't need them.
-            if (IsDirectory)
+            if (isDirectory)
             {
                 path += ".mp4";
             }
@@ -29,28 +29,20 @@ namespace Emby.Naming.TV
 
             foreach (var expression in _options.EpisodeExpressions)
             {
-                if (supportsAbsoluteNumbers.HasValue)
+                if (supportsAbsoluteNumbers.HasValue
+                    && expression.SupportsAbsoluteEpisodeNumbers != supportsAbsoluteNumbers.Value)
                 {
-                    if (expression.SupportsAbsoluteEpisodeNumbers != supportsAbsoluteNumbers.Value)
-                    {
-                        continue;
-                    }
+                    continue;
                 }
 
-                if (isNamed.HasValue)
+                if (isNamed.HasValue && expression.IsNamed != isNamed.Value)
                 {
-                    if (expression.IsNamed != isNamed.Value)
-                    {
-                        continue;
-                    }
+                    continue;
                 }
 
-                if (isOptimistic.HasValue)
+                if (isOptimistic.HasValue && expression.IsOptimistic != isOptimistic.Value)
                 {
-                    if (expression.IsOptimistic != isOptimistic.Value)
-                    {
-                        continue;
-                    }
+                    continue;
                 }
 
                 var currentResult = Parse(path, expression);
@@ -97,7 +89,8 @@ namespace Emby.Naming.TV
                     DateTime date;
                     if (expression.DateTimeFormats.Length > 0)
                     {
-                        if (DateTime.TryParseExact(match.Groups[0].Value,
+                        if (DateTime.TryParseExact(
+                            match.Groups[0].Value,
                             expression.DateTimeFormats,
                             CultureInfo.InvariantCulture,
                             DateTimeStyles.None,
@@ -109,17 +102,15 @@ namespace Emby.Naming.TV
                             result.Success = true;
                         }
                     }
-                    else
+                    else if (DateTime.TryParse(match.Groups[0].Value, out date))
                     {
-                        if (DateTime.TryParse(match.Groups[0].Value, out date))
-                        {
-                            result.Year = date.Year;
-                            result.Month = date.Month;
-                            result.Day = date.Day;
-                            result.Success = true;
-                        }
+                        result.Year = date.Year;
+                        result.Month = date.Month;
+                        result.Day = date.Day;
+                        result.Success = true;
                     }
 
+
                     // TODO: Only consider success if date successfully parsed?
                     result.Success = true;
                 }
@@ -142,7 +133,8 @@ namespace Emby.Naming.TV
                         // or a 'p' or 'i' as what you would get with a pixel resolution specification.
                         // 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)
+                        if (nextIndex >= name.Length
+                            || "0123456789iIpP".IndexOf(name[nextIndex]) == -1)
                         {
                             if (int.TryParse(endingNumberGroup.Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out num))
                             {
@@ -160,6 +152,7 @@ namespace Emby.Naming.TV
                     {
                         result.SeasonNumber = num;
                     }
+
                     if (int.TryParse(match.Groups[2].Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out num))
                     {
                         result.EpisodeNumber = num;
@@ -171,8 +164,11 @@ namespace Emby.Naming.TV
                 // Invalidate match when the season is 200 through 1927 or above 2500
                 // because it is an error unless the TV show is intentionally using false season numbers.
                 // It avoids erroneous parsing of something like "Series Special (1920x1080).mkv" as being season 1920 episode 1080.
-                if (result.SeasonNumber >= 200 && result.SeasonNumber < 1928 || result.SeasonNumber > 2500)
+                if ((result.SeasonNumber >= 200 && result.SeasonNumber < 1928)
+                    || result.SeasonNumber > 2500)
+                {
                     result.Success = false;
+                }
 
                 result.IsByDate = expression.IsByDate;
             }

+ 7 - 0
Emby.Naming/TV/EpisodePathParserResult.cs

@@ -3,14 +3,21 @@ namespace Emby.Naming.TV
     public class EpisodePathParserResult
     {
         public int? SeasonNumber { get; set; }
+
         public int? EpisodeNumber { get; set; }
+
         public int? EndingEpsiodeNumber { get; set; }
+
         public string SeriesName { get; set; }
+
         public bool Success { get; set; }
 
         public bool IsByDate { get; set; }
+
         public int? Year { get; set; }
+
         public int? Month { get; set; }
+
         public int? Day { get; set; }
     }
 }

+ 9 - 3
Emby.Naming/TV/EpisodeResolver.cs

@@ -15,7 +15,13 @@ namespace Emby.Naming.TV
             _options = options;
         }
 
-        public EpisodeInfo Resolve(string path, bool IsDirectory, bool? isNamed = null, bool? isOptimistic = null, bool? supportsAbsoluteNumbers = null, bool fillExtendedInfo = true)
+        public EpisodeInfo Resolve(
+            string path,
+            bool isDirectory,
+            bool? isNamed = null,
+            bool? isOptimistic = null,
+            bool? supportsAbsoluteNumbers = null,
+            bool fillExtendedInfo = true)
         {
             if (string.IsNullOrEmpty(path))
             {
@@ -26,7 +32,7 @@ namespace Emby.Naming.TV
             string container = null;
             string stubType = null;
 
-            if (!IsDirectory)
+            if (!isDirectory)
             {
                 var extension = Path.GetExtension(path);
                 // Check supported extensions
@@ -52,7 +58,7 @@ namespace Emby.Naming.TV
             var format3DResult = new Format3DParser(_options).Parse(flags);
 
             var parsingResult = new EpisodePathParser(_options)
-                .Parse(path, IsDirectory, isNamed, isOptimistic, supportsAbsoluteNumbers, fillExtendedInfo);
+                .Parse(path, isDirectory, isNamed, isOptimistic, supportsAbsoluteNumbers, fillExtendedInfo);
 
             return new EpisodeInfo
             {

+ 20 - 22
Emby.Naming/TV/SeasonPathParser.cs

@@ -3,30 +3,24 @@ using System.Globalization;
 using System.IO;
 using System.Linq;
 using Emby.Naming.Common;
+using Emby.Naming.Extensions;
 
 namespace Emby.Naming.TV
 {
     public class SeasonPathParser
     {
-        private readonly NamingOptions _options;
-
-        public SeasonPathParser(NamingOptions options)
-        {
-            _options = options;
-        }
-
         public SeasonPathParserResult Parse(string path, bool supportSpecialAliases, bool supportNumericSeasonFolders)
         {
             var result = new SeasonPathParserResult();
 
             var seasonNumberInfo = GetSeasonNumberFromPath(path, supportSpecialAliases, supportNumericSeasonFolders);
 
-            result.SeasonNumber = seasonNumberInfo.Item1;
+            result.SeasonNumber = seasonNumberInfo.seasonNumber;
 
             if (result.SeasonNumber.HasValue)
             {
                 result.Success = true;
-                result.IsSeasonFolder = seasonNumberInfo.Item2;
+                result.IsSeasonFolder = seasonNumberInfo.isSeasonFolder;
             }
 
             return result;
@@ -35,7 +29,7 @@ namespace Emby.Naming.TV
         /// <summary>
         /// A season folder must contain one of these somewhere in the name
         /// </summary>
-        private static readonly string[] SeasonFolderNames =
+        private static readonly string[] _seasonFolderNames =
         {
             "season",
             "sæson",
@@ -54,19 +48,23 @@ namespace Emby.Naming.TV
         /// <param name="supportSpecialAliases">if set to <c>true</c> [support special aliases].</param>
         /// <param name="supportNumericSeasonFolders">if set to <c>true</c> [support numeric season folders].</param>
         /// <returns>System.Nullable{System.Int32}.</returns>
-        private Tuple<int?, bool> GetSeasonNumberFromPath(string path, bool supportSpecialAliases, bool supportNumericSeasonFolders)
+        private static (int? seasonNumber, bool isSeasonFolder) GetSeasonNumberFromPath(
+            string path,
+            bool supportSpecialAliases,
+            bool supportNumericSeasonFolders)
         {
-            var filename = Path.GetFileName(path);
+            var filename = Path.GetFileName(path) ?? string.Empty;
 
             if (supportSpecialAliases)
             {
                 if (string.Equals(filename, "specials", StringComparison.OrdinalIgnoreCase))
                 {
-                    return new Tuple<int?, bool>(0, true);
+                    return (0, true);
                 }
+
                 if (string.Equals(filename, "extras", StringComparison.OrdinalIgnoreCase))
                 {
-                    return new Tuple<int?, bool>(0, true);
+                    return (0, true);
                 }
             }
 
@@ -74,7 +72,7 @@ namespace Emby.Naming.TV
             {
                 if (int.TryParse(filename, NumberStyles.Integer, CultureInfo.InvariantCulture, out var val))
                 {
-                    return new Tuple<int?, bool>(val, true);
+                    return (val, true);
                 }
             }
 
@@ -84,12 +82,12 @@ namespace Emby.Naming.TV
 
                 if (int.TryParse(testFilename, NumberStyles.Integer, CultureInfo.InvariantCulture, out var val))
                 {
-                    return new Tuple<int?, bool>(val, true);
+                    return (val, true);
                 }
             }
 
             // Look for one of the season folder names
-            foreach (var name in SeasonFolderNames)
+            foreach (var name in _seasonFolderNames)
             {
                 var index = filename.IndexOf(name, StringComparison.OrdinalIgnoreCase);
 
@@ -107,10 +105,10 @@ namespace Emby.Naming.TV
 
             var parts = filename.Split(new[] { '.', '_', ' ', '-' }, StringSplitOptions.RemoveEmptyEntries);
             var resultNumber = parts.Select(GetSeasonNumberFromPart).FirstOrDefault(i => i.HasValue);
-            return new Tuple<int?, bool>(resultNumber, true);
+            return (resultNumber, true);
         }
 
-        private int? GetSeasonNumberFromPart(string part)
+        private static int? GetSeasonNumberFromPart(string part)
         {
             if (part.Length < 2 || !part.StartsWith("s", StringComparison.OrdinalIgnoreCase))
             {
@@ -132,7 +130,7 @@ namespace Emby.Naming.TV
         /// </summary>
         /// <param name="path">The path.</param>
         /// <returns>System.Nullable{System.Int32}.</returns>
-        private Tuple<int?, bool> GetSeasonNumberFromPathSubstring(string path)
+        private static (int? seasonNumber, bool isSeasonFolder) GetSeasonNumberFromPathSubstring(string path)
         {
             var numericStart = -1;
             var length = 0;
@@ -174,10 +172,10 @@ namespace Emby.Naming.TV
 
             if (numericStart == -1)
             {
-                return new Tuple<int?, bool>(null, isSeasonFolder);
+                return (null, isSeasonFolder);
             }
 
-            return new Tuple<int?, bool>(int.Parse(path.Substring(numericStart, length), CultureInfo.InvariantCulture), isSeasonFolder);
+            return (int.Parse(path.Substring(numericStart, length), CultureInfo.InvariantCulture), isSeasonFolder);
         }
     }
 }

+ 2 - 0
Emby.Naming/TV/SeasonPathParserResult.cs

@@ -7,11 +7,13 @@ namespace Emby.Naming.TV
         /// </summary>
         /// <value>The season number.</value>
         public int? SeasonNumber { get; set; }
+
         /// <summary>
         /// Gets or sets a value indicating whether this <see cref="SeasonPathParserResult"/> is success.
         /// </summary>
         /// <value><c>true</c> if success; otherwise, <c>false</c>.</value>
         public bool Success { get; set; }
+
         public bool IsSeasonFolder { get; set; }
     }
 }

+ 10 - 10
Emby.Naming/Video/CleanDateTimeParser.cs

@@ -27,8 +27,8 @@ namespace Emby.Naming.Video
             {
                 var extension = Path.GetExtension(name) ?? string.Empty;
                 // Check supported extensions
-                if (!_options.VideoFileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase) &&
-                    !_options.AudioFileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase))
+                if (!_options.VideoFileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase)
+                    && !_options.AudioFileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase))
                 {
                     // Dummy up a file extension because the expressions will fail without one
                     // This is tricky because we can't just check Path.GetExtension for empty
@@ -38,7 +38,6 @@ namespace Emby.Naming.Video
             }
             catch (ArgumentException)
             {
-
             }
 
             var result = _options.CleanDateTimeRegexes.Select(i => Clean(name, i))
@@ -69,14 +68,15 @@ namespace Emby.Naming.Video
 
             var match = expression.Match(name);
 
-            if (match.Success && match.Groups.Count == 4)
+            if (match.Success
+                && match.Groups.Count == 4
+                && match.Groups[1].Success
+                && match.Groups[2].Success
+                && int.TryParse(match.Groups[2].Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var year))
             {
-                if (match.Groups[1].Success && match.Groups[2].Success && int.TryParse(match.Groups[2].Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var year))
-                {
-                    name = match.Groups[1].Value;
-                    result.Year = year;
-                    result.HasChanged = true;
-                }
+                name = match.Groups[1].Value;
+                result.Year = year;
+                result.HasChanged = true;
             }
 
             result.Name = name;

+ 0 - 2
Emby.Naming/Video/ExtraResolver.cs

@@ -56,7 +56,6 @@ namespace Emby.Naming.Video
                     result.Rule = rule;
                 }
             }
-
             else if (rule.RuleType == ExtraRuleType.Suffix)
             {
                 var filename = Path.GetFileNameWithoutExtension(path);
@@ -67,7 +66,6 @@ namespace Emby.Naming.Video
                     result.Rule = rule;
                 }
             }
-
             else if (rule.RuleType == ExtraRuleType.Regex)
             {
                 var filename = Path.GetFileName(path);

+ 2 - 2
Emby.Naming/Video/FileStack.cs

@@ -15,9 +15,9 @@ namespace Emby.Naming.Video
             Files = new List<string>();
         }
 
-        public bool ContainsFile(string file, bool IsDirectory)
+        public bool ContainsFile(string file, bool isDirectory)
         {
-            if (IsDirectoryStack == IsDirectory)
+            if (IsDirectoryStack == isDirectory)
             {
                 return Files.Contains(file, StringComparer.OrdinalIgnoreCase);
             }

+ 7 - 3
Emby.Naming/Video/Format3DParser.cs

@@ -15,10 +15,12 @@ namespace Emby.Naming.Video
 
         public Format3DResult Parse(string path)
         {
-            var delimeters = _options.VideoFlagDelimiters.ToList();
-            delimeters.Add(' ');
+            int oldLen = _options.VideoFlagDelimiters.Length;
+            var delimeters = new char[oldLen + 1];
+            _options.VideoFlagDelimiters.CopyTo(delimeters, 0);
+            delimeters[oldLen] = ' ';
 
-            return Parse(new FlagParser(_options).GetFlags(path, delimeters.ToArray()));
+            return Parse(new FlagParser(_options).GetFlags(path, delimeters));
         }
 
         internal Format3DResult Parse(string[] videoFlags)
@@ -66,8 +68,10 @@ namespace Emby.Naming.Video
                             format = flag;
                             result.Tokens.Add(rule.Token);
                         }
+
                         break;
                     }
+
                     foundPrefix = string.Equals(flag, rule.PreceedingToken, StringComparison.OrdinalIgnoreCase);
                 }
 

+ 7 - 5
Emby.Naming/Video/Format3DResult.cs

@@ -4,25 +4,27 @@ namespace Emby.Naming.Video
 {
     public class Format3DResult
     {
+        public Format3DResult()
+        {
+            Tokens = new List<string>();
+        }
+
         /// <summary>
         /// Gets or sets a value indicating whether [is3 d].
         /// </summary>
         /// <value><c>true</c> if [is3 d]; otherwise, <c>false</c>.</value>
         public bool Is3D { get; set; }
+
         /// <summary>
         /// Gets or sets the format3 d.
         /// </summary>
         /// <value>The format3 d.</value>
         public string Format3D { get; set; }
+
         /// <summary>
         /// Gets or sets the tokens.
         /// </summary>
         /// <value>The tokens.</value>
         public List<string> Tokens { get; set; }
-
-        public Format3DResult()
-        {
-            Tokens = new List<string>();
-        }
     }
 }

+ 13 - 6
Emby.Naming/Video/StackResolver.cs

@@ -40,17 +40,24 @@ namespace Emby.Naming.Video
             var result = new StackResult();
             foreach (var directory in files.GroupBy(file => file.IsDirectory ? file.FullName : Path.GetDirectoryName(file.FullName)))
             {
-                var stack = new FileStack();
-                stack.Name = Path.GetFileName(directory.Key);
-                stack.IsDirectoryStack = false;
+                var stack = new FileStack()
+                {
+                    Name = Path.GetFileName(directory.Key),
+                    IsDirectoryStack = false
+                };
                 foreach (var file in directory)
                 {
                     if (file.IsDirectory)
+                    {
                         continue;
+                    }
+
                     stack.Files.Add(file.FullName);
                 }
+
                 result.Stacks.Add(stack);
             }
+
             return result;
         }
 
@@ -114,16 +121,16 @@ namespace Emby.Naming.Video
                                 {
                                     if (!string.Equals(volume1, volume2, StringComparison.OrdinalIgnoreCase))
                                     {
-                                        if (string.Equals(ignore1, ignore2, StringComparison.OrdinalIgnoreCase) &&
-                                            string.Equals(extension1, extension2, StringComparison.OrdinalIgnoreCase))
+                                        if (string.Equals(ignore1, ignore2, StringComparison.OrdinalIgnoreCase)
+                                            && string.Equals(extension1, extension2, StringComparison.OrdinalIgnoreCase))
                                         {
                                             if (stack.Files.Count == 0)
                                             {
                                                 stack.Name = title1 + ignore1;
                                                 stack.IsDirectoryStack = file1.IsDirectory;
-                                                //stack.Name = title1 + ignore1 + extension1;
                                                 stack.Files.Add(file1.FullName);
                                             }
+
                                             stack.Files.Add(file2.FullName);
                                         }
                                         else

+ 20 - 12
Emby.Naming/Video/StubResolver.cs

@@ -9,24 +9,32 @@ namespace Emby.Naming.Video
     {
         public static StubResult ResolveFile(string path, NamingOptions options)
         {
-            var result = new StubResult();
-            var extension = Path.GetExtension(path) ?? string.Empty;
+            if (path == null)
+            {
+                return default(StubResult);
+            }
+
+            var extension = Path.GetExtension(path);
 
-            if (options.StubFileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase))
+            if (!options.StubFileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase))
             {
-                result.IsStub = true;
+                return default(StubResult);
+            }
 
-                path = Path.GetFileNameWithoutExtension(path);
+            var result = new StubResult()
+            {
+                IsStub = true
+            };
 
-                var token = (Path.GetExtension(path) ?? string.Empty).TrimStart('.');
+            path = Path.GetFileNameWithoutExtension(path);
+            var token = Path.GetExtension(path).TrimStart('.');
 
-                foreach (var rule in options.StubTypes)
+            foreach (var rule in options.StubTypes)
+            {
+                if (string.Equals(rule.Token, token, StringComparison.OrdinalIgnoreCase))
                 {
-                    if (string.Equals(rule.Token, token, StringComparison.OrdinalIgnoreCase))
-                    {
-                        result.StubType = rule.StubType;
-                        break;
-                    }
+                    result.StubType = rule.StubType;
+                    break;
                 }
             }
 

+ 1 - 0
Emby.Naming/Video/StubResult.cs

@@ -7,6 +7,7 @@ namespace Emby.Naming.Video
         /// </summary>
         /// <value><c>true</c> if this instance is stub; otherwise, <c>false</c>.</value>
         public bool IsStub { get; set; }
+
         /// <summary>
         /// Gets or sets the type of the stub.
         /// </summary>

+ 1 - 0
Emby.Naming/Video/StubTypeRule.cs

@@ -7,6 +7,7 @@ namespace Emby.Naming.Video
         /// </summary>
         /// <value>The token.</value>
         public string Token { get; set; }
+
         /// <summary>
         /// Gets or sets the type of the stub.
         /// </summary>

+ 11 - 1
Emby.Naming/Video/VideoFileInfo.cs

@@ -1,4 +1,3 @@
-
 namespace Emby.Naming.Video
 {
     /// <summary>
@@ -11,56 +10,67 @@ namespace Emby.Naming.Video
         /// </summary>
         /// <value>The path.</value>
         public string Path { get; set; }
+
         /// <summary>
         /// Gets or sets the container.
         /// </summary>
         /// <value>The container.</value>
         public string Container { get; set; }
+
         /// <summary>
         /// Gets or sets the name.
         /// </summary>
         /// <value>The name.</value>
         public string Name { get; set; }
+
         /// <summary>
         /// Gets or sets the year.
         /// </summary>
         /// <value>The year.</value>
         public int? Year { get; set; }
+
         /// <summary>
         /// Gets or sets the type of the extra, e.g. trailer, theme song, behing the scenes, etc.
         /// </summary>
         /// <value>The type of the extra.</value>
         public string ExtraType { get; set; }
+
         /// <summary>
         /// Gets or sets the extra rule.
         /// </summary>
         /// <value>The extra rule.</value>
         public ExtraRule ExtraRule { get; set; }
+
         /// <summary>
         /// Gets or sets the format3 d.
         /// </summary>
         /// <value>The format3 d.</value>
         public string Format3D { get; set; }
+
         /// <summary>
         /// Gets or sets a value indicating whether [is3 d].
         /// </summary>
         /// <value><c>true</c> if [is3 d]; otherwise, <c>false</c>.</value>
         public bool Is3D { get; set; }
+
         /// <summary>
         /// Gets or sets a value indicating whether this instance is stub.
         /// </summary>
         /// <value><c>true</c> if this instance is stub; otherwise, <c>false</c>.</value>
         public bool IsStub { get; set; }
+
         /// <summary>
         /// Gets or sets the type of the stub.
         /// </summary>
         /// <value>The type of the stub.</value>
         public string StubType { get; set; }
+
         /// <summary>
         /// Gets or sets the type.
         /// </summary>
         /// <value>The type.</value>
         public bool IsDirectory { get; set; }
+
         /// <summary>
         /// Gets the file name without extension.
         /// </summary>

+ 4 - 0
Emby.Naming/Video/VideoInfo.cs

@@ -12,21 +12,25 @@ namespace Emby.Naming.Video
         /// </summary>
         /// <value>The name.</value>
         public string Name { get; set; }
+
         /// <summary>
         /// Gets or sets the year.
         /// </summary>
         /// <value>The year.</value>
         public int? Year { get; set; }
+
         /// <summary>
         /// Gets or sets the files.
         /// </summary>
         /// <value>The files.</value>
         public List<VideoFileInfo> Files { get; set; }
+
         /// <summary>
         /// Gets or sets the extras.
         /// </summary>
         /// <value>The extras.</value>
         public List<VideoFileInfo> Extras { get; set; }
+
         /// <summary>
         /// Gets or sets the alternate versions.
         /// </summary>

+ 18 - 22
Emby.Naming/Video/VideoListResolver.cs

@@ -53,7 +53,7 @@ namespace Emby.Naming.Video
                     Name = stack.Name
                 };
 
-                info.Year = info.Files.First().Year;
+                info.Year = info.Files[0].Year;
 
                 var extraBaseNames = new List<string>
                 {
@@ -87,7 +87,7 @@ namespace Emby.Naming.Video
                     Name = media.Name
                 };
 
-                info.Year = info.Files.First().Year;
+                info.Year = info.Files[0].Year;
 
                 var extras = GetExtras(remainingFiles, new List<string> { media.FileNameWithoutExtension });
 
@@ -115,7 +115,7 @@ namespace Emby.Naming.Video
 
                 if (!string.IsNullOrEmpty(parentPath))
                 {
-                    var folderName = Path.GetFileName(Path.GetDirectoryName(videoPath));
+                    var folderName = Path.GetFileName(parentPath);
                     if (!string.IsNullOrEmpty(folderName))
                     {
                         var extras = GetExtras(remainingFiles, new List<string> { folderName });
@@ -163,9 +163,7 @@ namespace Emby.Naming.Video
                 Year = i.Year
             }));
 
-            var orderedList = list.OrderBy(i => i.Name);
-
-            return orderedList;
+            return list.OrderBy(i => i.Name);
         }
 
         private IEnumerable<VideoInfo> GetVideosGroupedByVersion(List<VideoInfo> videos)
@@ -179,23 +177,21 @@ namespace Emby.Naming.Video
 
             var folderName = Path.GetFileName(Path.GetDirectoryName(videos[0].Files[0].Path));
 
-            if (!string.IsNullOrEmpty(folderName) && folderName.Length > 1)
+            if (!string.IsNullOrEmpty(folderName)
+                && folderName.Length > 1
+                && videos.All(i => i.Files.Count == 1
+                && IsEligibleForMultiVersion(folderName, i.Files[0].Path))
+                && HaveSameYear(videos))
             {
-                if (videos.All(i => i.Files.Count == 1 && IsEligibleForMultiVersion(folderName, i.Files[0].Path)))
-                {
-                    if (HaveSameYear(videos))
-                    {
-                        var ordered = videos.OrderBy(i => i.Name).ToList();
+                var ordered = videos.OrderBy(i => i.Name).ToList();
 
-                        list.Add(ordered[0]);
+                list.Add(ordered[0]);
 
-                        list[0].AlternateVersions = ordered.Skip(1).Select(i => i.Files[0]).ToList();
-                        list[0].Name = folderName;
-                        list[0].Extras.AddRange(ordered.Skip(1).SelectMany(i => i.Extras));
+                list[0].AlternateVersions = ordered.Skip(1).Select(i => i.Files[0]).ToList();
+                list[0].Name = folderName;
+                list[0].Extras.AddRange(ordered.Skip(1).SelectMany(i => i.Extras));
 
-                        return list;
-                    }
-                }
+                return list;
             }
 
             return videos;
@@ -213,9 +209,9 @@ namespace Emby.Naming.Video
             if (testFilename.StartsWith(folderName, StringComparison.OrdinalIgnoreCase))
             {
                 testFilename = testFilename.Substring(folderName.Length).Trim();
-                return string.IsNullOrEmpty(testFilename) ||
-                       testFilename.StartsWith("-") ||
-                       string.IsNullOrWhiteSpace(Regex.Replace(testFilename, @"\[([^]]*)\]", string.Empty)) ;
+                return string.IsNullOrEmpty(testFilename)
+                    || testFilename[0] == '-'
+                    || string.IsNullOrWhiteSpace(Regex.Replace(testFilename, @"\[([^]]*)\]", string.Empty));
             }
 
             return false;

+ 7 - 5
Emby.Naming/Video/VideoResolver.cs

@@ -38,10 +38,11 @@ namespace Emby.Naming.Video
         /// Resolves the specified path.
         /// </summary>
         /// <param name="path">The path.</param>
-        /// <param name="IsDirectory">if set to <c>true</c> [is folder].</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>
         /// <returns>VideoFileInfo.</returns>
         /// <exception cref="ArgumentNullException">path</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))
             {
@@ -52,9 +53,10 @@ namespace Emby.Naming.Video
             string container = null;
             string stubType = null;
 
-            if (!IsDirectory)
+            if (!isDirectory)
             {
                 var extension = Path.GetExtension(path);
+
                 // Check supported extensions
                 if (!_options.VideoFileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase))
                 {
@@ -79,7 +81,7 @@ namespace Emby.Naming.Video
 
             var extraResult = new ExtraResolver(_options).GetExtraInfo(path);
 
-            var name = IsDirectory
+            var name = isDirectory
                 ? Path.GetFileName(path)
                 : Path.GetFileNameWithoutExtension(path);
 
@@ -108,7 +110,7 @@ namespace Emby.Naming.Video
                 Is3D = format3DResult.Is3D,
                 Format3D = format3DResult.Format3D,
                 ExtraType = extraResult.ExtraType,
-                IsDirectory = IsDirectory,
+                IsDirectory = isDirectory,
                 ExtraRule = extraResult.Rule
             };
         }

+ 2 - 2
Emby.Server.Implementations/Emby.Server.Implementations.csproj

@@ -52,8 +52,8 @@
 
   <!-- Code analysers-->
   <ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
-    <PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.6.3" />
-    <PackageReference Include="StyleCop.Analyzers" Version="1.0.2" />
+    <PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.2" />
+    <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" />
     <PackageReference Include="SerilogAnalyzer" Version="0.15.0" />
   </ItemGroup>
 

+ 1 - 1
Emby.Server.Implementations/Library/LibraryManager.cs

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

+ 1 - 1
Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs

@@ -52,7 +52,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
 
                 var path = args.Path;
 
-                var seasonParserResult = new SeasonPathParser(namingOptions).Parse(path, true, true);
+                var seasonParserResult = new SeasonPathParser().Parse(path, true, true);
 
                 var season = new Season
                 {

+ 1 - 3
Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs

@@ -194,9 +194,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 namingOptions = ((LibraryManager)libraryManager).GetNamingOptions();
-
-            var seasonNumber = new SeasonPathParser(namingOptions).Parse(path, isTvContentType, isTvContentType).SeasonNumber;
+            var seasonNumber = new SeasonPathParser().Parse(path, isTvContentType, isTvContentType).SeasonNumber;
 
             return seasonNumber.HasValue;
         }

+ 3 - 3
Jellyfin.Server/Jellyfin.Server.csproj

@@ -12,7 +12,7 @@
     <!-- We need C# 7.1 for async main-->
     <LangVersion>latest</LangVersion>
     <!-- Disable documentation warnings (for now) -->
-    <NoWarn>SA1600;SA1601;CS1591</NoWarn>
+    <NoWarn>SA1600;SA1601;SA1629;CS1591</NoWarn>
     <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
   </PropertyGroup>
 
@@ -26,8 +26,8 @@
 
   <!-- Code analysers-->
   <ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
-    <PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.6.3" />
-    <PackageReference Include="StyleCop.Analyzers" Version="1.0.2" />
+    <PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.2" />
+    <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" />
     <PackageReference Include="SerilogAnalyzer" Version="0.15.0" />
   </ItemGroup>
 

+ 5 - 1
Jellyfin.Server/Program.cs

@@ -122,8 +122,12 @@ namespace Jellyfin.Server
             // The default connection limit is 10 for ASP.NET hosted applications and 2 for all others.
             ServicePointManager.DefaultConnectionLimit = Math.Max(96, ServicePointManager.DefaultConnectionLimit);
 
+// CA5359: Do Not Disable Certificate Validation
+#pragma warning disable CA5359
+
             // Allow all https requests
             ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(delegate { return true; });
+#pragma warning restore CA5359
 
             var fileSystem = new ManagedFileSystem(_loggerFactory, appPaths);
 
@@ -368,7 +372,7 @@ namespace Jellyfin.Server
             }
             catch (Exception ex)
             {
-                _logger.LogInformation(ex, "Skia not available. Will fallback to NullIMageEncoder. {0}");
+                _logger.LogInformation(ex, "Skia not available. Will fallback to NullIMageEncoder.");
             }
 
             return new NullImageEncoder();

+ 5 - 0
jellyfin.ruleset

@@ -14,12 +14,17 @@
     <Rule Id="SA1200" Action="None" />
     <!-- disable warning SA1309: Fields must not begin with an underscore -->
     <Rule Id="SA1309" Action="None" />
+    <!-- disable warning SA1413: Use trailing comma in multi-line initializers -->
+    <Rule Id="SA1413" Action="None" />
     <!-- disable warning SA1512: Single-line comments must not be followed by blank line -->
     <Rule Id="SA1512" Action="None" />
     <!-- disable warning SA1633: The file header is missing or not located at the top of the file -->
     <Rule Id="SA1633" Action="None" />
   </Rules>
+
   <Rules AnalyzerId="Microsoft.CodeAnalysis.FxCopAnalyzers" RuleNamespace="Microsoft.Design">
+    <!-- disable warning CA1031: Do not catch general exception types -->
+    <Rule Id="CA1031" Action="Info" />
     <!-- disable warning CA1822: Member does not access instance data and can be marked as static -->
     <Rule Id="CA1822" Action="Info" />