diff options
Diffstat (limited to 'MediaBrowser.Providers/Manager/MetadataService.cs')
| -rw-r--r-- | MediaBrowser.Providers/Manager/MetadataService.cs | 178 |
1 files changed, 102 insertions, 76 deletions
diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index e0272bc7b..beece997d 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -4,11 +4,11 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -16,8 +16,8 @@ using System.Threading.Tasks; namespace MediaBrowser.Providers.Manager { public abstract class MetadataService<TItemType, TIdType> : IMetadataService - where TItemType : IHasMetadata, new() - where TIdType : ItemId, new() + where TItemType : IHasMetadata, IHasLookupInfo<TIdType>, new() + where TIdType : ItemLookupInfo, new() { protected readonly IServerConfigurationManager ServerConfigurationManager; protected readonly ILogger Logger; @@ -37,10 +37,19 @@ namespace MediaBrowser.Providers.Manager /// <summary> /// Saves the provider result. /// </summary> + /// <param name="item">The item.</param> /// <param name="result">The result.</param> /// <returns>Task.</returns> - protected Task SaveProviderResult(MetadataStatus result) + protected Task SaveProviderResult(TItemType item, MetadataStatus result) { + result.ItemId = item.Id; + result.ItemName = item.Name; + result.ItemType = item.GetType().Name; + + var series = item as IHasSeries; + + result.SeriesName = series == null ? null : series.SeriesName; + return ProviderRepo.SaveMetadataStatus(result, CancellationToken.None); } @@ -56,10 +65,15 @@ namespace MediaBrowser.Providers.Manager public async Task RefreshMetadata(IHasMetadata item, MetadataRefreshOptions refreshOptions, CancellationToken cancellationToken) { + if (refreshOptions.DirectoryService == null) + { + refreshOptions.DirectoryService = new DirectoryService(Logger); + } + var itemOfType = (TItemType)item; - var config = GetMetadataOptions(itemOfType); + var config = ProviderManager.GetMetadataOptions(item); - var updateType = ItemUpdateType.Unspecified; + var updateType = ItemUpdateType.None; var refreshResult = GetLastResult(item.Id); refreshResult.LastErrorMessage = string.Empty; refreshResult.LastStatus = ProviderRefreshStatus.Success; @@ -73,7 +87,7 @@ namespace MediaBrowser.Providers.Manager try { // Always validate images and check for new locally stored ones. - if (itemImageProvider.ValidateImages(item, allImageProviders.OfType<ILocalImageProvider>())) + if (itemImageProvider.ValidateImages(item, allImageProviders.OfType<ILocalImageProvider>(), refreshOptions.DirectoryService)) { updateType = updateType | ItemUpdateType.ImageUpdate; } @@ -92,13 +106,12 @@ namespace MediaBrowser.Providers.Manager if (providers.Count > 0 || !refreshResult.DateLastMetadataRefresh.HasValue) { - updateType = updateType | BeforeMetadataRefresh(itemOfType); + updateType = updateType | item.BeforeMetadataRefresh(); } if (providers.Count > 0) { - - var result = await RefreshWithProviders(itemOfType, refreshOptions, providers, cancellationToken).ConfigureAwait(false); + var result = await RefreshWithProviders(itemOfType, refreshOptions, providers, itemImageProvider, cancellationToken).ConfigureAwait(false); updateType = updateType | result.UpdateType; refreshResult.AddStatus(result.Status, result.ErrorMessage); @@ -125,44 +138,21 @@ namespace MediaBrowser.Providers.Manager updateType = updateType | BeforeSave(itemOfType); - var providersHadChanges = updateType > ItemUpdateType.Unspecified; + var providersHadChanges = updateType > ItemUpdateType.None; - if (refreshOptions.ForceSave || providersHadChanges) + // Save if changes were made, or it's never been saved before + if (refreshOptions.ForceSave || providersHadChanges || item.DateLastSaved == default(DateTime)) { - if (string.IsNullOrEmpty(item.Name)) - { - throw new InvalidOperationException(item.GetType().Name + " has no name: " + item.Path); - } - // Save to database await SaveItem(itemOfType, updateType, cancellationToken); } if (providersHadChanges || refreshResult.IsDirty) { - await SaveProviderResult(refreshResult).ConfigureAwait(false); + await SaveProviderResult(itemOfType, refreshResult).ConfigureAwait(false); } } - 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; - } - - /// <summary> - /// Befores the metadata refresh. - /// </summary> - /// <param name="item">The item.</param> - /// <returns>ItemUpdateType.</returns> - protected virtual ItemUpdateType BeforeMetadataRefresh(TItemType item) - { - return ItemUpdateType.Unspecified; - } - /// <summary> /// Befores the save. /// </summary> @@ -170,7 +160,15 @@ namespace MediaBrowser.Providers.Manager /// <returns>ItemUpdateType.</returns> protected virtual ItemUpdateType BeforeSave(TItemType item) { - return ItemUpdateType.Unspecified; + var updateType = ItemUpdateType.None; + + if (string.IsNullOrEmpty(item.Name) && !string.IsNullOrEmpty(item.Path)) + { + item.Name = Path.GetFileNameWithoutExtension(item.Path); + updateType = updateType | ItemUpdateType.MetadataEdit; + } + + return updateType; } /// <summary> @@ -194,15 +192,37 @@ namespace MediaBrowser.Providers.Manager var currentItem = item; var providersWithChanges = providers.OfType<IHasChangeMonitor>() - .Where(i => i.HasChanged(currentItem, currentItem.DateLastSaved)) + .Where(i => i.HasChanged(currentItem, options.DirectoryService, currentItem.DateLastSaved)) + .Cast<IMetadataProvider<TItemType>>() .ToList(); - // If local providers are the only ones with changes, then just run those - if (providersWithChanges.All(i => i is ILocalMetadataProvider)) + if (providersWithChanges.Count == 0) { - providers = providersWithChanges.Count == 0 ? - new List<IMetadataProvider<TItemType>>() : - providers.Where(i => i is ILocalMetadataProvider).ToList(); + providers = new List<IMetadataProvider<TItemType>>(); + } + else + { + providers = providers.Where(i => + { + // If any provider reports a change, always run local ones as well + if (i is ILocalMetadataProvider) + { + return true; + } + + var anyRemoteProvidersChanged = providersWithChanges.OfType<IRemoteMetadataProvider>() + .Any(); + + // If any remote providers changed, run them all so that priorities can be honored + if (i is IRemoteMetadataProvider) + { + return anyRemoteProvidersChanged; + } + + // Run custom providers if they report a change or any remote providers change + return anyRemoteProvidersChanged || providersWithChanges.Contains(i); + + }).ToList(); } } @@ -223,7 +243,7 @@ namespace MediaBrowser.Providers.Manager var currentItem = item; providers = providers.OfType<IHasChangeMonitor>() - .Where(i => i.HasChanged(currentItem, dateLastImageRefresh.Value)) + .Where(i => i.HasChanged(currentItem, options.DirectoryService, dateLastImageRefresh.Value)) .Cast<IImageProvider>() .ToList(); } @@ -231,27 +251,9 @@ namespace MediaBrowser.Providers.Manager return providers; } - protected abstract Task SaveItem(TItemType item, ItemUpdateType reason, CancellationToken cancellationToken); - - protected virtual TIdType GetId(TItemType item) + protected Task SaveItem(TItemType item, ItemUpdateType reason, CancellationToken cancellationToken) { - var id = new TIdType - { - MetadataCountryCode = item.GetPreferredMetadataCountryCode(), - MetadataLanguage = item.GetPreferredMetadataLanguage(), - Name = item.Name, - ProviderIds = item.ProviderIds - }; - - var baseItem = item as BaseItem; - - if (baseItem != null) - { - id.IndexNumber = baseItem.IndexNumber; - id.ParentIndexNumber = baseItem.ParentIndexNumber; - } - - return id; + return item.UpdateToRepository(reason, cancellationToken); } public bool CanRefresh(IHasMetadata item) @@ -259,11 +261,11 @@ namespace MediaBrowser.Providers.Manager return item is TItemType; } - protected virtual async Task<RefreshResult> RefreshWithProviders(TItemType item, MetadataRefreshOptions options, List<IMetadataProvider> providers, CancellationToken cancellationToken) + protected virtual async Task<RefreshResult> RefreshWithProviders(TItemType item, MetadataRefreshOptions options, List<IMetadataProvider> providers, ItemImageProvider imageService, CancellationToken cancellationToken) { var refreshResult = new RefreshResult { - UpdateType = ItemUpdateType.Unspecified, + UpdateType = ItemUpdateType.None, Providers = providers.Select(i => i.GetType().FullName.GetMD5()).ToList() }; @@ -273,7 +275,7 @@ namespace MediaBrowser.Providers.Manager // If replacing all metadata, run internet providers first if (options.ReplaceAllMetadata) { - await ExecuteRemoteProviders(item, temp, providers.OfType<IRemoteMetadataProvider<TItemType>>(), refreshResult, cancellationToken).ConfigureAwait(false); + await ExecuteRemoteProviders(item, temp, providers.OfType<IRemoteMetadataProvider<TItemType, TIdType>>(), refreshResult, cancellationToken).ConfigureAwait(false); } var hasLocalMetadata = false; @@ -290,6 +292,11 @@ namespace MediaBrowser.Providers.Manager if (localItem.HasMetadata) { + if (imageService.MergeImages(item, localItem.Images)) + { + refreshResult.UpdateType = refreshResult.UpdateType | ItemUpdateType.MetadataImport; + } + if (!string.IsNullOrEmpty(localItem.Item.Name)) { MergeData(localItem.Item, temp, new List<MetadataFields>(), !options.ReplaceAllMetadata, true); @@ -319,31 +326,32 @@ namespace MediaBrowser.Providers.Manager } } - if (!options.ReplaceAllMetadata && !hasLocalMetadata) + // Local metadata is king - if any is found don't run remote providers + if ((!options.ReplaceAllMetadata && !hasLocalMetadata) || options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh) { - await ExecuteRemoteProviders(item, temp, providers.OfType<IRemoteMetadataProvider<TItemType>>(), refreshResult, cancellationToken).ConfigureAwait(false); + await ExecuteRemoteProviders(item, temp, providers.OfType<IRemoteMetadataProvider<TItemType, TIdType>>(), refreshResult, cancellationToken).ConfigureAwait(false); } - if (refreshResult.UpdateType > ItemUpdateType.Unspecified) + if (refreshResult.UpdateType > ItemUpdateType.None) { MergeData(temp, item, item.LockedFields, true, true); } foreach (var provider in providers.OfType<ICustomMetadataProvider<TItemType>>()) { - await RunCustomProvider(provider, item, refreshResult, cancellationToken).ConfigureAwait(false); + await RunCustomProvider(provider, item, options.DirectoryService, refreshResult, cancellationToken).ConfigureAwait(false); } return refreshResult; } - private async Task RunCustomProvider(ICustomMetadataProvider<TItemType> provider, TItemType item, RefreshResult refreshResult, CancellationToken cancellationToken) + private async Task RunCustomProvider(ICustomMetadataProvider<TItemType> provider, TItemType item, IDirectoryService directoryService, RefreshResult refreshResult, CancellationToken cancellationToken) { Logger.Debug("Running {0} for {1}", provider.GetType().Name, item.Path ?? item.Name); try { - refreshResult.UpdateType = refreshResult.UpdateType | await provider.FetchAsync(item, cancellationToken).ConfigureAwait(false); + refreshResult.UpdateType = refreshResult.UpdateType | await provider.FetchAsync(item, directoryService, cancellationToken).ConfigureAwait(false); } catch (OperationCanceledException) { @@ -362,14 +370,23 @@ namespace MediaBrowser.Providers.Manager return new TItemType(); } - private async Task ExecuteRemoteProviders(TItemType item, TItemType temp, IEnumerable<IRemoteMetadataProvider<TItemType>> providers, RefreshResult refreshResult, CancellationToken cancellationToken) + private async Task ExecuteRemoteProviders(TItemType item, TItemType temp, IEnumerable<IRemoteMetadataProvider<TItemType, TIdType>> providers, RefreshResult refreshResult, CancellationToken cancellationToken) { - var id = GetId(item); + TIdType id = null; foreach (var provider in providers) { Logger.Debug("Running {0} for {1}", provider.GetType().Name, item.Path ?? item.Name); + if (id == null) + { + id = item.GetLookupInfo(); + } + else + { + MergeNewData(temp, id); + } + try { var result = await provider.GetMetadata(id, cancellationToken).ConfigureAwait(false); @@ -394,6 +411,15 @@ namespace MediaBrowser.Providers.Manager } } + private void MergeNewData(TItemType source, TIdType lookupInfo) + { + // Copy new provider id's that may have been obtained + foreach (var providerId in source.ProviderIds) + { + lookupInfo.ProviderIds[providerId.Key] = providerId.Value; + } + } + protected abstract void MergeData(TItemType source, TItemType target, List<MetadataFields> lockedFields, bool replaceData, bool mergeMetadataSettings); public virtual int Order |
