From 11d7c00de9731b3b875ea5bb3afa02e1dfd7b950 Mon Sep 17 00:00:00 2001 From: SenorSmartyPants Date: Wed, 10 May 2023 18:46:55 -0500 Subject: [PATCH] Fix local JPG primary image for video being overwritten by screen grabber (#9552) --- .../Manager/ItemImageProvider.cs | 42 +++++++++++++++++-- .../Manager/MetadataService.cs | 19 ++++----- .../Manager/ItemImageProviderTests.cs | 6 +-- 3 files changed, 48 insertions(+), 19 deletions(-) diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index ba2d2db2f7..dab36625e5 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -32,6 +32,7 @@ namespace MediaBrowser.Providers.Manager private readonly ILogger _logger; private readonly IProviderManager _providerManager; private readonly IFileSystem _fileSystem; + private static readonly ImageType[] AllImageTypes = Enum.GetValues(); /// /// Image types that are only one per item. @@ -90,11 +91,12 @@ namespace MediaBrowser.Providers.Manager /// /// The to validate images for. /// The providers to use, must include (s) for local scanning. - /// The directory service for s to use. + /// The refresh options. /// true if changes were made to the item; otherwise false. - public bool ValidateImages(BaseItem item, IEnumerable providers, IDirectoryService directoryService) + public bool ValidateImages(BaseItem item, IEnumerable providers, ImageRefreshOptions refreshOptions) { var hasChanges = false; + IDirectoryService directoryService = refreshOptions?.DirectoryService; if (item is not Photo) { @@ -102,7 +104,7 @@ namespace MediaBrowser.Providers.Manager .SelectMany(i => i.GetImages(item, directoryService)) .ToList(); - if (MergeImages(item, images)) + if (MergeImages(item, images, refreshOptions)) { hasChanges = true; } @@ -381,15 +383,36 @@ namespace MediaBrowser.Providers.Manager item.RemoveImages(images); } + /// + /// Merges a list of images into the provided item, validating existing images and replacing them or adding new images as necessary. + /// + /// The refresh options. + /// List of imageTypes to remove from ReplaceImages. + public void UpdateReplaceImages(ImageRefreshOptions refreshOptions, ICollection dontReplaceImages) + { + if (refreshOptions is not null) + { + if (refreshOptions.ReplaceAllImages) + { + refreshOptions.ReplaceAllImages = false; + refreshOptions.ReplaceImages = AllImageTypes.ToList(); + } + + refreshOptions.ReplaceImages = refreshOptions.ReplaceImages.Except(dontReplaceImages).ToList(); + } + } + /// /// Merges a list of images into the provided item, validating existing images and replacing them or adding new images as necessary. /// /// The to modify. /// The new images to place in item. + /// The refresh options. /// true if changes were made to the item; otherwise false. - public bool MergeImages(BaseItem item, IReadOnlyList images) + public bool MergeImages(BaseItem item, IReadOnlyList images, ImageRefreshOptions refreshOptions) { var changed = item.ValidateImages(); + var foundImageTypes = new List(); for (var i = 0; i < _singularImages.Length; i++) { @@ -399,6 +422,11 @@ namespace MediaBrowser.Providers.Manager if (image is not null) { var currentImage = item.GetImageInfo(type, 0); + // if image file is stored with media, don't replace that later + if (item.ContainingFolderPath is not null && item.ContainingFolderPath.Contains(Path.GetDirectoryName(image.FileInfo.FullName), StringComparison.OrdinalIgnoreCase)) + { + foundImageTypes.Add(type); + } if (currentImage is null || !string.Equals(currentImage.Path, image.FileInfo.FullName, StringComparison.OrdinalIgnoreCase)) { @@ -425,6 +453,12 @@ namespace MediaBrowser.Providers.Manager if (UpdateMultiImages(item, images, ImageType.Backdrop)) { changed = true; + foundImageTypes.Add(ImageType.Backdrop); + } + + if (foundImageTypes.Count > 0) + { + UpdateReplaceImages(refreshOptions, foundImageTypes); } return changed; diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index bcc9b809c2..80f77f7c3a 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -26,8 +26,6 @@ namespace MediaBrowser.Providers.Manager where TItemType : BaseItem, IHasLookupInfo, new() where TIdType : ItemLookupInfo, new() { - private static readonly ImageType[] AllImageTypes = Enum.GetValues(); - protected MetadataService(IServerConfigurationManager serverConfigurationManager, ILogger> logger, IProviderManager providerManager, IFileSystem fileSystem, ILibraryManager libraryManager) { ServerConfigurationManager = serverConfigurationManager; @@ -110,7 +108,7 @@ namespace MediaBrowser.Providers.Manager try { // Always validate images and check for new locally stored ones. - if (ImageProvider.ValidateImages(item, allImageProviders.OfType(), refreshOptions.DirectoryService)) + if (ImageProvider.ValidateImages(item, allImageProviders.OfType(), refreshOptions)) { updateType |= ItemUpdateType.ImageUpdate; } @@ -674,8 +672,7 @@ namespace MediaBrowser.Providers.Manager } var hasLocalMetadata = false; - var replaceImages = AllImageTypes.ToList(); - var localImagesFound = false; + var foundImageTypes = new List(); foreach (var provider in providers.OfType>()) { @@ -703,9 +700,8 @@ namespace MediaBrowser.Providers.Manager await ProviderManager.SaveImage(item, remoteImage.Url, remoteImage.Type, null, cancellationToken).ConfigureAwait(false); refreshResult.UpdateType |= ItemUpdateType.ImageUpdate; - // remove imagetype that has just been downloaded - replaceImages.Remove(remoteImage.Type); - localImagesFound = true; + // remember imagetype that has just been downloaded + foundImageTypes.Add(remoteImage.Type); } catch (HttpRequestException ex) { @@ -713,13 +709,12 @@ namespace MediaBrowser.Providers.Manager } } - if (localImagesFound) + if (foundImageTypes.Count > 0) { - options.ReplaceAllImages = false; - options.ReplaceImages = replaceImages; + imageService.UpdateReplaceImages(options, foundImageTypes); } - if (imageService.MergeImages(item, localItem.Images)) + if (imageService.MergeImages(item, localItem.Images, options)) { refreshResult.UpdateType |= ItemUpdateType.ImageUpdate; } diff --git a/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs b/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs index 08b343cd89..925e8fa199 100644 --- a/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs +++ b/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs @@ -94,7 +94,7 @@ namespace Jellyfin.Providers.Tests.Manager public void MergeImages_EmptyItemNewImagesEmpty_NoChange() { var itemImageProvider = GetItemImageProvider(null, null); - var changed = itemImageProvider.MergeImages(new Video(), Array.Empty()); + var changed = itemImageProvider.MergeImages(new Video(), Array.Empty(), new ImageRefreshOptions(Mock.Of())); Assert.False(changed); } @@ -108,7 +108,7 @@ namespace Jellyfin.Providers.Tests.Manager var images = GetImages(imageType, imageCount, false); var itemImageProvider = GetItemImageProvider(null, null); - var changed = itemImageProvider.MergeImages(item, images); + var changed = itemImageProvider.MergeImages(item, images, new ImageRefreshOptions(Mock.Of())); Assert.True(changed); // adds for types that allow multiple, replaces singular type images @@ -151,7 +151,7 @@ namespace Jellyfin.Providers.Tests.Manager var images = GetImages(imageType, imageCount, true); var itemImageProvider = GetItemImageProvider(null, fileSystem); - var changed = itemImageProvider.MergeImages(item, images); + var changed = itemImageProvider.MergeImages(item, images, new ImageRefreshOptions(Mock.Of())); if (updateTime) {