From 44bb192ce0e286ced703394f733ca033b489ebc5 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 9 Feb 2014 18:08:01 -0500 Subject: update wizard function of enable/disable local metadata saving --- MediaBrowser.Api/ConfigurationService.cs | 90 ++++++++++ MediaBrowser.Controller/Library/ILibraryManager.cs | 6 +- .../Library/ILibraryPrescanTask.cs | 20 --- .../Library/IPeoplePrescanTask.cs | 20 --- .../MediaBrowser.Controller.csproj | 2 - .../Providers/IProviderManager.cs | 7 + .../Folders/UserRootFolderNameProvider.cs | 42 ----- MediaBrowser.Providers/Manager/MetadataService.cs | 11 +- MediaBrowser.Providers/Manager/ProviderManager.cs | 21 ++- .../MediaBrowser.Providers.csproj | 7 +- .../Movies/FanArtMovieUpdatesPostScanTask.cs | 168 ++++++++++++++++++ .../Movies/FanArtMovieUpdatesPrescanTask.cs | 168 ------------------ .../Music/FanArtUpdatesPostScanTask.cs | 192 +++++++++++++++++++++ .../Music/FanArtUpdatesPrescanTask.cs | 192 --------------------- MediaBrowser.Providers/Savers/AlbumXmlSaver.cs | 2 +- MediaBrowser.Providers/Savers/ArtistXmlSaver.cs | 14 +- MediaBrowser.Providers/Savers/BoxSetXmlSaver.cs | 2 +- MediaBrowser.Providers/Savers/EpisodeXmlSaver.cs | 2 +- MediaBrowser.Providers/Savers/FolderXmlSaver.cs | 11 +- .../Savers/GameSystemXmlSaver.cs | 2 +- MediaBrowser.Providers/Savers/GameXmlSaver.cs | 2 +- MediaBrowser.Providers/Savers/MovieXmlSaver.cs | 2 +- MediaBrowser.Providers/Savers/SeasonXmlSaver.cs | 2 +- MediaBrowser.Providers/Savers/SeriesXmlSaver.cs | 2 +- .../TV/FanArtTvUpdatesPostScanTask.cs | 182 +++++++++++++++++++ .../TV/FanArtTvUpdatesPrescanTask.cs | 182 ------------------- MediaBrowser.Providers/TV/SeriesPostScanTask.cs | 11 +- MediaBrowser.Providers/TV/TvdbPrescanTask.cs | 2 +- .../Library/LibraryManager.cs | 92 ++-------- .../Library/Validators/PeopleValidator.cs | 62 +------ MediaBrowser.ServerApplication/ApplicationHost.cs | 4 +- 31 files changed, 700 insertions(+), 822 deletions(-) delete mode 100644 MediaBrowser.Controller/Library/ILibraryPrescanTask.cs delete mode 100644 MediaBrowser.Controller/Library/IPeoplePrescanTask.cs delete mode 100644 MediaBrowser.Providers/Folders/UserRootFolderNameProvider.cs create mode 100644 MediaBrowser.Providers/Movies/FanArtMovieUpdatesPostScanTask.cs delete mode 100644 MediaBrowser.Providers/Movies/FanArtMovieUpdatesPrescanTask.cs create mode 100644 MediaBrowser.Providers/Music/FanArtUpdatesPostScanTask.cs delete mode 100644 MediaBrowser.Providers/Music/FanArtUpdatesPrescanTask.cs create mode 100644 MediaBrowser.Providers/TV/FanArtTvUpdatesPostScanTask.cs delete mode 100644 MediaBrowser.Providers/TV/FanArtTvUpdatesPrescanTask.cs diff --git a/MediaBrowser.Api/ConfigurationService.cs b/MediaBrowser.Api/ConfigurationService.cs index b2a5fa7a7..98897b9d1 100644 --- a/MediaBrowser.Api/ConfigurationService.cs +++ b/MediaBrowser.Api/ConfigurationService.cs @@ -1,10 +1,15 @@ using MediaBrowser.Common.Extensions; using MediaBrowser.Common.IO; using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Entities.Movies; +using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Serialization; using ServiceStack; +using System; using System.Collections.Generic; using System.Linq; @@ -43,6 +48,13 @@ namespace MediaBrowser.Api } + [Route("/System/Configuration/SaveLocalMetadata", "POST")] + [Api(("Updates saving of local metadata and images for all types"))] + public class UpdateSaveLocalMetadata : IReturnVoid + { + public bool Enabled { get; set; } + } + public class ConfigurationService : BaseApiService { /// @@ -106,5 +118,83 @@ namespace MediaBrowser.Api { return ToOptimizedSerializedResultUsingCache(_providerManager.GetAllMetadataPlugins().ToList()); } + + /// + /// This is a temporary method used until image settings get broken out. + /// + /// + public void Post(UpdateSaveLocalMetadata request) + { + var config = _configurationManager.Configuration; + + if (request.Enabled) + { + config.SaveLocalMeta = true; + + foreach (var options in config.MetadataOptions) + { + options.DisabledMetadataSavers = new string[] { }; + } + } + else + { + config.SaveLocalMeta = false; + + DisableSaversForType(typeof(Game), config); + DisableSaversForType(typeof(GameSystem), config); + DisableSaversForType(typeof(Movie), config); + DisableSaversForType(typeof(Trailer), config); + DisableSaversForType(typeof(BoxSet), config); + DisableSaversForType(typeof(Book), config); + DisableSaversForType(typeof(Series), config); + DisableSaversForType(typeof(Season), config); + DisableSaversForType(typeof(Episode), config); + DisableSaversForType(typeof(MusicAlbum), config); + DisableSaversForType(typeof(MusicArtist), config); + DisableSaversForType(typeof(AdultVideo), config); + DisableSaversForType(typeof(MusicVideo), config); + DisableSaversForType(typeof(Video), config); + } + + _configurationManager.SaveConfiguration(); + } + + private void DisableSaversForType(Type type, ServerConfiguration config) + { + var options = GetMetadataOptions(type, config); + + const string mediabrowserSaverName = "Media Browser Xml"; + + if (!options.DisabledMetadataSavers.Contains(mediabrowserSaverName, StringComparer.OrdinalIgnoreCase)) + { + var list = options.DisabledMetadataSavers.ToList(); + + list.Add(mediabrowserSaverName); + + options.DisabledMetadataSavers = list.ToArray(); + } + } + + private MetadataOptions GetMetadataOptions(Type type, ServerConfiguration config) + { + var options = config.MetadataOptions + .FirstOrDefault(i => string.Equals(i.ItemType, type.Name, StringComparison.OrdinalIgnoreCase)); + + if (options == null) + { + var list = config.MetadataOptions.ToList(); + + options = new MetadataOptions + { + ItemType = type.Name + }; + + list.Add(options); + + config.MetadataOptions = list.ToArray(); + } + + return options; + } } } diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index d8ba019db..7c803e651 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -162,17 +162,13 @@ namespace MediaBrowser.Controller.Library /// The resolvers. /// The intro providers. /// The item comparers. - /// The prescan tasks. /// The postscan tasks. - /// The people prescan tasks. void AddParts(IEnumerable rules, IEnumerable pluginFolders, IEnumerable resolvers, IEnumerable introProviders, IEnumerable itemComparers, - IEnumerable prescanTasks, - IEnumerable postscanTasks, - IEnumerable peoplePrescanTasks); + IEnumerable postscanTasks); /// /// Sorts the specified items. diff --git a/MediaBrowser.Controller/Library/ILibraryPrescanTask.cs b/MediaBrowser.Controller/Library/ILibraryPrescanTask.cs deleted file mode 100644 index 6a48ba777..000000000 --- a/MediaBrowser.Controller/Library/ILibraryPrescanTask.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Controller.Library -{ - /// - /// An interface for tasks that run prior to the media library scan - /// - public interface ILibraryPrescanTask - { - /// - /// Runs the specified progress. - /// - /// The progress. - /// The cancellation token. - /// Task. - Task Run(IProgress progress, CancellationToken cancellationToken); - } -} diff --git a/MediaBrowser.Controller/Library/IPeoplePrescanTask.cs b/MediaBrowser.Controller/Library/IPeoplePrescanTask.cs deleted file mode 100644 index 04d179bae..000000000 --- a/MediaBrowser.Controller/Library/IPeoplePrescanTask.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Controller.Library -{ - /// - /// Interface IPeoplePrescanTask - /// - public interface IPeoplePrescanTask - { - /// - /// Runs the specified progress. - /// - /// The progress. - /// The cancellation token. - /// Task. - Task Run(IProgress progress, CancellationToken cancellationToken); - } -} diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index efc74e483..18ac01c8b 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -111,9 +111,7 @@ - - diff --git a/MediaBrowser.Controller/Providers/IProviderManager.cs b/MediaBrowser.Controller/Providers/IProviderManager.cs index 4475642cd..e7eb27503 100644 --- a/MediaBrowser.Controller/Providers/IProviderManager.cs +++ b/MediaBrowser.Controller/Providers/IProviderManager.cs @@ -88,5 +88,12 @@ namespace MediaBrowser.Controller.Providers /// Type of the update. /// Task. Task SaveMetadata(IHasMetadata item, ItemUpdateType updateType); + + /// + /// Gets the metadata options. + /// + /// The item. + /// MetadataOptions. + MetadataOptions GetMetadataOptions(IHasMetadata item); } } \ No newline at end of file diff --git a/MediaBrowser.Providers/Folders/UserRootFolderNameProvider.cs b/MediaBrowser.Providers/Folders/UserRootFolderNameProvider.cs deleted file mode 100644 index 043e32d11..000000000 --- a/MediaBrowser.Providers/Folders/UserRootFolderNameProvider.cs +++ /dev/null @@ -1,42 +0,0 @@ -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Logging; -using System; -using System.IO; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Providers.Folders -{ - public class UserRootFolderNameProvider : BaseMetadataProvider - { - public UserRootFolderNameProvider(ILogManager logManager, IServerConfigurationManager configurationManager) - : base(logManager, configurationManager) - { - } - - public override bool Supports(BaseItem item) - { - return item is UserRootFolder; - } - - public override Task FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) - { - var parentName = Path.GetFileNameWithoutExtension(item.Path); - - if (string.Equals(parentName, "default", StringComparison.OrdinalIgnoreCase)) - { - item.Name = "Media Library"; - } - - SetLastRefreshed(item, DateTime.UtcNow, providerInfo); - return TrueTaskResult; - } - - public override MetadataProviderPriority Priority - { - get { return MetadataProviderPriority.First; } - } - } -} diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index f7c2cef94..93879d826 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -71,7 +71,7 @@ namespace MediaBrowser.Providers.Manager } var itemOfType = (TItemType)item; - var config = GetMetadataOptions(itemOfType); + var config = ProviderManager.GetMetadataOptions(item); var updateType = ItemUpdateType.Unspecified; var refreshResult = GetLastResult(item.Id); @@ -157,15 +157,6 @@ namespace MediaBrowser.Providers.Manager } } - private readonly MetadataOptions _defaultOptions = new MetadataOptions(); - protected MetadataOptions GetMetadataOptions(TItemType item) - { - var type = item.GetType().Name; - return ServerConfigurationManager.Configuration.MetadataOptions - .FirstOrDefault(i => string.Equals(i.ItemType, type, StringComparison.OrdinalIgnoreCase)) ?? - _defaultOptions; - } - /// /// Befores the metadata refresh. /// diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index fd19d572c..a6817cf32 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -470,7 +470,7 @@ namespace MediaBrowser.Providers.Manager })); // Savers - list.AddRange(_savers.Where(i => IsSaverEnabledForItem(i, item, ItemUpdateType.MetadataEdit)).OrderBy(i => i.Name).Select(i => new MetadataPlugin + list.AddRange(_savers.Where(i => IsSaverEnabledForItem(i, item, ItemUpdateType.MetadataEdit, false)).OrderBy(i => i.Name).Select(i => new MetadataPlugin { Name = i.Name, Type = MetadataPluginType.MetadataSaver @@ -498,6 +498,14 @@ namespace MediaBrowser.Providers.Manager private readonly ConcurrentDictionary _fileLocks = new ConcurrentDictionary(); + public MetadataOptions GetMetadataOptions(IHasMetadata item) + { + var type = item.GetType().Name; + return ConfigurationManager.Configuration.MetadataOptions + .FirstOrDefault(i => string.Equals(i.ItemType, type, StringComparison.OrdinalIgnoreCase)) ?? + new MetadataOptions(); + } + /// /// Saves the metadata. /// @@ -506,7 +514,7 @@ namespace MediaBrowser.Providers.Manager /// Task. public async Task SaveMetadata(IHasMetadata item, ItemUpdateType updateType) { - foreach (var saver in _savers.Where(i => IsSaverEnabledForItem(i, item, updateType))) + foreach (var saver in _savers.Where(i => IsSaverEnabledForItem(i, item, updateType, true))) { _logger.Debug("Saving {0} to {1}.", item.Path ?? item.Name, saver.Name); @@ -559,10 +567,17 @@ namespace MediaBrowser.Providers.Manager } } - private bool IsSaverEnabledForItem(IMetadataSaver saver, IHasMetadata item, ItemUpdateType updateType) + private bool IsSaverEnabledForItem(IMetadataSaver saver, IHasMetadata item, ItemUpdateType updateType, bool enforceConfiguration) { + var options = GetMetadataOptions(item); + try { + if (enforceConfiguration && options.DisabledMetadataSavers.Contains(saver.Name, StringComparer.OrdinalIgnoreCase)) + { + return false; + } + return saver.IsEnabledFor(item, updateType); } catch (Exception ex) diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 672cd86a6..5cf4b2591 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -135,11 +135,11 @@ - + - + @@ -172,7 +172,7 @@ - + @@ -190,7 +190,6 @@ - diff --git a/MediaBrowser.Providers/Movies/FanArtMovieUpdatesPostScanTask.cs b/MediaBrowser.Providers/Movies/FanArtMovieUpdatesPostScanTask.cs new file mode 100644 index 000000000..6f911d411 --- /dev/null +++ b/MediaBrowser.Providers/Movies/FanArtMovieUpdatesPostScanTask.cs @@ -0,0 +1,168 @@ +using MediaBrowser.Common.IO; +using MediaBrowser.Common.Net; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Library; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Serialization; +using MediaBrowser.Providers.Music; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Providers.Movies +{ + class FanartMovieUpdatesPostScanTask : ILibraryPostScanTask + { + private const string UpdatesUrl = "http://api.fanart.tv/webservice/newmovies/{0}/{1}/"; + + /// + /// The _HTTP client + /// + private readonly IHttpClient _httpClient; + /// + /// The _logger + /// + private readonly ILogger _logger; + /// + /// The _config + /// + private readonly IServerConfigurationManager _config; + private readonly IJsonSerializer _jsonSerializer; + private readonly IFileSystem _fileSystem; + + private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); + + public FanartMovieUpdatesPostScanTask(IJsonSerializer jsonSerializer, IServerConfigurationManager config, ILogger logger, IHttpClient httpClient, IFileSystem fileSystem) + { + _jsonSerializer = jsonSerializer; + _config = config; + _logger = logger; + _httpClient = httpClient; + _fileSystem = fileSystem; + } + + /// + /// Runs the specified progress. + /// + /// The progress. + /// The cancellation token. + /// Task. + public async Task Run(IProgress progress, CancellationToken cancellationToken) + { + if (!_config.Configuration.EnableInternetProviders || !_config.Configuration.EnableFanArtUpdates) + { + progress.Report(100); + return; + } + + var path = FanartMovieImageProvider.GetMoviesDataPath(_config.CommonApplicationPaths); + + Directory.CreateDirectory(path); + + var timestampFile = Path.Combine(path, "time.txt"); + + var timestampFileInfo = new FileInfo(timestampFile); + + // Don't check for updates every single time + if (timestampFileInfo.Exists && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(timestampFileInfo)).TotalDays < 3) + { + return; + } + + // Find out the last time we queried for updates + var lastUpdateTime = timestampFileInfo.Exists ? File.ReadAllText(timestampFile, Encoding.UTF8) : string.Empty; + + var existingDirectories = Directory.EnumerateDirectories(path).Select(Path.GetFileName).ToList(); + + // If this is our first time, don't do any updates and just record the timestamp + if (!string.IsNullOrEmpty(lastUpdateTime)) + { + var moviesToUpdate = await GetMovieIdsToUpdate(existingDirectories, lastUpdateTime, cancellationToken).ConfigureAwait(false); + + progress.Report(5); + + await UpdateMovies(moviesToUpdate, progress, cancellationToken).ConfigureAwait(false); + } + + var newUpdateTime = Convert.ToInt64(DateTimeToUnixTimestamp(DateTime.UtcNow)).ToString(UsCulture); + + File.WriteAllText(timestampFile, newUpdateTime, Encoding.UTF8); + + progress.Report(100); + } + + private async Task> GetMovieIdsToUpdate(IEnumerable existingIds, string lastUpdateTime, CancellationToken cancellationToken) + { + // First get last time + using (var stream = await _httpClient.Get(new HttpRequestOptions + { + Url = string.Format(UpdatesUrl, FanartArtistProvider.ApiKey, lastUpdateTime), + CancellationToken = cancellationToken, + EnableHttpCompression = true, + ResourcePool = FanartArtistProvider.FanArtResourcePool + + }).ConfigureAwait(false)) + { + using (var reader = new StreamReader(stream)) + { + var json = await reader.ReadToEndAsync().ConfigureAwait(false); + + // If empty fanart will return a string of "null", rather than an empty list + if (string.Equals(json, "null", StringComparison.OrdinalIgnoreCase)) + { + return new List(); + } + + var updates = _jsonSerializer.DeserializeFromString>(json); + + var existingDictionary = existingIds.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase); + + return updates.Select(i => i.id).Where(existingDictionary.ContainsKey); + } + } + } + + private async Task UpdateMovies(IEnumerable idList, IProgress progress, CancellationToken cancellationToken) + { + var list = idList.ToList(); + var numComplete = 0; + + foreach (var id in list) + { + _logger.Info("Updating movie " + id); + + await FanartMovieImageProvider.Current.DownloadMovieXml(id, cancellationToken).ConfigureAwait(false); + + numComplete++; + double percent = numComplete; + percent /= list.Count; + percent *= 95; + + progress.Report(percent + 5); + } + } + + /// + /// Dates the time to unix timestamp. + /// + /// The date time. + /// System.Double. + private static double DateTimeToUnixTimestamp(DateTime dateTime) + { + return (dateTime - new DateTime(1970, 1, 1).ToUniversalTime()).TotalSeconds; + } + + public class FanArtUpdate + { + public string id { get; set; } + public string name { get; set; } + public string new_images { get; set; } + public string total_images { get; set; } + } + } +} diff --git a/MediaBrowser.Providers/Movies/FanArtMovieUpdatesPrescanTask.cs b/MediaBrowser.Providers/Movies/FanArtMovieUpdatesPrescanTask.cs deleted file mode 100644 index 600ba1925..000000000 --- a/MediaBrowser.Providers/Movies/FanArtMovieUpdatesPrescanTask.cs +++ /dev/null @@ -1,168 +0,0 @@ -using MediaBrowser.Common.IO; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Serialization; -using MediaBrowser.Providers.Music; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Providers.Movies -{ - class FanartMovieUpdatesPrescanTask : ILibraryPostScanTask - { - private const string UpdatesUrl = "http://api.fanart.tv/webservice/newmovies/{0}/{1}/"; - - /// - /// The _HTTP client - /// - private readonly IHttpClient _httpClient; - /// - /// The _logger - /// - private readonly ILogger _logger; - /// - /// The _config - /// - private readonly IServerConfigurationManager _config; - private readonly IJsonSerializer _jsonSerializer; - private readonly IFileSystem _fileSystem; - - private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); - - public FanartMovieUpdatesPrescanTask(IJsonSerializer jsonSerializer, IServerConfigurationManager config, ILogger logger, IHttpClient httpClient, IFileSystem fileSystem) - { - _jsonSerializer = jsonSerializer; - _config = config; - _logger = logger; - _httpClient = httpClient; - _fileSystem = fileSystem; - } - - /// - /// Runs the specified progress. - /// - /// The progress. - /// The cancellation token. - /// Task. - public async Task Run(IProgress progress, CancellationToken cancellationToken) - { - if (!_config.Configuration.EnableInternetProviders || !_config.Configuration.EnableFanArtUpdates) - { - progress.Report(100); - return; - } - - var path = FanartMovieImageProvider.GetMoviesDataPath(_config.CommonApplicationPaths); - - Directory.CreateDirectory(path); - - var timestampFile = Path.Combine(path, "time.txt"); - - var timestampFileInfo = new FileInfo(timestampFile); - - // Don't check for updates every single time - if (timestampFileInfo.Exists && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(timestampFileInfo)).TotalDays < 3) - { - return; - } - - // Find out the last time we queried for updates - var lastUpdateTime = timestampFileInfo.Exists ? File.ReadAllText(timestampFile, Encoding.UTF8) : string.Empty; - - var existingDirectories = Directory.EnumerateDirectories(path).Select(Path.GetFileName).ToList(); - - // If this is our first time, don't do any updates and just record the timestamp - if (!string.IsNullOrEmpty(lastUpdateTime)) - { - var moviesToUpdate = await GetMovieIdsToUpdate(existingDirectories, lastUpdateTime, cancellationToken).ConfigureAwait(false); - - progress.Report(5); - - await UpdateMovies(moviesToUpdate, progress, cancellationToken).ConfigureAwait(false); - } - - var newUpdateTime = Convert.ToInt64(DateTimeToUnixTimestamp(DateTime.UtcNow)).ToString(UsCulture); - - File.WriteAllText(timestampFile, newUpdateTime, Encoding.UTF8); - - progress.Report(100); - } - - private async Task> GetMovieIdsToUpdate(IEnumerable existingIds, string lastUpdateTime, CancellationToken cancellationToken) - { - // First get last time - using (var stream = await _httpClient.Get(new HttpRequestOptions - { - Url = string.Format(UpdatesUrl, FanartArtistProvider.ApiKey, lastUpdateTime), - CancellationToken = cancellationToken, - EnableHttpCompression = true, - ResourcePool = FanartArtistProvider.FanArtResourcePool - - }).ConfigureAwait(false)) - { - using (var reader = new StreamReader(stream)) - { - var json = await reader.ReadToEndAsync().ConfigureAwait(false); - - // If empty fanart will return a string of "null", rather than an empty list - if (string.Equals(json, "null", StringComparison.OrdinalIgnoreCase)) - { - return new List(); - } - - var updates = _jsonSerializer.DeserializeFromString>(json); - - var existingDictionary = existingIds.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase); - - return updates.Select(i => i.id).Where(existingDictionary.ContainsKey); - } - } - } - - private async Task UpdateMovies(IEnumerable idList, IProgress progress, CancellationToken cancellationToken) - { - var list = idList.ToList(); - var numComplete = 0; - - foreach (var id in list) - { - _logger.Info("Updating movie " + id); - - await FanartMovieImageProvider.Current.DownloadMovieXml(id, cancellationToken).ConfigureAwait(false); - - numComplete++; - double percent = numComplete; - percent /= list.Count; - percent *= 95; - - progress.Report(percent + 5); - } - } - - /// - /// Dates the time to unix timestamp. - /// - /// The date time. - /// System.Double. - private static double DateTimeToUnixTimestamp(DateTime dateTime) - { - return (dateTime - new DateTime(1970, 1, 1).ToUniversalTime()).TotalSeconds; - } - - public class FanArtUpdate - { - public string id { get; set; } - public string name { get; set; } - public string new_images { get; set; } - public string total_images { get; set; } - } - } -} diff --git a/MediaBrowser.Providers/Music/FanArtUpdatesPostScanTask.cs b/MediaBrowser.Providers/Music/FanArtUpdatesPostScanTask.cs new file mode 100644 index 000000000..9d24490b2 --- /dev/null +++ b/MediaBrowser.Providers/Music/FanArtUpdatesPostScanTask.cs @@ -0,0 +1,192 @@ +using MediaBrowser.Common.IO; +using MediaBrowser.Common.Net; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Library; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Serialization; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Providers.Music +{ + class FanartUpdatesPostScanTask : ILibraryPostScanTask + { + private const string UpdatesUrl = "http://api.fanart.tv/webservice/newmusic/{0}/{1}/"; + + /// + /// The _HTTP client + /// + private readonly IHttpClient _httpClient; + /// + /// The _logger + /// + private readonly ILogger _logger; + /// + /// The _config + /// + private readonly IServerConfigurationManager _config; + private readonly IJsonSerializer _jsonSerializer; + private readonly IFileSystem _fileSystem; + + private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); + + public FanartUpdatesPostScanTask(IJsonSerializer jsonSerializer, IServerConfigurationManager config, ILogger logger, IHttpClient httpClient, IFileSystem fileSystem) + { + _jsonSerializer = jsonSerializer; + _config = config; + _logger = logger; + _httpClient = httpClient; + _fileSystem = fileSystem; + } + + /// + /// Runs the specified progress. + /// + /// The progress. + /// The cancellation token. + /// Task. + public async Task Run(IProgress progress, CancellationToken cancellationToken) + { + if (!_config.Configuration.EnableInternetProviders || !_config.Configuration.EnableFanArtUpdates) + { + progress.Report(100); + return; + } + + var path = FanartArtistProvider.GetArtistDataPath(_config.CommonApplicationPaths); + + Directory.CreateDirectory(path); + + var timestampFile = Path.Combine(path, "time.txt"); + + var timestampFileInfo = new FileInfo(timestampFile); + + // Don't check for updates every single time + if (timestampFileInfo.Exists && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(timestampFileInfo)).TotalDays < 3) + { + return; + } + + // Find out the last time we queried for updates + var lastUpdateTime = timestampFileInfo.Exists ? File.ReadAllText(timestampFile, Encoding.UTF8) : string.Empty; + + var existingDirectories = Directory.EnumerateDirectories(path).Select(Path.GetFileName).ToList(); + + // If this is our first time, don't do any updates and just record the timestamp + if (!string.IsNullOrEmpty(lastUpdateTime)) + { + var artistsToUpdate = await GetArtistIdsToUpdate(existingDirectories, lastUpdateTime, cancellationToken).ConfigureAwait(false); + + progress.Report(5); + + await UpdateArtists(artistsToUpdate, progress, cancellationToken).ConfigureAwait(false); + } + + var newUpdateTime = Convert.ToInt64(DateTimeToUnixTimestamp(DateTime.UtcNow)).ToString(UsCulture); + + File.WriteAllText(timestampFile, newUpdateTime, Encoding.UTF8); + + progress.Report(100); + } + + /// + /// Gets the artist ids to update. + /// + /// The existing series ids. + /// The last update time. + /// The cancellation token. + /// Task{IEnumerable{System.String}}. + private async Task> GetArtistIdsToUpdate(IEnumerable existingArtistIds, string lastUpdateTime, CancellationToken cancellationToken) + { + // First get last time + using (var stream = await _httpClient.Get(new HttpRequestOptions + { + Url = string.Format(UpdatesUrl, FanartArtistProvider.ApiKey, lastUpdateTime), + CancellationToken = cancellationToken, + EnableHttpCompression = true, + ResourcePool = FanartArtistProvider.FanArtResourcePool + + }).ConfigureAwait(false)) + { + // If empty fanart will return a string of "null", rather than an empty list + using (var reader = new StreamReader(stream)) + { + var json = await reader.ReadToEndAsync().ConfigureAwait(false); + + if (string.Equals(json, "null", StringComparison.OrdinalIgnoreCase)) + { + return new List(); + } + + var existingDictionary = existingArtistIds.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase); + + var updates = _jsonSerializer.DeserializeFromString>(json); + + return updates.Select(i => i.id).Where(existingDictionary.ContainsKey); + } + } + } + + /// + /// Updates the artists. + /// + /// The id list. + /// The progress. + /// The cancellation token. + /// Task. + private async Task UpdateArtists(IEnumerable idList, IProgress progress, CancellationToken cancellationToken) + { + var list = idList.ToList(); + var numComplete = 0; + + foreach (var id in list) + { + await UpdateArtist(id, cancellationToken).ConfigureAwait(false); + + numComplete++; + double percent = numComplete; + percent /= list.Count; + percent *= 95; + + progress.Report(percent + 5); + } + } + + /// + /// Updates the artist. + /// + /// The musicBrainzId. + /// The cancellation token. + /// Task. + private Task UpdateArtist(string musicBrainzId, CancellationToken cancellationToken) + { + _logger.Info("Updating artist " + musicBrainzId); + + return FanartArtistProvider.Current.DownloadArtistXml(musicBrainzId, cancellationToken); + } + + /// + /// Dates the time to unix timestamp. + /// + /// The date time. + /// System.Double. + private static double DateTimeToUnixTimestamp(DateTime dateTime) + { + return (dateTime - new DateTime(1970, 1, 1).ToUniversalTime()).TotalSeconds; + } + + public class FanArtUpdate + { + public string id { get; set; } + public string name { get; set; } + public string new_images { get; set; } + public string total_images { get; set; } + } + } +} diff --git a/MediaBrowser.Providers/Music/FanArtUpdatesPrescanTask.cs b/MediaBrowser.Providers/Music/FanArtUpdatesPrescanTask.cs deleted file mode 100644 index d002c02f2..000000000 --- a/MediaBrowser.Providers/Music/FanArtUpdatesPrescanTask.cs +++ /dev/null @@ -1,192 +0,0 @@ -using MediaBrowser.Common.IO; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Serialization; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Providers.Music -{ - class FanartUpdatesPrescanTask : ILibraryPostScanTask - { - private const string UpdatesUrl = "http://api.fanart.tv/webservice/newmusic/{0}/{1}/"; - - /// - /// The _HTTP client - /// - private readonly IHttpClient _httpClient; - /// - /// The _logger - /// - private readonly ILogger _logger; - /// - /// The _config - /// - private readonly IServerConfigurationManager _config; - private readonly IJsonSerializer _jsonSerializer; - private readonly IFileSystem _fileSystem; - - private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); - - public FanartUpdatesPrescanTask(IJsonSerializer jsonSerializer, IServerConfigurationManager config, ILogger logger, IHttpClient httpClient, IFileSystem fileSystem) - { - _jsonSerializer = jsonSerializer; - _config = config; - _logger = logger; - _httpClient = httpClient; - _fileSystem = fileSystem; - } - - /// - /// Runs the specified progress. - /// - /// The progress. - /// The cancellation token. - /// Task. - public async Task Run(IProgress progress, CancellationToken cancellationToken) - { - if (!_config.Configuration.EnableInternetProviders || !_config.Configuration.EnableFanArtUpdates) - { - progress.Report(100); - return; - } - - var path = FanartArtistProvider.GetArtistDataPath(_config.CommonApplicationPaths); - - Directory.CreateDirectory(path); - - var timestampFile = Path.Combine(path, "time.txt"); - - var timestampFileInfo = new FileInfo(timestampFile); - - // Don't check for updates every single time - if (timestampFileInfo.Exists && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(timestampFileInfo)).TotalDays < 3) - { - return; - } - - // Find out the last time we queried for updates - var lastUpdateTime = timestampFileInfo.Exists ? File.ReadAllText(timestampFile, Encoding.UTF8) : string.Empty; - - var existingDirectories = Directory.EnumerateDirectories(path).Select(Path.GetFileName).ToList(); - - // If this is our first time, don't do any updates and just record the timestamp - if (!string.IsNullOrEmpty(lastUpdateTime)) - { - var artistsToUpdate = await GetArtistIdsToUpdate(existingDirectories, lastUpdateTime, cancellationToken).ConfigureAwait(false); - - progress.Report(5); - - await UpdateArtists(artistsToUpdate, progress, cancellationToken).ConfigureAwait(false); - } - - var newUpdateTime = Convert.ToInt64(DateTimeToUnixTimestamp(DateTime.UtcNow)).ToString(UsCulture); - - File.WriteAllText(timestampFile, newUpdateTime, Encoding.UTF8); - - progress.Report(100); - } - - /// - /// Gets the artist ids to update. - /// - /// The existing series ids. - /// The last update time. - /// The cancellation token. - /// Task{IEnumerable{System.String}}. - private async Task> GetArtistIdsToUpdate(IEnumerable existingArtistIds, string lastUpdateTime, CancellationToken cancellationToken) - { - // First get last time - using (var stream = await _httpClient.Get(new HttpRequestOptions - { - Url = string.Format(UpdatesUrl, FanartArtistProvider.ApiKey, lastUpdateTime), - CancellationToken = cancellationToken, - EnableHttpCompression = true, - ResourcePool = FanartArtistProvider.FanArtResourcePool - - }).ConfigureAwait(false)) - { - // If empty fanart will return a string of "null", rather than an empty list - using (var reader = new StreamReader(stream)) - { - var json = await reader.ReadToEndAsync().ConfigureAwait(false); - - if (string.Equals(json, "null", StringComparison.OrdinalIgnoreCase)) - { - return new List(); - } - - var existingDictionary = existingArtistIds.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase); - - var updates = _jsonSerializer.DeserializeFromString>(json); - - return updates.Select(i => i.id).Where(existingDictionary.ContainsKey); - } - } - } - - /// - /// Updates the artists. - /// - /// The id list. - /// The progress. - /// The cancellation token. - /// Task. - private async Task UpdateArtists(IEnumerable idList, IProgress progress, CancellationToken cancellationToken) - { - var list = idList.ToList(); - var numComplete = 0; - - foreach (var id in list) - { - await UpdateArtist(id, cancellationToken).ConfigureAwait(false); - - numComplete++; - double percent = numComplete; - percent /= list.Count; - percent *= 95; - - progress.Report(percent + 5); - } - } - - /// - /// Updates the artist. - /// - /// The musicBrainzId. - /// The cancellation token. - /// Task. - private Task UpdateArtist(string musicBrainzId, CancellationToken cancellationToken) - { - _logger.Info("Updating artist " + musicBrainzId); - - return FanartArtistProvider.Current.DownloadArtistXml(musicBrainzId, cancellationToken); - } - - /// - /// Dates the time to unix timestamp. - /// - /// The date time. - /// System.Double. - private static double DateTimeToUnixTimestamp(DateTime dateTime) - { - return (dateTime - new DateTime(1970, 1, 1).ToUniversalTime()).TotalSeconds; - } - - public class FanArtUpdate - { - public string id { get; set; } - public string name { get; set; } - public string new_images { get; set; } - public string total_images { get; set; } - } - } -} diff --git a/MediaBrowser.Providers/Savers/AlbumXmlSaver.cs b/MediaBrowser.Providers/Savers/AlbumXmlSaver.cs index 74c507394..a1595bce1 100644 --- a/MediaBrowser.Providers/Savers/AlbumXmlSaver.cs +++ b/MediaBrowser.Providers/Savers/AlbumXmlSaver.cs @@ -46,7 +46,7 @@ namespace MediaBrowser.Providers.Savers var wasMetadataDownloaded = (updateType & ItemUpdateType.MetadataDownload) == ItemUpdateType.MetadataDownload; // If new metadata has been downloaded and save local is on - if (item.IsSaveLocalMetadataEnabled() && (wasMetadataEdited || wasMetadataDownloaded)) + if (wasMetadataEdited || wasMetadataDownloaded) { return item is MusicAlbum; } diff --git a/MediaBrowser.Providers/Savers/ArtistXmlSaver.cs b/MediaBrowser.Providers/Savers/ArtistXmlSaver.cs index c5c564fba..5a7b85205 100644 --- a/MediaBrowser.Providers/Savers/ArtistXmlSaver.cs +++ b/MediaBrowser.Providers/Savers/ArtistXmlSaver.cs @@ -47,20 +47,10 @@ namespace MediaBrowser.Providers.Savers var wasMetadataEdited = (updateType & ItemUpdateType.MetadataEdit) == ItemUpdateType.MetadataEdit; var wasMetadataDownloaded = (updateType & ItemUpdateType.MetadataDownload) == ItemUpdateType.MetadataDownload; - // If new metadata has been downloaded and save local is on - if (item.IsSaveLocalMetadataEnabled() && (wasMetadataEdited || wasMetadataDownloaded)) - { - if (item is MusicArtist) - { - return true; - } - } - // If new metadata has been downloaded or metadata was manually edited, proceed - if (wasMetadataDownloaded || wasMetadataEdited) + if (wasMetadataEdited || wasMetadataDownloaded) { - var artist = item as MusicArtist; - if (artist != null && artist.IsAccessedByName) + if (item is MusicArtist) { return true; } diff --git a/MediaBrowser.Providers/Savers/BoxSetXmlSaver.cs b/MediaBrowser.Providers/Savers/BoxSetXmlSaver.cs index fb5c57095..7b142b68e 100644 --- a/MediaBrowser.Providers/Savers/BoxSetXmlSaver.cs +++ b/MediaBrowser.Providers/Savers/BoxSetXmlSaver.cs @@ -46,7 +46,7 @@ namespace MediaBrowser.Providers.Savers var wasMetadataDownloaded = (updateType & ItemUpdateType.MetadataDownload) == ItemUpdateType.MetadataDownload; // If new metadata has been downloaded and save local is on - if (item.IsSaveLocalMetadataEnabled() && (wasMetadataEdited || wasMetadataDownloaded)) + if (wasMetadataEdited || wasMetadataDownloaded) { return item is BoxSet; } diff --git a/MediaBrowser.Providers/Savers/EpisodeXmlSaver.cs b/MediaBrowser.Providers/Savers/EpisodeXmlSaver.cs index f9932ce75..af73791c9 100644 --- a/MediaBrowser.Providers/Savers/EpisodeXmlSaver.cs +++ b/MediaBrowser.Providers/Savers/EpisodeXmlSaver.cs @@ -37,7 +37,7 @@ namespace MediaBrowser.Providers.Savers var wasMetadataDownloaded = (updateType & ItemUpdateType.MetadataDownload) == ItemUpdateType.MetadataDownload; // If new metadata has been downloaded and save local is on - if (item.IsSaveLocalMetadataEnabled() && (wasMetadataEdited || wasMetadataDownloaded)) + if (wasMetadataEdited || wasMetadataDownloaded) { return item is Episode; } diff --git a/MediaBrowser.Providers/Savers/FolderXmlSaver.cs b/MediaBrowser.Providers/Savers/FolderXmlSaver.cs index 5c21443ce..40e1ab019 100644 --- a/MediaBrowser.Providers/Savers/FolderXmlSaver.cs +++ b/MediaBrowser.Providers/Savers/FolderXmlSaver.cs @@ -55,7 +55,7 @@ namespace MediaBrowser.Providers.Savers var wasMetadataDownloaded = (updateType & ItemUpdateType.MetadataDownload) == ItemUpdateType.MetadataDownload; // If new metadata has been downloaded and save local is on - if (item.IsSaveLocalMetadataEnabled() && (wasMetadataEdited || wasMetadataDownloaded)) + if (wasMetadataEdited || wasMetadataDownloaded) { if (!(item is Series) && !(item is BoxSet) && !(item is MusicArtist) && !(item is MusicAlbum) && !(item is Season) && @@ -65,15 +65,6 @@ namespace MediaBrowser.Providers.Savers } } - // If new metadata has been downloaded or metadata was manually edited, proceed - if (wasMetadataDownloaded || wasMetadataEdited) - { - if (item is AggregateFolder || item is UserRootFolder || item is CollectionFolder) - { - return true; - } - } - return false; } diff --git a/MediaBrowser.Providers/Savers/GameSystemXmlSaver.cs b/MediaBrowser.Providers/Savers/GameSystemXmlSaver.cs index f0d34df08..020f8987c 100644 --- a/MediaBrowser.Providers/Savers/GameSystemXmlSaver.cs +++ b/MediaBrowser.Providers/Savers/GameSystemXmlSaver.cs @@ -46,7 +46,7 @@ namespace MediaBrowser.Providers.Savers var wasMetadataDownloaded = (updateType & ItemUpdateType.MetadataDownload) == ItemUpdateType.MetadataDownload; // If new metadata has been downloaded and save local is on - if (item.IsSaveLocalMetadataEnabled() && (wasMetadataEdited || wasMetadataDownloaded)) + if (wasMetadataEdited || wasMetadataDownloaded) { return item is GameSystem; } diff --git a/MediaBrowser.Providers/Savers/GameXmlSaver.cs b/MediaBrowser.Providers/Savers/GameXmlSaver.cs index a2a96909f..6f50cfda8 100644 --- a/MediaBrowser.Providers/Savers/GameXmlSaver.cs +++ b/MediaBrowser.Providers/Savers/GameXmlSaver.cs @@ -49,7 +49,7 @@ namespace MediaBrowser.Providers.Savers var wasMetadataDownloaded = (updateType & ItemUpdateType.MetadataDownload) == ItemUpdateType.MetadataDownload; // If new metadata has been downloaded and save local is on - if (item.IsSaveLocalMetadataEnabled() && (wasMetadataEdited || wasMetadataDownloaded)) + if (wasMetadataEdited || wasMetadataDownloaded) { return item is Game; } diff --git a/MediaBrowser.Providers/Savers/MovieXmlSaver.cs b/MediaBrowser.Providers/Savers/MovieXmlSaver.cs index e62a86af0..851c81f54 100644 --- a/MediaBrowser.Providers/Savers/MovieXmlSaver.cs +++ b/MediaBrowser.Providers/Savers/MovieXmlSaver.cs @@ -56,7 +56,7 @@ namespace MediaBrowser.Providers.Savers var wasMetadataDownloaded = (updateType & ItemUpdateType.MetadataDownload) == ItemUpdateType.MetadataDownload; // If new metadata has been downloaded and save local is on - if (item.IsSaveLocalMetadataEnabled() && (wasMetadataEdited || wasMetadataDownloaded)) + if (wasMetadataEdited || wasMetadataDownloaded) { var video = item as Video; // Check parent for null to avoid running this against things like video backdrops diff --git a/MediaBrowser.Providers/Savers/SeasonXmlSaver.cs b/MediaBrowser.Providers/Savers/SeasonXmlSaver.cs index cc0bf8b36..f8d4549cf 100644 --- a/MediaBrowser.Providers/Savers/SeasonXmlSaver.cs +++ b/MediaBrowser.Providers/Savers/SeasonXmlSaver.cs @@ -46,7 +46,7 @@ namespace MediaBrowser.Providers.Savers var wasMetadataDownloaded = (updateType & ItemUpdateType.MetadataDownload) == ItemUpdateType.MetadataDownload; // If new metadata has been downloaded and save local is on - if (item.IsSaveLocalMetadataEnabled() && (wasMetadataEdited || wasMetadataDownloaded)) + if (wasMetadataEdited || wasMetadataDownloaded) { return item is Season; } diff --git a/MediaBrowser.Providers/Savers/SeriesXmlSaver.cs b/MediaBrowser.Providers/Savers/SeriesXmlSaver.cs index ffd90b5d1..df0a87c35 100644 --- a/MediaBrowser.Providers/Savers/SeriesXmlSaver.cs +++ b/MediaBrowser.Providers/Savers/SeriesXmlSaver.cs @@ -46,7 +46,7 @@ namespace MediaBrowser.Providers.Savers var wasMetadataDownloaded = (updateType & ItemUpdateType.MetadataDownload) == ItemUpdateType.MetadataDownload; // If new metadata has been downloaded and save local is on - if (item.IsSaveLocalMetadataEnabled() && (wasMetadataEdited || wasMetadataDownloaded)) + if (wasMetadataEdited || wasMetadataDownloaded) { return item is Series; } diff --git a/MediaBrowser.Providers/TV/FanArtTvUpdatesPostScanTask.cs b/MediaBrowser.Providers/TV/FanArtTvUpdatesPostScanTask.cs new file mode 100644 index 000000000..50099dcb8 --- /dev/null +++ b/MediaBrowser.Providers/TV/FanArtTvUpdatesPostScanTask.cs @@ -0,0 +1,182 @@ +using MediaBrowser.Common.IO; +using MediaBrowser.Common.Net; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Library; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Serialization; +using MediaBrowser.Providers.Music; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Providers.TV +{ + class FanArtTvUpdatesPostScanTask : ILibraryPostScanTask + { + private const string UpdatesUrl = "http://api.fanart.tv/webservice/newtv/{0}/{1}/"; + + /// + /// The _HTTP client + /// + private readonly IHttpClient _httpClient; + /// + /// The _logger + /// + private readonly ILogger _logger; + /// + /// The _config + /// + private readonly IServerConfigurationManager _config; + private readonly IJsonSerializer _jsonSerializer; + private readonly IFileSystem _fileSystem; + + private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); + + public FanArtTvUpdatesPostScanTask(IJsonSerializer jsonSerializer, IServerConfigurationManager config, ILogger logger, IHttpClient httpClient, IFileSystem fileSystem) + { + _jsonSerializer = jsonSerializer; + _config = config; + _logger = logger; + _httpClient = httpClient; + _fileSystem = fileSystem; + } + + /// + /// Runs the specified progress. + /// + /// The progress. + /// The cancellation token. + /// Task. + public async Task Run(IProgress progress, CancellationToken cancellationToken) + { + if (!_config.Configuration.EnableInternetProviders || !_config.Configuration.EnableFanArtUpdates) + { + progress.Report(100); + return; + } + + var path = FanartSeriesProvider.GetSeriesDataPath(_config.CommonApplicationPaths); + + Directory.CreateDirectory(path); + + var timestampFile = Path.Combine(path, "time.txt"); + + var timestampFileInfo = new FileInfo(timestampFile); + + // Don't check for updates every single time + if (timestampFileInfo.Exists && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(timestampFileInfo)).TotalDays < 3) + { + return; + } + + // Find out the last time we queried for updates + var lastUpdateTime = timestampFileInfo.Exists ? File.ReadAllText(timestampFile, Encoding.UTF8) : string.Empty; + + var existingDirectories = Directory.EnumerateDirectories(path).Select(Path.GetFileName).ToList(); + + // If this is our first time, don't do any updates and just record the timestamp + if (!string.IsNullOrEmpty(lastUpdateTime)) + { + var seriesToUpdate = await GetSeriesIdsToUpdate(existingDirectories, lastUpdateTime, cancellationToken).ConfigureAwait(false); + + progress.Report(5); + + await UpdateSeries(seriesToUpdate, progress, cancellationToken).ConfigureAwait(false); + } + + var newUpdateTime = Convert.ToInt64(DateTimeToUnixTimestamp(DateTime.UtcNow)).ToString(UsCulture); + + File.WriteAllText(timestampFile, newUpdateTime, Encoding.UTF8); + + progress.Report(100); + } + + /// + /// Gets the series ids to update. + /// + /// The existing series ids. + /// The last update time. + /// The cancellation token. + /// Task{IEnumerable{System.String}}. + private async Task> GetSeriesIdsToUpdate(IEnumerable existingSeriesIds, string lastUpdateTime, CancellationToken cancellationToken) + { + // First get last time + using (var stream = await _httpClient.Get(new HttpRequestOptions + { + Url = string.Format(UpdatesUrl, FanartArtistProvider.ApiKey, lastUpdateTime), + CancellationToken = cancellationToken, + EnableHttpCompression = true, + ResourcePool = FanartArtistProvider.FanArtResourcePool + + }).ConfigureAwait(false)) + { + // If empty fanart will return a string of "null", rather than an empty list + using (var reader = new StreamReader(stream)) + { + var json = await reader.ReadToEndAsync().ConfigureAwait(false); + + if (string.Equals(json, "null", StringComparison.OrdinalIgnoreCase)) + { + return new List(); + } + + var existingDictionary = existingSeriesIds.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase); + + var updates = _jsonSerializer.DeserializeFromString>(json); + + return updates.Select(i => i.id).Where(existingDictionary.ContainsKey); + } + } + } + + /// + /// Updates the series. + /// + /// The id list. + /// The progress. + /// The cancellation token. + /// Task. + private async Task UpdateSeries(IEnumerable idList, IProgress progress, CancellationToken cancellationToken) + { + var list = idList.ToList(); + var numComplete = 0; + + foreach (var id in list) + { + _logger.Info("Updating series " + id); + + await FanartSeriesProvider.Current.DownloadSeriesXml(id, cancellationToken).ConfigureAwait(false); + + numComplete++; + double percent = numComplete; + percent /= list.Count; + percent *= 95; + + progress.Report(percent + 5); + } + } + + /// + /// Dates the time to unix timestamp. + /// + /// The date time. + /// System.Double. + private static double DateTimeToUnixTimestamp(DateTime dateTime) + { + return (dateTime - new DateTime(1970, 1, 1).ToUniversalTime()).TotalSeconds; + } + + public class FanArtUpdate + { + public string id { get; set; } + public string name { get; set; } + public string new_images { get; set; } + public string total_images { get; set; } + } + } +} diff --git a/MediaBrowser.Providers/TV/FanArtTvUpdatesPrescanTask.cs b/MediaBrowser.Providers/TV/FanArtTvUpdatesPrescanTask.cs deleted file mode 100644 index db546f3a3..000000000 --- a/MediaBrowser.Providers/TV/FanArtTvUpdatesPrescanTask.cs +++ /dev/null @@ -1,182 +0,0 @@ -using MediaBrowser.Common.IO; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Serialization; -using MediaBrowser.Providers.Music; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Providers.TV -{ - class FanArtTvUpdatesPrescanTask : ILibraryPostScanTask - { - private const string UpdatesUrl = "http://api.fanart.tv/webservice/newtv/{0}/{1}/"; - - /// - /// The _HTTP client - /// - private readonly IHttpClient _httpClient; - /// - /// The _logger - /// - private readonly ILogger _logger; - /// - /// The _config - /// - private readonly IServerConfigurationManager _config; - private readonly IJsonSerializer _jsonSerializer; - private readonly IFileSystem _fileSystem; - - private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); - - public FanArtTvUpdatesPrescanTask(IJsonSerializer jsonSerializer, IServerConfigurationManager config, ILogger logger, IHttpClient httpClient, IFileSystem fileSystem) - { - _jsonSerializer = jsonSerializer; - _config = config; - _logger = logger; - _httpClient = httpClient; - _fileSystem = fileSystem; - } - - /// - /// Runs the specified progress. - /// - /// The progress. - /// The cancellation token. - /// Task. - public async Task Run(IProgress progress, CancellationToken cancellationToken) - { - if (!_config.Configuration.EnableInternetProviders || !_config.Configuration.EnableFanArtUpdates) - { - progress.Report(100); - return; - } - - var path = FanartSeriesProvider.GetSeriesDataPath(_config.CommonApplicationPaths); - - Directory.CreateDirectory(path); - - var timestampFile = Path.Combine(path, "time.txt"); - - var timestampFileInfo = new FileInfo(timestampFile); - - // Don't check for updates every single time - if (timestampFileInfo.Exists && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(timestampFileInfo)).TotalDays < 3) - { - return; - } - - // Find out the last time we queried for updates - var lastUpdateTime = timestampFileInfo.Exists ? File.ReadAllText(timestampFile, Encoding.UTF8) : string.Empty; - - var existingDirectories = Directory.EnumerateDirectories(path).Select(Path.GetFileName).ToList(); - - // If this is our first time, don't do any updates and just record the timestamp - if (!string.IsNullOrEmpty(lastUpdateTime)) - { - var seriesToUpdate = await GetSeriesIdsToUpdate(existingDirectories, lastUpdateTime, cancellationToken).ConfigureAwait(false); - - progress.Report(5); - - await UpdateSeries(seriesToUpdate, progress, cancellationToken).ConfigureAwait(false); - } - - var newUpdateTime = Convert.ToInt64(DateTimeToUnixTimestamp(DateTime.UtcNow)).ToString(UsCulture); - - File.WriteAllText(timestampFile, newUpdateTime, Encoding.UTF8); - - progress.Report(100); - } - - /// - /// Gets the series ids to update. - /// - /// The existing series ids. - /// The last update time. - /// The cancellation token. - /// Task{IEnumerable{System.String}}. - private async Task> GetSeriesIdsToUpdate(IEnumerable existingSeriesIds, string lastUpdateTime, CancellationToken cancellationToken) - { - // First get last time - using (var stream = await _httpClient.Get(new HttpRequestOptions - { - Url = string.Format(UpdatesUrl, FanartArtistProvider.ApiKey, lastUpdateTime), - CancellationToken = cancellationToken, - EnableHttpCompression = true, - ResourcePool = FanartArtistProvider.FanArtResourcePool - - }).ConfigureAwait(false)) - { - // If empty fanart will return a string of "null", rather than an empty list - using (var reader = new StreamReader(stream)) - { - var json = await reader.ReadToEndAsync().ConfigureAwait(false); - - if (string.Equals(json, "null", StringComparison.OrdinalIgnoreCase)) - { - return new List(); - } - - var existingDictionary = existingSeriesIds.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase); - - var updates = _jsonSerializer.DeserializeFromString>(json); - - return updates.Select(i => i.id).Where(existingDictionary.ContainsKey); - } - } - } - - /// - /// Updates the series. - /// - /// The id list. - /// The progress. - /// The cancellation token. - /// Task. - private async Task UpdateSeries(IEnumerable idList, IProgress progress, CancellationToken cancellationToken) - { - var list = idList.ToList(); - var numComplete = 0; - - foreach (var id in list) - { - _logger.Info("Updating series " + id); - - await FanartSeriesProvider.Current.DownloadSeriesXml(id, cancellationToken).ConfigureAwait(false); - - numComplete++; - double percent = numComplete; - percent /= list.Count; - percent *= 95; - - progress.Report(percent + 5); - } - } - - /// - /// Dates the time to unix timestamp. - /// - /// The date time. - /// System.Double. - private static double DateTimeToUnixTimestamp(DateTime dateTime) - { - return (dateTime - new DateTime(1970, 1, 1).ToUniversalTime()).TotalSeconds; - } - - public class FanArtUpdate - { - public string id { get; set; } - public string name { get; set; } - public string new_images { get; set; } - public string total_images { get; set; } - } - } -} diff --git a/MediaBrowser.Providers/TV/SeriesPostScanTask.cs b/MediaBrowser.Providers/TV/SeriesPostScanTask.cs index 528661680..035528734 100644 --- a/MediaBrowser.Providers/TV/SeriesPostScanTask.cs +++ b/MediaBrowser.Providers/TV/SeriesPostScanTask.cs @@ -17,7 +17,7 @@ using System.Xml; namespace MediaBrowser.Providers.TV { - class SeriesPostScanTask : ILibraryPostScanTask + class SeriesPostScanTask : ILibraryPostScanTask, IHasOrder { /// /// The _library manager @@ -89,6 +89,15 @@ namespace MediaBrowser.Providers.TV progress.Report(percent); } } + + public int Order + { + get + { + // Run after tvdb update task + return 1; + } + } } class MissingEpisodeProvider diff --git a/MediaBrowser.Providers/TV/TvdbPrescanTask.cs b/MediaBrowser.Providers/TV/TvdbPrescanTask.cs index af4c27278..a9edeee0e 100644 --- a/MediaBrowser.Providers/TV/TvdbPrescanTask.cs +++ b/MediaBrowser.Providers/TV/TvdbPrescanTask.cs @@ -21,7 +21,7 @@ namespace MediaBrowser.Providers.TV /// /// Class TvdbPrescanTask /// - public class TvdbPrescanTask : ILibraryPrescanTask + public class TvdbPrescanTask : ILibraryPostScanTask { /// /// The server time URL diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index 49b2ad562..92d7a4a90 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -38,24 +38,13 @@ namespace MediaBrowser.Server.Implementations.Library /// Gets or sets the postscan tasks. /// /// The postscan tasks. - private IEnumerable PostscanTasks { get; set; } - /// - /// Gets or sets the prescan tasks. - /// - /// The prescan tasks. - private IEnumerable PrescanTasks { get; set; } - - /// - /// Gets or sets the people prescan tasks. - /// - /// The people prescan tasks. - private IEnumerable PeoplePrescanTasks { get; set; } + private ILibraryPostScanTask[] PostscanTasks { get; set; } /// /// Gets the intro providers. /// /// The intro providers. - private IEnumerable IntroProviders { get; set; } + private IIntroProvider[] IntroProviders { get; set; } /// /// Gets the list of entity resolution ignore rules @@ -205,26 +194,27 @@ namespace MediaBrowser.Server.Implementations.Library /// The resolvers. /// The intro providers. /// The item comparers. - /// The prescan tasks. /// The postscan tasks. - /// The people prescan tasks. public void AddParts(IEnumerable rules, IEnumerable pluginFolders, IEnumerable resolvers, IEnumerable introProviders, IEnumerable itemComparers, - IEnumerable prescanTasks, - IEnumerable postscanTasks, - IEnumerable peoplePrescanTasks) + IEnumerable postscanTasks) { EntityResolutionIgnoreRules = rules.ToArray(); PluginFolderCreators = pluginFolders.ToArray(); EntityResolvers = resolvers.OrderBy(i => i.Priority).ToArray(); - IntroProviders = introProviders; + IntroProviders = introProviders.ToArray(); Comparers = itemComparers.ToArray(); - PrescanTasks = prescanTasks; - PostscanTasks = postscanTasks; - PeoplePrescanTasks = peoplePrescanTasks; + + PostscanTasks = postscanTasks.OrderBy(i => + { + var hasOrder = i as IHasOrder; + + return hasOrder == null ? 0 : hasOrder.Order; + + }).ToArray(); } /// @@ -845,7 +835,7 @@ namespace MediaBrowser.Server.Implementations.Library /// Task. public Task ValidatePeople(CancellationToken cancellationToken, IProgress progress) { - return new PeopleValidator(this, PeoplePrescanTasks, _logger).ValidatePeople(cancellationToken, progress); + return new PeopleValidator(this, _logger).ValidatePeople(cancellationToken, progress); } /// @@ -970,14 +960,9 @@ namespace MediaBrowser.Server.Implementations.Library innerProgress.RegisterAction(pct => progress.Report(2 + pct * .13)); - // Run prescan tasks - await RunPrescanTasks(innerProgress, cancellationToken).ConfigureAwait(false); - - progress.Report(15); - innerProgress = new ActionableProgress(); - innerProgress.RegisterAction(pct => progress.Report(15 + pct * .6)); + innerProgress.RegisterAction(pct => progress.Report(2 + pct * .73)); // Now validate the entire media library await RootFolder.ValidateChildren(innerProgress, cancellationToken, new MetadataRefreshOptions(), recursive: true).ConfigureAwait(false); @@ -998,55 +983,6 @@ namespace MediaBrowser.Server.Implementations.Library GC.Collect(2, GCCollectionMode.Forced, true); } - /// - /// Runs the prescan tasks. - /// - /// The progress. - /// The cancellation token. - /// Task. - private async Task RunPrescanTasks(IProgress progress, CancellationToken cancellationToken) - { - var tasks = PrescanTasks.ToList(); - - var numComplete = 0; - var numTasks = tasks.Count; - - foreach (var task in tasks) - { - var innerProgress = new ActionableProgress(); - - // Prevent access to modified closure - var currentNumComplete = numComplete; - - innerProgress.RegisterAction(pct => - { - double innerPercent = (currentNumComplete * 100) + pct; - innerPercent /= numTasks; - progress.Report(innerPercent); - }); - - try - { - await task.Run(innerProgress, cancellationToken); - } - catch (OperationCanceledException) - { - _logger.Info("Pre-scan task cancelled: {0}", task.GetType().Name); - } - catch (Exception ex) - { - _logger.ErrorException("Error running pre-scan task", ex); - } - - numComplete++; - double percent = numComplete; - percent /= numTasks; - progress.Report(percent * 100); - } - - progress.Report(100); - } - /// /// Runs the post scan tasks. /// diff --git a/MediaBrowser.Server.Implementations/Library/Validators/PeopleValidator.cs b/MediaBrowser.Server.Implementations/Library/Validators/PeopleValidator.cs index 26e9a23e9..268bccd7a 100644 --- a/MediaBrowser.Server.Implementations/Library/Validators/PeopleValidator.cs +++ b/MediaBrowser.Server.Implementations/Library/Validators/PeopleValidator.cs @@ -3,7 +3,6 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Model.Logging; using MoreLinq; using System; -using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -24,19 +23,15 @@ namespace MediaBrowser.Server.Implementations.Library.Validators /// private readonly ILogger _logger; - private readonly IEnumerable _prescanTasks; - /// /// Initializes a new instance of the class. /// /// The library manager. - /// The prescan tasks. /// The logger. - public PeopleValidator(ILibraryManager libraryManager, IEnumerable prescanTasks, ILogger logger) + public PeopleValidator(ILibraryManager libraryManager, ILogger logger) { _libraryManager = libraryManager; _logger = logger; - _prescanTasks = prescanTasks; } /// @@ -51,11 +46,6 @@ namespace MediaBrowser.Server.Implementations.Library.Validators innerProgress.RegisterAction(pct => progress.Report(pct * .15)); - // Run prescan tasks - await RunPrescanTasks(innerProgress, cancellationToken).ConfigureAwait(false); - - progress.Report(15); - var people = _libraryManager.RootFolder.GetRecursiveChildren() .SelectMany(c => c.People) .DistinctBy(p => p.Name, StringComparer.OrdinalIgnoreCase) @@ -94,55 +84,5 @@ namespace MediaBrowser.Server.Implementations.Library.Validators GC.Collect(2, GCCollectionMode.Forced, true); GC.Collect(2, GCCollectionMode.Forced, true); } - - /// - /// Runs the prescan tasks. - /// - /// The progress. - /// The cancellation token. - /// Task. - private async Task RunPrescanTasks(IProgress progress, CancellationToken cancellationToken) - { - var tasks = _prescanTasks.ToList(); - - var numComplete = 0; - var numTasks = tasks.Count; - - foreach (var task in tasks) - { - var innerProgress = new ActionableProgress(); - - // Prevent access to modified closure - var currentNumComplete = numComplete; - - innerProgress.RegisterAction(pct => - { - double innerPercent = (currentNumComplete * 100) + pct; - innerPercent /= numTasks; - progress.Report(innerPercent); - }); - - try - { - await task.Run(innerProgress, cancellationToken); - } - catch (OperationCanceledException) - { - _logger.Info("Pre-scan task cancelled: {0}", task.GetType().Name); - break; - } - catch (Exception ex) - { - _logger.ErrorException("Error running pre-scan task", ex); - } - - numComplete++; - double percent = numComplete; - percent /= numTasks; - progress.Report(percent * 100); - } - - progress.Report(100); - } } } diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs index cd2f5779a..695697f8f 100644 --- a/MediaBrowser.ServerApplication/ApplicationHost.cs +++ b/MediaBrowser.ServerApplication/ApplicationHost.cs @@ -497,9 +497,7 @@ namespace MediaBrowser.ServerApplication GetExports(), GetExports(), GetExports(), - GetExports(), - GetExports(), - GetExports()); + GetExports()); ProviderManager.AddParts(GetExports(), GetExports(), GetExports(), GetExports()); -- cgit v1.2.3