コード例 #1
0
ファイル: ProviderManager.cs プロジェクト: sxryt/jellyfin
        private IEnumerable <IImageProvider> GetImageProviders(BaseItem item, LibraryOptions libraryOptions, MetadataOptions options, ImageRefreshOptions refreshOptions, bool includeDisabled)
        {
            // Avoid implicitly captured closure
            var currentOptions = options;

            var typeOptions      = libraryOptions.GetTypeOptions(item.GetType().Name);
            var typeFetcherOrder = typeOptions == null ? null : typeOptions.ImageFetcherOrder;

            return(ImageProviders.Where(i => CanRefresh(i, item, libraryOptions, options, refreshOptions, includeDisabled))
                   .OrderBy(i =>
            {
                // See if there's a user-defined order
                if (!(i is ILocalImageProvider))
                {
                    var fetcherOrder = typeFetcherOrder ?? currentOptions.ImageFetcherOrder;

                    var index = Array.IndexOf(fetcherOrder, i.Name);

                    if (index != -1)
                    {
                        return index;
                    }
                }

                // Not configured. Just return some high number to put it at the end.
                return 100;
            })
                   .ThenBy(GetOrder));
        }
コード例 #2
0
        private async Task DownloadMultiImages(BaseItem item, ImageType imageType, ImageRefreshOptions refreshOptions, int limit, IRemoteImageProvider provider, RefreshResult result, IEnumerable <RemoteImageInfo> images, int minWidth, CancellationToken cancellationToken)
        {
            foreach (var image in images.Where(i => i.Type == imageType))
            {
                if (item.GetImages(imageType).Count() >= limit)
                {
                    break;
                }

                if (image.Width.HasValue && image.Width.Value < minWidth)
                {
                    continue;
                }

                var url = image.Url;

                if (EnableImageStub(item))
                {
                    SaveImageStub(item, imageType, new[] { url });
                    result.UpdateType |= ItemUpdateType.ImageUpdate;
                    continue;
                }

                try
                {
                    using var response = await provider.GetImageResponse(url, cancellationToken).ConfigureAwait(false);

                    // Sometimes providers send back bad urls. Just move to the next image
                    if (response.StatusCode == HttpStatusCode.NotFound || response.StatusCode == HttpStatusCode.Forbidden)
                    {
                        _logger.LogDebug("{Url} returned {StatusCode}, ignoring", url, response.StatusCode);
                        continue;
                    }

                    if (!response.IsSuccessStatusCode)
                    {
                        _logger.LogWarning("{Url} returned {StatusCode}, skipping all remaining requests", url, response.StatusCode);
                        break;
                    }

                    // If there's already an image of the same file size, skip it unless doing a full refresh
                    if (response.Content.Headers.ContentLength.HasValue && !refreshOptions.IsReplacingImage(imageType))
                    {
                        try
                        {
                            if (item.GetImages(imageType).Any(i => _fileSystem.GetFileInfo(i.Path).Length == response.Content.Headers.ContentLength.Value))
                            {
                                response.Content.Dispose();
                                continue;
                            }
                        }
                        catch (IOException ex)
                        {
                            _logger.LogError(ex, "Error examining images");
                        }
                    }

                    await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);

                    await _providerManager.SaveImage(
                        item,
                        stream,
                        response.Content.Headers.ContentType.MediaType,
                        imageType,
                        null,
                        cancellationToken).ConfigureAwait(false);

                    result.UpdateType = result.UpdateType | ItemUpdateType.ImageUpdate;
                }
                catch (HttpRequestException)
                {
                    break;
                }
            }
        }
コード例 #3
0
ファイル: ProviderManager.cs プロジェクト: sxryt/jellyfin
 public IEnumerable <IImageProvider> GetImageProviders(BaseItem item, ImageRefreshOptions refreshOptions)
 {
     return(GetImageProviders(item, _libraryManagerFactory().GetLibraryOptions(item), GetMetadataOptions(item), refreshOptions, false));
 }
コード例 #4
0
        private async Task RefreshFromProvider(
            BaseItem item,
            IDynamicImageProvider provider,
            ImageRefreshOptions refreshOptions,
            TypeOptions savedOptions,
            ICollection <ImageType> downloadedImages,
            RefreshResult result,
            CancellationToken cancellationToken)
        {
            try
            {
                var images = provider.GetSupportedImages(item);

                foreach (var imageType in images)
                {
                    if (!IsEnabled(savedOptions, imageType))
                    {
                        continue;
                    }

                    if (!HasImage(item, imageType) || (refreshOptions.IsReplacingImage(imageType) && !downloadedImages.Contains(imageType)))
                    {
                        _logger.LogDebug("Running {0} for {1}", provider.GetType().Name, item.Path ?? item.Name);

                        var response = await provider.GetImage(item, imageType, cancellationToken).ConfigureAwait(false);

                        if (response.HasImage)
                        {
                            if (string.IsNullOrEmpty(response.Path))
                            {
                                var mimeType = response.Format.GetMimeType();

                                await _providerManager.SaveImage(item, response.Stream, mimeType, imageType, null, cancellationToken).ConfigureAwait(false);
                            }
                            else
                            {
                                if (response.Protocol == MediaProtocol.Http)
                                {
                                    _logger.LogDebug("Setting image url into item {0}", item.Id);
                                    var index = item.AllowsMultipleImages(imageType) ? item.GetImages(imageType).Count() : 0;
                                    item.SetImage(
                                        new ItemImageInfo
                                    {
                                        Path = response.Path,
                                        Type = imageType
                                    },
                                        index);
                                }
                                else
                                {
                                    var mimeType = MimeTypes.GetMimeType(response.Path);

                                    var stream = AsyncFile.OpenRead(response.Path);

                                    await _providerManager.SaveImage(item, stream, mimeType, imageType, null, cancellationToken).ConfigureAwait(false);
                                }
                            }

                            downloadedImages.Add(imageType);
                            result.UpdateType |= ItemUpdateType.ImageUpdate;
                        }
                    }
                }
            }
            catch (OperationCanceledException)
            {
                throw;
            }
            catch (Exception ex)
            {
                result.ErrorMessage = ex.Message;
                _logger.LogError(ex, "Error in {Provider}", provider.Name);
            }
        }
コード例 #5
0
        private async Task RefreshFromProvider(
            BaseItem item,
            IRemoteImageProvider provider,
            ImageRefreshOptions refreshOptions,
            TypeOptions savedOptions,
            int backdropLimit,
            ICollection <ImageType> downloadedImages,
            RefreshResult result,
            CancellationToken cancellationToken)
        {
            try
            {
                if (!item.SupportsRemoteImageDownloading)
                {
                    return;
                }

                if (!refreshOptions.ReplaceAllImages &&
                    refreshOptions.ReplaceImages.Length == 0 &&
                    ContainsImages(item, provider.GetSupportedImages(item).ToList(), savedOptions, backdropLimit))
                {
                    return;
                }

                _logger.LogDebug("Running {0} for {1}", provider.GetType().Name, item.Path ?? item.Name);

                var images = await _providerManager.GetAvailableRemoteImages(
                    item,
                    new RemoteImageQuery(provider.Name)
                {
                    IncludeAllLanguages      = true,
                    IncludeDisabledProviders = false,
                },
                    cancellationToken).ConfigureAwait(false);

                var list = images.ToList();
                int minWidth;

                foreach (var imageType in _singularImages)
                {
                    if (!IsEnabled(savedOptions, imageType))
                    {
                        continue;
                    }

                    if (!HasImage(item, imageType) || (refreshOptions.IsReplacingImage(imageType) && !downloadedImages.Contains(imageType)))
                    {
                        minWidth = savedOptions.GetMinWidth(imageType);
                        var downloaded = await DownloadImage(item, provider, result, list, minWidth, imageType, cancellationToken).ConfigureAwait(false);

                        if (downloaded)
                        {
                            downloadedImages.Add(imageType);
                        }
                    }
                }

                minWidth = savedOptions.GetMinWidth(ImageType.Backdrop);
                await DownloadMultiImages(item, ImageType.Backdrop, refreshOptions, backdropLimit, provider, result, list, minWidth, cancellationToken).ConfigureAwait(false);
            }
            catch (OperationCanceledException)
            {
                throw;
            }
            catch (Exception ex)
            {
                result.ErrorMessage = ex.Message;
                _logger.LogError(ex, "Error in {Provider}", provider.Name);
            }
        }
コード例 #6
0
        protected virtual IEnumerable <IImageProvider> GetNonLocalImageProviders(IHasMetadata item, IEnumerable <IImageProvider> allImageProviders, MetadataStatus status, ImageRefreshOptions options)
        {
            // Get providers to refresh
            var providers = allImageProviders.Where(i => !(i is ILocalImageProvider)).ToList();

            // Run all if either of these flags are true
            var runAllProviders = options.ImageRefreshMode == ImageRefreshMode.FullRefresh || !status.DateLastImagesRefresh.HasValue;

            if (!runAllProviders)
            {
                providers = providers
                            .Where(i =>
                {
                    var hasChangeMonitor = i as IHasChangeMonitor;
                    if (hasChangeMonitor != null)
                    {
                        return(HasChanged(item, hasChangeMonitor, status.DateLastImagesRefresh.Value, options.DirectoryService));
                    }

                    var hasFileChangeMonitor = i as IHasItemChangeMonitor;
                    if (hasFileChangeMonitor != null)
                    {
                        return(HasChanged(item, hasFileChangeMonitor, status, options.DirectoryService));
                    }

                    return(false);
                })
                            .ToList();
            }

            return(providers);
        }
コード例 #7
0
ファイル: MetadataService.cs プロジェクト: jellyfin/jellyfin
        protected virtual IEnumerable <IImageProvider> GetNonLocalImageProviders(BaseItem item, IEnumerable <IImageProvider> allImageProviders, ImageRefreshOptions options)
        {
            // Get providers to refresh
            var providers = allImageProviders.Where(i => i is not ILocalImageProvider);

            var dateLastImageRefresh = item.DateLastRefreshed;

            // Run all if either of these flags are true
            var runAllProviders = options.ImageRefreshMode == MetadataRefreshMode.FullRefresh || dateLastImageRefresh == default(DateTime);

            if (!runAllProviders)
            {
                providers = providers
                            .Where(i =>
                {
                    if (i is IHasItemChangeMonitor hasFileChangeMonitor)
                    {
                        return(HasChanged(item, hasFileChangeMonitor, options.DirectoryService));
                    }

                    return(false);
                });
            }

            return(providers);
        }
コード例 #8
0
        /// <summary>
        /// Refreshes from provider.
        /// </summary>
        /// <param name="item">The item.</param>
        /// <param name="provider">The provider.</param>
        /// <param name="refreshOptions">The refresh options.</param>
        /// <param name="savedOptions">The saved options.</param>
        /// <param name="backdropLimit">The backdrop limit.</param>
        /// <param name="screenshotLimit">The screenshot limit.</param>
        /// <param name="downloadedImages">The downloaded images.</param>
        /// <param name="result">The result.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>Task.</returns>
        private async Task RefreshFromProvider(IHasImages item,
                                               IRemoteImageProvider provider,
                                               ImageRefreshOptions refreshOptions,
                                               MetadataOptions savedOptions,
                                               int backdropLimit,
                                               int screenshotLimit,
                                               ICollection <ImageType> downloadedImages,
                                               RefreshResult result,
                                               CancellationToken cancellationToken)
        {
            try
            {
                if (!item.SupportsRemoteImageDownloading)
                {
                    return;
                }

                if (!refreshOptions.ReplaceAllImages &&
                    refreshOptions.ReplaceImages.Count == 0 &&
                    ContainsImages(item, provider.GetSupportedImages(item).ToList(), savedOptions, backdropLimit, screenshotLimit))
                {
                    return;
                }

                _logger.Debug("Running {0} for {1}", provider.GetType().Name, item.Path ?? item.Name);

                var images = await _providerManager.GetAvailableRemoteImages(item, new RemoteImageQuery
                {
                    ProviderName             = provider.Name,
                    IncludeAllLanguages      = false,
                    IncludeDisabledProviders = false,
                }, cancellationToken).ConfigureAwait(false);

                var list = images.ToList();
                int minWidth;

                foreach (var imageType in _singularImages)
                {
                    if (!IsEnabled(savedOptions, imageType, item))
                    {
                        continue;
                    }

                    if (!item.HasImage(imageType) || (refreshOptions.IsReplacingImage(imageType) && !downloadedImages.Contains(imageType)))
                    {
                        minWidth = savedOptions.GetMinWidth(imageType);
                        var downloaded = await DownloadImage(item, provider, result, list, minWidth, imageType, cancellationToken).ConfigureAwait(false);

                        if (downloaded)
                        {
                            downloadedImages.Add(imageType);
                        }
                    }
                }

                if (!item.LockedFields.Contains(MetadataFields.Backdrops))
                {
                    minWidth = savedOptions.GetMinWidth(ImageType.Backdrop);
                    await DownloadBackdrops(item, ImageType.Backdrop, backdropLimit, provider, result, list, minWidth, cancellationToken).ConfigureAwait(false);
                }

                if (!item.LockedFields.Contains(MetadataFields.Screenshots))
                {
                    var hasScreenshots = item as IHasScreenshots;
                    if (hasScreenshots != null)
                    {
                        minWidth = savedOptions.GetMinWidth(ImageType.Screenshot);
                        await DownloadBackdrops(item, ImageType.Screenshot, screenshotLimit, provider, result, list, minWidth, cancellationToken).ConfigureAwait(false);
                    }
                }
            }
            catch (OperationCanceledException)
            {
                throw;
            }
            catch (Exception ex)
            {
                result.ErrorMessage = ex.Message;
                result.Status       = ProviderRefreshStatus.CompletedWithErrors;
                _logger.ErrorException("Error in {0}", ex, provider.Name);
            }
        }
コード例 #9
0
        public async Task <RefreshResult> RefreshImages(IHasImages item, IEnumerable <IImageProvider> imageProviders, ImageRefreshOptions refreshOptions, MetadataOptions savedOptions, CancellationToken cancellationToken)
        {
            if (refreshOptions.IsReplacingImage(ImageType.Backdrop))
            {
                ClearImages(item, ImageType.Backdrop);
            }
            if (refreshOptions.IsReplacingImage(ImageType.Screenshot))
            {
                ClearImages(item, ImageType.Screenshot);
            }

            var result = new RefreshResult {
                UpdateType = ItemUpdateType.None
            };

            var providers = imageProviders.ToList();

            var providerIds = new List <Guid>();

            // In order to avoid duplicates, only download these if there are none already
            var backdropLimit    = savedOptions.GetLimit(ImageType.Backdrop);
            var screenshotLimit  = savedOptions.GetLimit(ImageType.Screenshot);
            var downloadedImages = new List <ImageType>();

            foreach (var provider in providers)
            {
                var remoteProvider = provider as IRemoteImageProvider;

                if (remoteProvider != null)
                {
                    await RefreshFromProvider(item, remoteProvider, refreshOptions, savedOptions, backdropLimit, screenshotLimit, downloadedImages, result, cancellationToken).ConfigureAwait(false);

                    providerIds.Add(provider.GetType().FullName.GetMD5());
                    continue;
                }

                var dynamicImageProvider = provider as IDynamicImageProvider;

                if (dynamicImageProvider != null)
                {
                    await RefreshFromProvider(item, dynamicImageProvider, refreshOptions, savedOptions, downloadedImages, result, cancellationToken).ConfigureAwait(false);

                    providerIds.Add(provider.GetType().FullName.GetMD5());
                }
            }

            result.Providers = providerIds;

            return(result);
        }
コード例 #10
0
        private bool CanRefresh(IImageProvider provider, IHasMetadata item, MetadataOptions options, ImageRefreshOptions refreshOptions, bool includeDisabled)
        {
            if (!includeDisabled)
            {
                // If locked only allow local providers
                if (item.IsLocked && !(provider is ILocalImageProvider))
                {
                    if (refreshOptions.ImageRefreshMode != ImageRefreshMode.FullRefresh)
                    {
                        return(false);
                    }
                }

                if (provider is IRemoteImageProvider || provider is IDynamicImageProvider)
                {
                    if (Array.IndexOf(options.DisabledImageFetchers, provider.Name) != -1)
                    {
                        return(false);
                    }

                    if (provider is IRemoteImageProvider)
                    {
                        if (!refreshOptions.ForceEnableInternetMetadata && !item.IsInternetMetadataEnabled())
                        {
                            return(false);
                        }
                    }
                }
            }

            try
            {
                return(provider.Supports(item));
            }
            catch (Exception ex)
            {
                _logger.ErrorException("{0} failed in Supports for type {1}", ex, provider.GetType().Name, item.GetType().Name);
                return(false);
            }
        }
コード例 #11
0
        private IEnumerable <IImageProvider> GetImageProviders(IHasMetadata item, MetadataOptions options, ImageRefreshOptions refreshOptions, bool includeDisabled)
        {
            // Avoid implicitly captured closure
            var currentOptions = options;

            return(ImageProviders.Where(i => CanRefresh(i, item, options, refreshOptions, includeDisabled))
                   .OrderBy(i =>
            {
                // See if there's a user-defined order
                if (!(i is ILocalImageProvider))
                {
                    var index = Array.IndexOf(currentOptions.ImageFetcherOrder, i.Name);

                    if (index != -1)
                    {
                        return index;
                    }
                }

                // Not configured. Just return some high number to put it at the end.
                return 100;
            })
                   .ThenBy(GetOrder));
        }
コード例 #12
0
 public IEnumerable <IImageProvider> GetImageProviders(IHasMetadata item, ImageRefreshOptions refreshOptions)
 {
     return(GetImageProviders(item, GetMetadataOptions(item), refreshOptions, false));
 }
コード例 #13
0
ファイル: ItemImageProvider.cs プロジェクト: vesoapp/veso
        public async Task <RefreshResult> RefreshImages(BaseItem item, LibraryOptions libraryOptions, List <IImageProvider> providers, ImageRefreshOptions refreshOptions, MetadataOptions savedOptions, CancellationToken cancellationToken)
        {
            if (refreshOptions.IsReplacingImage(ImageType.Backdrop))
            {
                ClearImages(item, ImageType.Backdrop);
            }
            if (refreshOptions.IsReplacingImage(ImageType.Screenshot))
            {
                ClearImages(item, ImageType.Screenshot);
            }

            var result = new RefreshResult {
                UpdateType = ItemUpdateType.None
            };

            var typeName    = item.GetType().Name;
            var typeOptions = libraryOptions.GetTypeOptions(typeName) ?? new TypeOptions {
                Type = typeName
            };

            // In order to avoid duplicates, only download these if there are none already
            var backdropLimit    = typeOptions.GetLimit(ImageType.Backdrop);
            var screenshotLimit  = typeOptions.GetLimit(ImageType.Screenshot);
            var downloadedImages = new List <ImageType>();

            foreach (var provider in providers)
            {
                var remoteProvider = provider as IRemoteImageProvider;

                if (remoteProvider != null)
                {
                    await RefreshFromProvider(item, libraryOptions, remoteProvider, refreshOptions, typeOptions, backdropLimit, screenshotLimit, downloadedImages, result, cancellationToken).ConfigureAwait(false);

                    continue;
                }

                var dynamicImageProvider = provider as IDynamicImageProvider;

                if (dynamicImageProvider != null)
                {
                    await RefreshFromProvider(item, dynamicImageProvider, refreshOptions, typeOptions, libraryOptions, downloadedImages, result, cancellationToken).ConfigureAwait(false);
                }
            }

            return(result);
        }
コード例 #14
0
ファイル: ItemImageProvider.cs プロジェクト: vesoapp/veso
        /// <summary>
        /// Refreshes from provider.
        /// </summary>
        private async Task RefreshFromProvider(BaseItem item,
                                               IDynamicImageProvider provider,
                                               ImageRefreshOptions refreshOptions,
                                               TypeOptions savedOptions,
                                               LibraryOptions libraryOptions,
                                               ICollection <ImageType> downloadedImages,
                                               RefreshResult result,
                                               CancellationToken cancellationToken)
        {
            try
            {
                var images = provider.GetSupportedImages(item);

                foreach (var imageType in images)
                {
                    if (!IsEnabled(savedOptions, imageType, item))
                    {
                        continue;
                    }

                    if (!HasImage(item, imageType) || (refreshOptions.IsReplacingImage(imageType) && !downloadedImages.Contains(imageType)))
                    {
                        _logger.LogDebug("Running {0} for {1}", provider.GetType().Name, item.Path ?? item.Name);

                        var response = await provider.GetImage(item, imageType, cancellationToken).ConfigureAwait(false);

                        if (response.HasImage)
                        {
                            if (!string.IsNullOrEmpty(response.Path))
                            {
                                if (response.Protocol == MediaProtocol.Http)
                                {
                                    _logger.LogDebug("Setting image url into item {0}", item.Id);
                                    item.SetImage(new ItemImageInfo
                                    {
                                        Path = response.Path,
                                        Type = imageType
                                    }, 0);
                                }
                                else
                                {
                                    var mimeType = MimeTypes.GetMimeType(response.Path);

                                    var stream = new FileStream(response.Path, FileMode.Open, FileAccess.Read, FileShare.Read, IODefaults.FileStreamBufferSize, true);

                                    await _providerManager.SaveImage(item, stream, mimeType, imageType, null, cancellationToken).ConfigureAwait(false);
                                }
                            }
                            else
                            {
                                var mimeType = "image/" + response.Format.ToString().ToLowerInvariant();

                                await _providerManager.SaveImage(item, response.Stream, mimeType, imageType, null, cancellationToken).ConfigureAwait(false);
                            }

                            downloadedImages.Add(imageType);
                            result.UpdateType = result.UpdateType | ItemUpdateType.ImageUpdate;
                        }
                    }
                }
            }
            catch (OperationCanceledException)
            {
                throw;
            }
            catch (Exception ex)
            {
                result.ErrorMessage = ex.Message;
                _logger.LogError(ex, "Error in {provider}", provider.Name);
            }
        }