Esempio n. 1
0
        protected virtual async Task <RefreshResult> RefreshWithProviders(
            MetadataResult <TItemType> metadata,
            TIdType id,
            MetadataRefreshOptions options,
            ICollection <IMetadataProvider> providers,
            ItemImageProvider imageService,
            CancellationToken cancellationToken)
        {
            var refreshResult = new RefreshResult
            {
                UpdateType = ItemUpdateType.None
            };

            var item = metadata.Item;

            var customProviders = providers.OfType <ICustomMetadataProvider <TItemType> >().ToList();
            var logName         = !item.IsFileProtocol ? item.Name ?? item.Path : item.Path ?? item.Name;

            foreach (var provider in customProviders.Where(i => i is IPreRefreshProvider))
            {
                await RunCustomProvider(provider, item, logName, options, refreshResult, cancellationToken).ConfigureAwait(false);
            }

            var temp = new MetadataResult <TItemType>
            {
                Item = CreateNew()
            };

            temp.Item.Path = item.Path;

            // If replacing all metadata, run internet providers first
            if (options.ReplaceAllMetadata)
            {
                var remoteResult = await ExecuteRemoteProviders(temp, logName, id, providers.OfType <IRemoteMetadataProvider <TItemType, TIdType> >(), cancellationToken)
                                   .ConfigureAwait(false);

                refreshResult.UpdateType  |= remoteResult.UpdateType;
                refreshResult.ErrorMessage = remoteResult.ErrorMessage;
                refreshResult.Failures    += remoteResult.Failures;
            }

            var hasLocalMetadata = false;

            foreach (var provider in providers.OfType <ILocalMetadataProvider <TItemType> >())
            {
                var providerName = provider.GetType().Name;
                Logger.LogDebug("Running {Provider} for {Item}", providerName, logName);

                var itemInfo = new ItemInfo(item);

                try
                {
                    var localItem = await provider.GetMetadata(itemInfo, options.DirectoryService, cancellationToken).ConfigureAwait(false);

                    if (localItem.HasMetadata)
                    {
                        foreach (var remoteImage in localItem.RemoteImages)
                        {
                            try
                            {
                                if (!options.IsReplacingImage(remoteImage.Type))
                                {
                                    continue;
                                }

                                await ProviderManager.SaveImage(item, remoteImage.Url, remoteImage.Type, null, cancellationToken).ConfigureAwait(false);

                                refreshResult.UpdateType |= ItemUpdateType.ImageUpdate;
                            }
                            catch (HttpRequestException ex)
                            {
                                Logger.LogError(ex, "Could not save {ImageType} image: {Url}", Enum.GetName(remoteImage.Type), remoteImage.Url);
                            }
                        }

                        if (imageService.MergeImages(item, localItem.Images))
                        {
                            refreshResult.UpdateType |= ItemUpdateType.ImageUpdate;
                        }

                        MergeData(localItem, temp, Array.Empty <MetadataField>(), !options.ReplaceAllMetadata, true);
                        refreshResult.UpdateType |= ItemUpdateType.MetadataImport;

                        // Only one local provider allowed per item
                        if (item.IsLocked || localItem.Item.IsLocked || IsFullLocalMetadata(localItem.Item))
                        {
                            hasLocalMetadata = true;
                        }

                        break;
                    }

                    Logger.LogDebug("{Provider} returned no metadata for {Item}", providerName, logName);
                }
                catch (OperationCanceledException)
                {
                    throw;
                }
                catch (Exception ex)
                {
                    Logger.LogError(ex, "Error in {Provider}", provider.Name);

                    // If a local provider fails, consider that a failure
                    refreshResult.ErrorMessage = ex.Message;
                }
            }

            // Local metadata is king - if any is found don't run remote providers
            if (!options.ReplaceAllMetadata && (!hasLocalMetadata || options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh || !item.StopRefreshIfLocalMetadataFound))
            {
                var remoteResult = await ExecuteRemoteProviders(temp, logName, id, providers.OfType <IRemoteMetadataProvider <TItemType, TIdType> >(), cancellationToken)
                                   .ConfigureAwait(false);

                refreshResult.UpdateType  |= remoteResult.UpdateType;
                refreshResult.ErrorMessage = remoteResult.ErrorMessage;
                refreshResult.Failures    += remoteResult.Failures;
            }

            if (providers.Any(i => i is not ICustomMetadataProvider))
            {
                if (refreshResult.UpdateType > ItemUpdateType.None)
                {
                    if (hasLocalMetadata)
                    {
                        MergeData(temp, metadata, item.LockedFields, true, true);
                    }
                    else
                    {
                        if (!options.RemoveOldMetadata)
                        {
                            MergeData(metadata, temp, Array.Empty <MetadataField>(), false, false);
                        }

                        MergeData(temp, metadata, item.LockedFields, true, false);
                    }
                }
            }

            foreach (var provider in customProviders.Where(i => i is not IPreRefreshProvider))
            {
                await RunCustomProvider(provider, item, logName, options, refreshResult, cancellationToken).ConfigureAwait(false);
            }

            return(refreshResult);
        }
Esempio n. 2
0
        protected virtual async Task <RefreshResult> RefreshWithProviders(
            MetadataResult <TItemType> metadata,
            TIdType id,
            MetadataRefreshOptions options,
            List <IMetadataProvider> providers,
            ItemImageProvider imageService,
            CancellationToken cancellationToken)
        {
            var refreshResult = new RefreshResult
            {
                UpdateType = ItemUpdateType.None
            };

            var item = metadata.Item;

            var customProviders = providers.OfType <ICustomMetadataProvider <TItemType> >().ToList();
            var logName         = !item.IsFileProtocol ? item.Name ?? item.Path : item.Path ?? item.Name;

            foreach (var provider in customProviders.Where(i => i is IPreRefreshProvider))
            {
                await RunCustomProvider(provider, item, logName, options, refreshResult, cancellationToken).ConfigureAwait(false);
            }

            var temp = new MetadataResult <TItemType>
            {
                Item = CreateNew()
            };

            temp.Item.Path = item.Path;

            var userDataList = new List <UserItemData>();

            // If replacing all metadata, run internet providers first
            if (options.ReplaceAllMetadata)
            {
                var remoteResult = await ExecuteRemoteProviders(temp, logName, id, providers.OfType <IRemoteMetadataProvider <TItemType, TIdType> >(), cancellationToken)
                                   .ConfigureAwait(false);

                refreshResult.UpdateType  |= remoteResult.UpdateType;
                refreshResult.ErrorMessage = remoteResult.ErrorMessage;
                refreshResult.Failures    += remoteResult.Failures;
            }

            var hasLocalMetadata = false;

            foreach (var provider in providers.OfType <ILocalMetadataProvider <TItemType> >().ToList())
            {
                var providerName = provider.GetType().Name;
                Logger.LogDebug("Running {0} for {1}", providerName, logName);

                var itemInfo = new ItemInfo(item);

                try
                {
                    var localItem = await provider.GetMetadata(itemInfo, options.DirectoryService, cancellationToken).ConfigureAwait(false);

                    if (localItem.HasMetadata)
                    {
                        foreach (var remoteImage in localItem.RemoteImages)
                        {
                            await ProviderManager.SaveImage(item, remoteImage.url, remoteImage.type, null, cancellationToken).ConfigureAwait(false);

                            refreshResult.UpdateType |= ItemUpdateType.ImageUpdate;
                        }

                        if (imageService.MergeImages(item, localItem.Images))
                        {
                            refreshResult.UpdateType |= ItemUpdateType.ImageUpdate;
                        }

                        if (localItem.UserDataList != null)
                        {
                            userDataList.AddRange(localItem.UserDataList);
                        }

                        MergeData(localItem, temp, Array.Empty <MetadataField>(), !options.ReplaceAllMetadata, true);
                        refreshResult.UpdateType |= ItemUpdateType.MetadataImport;

                        // Only one local provider allowed per item
                        if (item.IsLocked || localItem.Item.IsLocked || IsFullLocalMetadata(localItem.Item))
                        {
                            hasLocalMetadata = true;
                        }

                        break;
                    }

                    Logger.LogDebug("{0} returned no metadata for {1}", providerName, logName);
                }
                catch (OperationCanceledException)
                {
                    throw;
                }
                catch (Exception ex)
                {
                    Logger.LogError(ex, "Error in {provider}", provider.Name);

                    // If a local provider fails, consider that a failure
                    refreshResult.ErrorMessage = ex.Message;
                }
            }

            // Local metadata is king - if any is found don't run remote providers
            if (!options.ReplaceAllMetadata && (!hasLocalMetadata || options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh || !item.StopRefreshIfLocalMetadataFound))
            {
                var remoteResult = await ExecuteRemoteProviders(temp, logName, id, providers.OfType <IRemoteMetadataProvider <TItemType, TIdType> >(), cancellationToken)
                                   .ConfigureAwait(false);

                refreshResult.UpdateType  |= remoteResult.UpdateType;
                refreshResult.ErrorMessage = remoteResult.ErrorMessage;
                refreshResult.Failures    += remoteResult.Failures;
            }

            if (providers.Any(i => !(i is ICustomMetadataProvider)))
            {
                if (refreshResult.UpdateType > ItemUpdateType.None)
                {
                    if (hasLocalMetadata)
                    {
                        MergeData(temp, metadata, item.LockedFields, true, true);
                    }
                    else
                    {
                        // TODO: If the new metadata from above has some blank data, this can cause old data to get filled into those empty fields
                        MergeData(metadata, temp, Array.Empty <MetadataField>(), false, false);
                        MergeData(temp, metadata, item.LockedFields, true, false);
                    }
                }
            }

            // var isUnidentified = failedProviderCount > 0 && successfulProviderCount == 0;

            foreach (var provider in customProviders.Where(i => !(i is IPreRefreshProvider)))
            {
                await RunCustomProvider(provider, item, logName, options, refreshResult, cancellationToken).ConfigureAwait(false);
            }

            // ImportUserData(item, userDataList, cancellationToken);

            return(refreshResult);
        }