From a2bb9ca624d0e19f9c59f895790e5717576d27e6 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 13 Jan 2015 23:20:30 -0500 Subject: [PATCH] rework stub seasons --- .../MediaBrowser.Providers.csproj | 1 + .../TV/DummySeasonProvider.cs | 121 ++++++++++++++++++ .../TV/MissingEpisodeProvider.cs | 105 ++------------- .../TV/SeriesPostScanTask.cs | 7 + .../Library/Resolvers/Movies/MovieResolver.cs | 2 +- .../Localization/Server/server.json | 2 +- 6 files changed, 140 insertions(+), 98 deletions(-) create mode 100644 MediaBrowser.Providers/TV/DummySeasonProvider.cs diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 6ac1ab84e6..2df8f8e3c5 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -162,6 +162,7 @@ + diff --git a/MediaBrowser.Providers/TV/DummySeasonProvider.cs b/MediaBrowser.Providers/TV/DummySeasonProvider.cs new file mode 100644 index 0000000000..294c7e20f8 --- /dev/null +++ b/MediaBrowser.Providers/TV/DummySeasonProvider.cs @@ -0,0 +1,121 @@ +using MediaBrowser.Common.Extensions; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities.TV; +using MediaBrowser.Controller.Localization; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Logging; +using System; +using System.Globalization; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Providers.TV +{ + public class DummySeasonProvider + { + private readonly IServerConfigurationManager _config; + private readonly ILogger _logger; + private readonly ILocalizationManager _localization; + + private readonly CultureInfo _usCulture = new CultureInfo("en-US"); + + public DummySeasonProvider(IServerConfigurationManager config, ILogger logger, ILocalizationManager localization) + { + _config = config; + _logger = logger; + _localization = localization; + } + + public async Task Run(Series series, CancellationToken cancellationToken) + { + var hasNewSeasons = await AddDummySeasonFolders(series, cancellationToken).ConfigureAwait(false); + + if (hasNewSeasons) + { + var directoryService = new DirectoryService(); + + //await series.RefreshMetadata(new MetadataRefreshOptions(directoryService), cancellationToken).ConfigureAwait(false); + + //await series.ValidateChildren(new Progress(), cancellationToken, new MetadataRefreshOptions(directoryService)) + // .ConfigureAwait(false); + } + } + + private async Task AddDummySeasonFolders(Series series, CancellationToken cancellationToken) + { + var episodesInSeriesFolder = series.RecursiveChildren + .OfType() + .Where(i => !i.IsInSeasonFolder) + .ToList(); + + var hasChanges = false; + + // Loop through the unique season numbers + foreach (var seasonNumber in episodesInSeriesFolder.Select(i => i.ParentIndexNumber ?? -1) + .Where(i => i >= 0) + .Distinct() + .ToList()) + { + var hasSeason = series.Children.OfType() + .Any(i => i.IndexNumber.HasValue && i.IndexNumber.Value == seasonNumber); + + if (!hasSeason) + { + await AddSeason(series, seasonNumber, cancellationToken).ConfigureAwait(false); + + hasChanges = true; + } + } + + // Unknown season - create a dummy season to put these under + if (episodesInSeriesFolder.Any(i => !i.ParentIndexNumber.HasValue)) + { + var hasSeason = series.Children.OfType() + .Any(i => !i.IndexNumber.HasValue); + + if (!hasSeason) + { + await AddSeason(series, null, cancellationToken).ConfigureAwait(false); + + hasChanges = true; + } + } + + return hasChanges; + } + + /// + /// Adds the season. + /// + /// The series. + /// The season number. + /// The cancellation token. + /// Task{Season}. + public async Task AddSeason(Series series, + int? seasonNumber, + CancellationToken cancellationToken) + { + var seasonName = seasonNumber == 0 ? + _config.Configuration.SeasonZeroDisplayName : + (seasonNumber.HasValue ? string.Format(_localization.GetLocalizedString("NameSeasonNumber"), seasonNumber.Value.ToString(_usCulture)) : _localization.GetLocalizedString("NameSeasonUnknown")); + + _logger.Info("Creating Season {0} entry for {1}", seasonName, series.Name); + + var season = new Season + { + Name = seasonName, + IndexNumber = seasonNumber, + Parent = series, + DisplayMediaType = typeof(Season).Name, + Id = (series.Id + (seasonNumber ?? -1).ToString(_usCulture) + seasonName).GetMBId(typeof(Season)) + }; + + await series.AddChild(season, cancellationToken).ConfigureAwait(false); + + await season.RefreshMetadata(new MetadataRefreshOptions(), cancellationToken).ConfigureAwait(false); + + return season; + } + } +} diff --git a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs index 0b52956de5..707fa6e216 100644 --- a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs +++ b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs @@ -25,7 +25,7 @@ namespace MediaBrowser.Providers.TV private readonly ILibraryManager _libraryManager; private readonly ILocalizationManager _localization; - private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); + private readonly CultureInfo _usCulture = new CultureInfo("en-US"); public MissingEpisodeProvider(ILogger logger, IServerConfigurationManager config, ILibraryManager libraryManager, ILocalizationManager localization) { @@ -78,11 +78,11 @@ namespace MediaBrowser.Providers.TV { int seasonNumber; - if (int.TryParse(parts[1], NumberStyles.Integer, UsCulture, out seasonNumber)) + if (int.TryParse(parts[1], NumberStyles.Integer, _usCulture, out seasonNumber)) { int episodeNumber; - if (int.TryParse(parts[2], NumberStyles.Integer, UsCulture, out episodeNumber)) + if (int.TryParse(parts[2], NumberStyles.Integer, _usCulture, out episodeNumber)) { return new Tuple(seasonNumber, episodeNumber); } @@ -103,12 +103,6 @@ namespace MediaBrowser.Providers.TV .ConfigureAwait(false); var hasNewEpisodes = false; - var hasNewSeasons = false; - - foreach (var series in group) - { - hasNewSeasons = await AddDummySeasonFolders(series, cancellationToken).ConfigureAwait(false); - } if (_config.Configuration.EnableInternetProviders) { @@ -121,7 +115,7 @@ namespace MediaBrowser.Providers.TV } } - if (hasNewSeasons || hasNewEpisodes || anySeasonsRemoved || anyEpisodesRemoved) + if (hasNewEpisodes || anySeasonsRemoved || anyEpisodesRemoved) { foreach (var series in group) { @@ -160,55 +154,6 @@ namespace MediaBrowser.Providers.TV }); } - /// - /// For series with episodes directly under the series folder, this adds dummy seasons to enable regular browsing and metadata - /// - /// - /// - /// - private async Task AddDummySeasonFolders(Series series, CancellationToken cancellationToken) - { - var episodesInSeriesFolder = series.RecursiveChildren - .OfType() - .Where(i => !i.IsInSeasonFolder) - .ToList(); - - var hasChanges = false; - - // Loop through the unique season numbers - foreach (var seasonNumber in episodesInSeriesFolder.Select(i => i.ParentIndexNumber ?? -1) - .Where(i => i >= 0) - .Distinct() - .ToList()) - { - var hasSeason = series.Children.OfType() - .Any(i => i.IndexNumber.HasValue && i.IndexNumber.Value == seasonNumber); - - if (!hasSeason) - { - await AddSeason(series, seasonNumber, cancellationToken).ConfigureAwait(false); - - hasChanges = true; - } - } - - // Unknown season - create a dummy season to put these under - if (episodesInSeriesFolder.Any(i => !i.ParentIndexNumber.HasValue)) - { - var hasSeason = series.Children.OfType() - .Any(i => !i.IndexNumber.HasValue); - - if (!hasSeason) - { - await AddSeason(series, null, cancellationToken).ConfigureAwait(false); - - hasChanges = true; - } - } - - return hasChanges; - } - /// /// Adds the missing episodes. /// @@ -449,10 +394,11 @@ namespace MediaBrowser.Providers.TV if (season == null) { - season = await AddSeason(series, seasonNumber, cancellationToken).ConfigureAwait(false); + var provider = new DummySeasonProvider(_config, _logger, _localization); + season = await provider.AddSeason(series, seasonNumber, cancellationToken).ConfigureAwait(false); } - var name = string.Format("Episode {0}", episodeNumber.ToString(UsCulture)); + var name = string.Format("Episode {0}", episodeNumber.ToString(_usCulture)); var episode = new Episode { @@ -461,7 +407,7 @@ namespace MediaBrowser.Providers.TV ParentIndexNumber = seasonNumber, Parent = season, DisplayMediaType = typeof(Episode).Name, - Id = (series.Id + seasonNumber.ToString(UsCulture) + name).GetMBId(typeof(Episode)) + Id = (series.Id + seasonNumber.ToString(_usCulture) + name).GetMBId(typeof(Episode)) }; await season.AddChild(episode, cancellationToken).ConfigureAwait(false); @@ -471,39 +417,6 @@ namespace MediaBrowser.Providers.TV }, cancellationToken).ConfigureAwait(false); } - /// - /// Adds the season. - /// - /// The series. - /// The season number. - /// The cancellation token. - /// Task{Season}. - private async Task AddSeason(Series series, - int? seasonNumber, - CancellationToken cancellationToken) - { - var seasonName = seasonNumber == 0 ? - _config.Configuration.SeasonZeroDisplayName : - (seasonNumber.HasValue ? string.Format(_localization.GetLocalizedString("NameSeasonNumber"), seasonNumber.Value.ToString(UsCulture)) : _localization.GetLocalizedString("NameSeasonUnknown")); - - _logger.Info("Creating Season {0} entry for {1}", seasonName, series.Name); - - var season = new Season - { - Name = seasonName, - IndexNumber = seasonNumber, - Parent = series, - DisplayMediaType = typeof(Season).Name, - Id = (series.Id + (seasonNumber ?? -1).ToString(UsCulture) + seasonName).GetMBId(typeof(Season)) - }; - - await series.AddChild(season, cancellationToken).ConfigureAwait(false); - - await season.RefreshMetadata(new MetadataRefreshOptions(), cancellationToken).ConfigureAwait(false); - - return season; - } - /// /// Gets the existing episode. /// @@ -551,7 +464,7 @@ namespace MediaBrowser.Providers.TV private DateTime? GetAirDate(string seriesDataPath, int seasonNumber, int episodeNumber) { // First open up the tvdb xml file and make sure it has valid data - var filename = string.Format("episode-{0}-{1}.xml", seasonNumber.ToString(UsCulture), episodeNumber.ToString(UsCulture)); + var filename = string.Format("episode-{0}-{1}.xml", seasonNumber.ToString(_usCulture), episodeNumber.ToString(_usCulture)); var xmlPath = Path.Combine(seriesDataPath, filename); diff --git a/MediaBrowser.Providers/TV/SeriesPostScanTask.cs b/MediaBrowser.Providers/TV/SeriesPostScanTask.cs index 17a219f521..222438485e 100644 --- a/MediaBrowser.Providers/TV/SeriesPostScanTask.cs +++ b/MediaBrowser.Providers/TV/SeriesPostScanTask.cs @@ -48,6 +48,13 @@ namespace MediaBrowser.Providers.TV .OfType() .ToList(); + var provider = new DummySeasonProvider(_config, _logger, _localization); + + foreach (var series in seriesList) + { + await provider.Run(series, cancellationToken).ConfigureAwait(false); + } + var seriesGroups = FindSeriesGroups(seriesList).Where(g => !string.IsNullOrEmpty(g.Key)).ToList(); await new MissingEpisodeProvider(_logger, _config, _libraryManager, _localization).Run(seriesGroups, cancellationToken).ConfigureAwait(false); diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs index 4c0767b08a..96ae281b90 100644 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs +++ b/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs @@ -125,7 +125,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies Items = videos }; - var isInMixedFolder = resolverResult.Count > 0; + var isInMixedFolder = resolverResult.Count > 1; foreach (var video in resolverResult) { diff --git a/MediaBrowser.Server.Implementations/Localization/Server/server.json b/MediaBrowser.Server.Implementations/Localization/Server/server.json index 7bd42507d2..35d58837cb 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/server.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/server.json @@ -300,7 +300,7 @@ "LabelCachePath": "Cache path:", "LabelCachePathHelp": "Specify a custom location for server cache files, such as images.", "LabelImagesByNamePath": "Images by name path:", - "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, artist, genre and studio images.", + "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, genre and studio images.", "LabelMetadataPath": "Metadata path:", "LabelMetadataPathHelp": "Specify a custom location for downloaded artwork and metadata, if not saving within media folders.", "LabelTranscodingTempPath": "Transcoding temporary path:",