Browse Source

Merge pull request #6335 from richlander/media-provides-analysis-fixes

Bond-009 3 years ago
parent
commit
d639b030ac
30 changed files with 509 additions and 359 deletions
  1. 4 4
      MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs
  2. 3 1
      MediaBrowser.Providers/Manager/ItemImageProvider.cs
  3. 5 0
      MediaBrowser.Providers/Manager/MetadataService.cs
  4. 3 5
      MediaBrowser.Providers/MediaBrowser.Providers.csproj
  5. 1 1
      MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs
  6. 1 1
      MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
  7. 2 1
      MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs
  8. 2 1
      MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs
  9. 0 0
      MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumImageProvider.cs
  10. 11 8
      MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumProvider.cs
  11. 0 0
      MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistImageProvider.cs
  12. 9 8
      MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistProvider.cs
  13. 0 119
      MediaBrowser.Providers/Plugins/MusicBrainz/ExternalIds.cs
  14. 28 0
      MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumArtistExternalId.cs
  15. 28 0
      MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumExternalId.cs
  16. 197 178
      MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumProvider.cs
  17. 28 0
      MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzArtistExternalId.cs
  18. 2 2
      MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzArtistProvider.cs
  19. 28 0
      MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzOtherArtistExternalId.cs
  20. 28 0
      MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzReleaseGroupExternalId.cs
  21. 28 0
      MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzTrackId.cs
  22. 4 4
      MediaBrowser.Providers/Plugins/MusicBrainz/Plugin.cs
  23. 1 1
      MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs
  24. 44 1
      MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs
  25. 5 5
      MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs
  26. 21 1
      MediaBrowser.Providers/Plugins/Tmdb/TmdbClientManager.cs
  27. 2 1
      MediaBrowser.Providers/Studios/StudioMetadataService.cs
  28. 9 2
      MediaBrowser.Providers/Subtitles/SubtitleManager.cs
  29. 8 8
      MediaBrowser.Providers/TV/EpisodeMetadataService.cs
  30. 7 7
      MediaBrowser.Providers/TV/SeasonMetadataService.cs

+ 4 - 4
MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs

@@ -59,9 +59,9 @@ namespace MediaBrowser.Providers.BoxSets
         }
 
         /// <inheritdoc />
-        protected override ItemUpdateType BeforeSaveInternal(BoxSet item, bool isFullRefresh, ItemUpdateType currentUpdateType)
+        protected override ItemUpdateType BeforeSaveInternal(BoxSet item, bool isFullRefresh, ItemUpdateType updateType)
         {
-            var updateType = base.BeforeSaveInternal(item, isFullRefresh, currentUpdateType);
+            var updatedType = base.BeforeSaveInternal(item, isFullRefresh, updateType);
 
             var libraryFolderIds = item.GetLibraryFolderIds();
 
@@ -69,10 +69,10 @@ namespace MediaBrowser.Providers.BoxSets
             if (itemLibraryFolderIds == null || !libraryFolderIds.SequenceEqual(itemLibraryFolderIds))
             {
                 item.LibraryFolderIds = libraryFolderIds;
-                updateType |= ItemUpdateType.MetadataImport;
+                updatedType |= ItemUpdateType.MetadataImport;
             }
 
-            return updateType;
+            return updatedType;
         }
     }
 }

+ 3 - 1
MediaBrowser.Providers/Manager/ItemImageProvider.cs

@@ -1,7 +1,8 @@
-#pragma warning disable CS1591
+#pragma warning disable CA1002, CS1591
 
 using System;
 using System.Collections.Generic;
+using System.Collections.ObjectModel;
 using System.IO;
 using System.Linq;
 using System.Net;
@@ -536,6 +537,7 @@ namespace MediaBrowser.Providers.Manager
                     return true;
                 }
             }
+
             // We always want to use prefetched images
             return false;
         }

+ 5 - 0
MediaBrowser.Providers/Manager/MetadataService.cs

@@ -505,6 +505,11 @@ namespace MediaBrowser.Providers.Manager
         /// <summary>
         /// Gets the providers.
         /// </summary>
+        /// <param name="item">A media item.</param>
+        /// <param name="libraryOptions">The LibraryOptions to use.</param>
+        /// <param name="options">The MetadataRefreshOptions to use.</param>
+        /// <param name="isFirstRefresh">Specifies first refresh mode.</param>
+        /// <param name="requiresRefresh">Specifies refresh mode.</param>
         /// <returns>IEnumerable{`0}.</returns>
         protected IEnumerable<IMetadataProvider> GetProviders(BaseItem item, LibraryOptions libraryOptions, MetadataRefreshOptions options, bool isFirstRefresh, bool requiresRefresh)
         {

+ 3 - 5
MediaBrowser.Providers/MediaBrowser.Providers.csproj

@@ -29,12 +29,10 @@
     <TargetFramework>net5.0</TargetFramework>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
-    <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
-    <Nullable>disable</Nullable>
-  </PropertyGroup>
-
-  <PropertyGroup Condition=" '$(Configuration)' == 'Release'">
     <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+    <AnalysisMode Condition=" '$(Configuration)' == 'Debug'">AllEnabledByDefault</AnalysisMode>
+    <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet>
+    <Nullable>disable</Nullable>
   </PropertyGroup>
 
   <!-- Code Analyzers-->

+ 1 - 1
MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs

@@ -1,4 +1,4 @@
-#pragma warning disable CS1591
+#pragma warning disable CA1002, CS1591
 
 using System;
 using System.Collections.Generic;

+ 1 - 1
MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs

@@ -1,4 +1,4 @@
-#pragma warning disable CS1591
+#pragma warning disable CA1068, CS1591
 
 using System;
 using System.Collections.Generic;

+ 2 - 1
MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs

@@ -1,7 +1,8 @@
-#pragma warning disable CS1591
+#pragma warning disable CA1002, CS1591
 
 using System;
 using System.Collections.Generic;
+using System.Collections.ObjectModel;
 using System.Linq;
 using System.Threading;
 using System.Threading.Tasks;

+ 2 - 1
MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs

@@ -1,7 +1,8 @@
-#pragma warning disable CS1591
+#pragma warning disable CA1002, CS1591
 
 using System;
 using System.Collections.Generic;
+using System.Collections.ObjectModel;
 using System.IO;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Providers;

+ 0 - 0
MediaBrowser.Providers/Plugins/AudioDb/AlbumImageProvider.cs → MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumImageProvider.cs


+ 11 - 8
MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs → MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumProvider.cs

@@ -1,4 +1,4 @@
-#pragma warning disable CS1591
+#pragma warning disable CA1002, CS1591, SA1300
 
 using System;
 using System.Collections.Generic;
@@ -9,9 +9,9 @@ using System.Net.Http;
 using System.Text.Json;
 using System.Threading;
 using System.Threading.Tasks;
+using Jellyfin.Extensions.Json;
 using MediaBrowser.Common.Configuration;
 using MediaBrowser.Common.Extensions;
-using Jellyfin.Extensions.Json;
 using MediaBrowser.Common.Net;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities.Audio;
@@ -30,7 +30,9 @@ namespace MediaBrowser.Providers.Plugins.AudioDb
         private readonly IHttpClientFactory _httpClientFactory;
         private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options;
 
+#pragma warning disable SA1401, CA2211
         public static AudioDbAlbumProvider Current;
+#pragma warning restore SA1401, CA2211
 
         public AudioDbAlbumProvider(IServerConfigurationManager config, IFileSystem fileSystem, IHttpClientFactory httpClientFactory)
         {
@@ -196,6 +198,13 @@ namespace MediaBrowser.Providers.Plugins.AudioDb
             return Path.Combine(dataPath, "album.json");
         }
 
+        /// <inheritdoc />
+        public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
+        {
+            throw new NotImplementedException();
+        }
+
+#pragma warning disable CA1034, CA2227
         public class Album
         {
             public string idAlbum { get; set; }
@@ -279,11 +288,5 @@ namespace MediaBrowser.Providers.Plugins.AudioDb
         {
             public List<Album> album { get; set; }
         }
-
-        /// <inheritdoc />
-        public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
-        {
-            throw new NotImplementedException();
-        }
     }
 }

+ 0 - 0
MediaBrowser.Providers/Plugins/AudioDb/ArtistImageProvider.cs → MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistImageProvider.cs


+ 9 - 8
MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs → MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistProvider.cs

@@ -1,4 +1,4 @@
-#pragma warning disable CS1591
+#pragma warning disable CA1034, CS1591, CA1002, SA1028, SA1300
 
 using System;
 using System.Collections.Generic;
@@ -8,9 +8,9 @@ using System.Net.Http;
 using System.Text.Json;
 using System.Threading;
 using System.Threading.Tasks;
+using Jellyfin.Extensions.Json;
 using MediaBrowser.Common.Configuration;
 using MediaBrowser.Common.Extensions;
-using Jellyfin.Extensions.Json;
 using MediaBrowser.Common.Net;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities.Audio;
@@ -183,6 +183,12 @@ namespace MediaBrowser.Providers.Plugins.AudioDb
             return Path.Combine(dataPath, "artist.json");
         }
 
+        /// <inheritdoc />
+        public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
+        {
+            throw new NotImplementedException();
+        }
+
         public class Artist
         {
             public string idArtist { get; set; }
@@ -268,15 +274,10 @@ namespace MediaBrowser.Providers.Plugins.AudioDb
             public string strLocked { get; set; }
         }
 
+#pragma warning disable CA2227
         public class RootObject
         {
             public List<Artist> artists { get; set; }
         }
-
-        /// <inheritdoc />
-        public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
-        {
-            throw new NotImplementedException();
-        }
     }
 }

+ 0 - 119
MediaBrowser.Providers/Plugins/MusicBrainz/ExternalIds.cs

@@ -1,119 +0,0 @@
-#pragma warning disable CS1591
-
-using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Providers;
-using MediaBrowser.Providers.Plugins.MusicBrainz;
-
-namespace MediaBrowser.Providers.Music
-{
-    public class MusicBrainzReleaseGroupExternalId : IExternalId
-    {
-        /// <inheritdoc />
-        public string ProviderName => "MusicBrainz";
-
-        /// <inheritdoc />
-        public string Key => MetadataProvider.MusicBrainzReleaseGroup.ToString();
-
-        /// <inheritdoc />
-        public ExternalIdMediaType? Type => ExternalIdMediaType.ReleaseGroup;
-
-        /// <inheritdoc />
-        public string UrlFormatString => Plugin.Instance.Configuration.Server + "/release-group/{0}";
-
-        /// <inheritdoc />
-        public bool Supports(IHasProviderIds item) => item is Audio || item is MusicAlbum;
-    }
-
-    public class MusicBrainzAlbumArtistExternalId : IExternalId
-    {
-        /// <inheritdoc />
-        public string ProviderName => "MusicBrainz";
-
-        /// <inheritdoc />
-        public string Key => MetadataProvider.MusicBrainzAlbumArtist.ToString();
-
-        /// <inheritdoc />
-        public ExternalIdMediaType? Type => ExternalIdMediaType.AlbumArtist;
-
-        /// <inheritdoc />
-        public string UrlFormatString => Plugin.Instance.Configuration.Server + "/artist/{0}";
-
-        /// <inheritdoc />
-        public bool Supports(IHasProviderIds item) => item is Audio;
-    }
-
-    public class MusicBrainzAlbumExternalId : IExternalId
-    {
-        /// <inheritdoc />
-        public string ProviderName => "MusicBrainz";
-
-        /// <inheritdoc />
-        public string Key => MetadataProvider.MusicBrainzAlbum.ToString();
-
-        /// <inheritdoc />
-        public ExternalIdMediaType? Type => ExternalIdMediaType.Album;
-
-        /// <inheritdoc />
-        public string UrlFormatString => Plugin.Instance.Configuration.Server + "/release/{0}";
-
-        /// <inheritdoc />
-        public bool Supports(IHasProviderIds item) => item is Audio || item is MusicAlbum;
-    }
-
-    public class MusicBrainzArtistExternalId : IExternalId
-    {
-        /// <inheritdoc />
-        public string ProviderName => "MusicBrainz";
-
-        /// <inheritdoc />
-        public string Key => MetadataProvider.MusicBrainzArtist.ToString();
-
-        /// <inheritdoc />
-        public ExternalIdMediaType? Type => ExternalIdMediaType.Artist;
-
-        /// <inheritdoc />
-        public string UrlFormatString => Plugin.Instance.Configuration.Server + "/artist/{0}";
-
-        /// <inheritdoc />
-        public bool Supports(IHasProviderIds item) => item is MusicArtist;
-    }
-
-    public class MusicBrainzOtherArtistExternalId : IExternalId
-    {
-        /// <inheritdoc />
-        public string ProviderName => "MusicBrainz";
-
-        /// <inheritdoc />
-
-        public string Key => MetadataProvider.MusicBrainzArtist.ToString();
-
-        /// <inheritdoc />
-        public ExternalIdMediaType? Type => ExternalIdMediaType.OtherArtist;
-
-        /// <inheritdoc />
-        public string UrlFormatString => Plugin.Instance.Configuration.Server + "/artist/{0}";
-
-        /// <inheritdoc />
-        public bool Supports(IHasProviderIds item) => item is Audio || item is MusicAlbum;
-    }
-
-    public class MusicBrainzTrackId : IExternalId
-    {
-        /// <inheritdoc />
-        public string ProviderName => "MusicBrainz";
-
-        /// <inheritdoc />
-        public string Key => MetadataProvider.MusicBrainzTrack.ToString();
-
-        /// <inheritdoc />
-        public ExternalIdMediaType? Type => ExternalIdMediaType.Track;
-
-        /// <inheritdoc />
-        public string UrlFormatString => Plugin.Instance.Configuration.Server + "/track/{0}";
-
-        /// <inheritdoc />
-        public bool Supports(IHasProviderIds item) => item is Audio;
-    }
-}

+ 28 - 0
MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumArtistExternalId.cs

@@ -0,0 +1,28 @@
+#pragma warning disable CS1591
+
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Providers;
+using MediaBrowser.Providers.Plugins.MusicBrainz;
+
+namespace MediaBrowser.Providers.Music
+{
+    public class MusicBrainzAlbumArtistExternalId : IExternalId
+    {
+        /// <inheritdoc />
+        public string ProviderName => "MusicBrainz";
+
+        /// <inheritdoc />
+        public string Key => MetadataProvider.MusicBrainzAlbumArtist.ToString();
+
+        /// <inheritdoc />
+        public ExternalIdMediaType? Type => ExternalIdMediaType.AlbumArtist;
+
+        /// <inheritdoc />
+        public string UrlFormatString => Plugin.Instance.Configuration.Server + "/artist/{0}";
+
+        /// <inheritdoc />
+        public bool Supports(IHasProviderIds item) => item is Audio;
+    }
+}

+ 28 - 0
MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumExternalId.cs

@@ -0,0 +1,28 @@
+#pragma warning disable CS1591
+
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Providers;
+using MediaBrowser.Providers.Plugins.MusicBrainz;
+
+namespace MediaBrowser.Providers.Music
+{
+    public class MusicBrainzAlbumExternalId : IExternalId
+    {
+        /// <inheritdoc />
+        public string ProviderName => "MusicBrainz";
+
+        /// <inheritdoc />
+        public string Key => MetadataProvider.MusicBrainzAlbum.ToString();
+
+        /// <inheritdoc />
+        public ExternalIdMediaType? Type => ExternalIdMediaType.Album;
+
+        /// <inheritdoc />
+        public string UrlFormatString => Plugin.Instance.Configuration.Server + "/release/{0}";
+
+        /// <inheritdoc />
+        public bool Supports(IHasProviderIds item) => item is Audio || item is MusicAlbum;
+    }
+}

+ 197 - 178
MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumProvider.cs

@@ -1,4 +1,4 @@
-#pragma warning disable CS1591
+#pragma warning disable CS1591, SA1401
 
 using System;
 using System.Collections.Generic;
@@ -23,7 +23,7 @@ using Microsoft.Extensions.Logging;
 
 namespace MediaBrowser.Providers.Music
 {
-    public class MusicBrainzAlbumProvider : IRemoteMetadataProvider<MusicAlbum, AlbumInfo>, IHasOrder
+    public class MusicBrainzAlbumProvider : IRemoteMetadataProvider<MusicAlbum, AlbumInfo>, IHasOrder, IDisposable
     {
         /// <summary>
         /// For each single MB lookup/search, this is the maximum number of
@@ -36,7 +36,7 @@ namespace MediaBrowser.Providers.Music
         /// The Jellyfin user-agent is unrestricted but source IP must not exceed
         /// one request per second, therefore we rate limit to avoid throttling.
         /// Be prudent, use a value slightly above the minimun required.
-        /// https://musicbrainz.org/doc/XML_Web_Service/Rate_Limiting
+        /// https://musicbrainz.org/doc/XML_Web_Service/Rate_Limiting.
         /// </summary>
         private readonly long _musicBrainzQueryIntervalMs;
 
@@ -302,181 +302,6 @@ namespace MediaBrowser.Providers.Music
             return ReleaseResult.Parse(reader).FirstOrDefault();
         }
 
-        private class ReleaseResult
-        {
-            public string ReleaseId;
-            public string ReleaseGroupId;
-            public string Title;
-            public string Overview;
-            public int? Year;
-
-            public List<ValueTuple<string, string>> Artists = new List<ValueTuple<string, string>>();
-
-            public static IEnumerable<ReleaseResult> Parse(XmlReader reader)
-            {
-                reader.MoveToContent();
-                reader.Read();
-
-                // Loop through each element
-                while (!reader.EOF && reader.ReadState == ReadState.Interactive)
-                {
-                    if (reader.NodeType == XmlNodeType.Element)
-                    {
-                        switch (reader.Name)
-                        {
-                            case "release-list":
-                                {
-                                    if (reader.IsEmptyElement)
-                                    {
-                                        reader.Read();
-                                        continue;
-                                    }
-
-                                    using var subReader = reader.ReadSubtree();
-                                    return ParseReleaseList(subReader).ToList();
-                                }
-
-                            default:
-                                {
-                                    reader.Skip();
-                                    break;
-                                }
-                        }
-                    }
-                    else
-                    {
-                        reader.Read();
-                    }
-                }
-
-                return Enumerable.Empty<ReleaseResult>();
-            }
-
-            private static IEnumerable<ReleaseResult> ParseReleaseList(XmlReader reader)
-            {
-                reader.MoveToContent();
-                reader.Read();
-
-                // Loop through each element
-                while (!reader.EOF && reader.ReadState == ReadState.Interactive)
-                {
-                    if (reader.NodeType == XmlNodeType.Element)
-                    {
-                        switch (reader.Name)
-                        {
-                            case "release":
-                                {
-                                    if (reader.IsEmptyElement)
-                                    {
-                                        reader.Read();
-                                        continue;
-                                    }
-
-                                    var releaseId = reader.GetAttribute("id");
-
-                                    using var subReader = reader.ReadSubtree();
-                                    var release = ParseRelease(subReader, releaseId);
-                                    if (release != null)
-                                    {
-                                        yield return release;
-                                    }
-
-                                    break;
-                                }
-
-                            default:
-                                {
-                                    reader.Skip();
-                                    break;
-                                }
-                        }
-                    }
-                    else
-                    {
-                        reader.Read();
-                    }
-                }
-            }
-
-            private static ReleaseResult ParseRelease(XmlReader reader, string releaseId)
-            {
-                var result = new ReleaseResult
-                {
-                    ReleaseId = releaseId
-                };
-
-                reader.MoveToContent();
-                reader.Read();
-
-                // http://stackoverflow.com/questions/2299632/why-does-xmlreader-skip-every-other-element-if-there-is-no-whitespace-separator
-
-                // Loop through each element
-                while (!reader.EOF && reader.ReadState == ReadState.Interactive)
-                {
-                    if (reader.NodeType == XmlNodeType.Element)
-                    {
-                        switch (reader.Name)
-                        {
-                            case "title":
-                                {
-                                    result.Title = reader.ReadElementContentAsString();
-                                    break;
-                                }
-
-                            case "date":
-                                {
-                                    var val = reader.ReadElementContentAsString();
-                                    if (DateTime.TryParse(val, out var date))
-                                    {
-                                        result.Year = date.Year;
-                                    }
-
-                                    break;
-                                }
-
-                            case "annotation":
-                                {
-                                    result.Overview = reader.ReadElementContentAsString();
-                                    break;
-                                }
-
-                            case "release-group":
-                                {
-                                    result.ReleaseGroupId = reader.GetAttribute("id");
-                                    reader.Skip();
-                                    break;
-                                }
-
-                            case "artist-credit":
-                                {
-                                    using var subReader = reader.ReadSubtree();
-                                    var artist = ParseArtistCredit(subReader);
-
-                                    if (!string.IsNullOrEmpty(artist.Item1))
-                                    {
-                                        result.Artists.Add(artist);
-                                    }
-
-                                    break;
-                                }
-
-                            default:
-                                {
-                                    reader.Skip();
-                                    break;
-                                }
-                        }
-                    }
-                    else
-                    {
-                        reader.Read();
-                    }
-                }
-
-                return result;
-            }
-        }
-
         private static (string, string) ParseArtistCredit(XmlReader reader)
         {
             reader.MoveToContent();
@@ -496,6 +321,7 @@ namespace MediaBrowser.Providers.Music
                             using var subReader = reader.ReadSubtree();
                             return ParseArtistNameCredit(subReader);
                         }
+
                         default:
                         {
                             reader.Skip();
@@ -707,6 +533,9 @@ namespace MediaBrowser.Providers.Music
         /// A number of retries shall be made in order to try and satisfy the request before
         /// giving up and returning null.
         /// </summary>
+        /// <param name="url">Address of MusicBrainz server.</param>
+        /// <param name="cancellationToken">CancellationToken to use for method.</param>
+        /// <returns>Returns response from MusicBrainz service.</returns>
         internal async Task<HttpResponseMessage> GetMusicBrainzResponse(string url, CancellationToken cancellationToken)
         {
             await _apiRequestLock.WaitAsync(cancellationToken).ConfigureAwait(false);
@@ -762,5 +591,195 @@ namespace MediaBrowser.Providers.Music
         {
             throw new NotImplementedException();
         }
+
+        protected virtual void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                _apiRequestLock?.Dispose();
+            }
+        }
+
+        /// <inheritdoc />
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        private class ReleaseResult
+        {
+            public string ReleaseId;
+            public string ReleaseGroupId;
+            public string Title;
+            public string Overview;
+            public int? Year;
+
+            public List<ValueTuple<string, string>> Artists = new List<ValueTuple<string, string>>();
+
+            public static IEnumerable<ReleaseResult> Parse(XmlReader reader)
+            {
+                reader.MoveToContent();
+                reader.Read();
+
+                // Loop through each element
+                while (!reader.EOF && reader.ReadState == ReadState.Interactive)
+                {
+                    if (reader.NodeType == XmlNodeType.Element)
+                    {
+                        switch (reader.Name)
+                        {
+                            case "release-list":
+                                {
+                                    if (reader.IsEmptyElement)
+                                    {
+                                        reader.Read();
+                                        continue;
+                                    }
+
+                                    using var subReader = reader.ReadSubtree();
+                                    return ParseReleaseList(subReader).ToList();
+                                }
+
+                            default:
+                                {
+                                    reader.Skip();
+                                    break;
+                                }
+                        }
+                    }
+                    else
+                    {
+                        reader.Read();
+                    }
+                }
+
+                return Enumerable.Empty<ReleaseResult>();
+            }
+
+            private static IEnumerable<ReleaseResult> ParseReleaseList(XmlReader reader)
+            {
+                reader.MoveToContent();
+                reader.Read();
+
+                // Loop through each element
+                while (!reader.EOF && reader.ReadState == ReadState.Interactive)
+                {
+                    if (reader.NodeType == XmlNodeType.Element)
+                    {
+                        switch (reader.Name)
+                        {
+                            case "release":
+                                {
+                                    if (reader.IsEmptyElement)
+                                    {
+                                        reader.Read();
+                                        continue;
+                                    }
+
+                                    var releaseId = reader.GetAttribute("id");
+
+                                    using var subReader = reader.ReadSubtree();
+                                    var release = ParseRelease(subReader, releaseId);
+                                    if (release != null)
+                                    {
+                                        yield return release;
+                                    }
+
+                                    break;
+                                }
+
+                            default:
+                                {
+                                    reader.Skip();
+                                    break;
+                                }
+                        }
+                    }
+                    else
+                    {
+                        reader.Read();
+                    }
+                }
+            }
+
+            private static ReleaseResult ParseRelease(XmlReader reader, string releaseId)
+            {
+                var result = new ReleaseResult
+                {
+                    ReleaseId = releaseId
+                };
+
+                reader.MoveToContent();
+                reader.Read();
+
+                // http://stackoverflow.com/questions/2299632/why-does-xmlreader-skip-every-other-element-if-there-is-no-whitespace-separator
+
+                // Loop through each element
+                while (!reader.EOF && reader.ReadState == ReadState.Interactive)
+                {
+                    if (reader.NodeType == XmlNodeType.Element)
+                    {
+                        switch (reader.Name)
+                        {
+                            case "title":
+                                {
+                                    result.Title = reader.ReadElementContentAsString();
+                                    break;
+                                }
+
+                            case "date":
+                                {
+                                    var val = reader.ReadElementContentAsString();
+                                    if (DateTime.TryParse(val, out var date))
+                                    {
+                                        result.Year = date.Year;
+                                    }
+
+                                    break;
+                                }
+
+                            case "annotation":
+                                {
+                                    result.Overview = reader.ReadElementContentAsString();
+                                    break;
+                                }
+
+                            case "release-group":
+                                {
+                                    result.ReleaseGroupId = reader.GetAttribute("id");
+                                    reader.Skip();
+                                    break;
+                                }
+
+                            case "artist-credit":
+                                {
+                                    using var subReader = reader.ReadSubtree();
+                                    var artist = ParseArtistCredit(subReader);
+
+                                    if (!string.IsNullOrEmpty(artist.Item1))
+                                    {
+                                        result.Artists.Add(artist);
+                                    }
+
+                                    break;
+                                }
+
+                            default:
+                                {
+                                    reader.Skip();
+                                    break;
+                                }
+                        }
+                    }
+                    else
+                    {
+                        reader.Read();
+                    }
+                }
+
+                return result;
+            }
+        }
     }
 }

+ 28 - 0
MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzArtistExternalId.cs

@@ -0,0 +1,28 @@
+#pragma warning disable CS1591
+
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Providers;
+using MediaBrowser.Providers.Plugins.MusicBrainz;
+
+namespace MediaBrowser.Providers.Music
+{
+    public class MusicBrainzArtistExternalId : IExternalId
+    {
+        /// <inheritdoc />
+        public string ProviderName => "MusicBrainz";
+
+        /// <inheritdoc />
+        public string Key => MetadataProvider.MusicBrainzArtist.ToString();
+
+        /// <inheritdoc />
+        public ExternalIdMediaType? Type => ExternalIdMediaType.Artist;
+
+        /// <inheritdoc />
+        public string UrlFormatString => Plugin.Instance.Configuration.Server + "/artist/{0}";
+
+        /// <inheritdoc />
+        public bool Supports(IHasProviderIds item) => item is MusicArtist;
+    }
+}

+ 2 - 2
MediaBrowser.Providers/Plugins/MusicBrainz/ArtistProvider.cs → MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzArtistProvider.cs

@@ -22,6 +22,8 @@ namespace MediaBrowser.Providers.Music
 {
     public class MusicBrainzArtistProvider : IRemoteMetadataProvider<MusicArtist, ArtistInfo>
     {
+        public string Name => "MusicBrainz";
+
         /// <inheritdoc />
         public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(ArtistInfo searchInfo, CancellationToken cancellationToken)
         {
@@ -262,8 +264,6 @@ namespace MediaBrowser.Providers.Music
             return WebUtility.UrlEncode(name);
         }
 
-        public string Name => "MusicBrainz";
-
         public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
         {
             throw new NotImplementedException();

+ 28 - 0
MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzOtherArtistExternalId.cs

@@ -0,0 +1,28 @@
+#pragma warning disable CS1591
+
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Providers;
+using MediaBrowser.Providers.Plugins.MusicBrainz;
+
+namespace MediaBrowser.Providers.Music
+{
+    public class MusicBrainzOtherArtistExternalId : IExternalId
+    {
+        /// <inheritdoc />
+        public string ProviderName => "MusicBrainz";
+
+        /// <inheritdoc />
+        public string Key => MetadataProvider.MusicBrainzArtist.ToString();
+
+        /// <inheritdoc />
+        public ExternalIdMediaType? Type => ExternalIdMediaType.OtherArtist;
+
+        /// <inheritdoc />
+        public string UrlFormatString => Plugin.Instance.Configuration.Server + "/artist/{0}";
+
+        /// <inheritdoc />
+        public bool Supports(IHasProviderIds item) => item is Audio || item is MusicAlbum;
+    }
+}

+ 28 - 0
MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzReleaseGroupExternalId.cs

@@ -0,0 +1,28 @@
+#pragma warning disable CS1591
+
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Providers;
+using MediaBrowser.Providers.Plugins.MusicBrainz;
+
+namespace MediaBrowser.Providers.Music
+{
+    public class MusicBrainzReleaseGroupExternalId : IExternalId
+    {
+        /// <inheritdoc />
+        public string ProviderName => "MusicBrainz";
+
+        /// <inheritdoc />
+        public string Key => MetadataProvider.MusicBrainzReleaseGroup.ToString();
+
+        /// <inheritdoc />
+        public ExternalIdMediaType? Type => ExternalIdMediaType.ReleaseGroup;
+
+        /// <inheritdoc />
+        public string UrlFormatString => Plugin.Instance.Configuration.Server + "/release-group/{0}";
+
+        /// <inheritdoc />
+        public bool Supports(IHasProviderIds item) => item is Audio || item is MusicAlbum;
+    }
+}

+ 28 - 0
MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzTrackId.cs

@@ -0,0 +1,28 @@
+#pragma warning disable CS1591
+
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Providers;
+using MediaBrowser.Providers.Plugins.MusicBrainz;
+
+namespace MediaBrowser.Providers.Music
+{
+    public class MusicBrainzTrackId : IExternalId
+    {
+        /// <inheritdoc />
+        public string ProviderName => "MusicBrainz";
+
+        /// <inheritdoc />
+        public string Key => MetadataProvider.MusicBrainzTrack.ToString();
+
+        /// <inheritdoc />
+        public ExternalIdMediaType? Type => ExternalIdMediaType.Track;
+
+        /// <inheritdoc />
+        public string UrlFormatString => Plugin.Instance.Configuration.Server + "/track/{0}";
+
+        /// <inheritdoc />
+        public bool Supports(IHasProviderIds item) => item is Audio;
+    }
+}

+ 4 - 4
MediaBrowser.Providers/Plugins/MusicBrainz/Plugin.cs

@@ -11,6 +11,10 @@ namespace MediaBrowser.Providers.Plugins.MusicBrainz
 {
     public class Plugin : BasePlugin<PluginConfiguration>, IHasWebPages
     {
+        public const string DefaultServer = "https://musicbrainz.org";
+
+        public const long DefaultRateLimit = 2000u;
+
         public Plugin(IApplicationPaths applicationPaths, IXmlSerializer xmlSerializer)
             : base(applicationPaths, xmlSerializer)
         {
@@ -25,10 +29,6 @@ namespace MediaBrowser.Providers.Plugins.MusicBrainz
 
         public override string Description => "Get artist and album metadata from any MusicBrainz server.";
 
-        public const string DefaultServer = "https://musicbrainz.org";
-
-        public const long DefaultRateLimit = 2000u;
-
         // TODO remove when plugin removed from server.
         public override string ConfigurationFileName => "Jellyfin.Plugin.MusicBrainz.xml";
 

+ 1 - 1
MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs

@@ -1,4 +1,4 @@
-#pragma warning disable CS1591
+#pragma warning disable CS1591, SA1300
 
 using System;
 using System.Collections.Generic;

+ 44 - 1
MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs

@@ -1,4 +1,4 @@
-#pragma warning disable CS1591
+#pragma warning disable CS159, SA1300
 
 using System;
 using System.Collections.Generic;
@@ -20,6 +20,7 @@ using MediaBrowser.Model.IO;
 
 namespace MediaBrowser.Providers.Plugins.Omdb
 {
+    /// <summary>Provider for OMDB service.</summary>
     public class OmdbProvider
     {
         private readonly IFileSystem _fileSystem;
@@ -29,6 +30,11 @@ namespace MediaBrowser.Providers.Plugins.Omdb
         private readonly IApplicationHost _appHost;
         private readonly JsonSerializerOptions _jsonOptions;
 
+        /// <summary>Initializes a new instance of the <see cref="OmdbProvider"/> class.</summary>
+        /// <param name="httpClientFactory">HttpClientFactory to use for calls to OMDB service.</param>
+        /// <param name="fileSystem">IFileSystem to use for store OMDB data.</param>
+        /// <param name="appHost">IApplicationHost to use.</param>
+        /// <param name="configurationManager">IServerConfigurationManager to use.</param>
         public OmdbProvider(IHttpClientFactory httpClientFactory, IFileSystem fileSystem, IApplicationHost appHost, IServerConfigurationManager configurationManager)
         {
             _httpClientFactory = httpClientFactory;
@@ -41,6 +47,14 @@ namespace MediaBrowser.Providers.Plugins.Omdb
             _jsonOptions.Converters.Add(new JsonOmdbNotAvailableInt32Converter());
         }
 
+        /// <summary>Fetches data from OMDB service.</summary>
+        /// <param name="itemResult">Metadata about media item.</param>
+        /// <param name="imdbId">IMDB ID for media.</param>
+        /// <param name="language">Media language.</param>
+        /// <param name="country">Country of origin.</param>
+        /// <param name="cancellationToken">CancellationToken to use for operation.</param>
+        /// <typeparam name="T">The first generic type parameter.</typeparam>
+        /// <returns>Returns a Task object that can be awaited.</returns>
         public async Task Fetch<T>(MetadataResult<T> itemResult, string imdbId, string language, string country, CancellationToken cancellationToken)
             where T : BaseItem
         {
@@ -105,6 +119,17 @@ namespace MediaBrowser.Providers.Plugins.Omdb
             ParseAdditionalMetadata(itemResult, result);
         }
 
+        /// <summary>Gets data about an episode.</summary>
+        /// <param name="itemResult">Metadata about episode.</param>
+        /// <param name="episodeNumber">Episode number.</param>
+        /// <param name="seasonNumber">Season number.</param>
+        /// <param name="episodeImdbId">Episode ID.</param>
+        /// <param name="seriesImdbId">Season ID.</param>
+        /// <param name="language">Episode language.</param>
+        /// <param name="country">Country of origin.</param>
+        /// <param name="cancellationToken">CancellationToken to use for operation.</param>
+        /// <typeparam name="T">The first generic type parameter.</typeparam>
+        /// <returns>Whether operation was successful.</returns>
         public async Task<bool> FetchEpisodeData<T>(MetadataResult<T> itemResult, int episodeNumber, int seasonNumber, string episodeImdbId, string seriesImdbId, string language, string country, CancellationToken cancellationToken)
             where T : BaseItem
         {
@@ -236,6 +261,9 @@ namespace MediaBrowser.Providers.Plugins.Omdb
             return false;
         }
 
+        /// <summary>Gets OMDB URL.</summary>
+        /// <param name="query">Appends query string to URL.</param>
+        /// <returns>OMDB URL with optional query string.</returns>
         public static string GetOmdbUrl(string query)
         {
             const string Url = "https://www.omdbapi.com?apikey=2c9d9507";
@@ -327,6 +355,12 @@ namespace MediaBrowser.Providers.Plugins.Omdb
             return path;
         }
 
+        /// <summary>Gets response from OMDB service as type T.</summary>
+        /// <param name="httpClient">HttpClient instance to use for service call.</param>
+        /// <param name="url">Http URL to use for service call.</param>
+        /// <param name="cancellationToken">CancellationToken to use for service call.</param>
+        /// <typeparam name="T">The first generic type parameter.</typeparam>
+        /// <returns>OMDB service response as type T.</returns>
         public async Task<T> GetDeserializedOmdbResponse<T>(HttpClient httpClient, string url, CancellationToken cancellationToken)
         {
             using var response = await GetOmdbResponse(httpClient, url, cancellationToken).ConfigureAwait(false);
@@ -335,6 +369,11 @@ namespace MediaBrowser.Providers.Plugins.Omdb
             return await JsonSerializer.DeserializeAsync<T>(content, _jsonOptions, cancellationToken).ConfigureAwait(false);
         }
 
+        /// <summary>Gets response from OMDB service.</summary>
+        /// <param name="httpClient">HttpClient instance to use for service call.</param>
+        /// <param name="url">Http URL to use for service call.</param>
+        /// <param name="cancellationToken">CancellationToken to use for service call.</param>
+        /// <returns>OMDB service response as HttpResponseMessage.</returns>
         public static Task<HttpResponseMessage> GetOmdbResponse(HttpClient httpClient, string url, CancellationToken cancellationToken)
         {
             return httpClient.GetAsync(url, cancellationToken);
@@ -538,10 +577,14 @@ namespace MediaBrowser.Providers.Plugins.Omdb
             }
         }
 
+#pragma warning disable CA1034
+        /// <summary>Describes OMDB rating.</summary>
         public class OmdbRating
         {
+            /// <summary>Gets or sets rating source.</summary>
             public string Source { get; set; }
 
+            /// <summary>Gets or sets rating value.</summary>
             public string Value { get; set; }
         }
     }

+ 5 - 5
MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs

@@ -77,14 +77,14 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People
             return remoteSearchResults;
         }
 
-        public async Task<MetadataResult<Person>> GetMetadata(PersonLookupInfo id, CancellationToken cancellationToken)
+        public async Task<MetadataResult<Person>> GetMetadata(PersonLookupInfo info, CancellationToken cancellationToken)
         {
-            var personTmdbId = Convert.ToInt32(id.GetProviderId(MetadataProvider.Tmdb), CultureInfo.InvariantCulture);
+            var personTmdbId = Convert.ToInt32(info.GetProviderId(MetadataProvider.Tmdb), CultureInfo.InvariantCulture);
 
             // We don't already have an Id, need to fetch it
             if (personTmdbId <= 0)
             {
-                var personSearchResults = await _tmdbClientManager.SearchPersonAsync(id.Name, cancellationToken).ConfigureAwait(false);
+                var personSearchResults = await _tmdbClientManager.SearchPersonAsync(info.Name, cancellationToken).ConfigureAwait(false);
                 if (personSearchResults.Count > 0)
                 {
                     personTmdbId = personSearchResults[0].Id;
@@ -95,7 +95,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People
 
             if (personTmdbId > 0)
             {
-                var person = await _tmdbClientManager.GetPersonAsync(personTmdbId, id.MetadataLanguage, cancellationToken).ConfigureAwait(false);
+                var person = await _tmdbClientManager.GetPersonAsync(personTmdbId, info.MetadataLanguage, cancellationToken).ConfigureAwait(false);
 
                 result.HasMetadata = true;
 
@@ -103,7 +103,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People
                 {
                     // Take name from incoming info, don't rename the person
                     // TODO: This should go in PersonMetadataService, not each person provider
-                    Name = id.Name,
+                    Name = info.Name,
                     HomePageUrl = person.Homepage,
                     Overview = person.Biography,
                     PremiereDate = person.Birthday?.ToUniversalTime(),

+ 21 - 1
MediaBrowser.Providers/Plugins/Tmdb/TmdbClientManager.cs

@@ -18,7 +18,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb
     /// <summary>
     /// Manager class for abstracting the TMDb API client library.
     /// </summary>
-    public class TmdbClientManager
+    public class TmdbClientManager : IDisposable
     {
         private const int CacheDurationInHours = 1;
 
@@ -532,5 +532,25 @@ namespace MediaBrowser.Providers.Plugins.Tmdb
         {
             return !_tmDbClient.HasConfig ? _tmDbClient.GetConfigAsync() : Task.CompletedTask;
         }
+
+        /// <inheritdoc />
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+/// <summary>
+        /// Releases unmanaged and - optionally - managed resources.
+        /// </summary>
+        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
+        protected virtual void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                _memoryCache?.Dispose();
+                _tmDbClient?.Dispose();
+            }
+        }
     }
 }

+ 2 - 1
MediaBrowser.Providers/Studios/StudioMetadataService.cs

@@ -17,7 +17,8 @@ namespace MediaBrowser.Providers.Studios
             IServerConfigurationManager serverConfigurationManager,
             ILogger<StudioMetadataService> logger,
             IProviderManager providerManager,
-            IFileSystem fileSystem, ILibraryManager libraryManager)
+            IFileSystem fileSystem,
+            ILibraryManager libraryManager)
             : base(serverConfigurationManager, logger, providerManager, fileSystem, libraryManager)
         {
         }

+ 9 - 2
MediaBrowser.Providers/Subtitles/SubtitleManager.cs

@@ -252,8 +252,15 @@ namespace MediaBrowser.Providers.Subtitles
                 }
                 catch (Exception ex)
                 {
-                    (exs ??= new List<Exception>()).Add(ex);
-                }
+// Bug in analyzer -- https://github.com/dotnet/roslyn-analyzers/issues/5160
+#pragma warning disable CA1508
+                    exs ??= new List<Exception>()
+                            {
+                                ex
+                            };
+#pragma warning restore CA1508
+
+            }
                 finally
                 {
                     _monitor.ReportFileSystemChangeComplete(savePath, false);

+ 8 - 8
MediaBrowser.Providers/TV/EpisodeMetadataService.cs

@@ -25,46 +25,46 @@ namespace MediaBrowser.Providers.TV
         }
 
         /// <inheritdoc />
-        protected override ItemUpdateType BeforeSaveInternal(Episode item, bool isFullRefresh, ItemUpdateType currentUpdateType)
+        protected override ItemUpdateType BeforeSaveInternal(Episode item, bool isFullRefresh, ItemUpdateType updateType)
         {
-            var updateType = base.BeforeSaveInternal(item, isFullRefresh, currentUpdateType);
+            var updatedType = base.BeforeSaveInternal(item, isFullRefresh, updateType);
 
             var seriesName = item.FindSeriesName();
             if (!string.Equals(item.SeriesName, seriesName, StringComparison.Ordinal))
             {
                 item.SeriesName = seriesName;
-                updateType |= ItemUpdateType.MetadataImport;
+                updatedType |= ItemUpdateType.MetadataImport;
             }
 
             var seasonName = item.FindSeasonName();
             if (!string.Equals(item.SeasonName, seasonName, StringComparison.Ordinal))
             {
                 item.SeasonName = seasonName;
-                updateType |= ItemUpdateType.MetadataImport;
+                updatedType |= ItemUpdateType.MetadataImport;
             }
 
             var seriesId = item.FindSeriesId();
             if (!item.SeriesId.Equals(seriesId))
             {
                 item.SeriesId = seriesId;
-                updateType |= ItemUpdateType.MetadataImport;
+                updatedType |= ItemUpdateType.MetadataImport;
             }
 
             var seasonId = item.FindSeasonId();
             if (!item.SeasonId.Equals(seasonId))
             {
                 item.SeasonId = seasonId;
-                updateType |= ItemUpdateType.MetadataImport;
+                updatedType |= ItemUpdateType.MetadataImport;
             }
 
             var seriesPresentationUniqueKey = item.FindSeriesPresentationUniqueKey();
             if (!string.Equals(item.SeriesPresentationUniqueKey, seriesPresentationUniqueKey, StringComparison.Ordinal))
             {
                 item.SeriesPresentationUniqueKey = seriesPresentationUniqueKey;
-                updateType |= ItemUpdateType.MetadataImport;
+                updatedType |= ItemUpdateType.MetadataImport;
             }
 
-            return updateType;
+            return updatedType;
         }
 
         /// <inheritdoc />

+ 7 - 7
MediaBrowser.Providers/TV/SeasonMetadataService.cs

@@ -31,9 +31,9 @@ namespace MediaBrowser.Providers.TV
         protected override bool EnableUpdatingPremiereDateFromChildren => true;
 
         /// <inheritdoc />
-        protected override ItemUpdateType BeforeSaveInternal(Season item, bool isFullRefresh, ItemUpdateType currentUpdateType)
+        protected override ItemUpdateType BeforeSaveInternal(Season item, bool isFullRefresh, ItemUpdateType updateType)
         {
-            var updateType = base.BeforeSaveInternal(item, isFullRefresh, currentUpdateType);
+            var updatedType = base.BeforeSaveInternal(item, isFullRefresh, updateType);
 
             if (item.IndexNumber.HasValue && item.IndexNumber.Value == 0)
             {
@@ -42,7 +42,7 @@ namespace MediaBrowser.Providers.TV
                 if (!string.Equals(item.Name, seasonZeroDisplayName, StringComparison.OrdinalIgnoreCase))
                 {
                     item.Name = seasonZeroDisplayName;
-                    updateType = updateType | ItemUpdateType.MetadataEdit;
+                    updatedType = updatedType | ItemUpdateType.MetadataEdit;
                 }
             }
 
@@ -50,24 +50,24 @@ namespace MediaBrowser.Providers.TV
             if (!string.Equals(item.SeriesName, seriesName, StringComparison.Ordinal))
             {
                 item.SeriesName = seriesName;
-                updateType |= ItemUpdateType.MetadataImport;
+                updatedType |= ItemUpdateType.MetadataImport;
             }
 
             var seriesPresentationUniqueKey = item.FindSeriesPresentationUniqueKey();
             if (!string.Equals(item.SeriesPresentationUniqueKey, seriesPresentationUniqueKey, StringComparison.Ordinal))
             {
                 item.SeriesPresentationUniqueKey = seriesPresentationUniqueKey;
-                updateType |= ItemUpdateType.MetadataImport;
+                updatedType |= ItemUpdateType.MetadataImport;
             }
 
             var seriesId = item.FindSeriesId();
             if (!item.SeriesId.Equals(seriesId))
             {
                 item.SeriesId = seriesId;
-                updateType |= ItemUpdateType.MetadataImport;
+                updatedType |= ItemUpdateType.MetadataImport;
             }
 
-            return updateType;
+            return updatedType;
         }
 
         /// <inheritdoc />