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)); }
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; } } }
public IEnumerable <IImageProvider> GetImageProviders(BaseItem item, ImageRefreshOptions refreshOptions) { return(GetImageProviders(item, _libraryManagerFactory().GetLibraryOptions(item), GetMetadataOptions(item), refreshOptions, false)); }
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); } }
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); } }
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); }
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); }
/// <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); } }
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); }
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); } }
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)); }
public IEnumerable <IImageProvider> GetImageProviders(IHasMetadata item, ImageRefreshOptions refreshOptions) { return(GetImageProviders(item, GetMetadataOptions(item), refreshOptions, false)); }
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); }
/// <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); } }