diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs index 858c5b281..ff4a88162 100644 --- a/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs @@ -83,7 +83,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV var seasonNumber = season.IndexNumber.Value; if (string.IsNullOrEmpty(season.Name)) { - var seasonNames = series.SeasonNames; + var seasonNames = series.GetSeasonNames(); if (seasonNames.TryGetValue(seasonNumber, out var seasonName)) { season.Name = seasonName; diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index a49c1609d..d200721b2 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -25,19 +25,18 @@ namespace MediaBrowser.Controller.Entities.TV /// public class Series : Folder, IHasTrailers, IHasDisplayOrder, IHasLookupInfo, IMetadataContainer { + private readonly Dictionary _seasonNames; + public Series() { AirDays = Array.Empty(); - SeasonNames = new Dictionary(); + _seasonNames = new Dictionary(); } public DayOfWeek[] AirDays { get; set; } public string AirTime { get; set; } - [JsonIgnore] - public Dictionary SeasonNames { get; set; } - [JsonIgnore] public override bool SupportsAddingToPlaylist => true; @@ -213,6 +212,26 @@ namespace MediaBrowser.Controller.Entities.TV return LibraryManager.GetItemList(query); } + public Dictionary GetSeasonNames() + { + var newSeasons = Children.OfType() + .Where(s => s.IndexNumber.HasValue) + .Where(s => !_seasonNames.ContainsKey(s.IndexNumber.Value)) + .DistinctBy(s => s.IndexNumber); + + foreach (var season in newSeasons) + { + SetSeasonName(season.IndexNumber.Value, season.Name); + } + + return _seasonNames; + } + + public void SetSeasonName(int index, string name) + { + _seasonNames[index] = name; + } + private void SetSeasonQueryOptions(InternalItemsQuery query, User user) { var seriesKey = GetUniqueSeriesKey(this); diff --git a/MediaBrowser.Providers/TV/SeriesMetadataService.cs b/MediaBrowser.Providers/TV/SeriesMetadataService.cs index 0acc1c805..62eb0d89c 100644 --- a/MediaBrowser.Providers/TV/SeriesMetadataService.cs +++ b/MediaBrowser.Providers/TV/SeriesMetadataService.cs @@ -88,18 +88,22 @@ namespace MediaBrowser.Providers.TV var sourceItem = source.Item; var targetItem = target.Item; - var sourceSeasonNames = sourceItem.SeasonNames; - var targetSeasonNames = targetItem.SeasonNames; + var sourceSeasonNames = sourceItem.GetSeasonNames(); + var targetSeasonNames = targetItem.GetSeasonNames(); - if (replaceData || targetSeasonNames.Count == 0) - { - targetItem.SeasonNames = sourceSeasonNames; - } - else if (targetSeasonNames.Count != sourceSeasonNames.Count || !sourceSeasonNames.Keys.All(targetSeasonNames.ContainsKey)) + if (replaceData) { foreach (var (number, name) in sourceSeasonNames) { - targetSeasonNames.TryAdd(number, name); + targetItem.SetSeasonName(number, name); + } + } + else if (!sourceSeasonNames.Keys.All(targetSeasonNames.ContainsKey)) + { + var newSeasons = sourceSeasonNames.Where(s => !targetSeasonNames.ContainsKey(s.Key)); + foreach (var (number, name) in newSeasons) + { + targetItem.SetSeasonName(number, name); } } @@ -221,7 +225,7 @@ namespace MediaBrowser.Providers.TV /// The async task. private async Task UpdateAndCreateSeasonsAsync(Series series, CancellationToken cancellationToken) { - var seasonNames = series.SeasonNames; + var seasonNames = series.GetSeasonNames(); var seriesChildren = series.GetRecursiveChildren(i => i is Episode || i is Season); var seasons = seriesChildren.OfType().ToList(); var uniqueSeasonNumbers = seriesChildren @@ -245,7 +249,7 @@ namespace MediaBrowser.Providers.TV var season = await CreateSeasonAsync(series, seasonName, seasonNumber, cancellationToken).ConfigureAwait(false); series.AddChild(season); } - else if (!string.Equals(existingSeason.Name, seasonName, StringComparison.Ordinal)) + else if (!existingSeason.LockedFields.Contains(MetadataField.Name) && !string.Equals(existingSeason.Name, seasonName, StringComparison.Ordinal)) { existingSeason.Name = seasonName; await existingSeason.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, cancellationToken).ConfigureAwait(false); diff --git a/MediaBrowser.XbmcMetadata/Parsers/SeriesNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/SeriesNfoParser.cs index dbcfe7997..94df871e9 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/SeriesNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/SeriesNfoParser.cs @@ -107,7 +107,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers if (!string.IsNullOrWhiteSpace(name) && parsed) { - item.SeasonNames[seasonNumber] = name; + item.SetSeasonName(seasonNumber, name); } break;