aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Providers/Manager
diff options
context:
space:
mode:
authorferferga <ferferga.fer@gmail.com>2020-10-19 17:28:07 +0200
committerferferga <ferferga.fer@gmail.com>2020-10-19 17:28:07 +0200
commit9fd01fade6ac971ba72a2e7dd54e2295f23839bc (patch)
tree20a5ff4a1621e765fc93c0e53b149edb61ff3654 /MediaBrowser.Providers/Manager
parentba03ed65fe64b724b3e8b5b94b9cbe1075c61da2 (diff)
parent49ac4c4044b1777dc3a25544aead7b0b15b953e8 (diff)
Remove "download images in advance" option
Diffstat (limited to 'MediaBrowser.Providers/Manager')
-rw-r--r--MediaBrowser.Providers/Manager/ImageSaver.cs100
-rw-r--r--MediaBrowser.Providers/Manager/ItemImageProvider.cs181
-rw-r--r--MediaBrowser.Providers/Manager/MetadataService.cs156
-rw-r--r--MediaBrowser.Providers/Manager/ProviderManager.cs376
-rw-r--r--MediaBrowser.Providers/Manager/ProviderUtils.cs28
-rw-r--r--MediaBrowser.Providers/Manager/RefreshResult.cs15
6 files changed, 494 insertions, 362 deletions
diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs
index 3ab621ba41..19a42d506c 100644
--- a/MediaBrowser.Providers/Manager/ImageSaver.cs
+++ b/MediaBrowser.Providers/Manager/ImageSaver.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.Globalization;
@@ -9,30 +11,33 @@ using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Net;
using Microsoft.Extensions.Logging;
+using Episode = MediaBrowser.Controller.Entities.TV.Episode;
+using MusicAlbum = MediaBrowser.Controller.Entities.Audio.MusicAlbum;
+using Person = MediaBrowser.Controller.Entities.Person;
+using Season = MediaBrowser.Controller.Entities.TV.Season;
namespace MediaBrowser.Providers.Manager
{
/// <summary>
- /// Class ImageSaver
+ /// Class ImageSaver.
/// </summary>
public class ImageSaver
{
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
/// <summary>
- /// The _config
+ /// The _config.
/// </summary>
private readonly IServerConfigurationManager _config;
/// <summary>
- /// The _directory watchers
+ /// The _directory watchers.
/// </summary>
private readonly ILibraryMonitor _libraryMonitor;
private readonly IFileSystem _fileSystem;
@@ -53,6 +58,16 @@ namespace MediaBrowser.Providers.Manager
_logger = logger;
}
+ private bool EnableExtraThumbsDuplication
+ {
+ get
+ {
+ var config = _config.GetConfiguration<XbmcMetadataOptions>("xbmcmetadata");
+
+ return config.EnableExtraThumbsDuplication;
+ }
+ }
+
/// <summary>
/// Saves the image.
/// </summary>
@@ -63,7 +78,7 @@ namespace MediaBrowser.Providers.Manager
/// <param name="imageIndex">Index of the image.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
- /// <exception cref="ArgumentNullException">mimeType</exception>
+ /// <exception cref="ArgumentNullException">mimeType.</exception>
public Task SaveImage(BaseItem item, Stream source, string mimeType, ImageType type, int? imageIndex, CancellationToken cancellationToken)
{
return SaveImage(item, source, mimeType, type, imageIndex, null, cancellationToken);
@@ -78,11 +93,6 @@ namespace MediaBrowser.Providers.Manager
var saveLocally = item.SupportsLocalMetadata && item.IsSaveLocalMetadataEnabled() && !item.ExtraType.HasValue && !(item is Audio);
- if (item is User)
- {
- saveLocally = true;
- }
-
if (type != ImageType.Primary && item is Episode)
{
saveLocally = false;
@@ -105,6 +115,7 @@ namespace MediaBrowser.Providers.Manager
}
}
}
+
if (saveLocallyWithMedia.HasValue && !saveLocallyWithMedia.Value)
{
saveLocally = saveLocallyWithMedia.Value;
@@ -122,35 +133,40 @@ namespace MediaBrowser.Providers.Manager
var retryPaths = GetSavePaths(item, type, imageIndex, mimeType, false);
// If there are more than one output paths, the stream will need to be seekable
- var memoryStream = new MemoryStream();
- using (source)
+ if (paths.Length > 1 && !source.CanSeek)
{
- await source.CopyToAsync(memoryStream).ConfigureAwait(false);
- }
+ var memoryStream = new MemoryStream();
+ await using (source.ConfigureAwait(false))
+ {
+ await source.CopyToAsync(memoryStream).ConfigureAwait(false);
+ }
- source = memoryStream;
+ source = memoryStream;
+ }
var currentImage = GetCurrentImage(item, type, index);
var currentImageIsLocalFile = currentImage != null && currentImage.IsLocalFile;
- var currentImagePath = currentImage == null ? null : currentImage.Path;
+ var currentImagePath = currentImage?.Path;
var savedPaths = new List<string>();
- using (source)
+ await using (source.ConfigureAwait(false))
{
- var currentPathIndex = 0;
-
- foreach (var path in paths)
+ for (int i = 0; i < paths.Length; i++)
{
- source.Position = 0;
+ if (i != 0)
+ {
+ source.Position = 0;
+ }
+
string retryPath = null;
if (paths.Length == retryPaths.Length)
{
- retryPath = retryPaths[currentPathIndex];
+ retryPath = retryPaths[i];
}
- var savedPath = await SaveImageToLocation(source, path, retryPath, cancellationToken).ConfigureAwait(false);
+
+ var savedPath = await SaveImageToLocation(source, paths[i], retryPath, cancellationToken).ConfigureAwait(false);
savedPaths.Add(savedPath);
- currentPathIndex++;
}
}
@@ -172,7 +188,6 @@ namespace MediaBrowser.Providers.Manager
}
catch (FileNotFoundException)
{
-
}
finally
{
@@ -181,6 +196,11 @@ namespace MediaBrowser.Providers.Manager
}
}
+ public async Task SaveImage(Stream source, string path)
+ {
+ await SaveImageToLocation(source, path, path, CancellationToken.None).ConfigureAwait(false);
+ }
+
private async Task<string> SaveImageToLocation(Stream source, string path, string retryPath, CancellationToken cancellationToken)
{
try
@@ -217,7 +237,6 @@ namespace MediaBrowser.Providers.Manager
}
}
- source.Position = 0;
await SaveImageToLocation(source, retryPath, cancellationToken).ConfigureAwait(false);
return retryPath;
}
@@ -244,9 +263,9 @@ namespace MediaBrowser.Providers.Manager
_fileSystem.SetAttributes(path, false, false);
- using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous))
+ await using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous))
{
- await source.CopyToAsync(fs, IODefaults.CopyToBufferSize, cancellationToken).ConfigureAwait(false);
+ await source.CopyToAsync(fs, cancellationToken).ConfigureAwait(false);
}
if (_config.Configuration.SaveMetadataHidden)
@@ -302,7 +321,7 @@ namespace MediaBrowser.Providers.Manager
/// <exception cref="ArgumentNullException">
/// imageIndex
/// or
- /// imageIndex
+ /// imageIndex.
/// </exception>
private ItemImageInfo GetCurrentImage(BaseItem item, ImageType type, int imageIndex)
{
@@ -318,7 +337,8 @@ namespace MediaBrowser.Providers.Manager
/// <param name="path">The path.</param>
/// <exception cref="ArgumentNullException">imageIndex
/// or
- /// imageIndex</exception>
+ /// imageIndex.
+ /// </exception>
private void SetImagePath(BaseItem item, ImageType type, int? imageIndex, string path)
{
item.SetImagePath(type, imageIndex ?? 0, _fileSystem.GetFileInfo(path));
@@ -336,7 +356,7 @@ namespace MediaBrowser.Providers.Manager
/// <exception cref="ArgumentNullException">
/// imageIndex
/// or
- /// imageIndex
+ /// imageIndex.
/// </exception>
private string GetStandardSavePath(BaseItem item, ImageType type, int? imageIndex, string mimeType, bool saveLocally)
{
@@ -345,7 +365,7 @@ namespace MediaBrowser.Providers.Manager
if (string.IsNullOrWhiteSpace(extension))
{
- throw new ArgumentException(string.Format("Unable to determine image file extension from mime type {0}", mimeType));
+ throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "Unable to determine image file extension from mime type {0}", mimeType));
}
if (type == ImageType.Thumb && saveLocally)
@@ -439,7 +459,6 @@ namespace MediaBrowser.Providers.Manager
{
path = Path.Combine(Path.GetDirectoryName(item.Path), "metadata", filename + extension);
}
-
else if (item.IsInMixedFolder)
{
path = GetSavePathForItemInMixedFolder(item, type, filename, extension);
@@ -458,6 +477,7 @@ namespace MediaBrowser.Providers.Manager
{
filename = folderName;
}
+
path = Path.Combine(item.GetInternalMetadataPath(), filename + extension);
}
@@ -490,7 +510,7 @@ namespace MediaBrowser.Providers.Manager
/// <param name="imageIndex">Index of the image.</param>
/// <param name="mimeType">Type of the MIME.</param>
/// <returns>IEnumerable{System.String}.</returns>
- /// <exception cref="ArgumentNullException">imageIndex</exception>
+ /// <exception cref="ArgumentNullException">imageIndex.</exception>
private string[] GetCompatibleSavePaths(BaseItem item, ImageType type, int? imageIndex, string mimeType)
{
var season = item as Season;
@@ -549,6 +569,7 @@ namespace MediaBrowser.Providers.Manager
{
list.Add(Path.Combine(item.ContainingFolderPath, "extrathumbs", "thumb" + outputIndex.ToString(UsCulture) + extension));
}
+
return list.ToArray();
}
@@ -593,16 +614,6 @@ namespace MediaBrowser.Providers.Manager
return new[] { GetStandardSavePath(item, type, imageIndex, mimeType, true) };
}
- private bool EnableExtraThumbsDuplication
- {
- get
- {
- var config = _config.GetConfiguration<XbmcMetadataOptions>("xbmcmetadata");
-
- return config.EnableExtraThumbsDuplication;
- }
- }
-
/// <summary>
/// Gets the save path for item in mixed folder.
/// </summary>
@@ -617,6 +628,7 @@ namespace MediaBrowser.Providers.Manager
{
imageFilename = "poster";
}
+
var folder = Path.GetDirectoryName(item.Path);
return Path.Combine(folder, Path.GetFileNameWithoutExtension(item.Path) + "-" + imageFilename + extension);
diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs
index 60270d80cb..a57a85376e 100644
--- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs
+++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.IO;
@@ -26,6 +28,22 @@ namespace MediaBrowser.Providers.Manager
private readonly IProviderManager _providerManager;
private readonly IFileSystem _fileSystem;
+ /// <summary>
+ /// Image types that are only one per item.
+ /// </summary>
+ private readonly ImageType[] _singularImages =
+ {
+ ImageType.Primary,
+ ImageType.Art,
+ ImageType.Banner,
+ ImageType.Box,
+ ImageType.BoxRear,
+ ImageType.Disc,
+ ImageType.Logo,
+ ImageType.Menu,
+ ImageType.Thumb
+ };
+
public ItemImageProvider(ILogger logger, IProviderManager providerManager, IFileSystem fileSystem)
{
_logger = logger;
@@ -52,12 +70,18 @@ namespace MediaBrowser.Providers.Manager
return hasChanges;
}
- public async Task<RefreshResult> RefreshImages(BaseItem item, LibraryOptions libraryOptions, List<IImageProvider> providers, ImageRefreshOptions refreshOptions, MetadataOptions savedOptions, CancellationToken cancellationToken)
+ public async Task<RefreshResult> RefreshImages(
+ BaseItem item,
+ LibraryOptions libraryOptions,
+ List<IImageProvider> providers,
+ ImageRefreshOptions refreshOptions,
+ CancellationToken cancellationToken)
{
if (refreshOptions.IsReplacingImage(ImageType.Backdrop))
{
ClearImages(item, ImageType.Backdrop);
}
+
if (refreshOptions.IsReplacingImage(ImageType.Screenshot))
{
ClearImages(item, ImageType.Screenshot);
@@ -75,19 +99,15 @@ namespace MediaBrowser.Providers.Manager
foreach (var provider in providers)
{
- var remoteProvider = provider as IRemoteImageProvider;
-
- if (remoteProvider != null)
+ if (provider is IRemoteImageProvider remoteProvider)
{
await RefreshFromProvider(item, libraryOptions, remoteProvider, refreshOptions, typeOptions, backdropLimit, screenshotLimit, downloadedImages, result, cancellationToken).ConfigureAwait(false);
continue;
}
- var dynamicImageProvider = provider as IDynamicImageProvider;
-
- if (dynamicImageProvider != null)
+ if (provider is IDynamicImageProvider dynamicImageProvider)
{
- await RefreshFromProvider(item, dynamicImageProvider, refreshOptions, typeOptions, libraryOptions, downloadedImages, result, cancellationToken).ConfigureAwait(false);
+ await RefreshFromProvider(item, dynamicImageProvider, refreshOptions, typeOptions, downloadedImages, result, cancellationToken).ConfigureAwait(false);
}
}
@@ -97,11 +117,11 @@ namespace MediaBrowser.Providers.Manager
/// <summary>
/// Refreshes from provider.
/// </summary>
- private async Task RefreshFromProvider(BaseItem item,
+ private async Task RefreshFromProvider(
+ BaseItem item,
IDynamicImageProvider provider,
ImageRefreshOptions refreshOptions,
TypeOptions savedOptions,
- LibraryOptions libraryOptions,
ICollection<ImageType> downloadedImages,
RefreshResult result,
CancellationToken cancellationToken)
@@ -112,7 +132,10 @@ namespace MediaBrowser.Providers.Manager
foreach (var imageType in images)
{
- if (!IsEnabled(savedOptions, imageType, item)) continue;
+ if (!IsEnabled(savedOptions, imageType))
+ {
+ continue;
+ }
if (!HasImage(item, imageType) || (refreshOptions.IsReplacingImage(imageType) && !downloadedImages.Contains(imageType)))
{
@@ -127,12 +150,13 @@ namespace MediaBrowser.Providers.Manager
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);
+ item.SetImage(
+ new ItemImageInfo
+ {
+ Path = response.Path,
+ Type = imageType
+ },
+ 0);
}
else
{
@@ -151,7 +175,7 @@ namespace MediaBrowser.Providers.Manager
}
downloadedImages.Add(imageType);
- result.UpdateType = result.UpdateType | ItemUpdateType.ImageUpdate;
+ result.UpdateType |= ItemUpdateType.ImageUpdate;
}
}
}
@@ -167,29 +191,13 @@ namespace MediaBrowser.Providers.Manager
}
}
- /// <summary>
- /// Image types that are only one per item
- /// </summary>
- private readonly ImageType[] _singularImages =
- {
- ImageType.Primary,
- ImageType.Art,
- ImageType.Banner,
- ImageType.Box,
- ImageType.BoxRear,
- ImageType.Disc,
- ImageType.Logo,
- ImageType.Menu,
- ImageType.Thumb
- };
-
private bool HasImage(BaseItem item, ImageType type)
{
return item.HasImage(type);
}
/// <summary>
- /// Determines if an item already contains the given images
+ /// Determines if an item already contains the given images.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="images">The images.</param>
@@ -221,6 +229,7 @@ namespace MediaBrowser.Providers.Manager
/// Refreshes from provider.
/// </summary>
/// <param name="item">The item.</param>
+ /// <param name="libraryOptions">The library options.</param>
/// <param name="provider">The provider.</param>
/// <param name="refreshOptions">The refresh options.</param>
/// <param name="savedOptions">The saved options.</param>
@@ -230,7 +239,9 @@ namespace MediaBrowser.Providers.Manager
/// <param name="result">The result.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
- private async Task RefreshFromProvider(BaseItem item, LibraryOptions libraryOptions,
+ private async Task RefreshFromProvider(
+ BaseItem item,
+ LibraryOptions libraryOptions,
IRemoteImageProvider provider,
ImageRefreshOptions refreshOptions,
TypeOptions savedOptions,
@@ -256,20 +267,24 @@ namespace MediaBrowser.Providers.Manager
_logger.LogDebug("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 images = await _providerManager.GetAvailableRemoteImages(
+ item,
+ new RemoteImageQuery(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 (!IsEnabled(savedOptions, imageType))
+ {
+ continue;
+ }
if (!HasImage(item, imageType) || (refreshOptions.IsReplacingImage(imageType) && !downloadedImages.Contains(imageType)))
{
@@ -286,8 +301,7 @@ namespace MediaBrowser.Providers.Manager
minWidth = savedOptions.GetMinWidth(ImageType.Backdrop);
await DownloadBackdrops(item, libraryOptions, ImageType.Backdrop, backdropLimit, provider, result, list, minWidth, cancellationToken).ConfigureAwait(false);
- var hasScreenshots = item as IHasScreenshots;
- if (hasScreenshots != null)
+ if (item is IHasScreenshots hasScreenshots)
{
minWidth = savedOptions.GetMinWidth(ImageType.Screenshot);
await DownloadBackdrops(item, libraryOptions, ImageType.Screenshot, screenshotLimit, provider, result, list, minWidth, cancellationToken).ConfigureAwait(false);
@@ -304,7 +318,7 @@ namespace MediaBrowser.Providers.Manager
}
}
- private bool IsEnabled(TypeOptions options, ImageType type, BaseItem item)
+ private bool IsEnabled(TypeOptions options, ImageType type)
{
return options.IsEnabled(type);
}
@@ -329,7 +343,6 @@ namespace MediaBrowser.Providers.Manager
}
catch (FileNotFoundException)
{
-
}
}
@@ -365,7 +378,6 @@ namespace MediaBrowser.Providers.Manager
}
else
{
-
var newDateModified = _fileSystem.GetLastWriteTimeUtc(image.FileInfo);
// If date changed then we need to reset saved image dimensions
@@ -428,7 +440,9 @@ namespace MediaBrowser.Providers.Manager
return changed;
}
- private async Task<bool> DownloadImage(BaseItem item, LibraryOptions libraryOptions,
+ private async Task<bool> DownloadImage(
+ BaseItem item,
+ LibraryOptions libraryOptions,
IRemoteImageProvider provider,
RefreshResult result,
IEnumerable<RemoteImageInfo> images,
@@ -440,10 +454,10 @@ namespace MediaBrowser.Providers.Manager
.Where(i => i.Type == type && !(i.Width.HasValue && i.Width.Value < minWidth))
.ToList();
- if (EnableImageStub(item, type, libraryOptions) && eligibleImages.Count > 0)
+ if (EnableImageStub(item, libraryOptions) && eligibleImages.Count > 0)
{
SaveImageStub(item, type, eligibleImages.Select(i => i.Url));
- result.UpdateType = result.UpdateType | ItemUpdateType.ImageUpdate;
+ result.UpdateType |= ItemUpdateType.ImageUpdate;
return true;
}
@@ -453,20 +467,29 @@ namespace MediaBrowser.Providers.Manager
try
{
- var response = await provider.GetImageResponse(url, cancellationToken).ConfigureAwait(false);
-
- await _providerManager.SaveImage(item, response.Content, response.ContentType, type, null, cancellationToken).ConfigureAwait(false);
-
- result.UpdateType = result.UpdateType | ItemUpdateType.ImageUpdate;
+ using var response = await provider.GetImageResponse(url, cancellationToken).ConfigureAwait(false);
+ await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+
+ await _providerManager.SaveImage(
+ item,
+ stream,
+ response.Content.Headers.ContentType.MediaType,
+ type,
+ null,
+ cancellationToken).ConfigureAwait(false);
+
+ result.UpdateType |= ItemUpdateType.ImageUpdate;
return true;
}
catch (HttpException ex)
{
// Sometimes providers send back bad url's. Just move to the next image
- if (ex.StatusCode.HasValue && ex.StatusCode.Value == HttpStatusCode.NotFound)
+ if (ex.StatusCode.HasValue
+ && (ex.StatusCode.Value == HttpStatusCode.NotFound || ex.StatusCode.Value == HttpStatusCode.Forbidden))
{
continue;
}
+
break;
}
}
@@ -474,7 +497,7 @@ namespace MediaBrowser.Providers.Manager
return false;
}
- private bool EnableImageStub(BaseItem item, ImageType type, LibraryOptions libraryOptions)
+ private bool EnableImageStub(BaseItem item, LibraryOptions libraryOptions)
{
if (item is LiveTvProgram)
{
@@ -494,7 +517,7 @@ namespace MediaBrowser.Providers.Manager
return true;
}
}
-
+ // We always want to use prefetched images
return false;
}
@@ -507,14 +530,15 @@ namespace MediaBrowser.Providers.Manager
private void SaveImageStub(BaseItem item, ImageType imageType, IEnumerable<string> urls, int newIndex)
{
- var path = string.Join("|", urls.Take(1).ToArray());
-
- item.SetImage(new ItemImageInfo
- {
- Path = path,
- Type = imageType
+ var path = string.Join('|', urls.Take(1));
- }, newIndex);
+ item.SetImage(
+ new ItemImageInfo
+ {
+ Path = path,
+ Type = imageType
+ },
+ newIndex);
}
private async Task DownloadBackdrops(BaseItem item, LibraryOptions libraryOptions, ImageType imageType, int limit, IRemoteImageProvider provider, RefreshResult result, IEnumerable<RemoteImageInfo> images, int minWidth, CancellationToken cancellationToken)
@@ -533,23 +557,23 @@ namespace MediaBrowser.Providers.Manager
var url = image.Url;
- if (EnableImageStub(item, imageType, libraryOptions))
+ if (EnableImageStub(item, libraryOptions))
{
SaveImageStub(item, imageType, new[] { url });
- result.UpdateType = result.UpdateType | ItemUpdateType.ImageUpdate;
+ result.UpdateType |= ItemUpdateType.ImageUpdate;
continue;
}
try
{
- var response = await provider.GetImageResponse(url, cancellationToken).ConfigureAwait(false);
+ using var response = await provider.GetImageResponse(url, cancellationToken).ConfigureAwait(false);
// If there's already an image of the same size, skip it
- if (response.ContentLength.HasValue)
+ if (response.Content.Headers.ContentLength.HasValue)
{
try
{
- if (item.GetImages(imageType).Any(i => _fileSystem.GetFileInfo(i.Path).Length == response.ContentLength.Value))
+ if (item.GetImages(imageType).Any(i => _fileSystem.GetFileInfo(i.Path).Length == response.Content.Headers.ContentLength.Value))
{
response.Content.Dispose();
continue;
@@ -561,16 +585,25 @@ namespace MediaBrowser.Providers.Manager
}
}
- await _providerManager.SaveImage(item, response.Content, response.ContentType, imageType, null, cancellationToken).ConfigureAwait(false);
+ await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+ await _providerManager.SaveImage(
+ item,
+ stream,
+ response.Content.Headers.ContentType.MediaType,
+ imageType,
+ null,
+ cancellationToken).ConfigureAwait(false);
result.UpdateType = result.UpdateType | ItemUpdateType.ImageUpdate;
}
catch (HttpException ex)
{
// Sometimes providers send back bad urls. Just move onto the next image
- if (ex.StatusCode.HasValue && ex.StatusCode.Value == HttpStatusCode.NotFound)
+ if (ex.StatusCode.HasValue
+ && (ex.StatusCode.Value == HttpStatusCode.NotFound || ex.StatusCode.Value == HttpStatusCode.Forbidden))
{
continue;
}
+
break;
}
}
diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs
index dffdc468ad..a507bd4a6d 100644
--- a/MediaBrowser.Providers/Manager/MetadataService.cs
+++ b/MediaBrowser.Providers/Manager/MetadataService.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.Linq;
@@ -19,13 +21,7 @@ namespace MediaBrowser.Providers.Manager
where TItemType : BaseItem, IHasLookupInfo<TIdType>, new()
where TIdType : ItemLookupInfo, new()
{
- protected readonly IServerConfigurationManager ServerConfigurationManager;
- protected readonly ILogger Logger;
- protected readonly IProviderManager ProviderManager;
- protected readonly IFileSystem FileSystem;
- protected readonly ILibraryManager LibraryManager;
-
- protected MetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IFileSystem fileSystem, ILibraryManager libraryManager)
+ protected MetadataService(IServerConfigurationManager serverConfigurationManager, ILogger<MetadataService<TItemType, TIdType>> logger, IProviderManager providerManager, IFileSystem fileSystem, ILibraryManager libraryManager)
{
ServerConfigurationManager = serverConfigurationManager;
Logger = logger;
@@ -34,6 +30,26 @@ namespace MediaBrowser.Providers.Manager
LibraryManager = libraryManager;
}
+ protected IServerConfigurationManager ServerConfigurationManager { get; }
+
+ protected ILogger<MetadataService<TItemType, TIdType>> Logger { get; }
+
+ protected IProviderManager ProviderManager { get; }
+
+ protected IFileSystem FileSystem { get; }
+
+ protected ILibraryManager LibraryManager { get; }
+
+ protected virtual bool EnableUpdatingPremiereDateFromChildren => false;
+
+ protected virtual bool EnableUpdatingGenresFromChildren => false;
+
+ protected virtual bool EnableUpdatingStudiosFromChildren => false;
+
+ protected virtual bool EnableUpdatingOfficialRatingFromChildren => false;
+
+ public virtual int Order => 0;
+
private FileSystemMetadata TryGetFile(string path, IDirectoryService directoryService)
{
try
@@ -50,7 +66,6 @@ namespace MediaBrowser.Providers.Manager
public async Task<ItemUpdateType> RefreshMetadata(BaseItem item, MetadataRefreshOptions refreshOptions, CancellationToken cancellationToken)
{
var itemOfType = (TItemType)item;
- var config = ProviderManager.GetMetadataOptions(item);
var updateType = ItemUpdateType.None;
var requiresRefresh = false;
@@ -84,7 +99,7 @@ namespace MediaBrowser.Providers.Manager
// Always validate images and check for new locally stored ones.
if (itemImageProvider.ValidateImages(item, allImageProviders.OfType<ILocalImageProvider>(), refreshOptions.DirectoryService))
{
- updateType = updateType | ItemUpdateType.ImageUpdate;
+ updateType |= ItemUpdateType.ImageUpdate;
}
}
catch (Exception ex)
@@ -100,7 +115,7 @@ namespace MediaBrowser.Providers.Manager
bool hasRefreshedMetadata = true;
bool hasRefreshedImages = true;
- var isFirstRefresh = item.DateLastRefreshed == default(DateTime);
+ var isFirstRefresh = item.DateLastRefreshed == default;
// Next run metadata providers
if (refreshOptions.MetadataRefreshMode != MetadataRefreshMode.None)
@@ -112,7 +127,7 @@ namespace MediaBrowser.Providers.Manager
{
if (item.BeforeMetadataRefresh(refreshOptions.ReplaceAllMetadata))
{
- updateType = updateType | ItemUpdateType.MetadataImport;
+ updateType |= ItemUpdateType.MetadataImport;
}
}
@@ -125,12 +140,12 @@ namespace MediaBrowser.Providers.Manager
ApplySearchResult(id, refreshOptions.SearchResult);
}
- //await FindIdentities(id, cancellationToken).ConfigureAwait(false);
+ // await FindIdentities(id, cancellationToken).ConfigureAwait(false);
id.IsAutomated = refreshOptions.IsAutomated;
var result = await RefreshWithProviders(metadataResult, id, refreshOptions, providers, itemImageProvider, cancellationToken).ConfigureAwait(false);
- updateType = updateType | result.UpdateType;
+ updateType |= result.UpdateType;
if (result.Failures > 0)
{
hasRefreshedMetadata = false;
@@ -145,9 +160,9 @@ namespace MediaBrowser.Providers.Manager
if (providers.Count > 0)
{
- var result = await itemImageProvider.RefreshImages(itemOfType, libraryOptions, providers, refreshOptions, config, cancellationToken).ConfigureAwait(false);
+ var result = await itemImageProvider.RefreshImages(itemOfType, libraryOptions, providers, refreshOptions, cancellationToken).ConfigureAwait(false);
- updateType = updateType | result.UpdateType;
+ updateType |= result.UpdateType;
if (result.Failures > 0)
{
hasRefreshedImages = false;
@@ -156,7 +171,7 @@ namespace MediaBrowser.Providers.Manager
}
var beforeSaveResult = BeforeSave(itemOfType, isFirstRefresh || refreshOptions.ReplaceAllMetadata || refreshOptions.MetadataRefreshMode == MetadataRefreshMode.FullRefresh || requiresRefresh || refreshOptions.ForceSave, updateType);
- updateType = updateType | beforeSaveResult;
+ updateType |= beforeSaveResult;
// Save if changes were made, or it's never been saved before
if (refreshOptions.ForceSave || updateType > ItemUpdateType.None || isFirstRefresh || refreshOptions.ReplaceAllMetadata || requiresRefresh)
@@ -173,7 +188,7 @@ namespace MediaBrowser.Providers.Manager
// If any of these properties are set then make sure the updateType is not None, just to force everything to save
if (refreshOptions.ForceSave || refreshOptions.ReplaceAllMetadata)
{
- updateType = updateType | ItemUpdateType.MetadataDownload;
+ updateType |= ItemUpdateType.MetadataDownload;
}
if (hasRefreshedMetadata && hasRefreshedImages)
@@ -182,11 +197,11 @@ namespace MediaBrowser.Providers.Manager
}
else
{
- item.DateLastRefreshed = default(DateTime);
+ item.DateLastRefreshed = default;
}
// Save to database
- SaveItem(metadataResult, libraryOptions, updateType, cancellationToken);
+ await SaveItemAsync(metadataResult, libraryOptions, updateType, cancellationToken).ConfigureAwait(false);
}
await AfterMetadataRefresh(itemOfType, refreshOptions, cancellationToken).ConfigureAwait(false);
@@ -201,25 +216,26 @@ namespace MediaBrowser.Providers.Manager
lookupInfo.Year = result.ProductionYear;
}
- protected void SaveItem(MetadataResult<TItemType> result, LibraryOptions libraryOptions, ItemUpdateType reason, CancellationToken cancellationToken)
+ protected async Task SaveItemAsync(MetadataResult<TItemType> result, LibraryOptions libraryOptions, ItemUpdateType reason, CancellationToken cancellationToken)
{
if (result.Item.SupportsPeople && result.People != null)
{
var baseItem = result.Item;
LibraryManager.UpdatePeople(baseItem, result.People);
- SavePeopleMetadata(result.People, libraryOptions, cancellationToken);
+ await SavePeopleMetadataAsync(result.People, libraryOptions, cancellationToken).ConfigureAwait(false);
}
- result.Item.UpdateToRepository(reason, cancellationToken);
+
+ await result.Item.UpdateToRepositoryAsync(reason, cancellationToken).ConfigureAwait(false);
}
- private void SavePeopleMetadata(List<PersonInfo> people, LibraryOptions libraryOptions, CancellationToken cancellationToken)
+ private async Task SavePeopleMetadataAsync(List<PersonInfo> people, LibraryOptions libraryOptions, CancellationToken cancellationToken)
{
foreach (var person in people)
{
cancellationToken.ThrowIfCancellationRequested();
- if (person.ProviderIds.Any() || !string.IsNullOrWhiteSpace(person.ImageUrl))
+ if (person.ProviderIds.Count > 0 || !string.IsNullOrWhiteSpace(person.ImageUrl))
{
var updateType = ItemUpdateType.MetadataDownload;
@@ -236,21 +252,21 @@ namespace MediaBrowser.Providers.Manager
if (!string.IsNullOrWhiteSpace(person.ImageUrl) && !personEntity.HasImage(ImageType.Primary))
{
- AddPersonImage(personEntity, libraryOptions, person.ImageUrl, cancellationToken);
+ await AddPersonImageAsync(personEntity, libraryOptions, person.ImageUrl, cancellationToken).ConfigureAwait(false);
saveEntity = true;
- updateType = updateType | ItemUpdateType.ImageUpdate;
+ updateType |= ItemUpdateType.ImageUpdate;
}
if (saveEntity)
{
- personEntity.UpdateToRepository(updateType, cancellationToken);
+ await personEntity.UpdateToRepositoryAsync(updateType, cancellationToken).ConfigureAwait(false);
}
}
}
}
- private void AddPersonImage(Person personEntity, LibraryOptions libraryOptions, string imageUrl, CancellationToken cancellationToken)
+ private async Task AddPersonImageAsync(Person personEntity, LibraryOptions libraryOptions, string imageUrl, CancellationToken cancellationToken)
{
try
{
@@ -262,11 +278,13 @@ namespace MediaBrowser.Providers.Manager
Logger.LogError(ex, "Error in AddPersonImage");
}
- personEntity.SetImage(new ItemImageInfo
- {
- Path = imageUrl,
- Type = ImageType.Primary
- }, 0);
+ personEntity.SetImage(
+ new ItemImageInfo
+ {
+ Path = imageUrl,
+ Type = ImageType.Primary
+ },
+ 0);
}
protected virtual Task AfterMetadataRefresh(TItemType item, MetadataRefreshOptions refreshOptions, CancellationToken cancellationToken)
@@ -276,7 +294,7 @@ namespace MediaBrowser.Providers.Manager
}
/// <summary>
- /// Befores the save.
+ /// Before the save.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="isFullRefresh">if set to <c>true</c> [is full refresh].</param>
@@ -321,6 +339,7 @@ namespace MediaBrowser.Providers.Manager
{
return true;
}
+
var folder = item as Folder;
if (folder != null)
{
@@ -333,13 +352,12 @@ namespace MediaBrowser.Providers.Manager
protected virtual IList<BaseItem> GetChildrenForMetadataUpdates(TItemType item)
{
- var folder = item as Folder;
- if (folder != null)
+ if (item is Folder folder)
{
return folder.GetRecursiveChildren();
}
- return new List<BaseItem>();
+ return Array.Empty<BaseItem>();
}
protected virtual ItemUpdateType UpdateMetadataFromChildren(TItemType item, IList<BaseItem> children, bool isFullRefresh, ItemUpdateType currentUpdateType)
@@ -386,7 +404,7 @@ namespace MediaBrowser.Providers.Manager
{
if (!child.IsFolder)
{
- ticks += (child.RunTimeTicks ?? 0);
+ ticks += child.RunTimeTicks ?? 0;
}
}
@@ -419,6 +437,7 @@ namespace MediaBrowser.Providers.Manager
{
dateLastMediaAdded = childDateCreated;
}
+
any = true;
}
}
@@ -433,14 +452,6 @@ namespace MediaBrowser.Providers.Manager
return updateType;
}
- protected virtual bool EnableUpdatingPremiereDateFromChildren => false;
-
- protected virtual bool EnableUpdatingGenresFromChildren => false;
-
- protected virtual bool EnableUpdatingStudiosFromChildren => false;
-
- protected virtual bool EnableUpdatingOfficialRatingFromChildren => false;
-
private ItemUpdateType UpdatePremiereDate(TItemType item, IList<BaseItem> children)
{
var updateType = ItemUpdateType.None;
@@ -483,7 +494,7 @@ namespace MediaBrowser.Providers.Manager
{
var updateType = ItemUpdateType.None;
- if (!item.LockedFields.Contains(MetadataFields.Genres))
+ if (!item.LockedFields.Contains(MetadataField.Genres))
{
var currentList = item.Genres;
@@ -504,7 +515,7 @@ namespace MediaBrowser.Providers.Manager
{
var updateType = ItemUpdateType.None;
- if (!item.LockedFields.Contains(MetadataFields.Studios))
+ if (!item.LockedFields.Contains(MetadataField.Studios))
{
var currentList = item.Studios;
@@ -525,7 +536,7 @@ namespace MediaBrowser.Providers.Manager
{
var updateType = ItemUpdateType.None;
- if (!item.LockedFields.Contains(MetadataFields.OfficialRating))
+ if (!item.LockedFields.Contains(MetadataField.OfficialRating))
{
if (item.UpdateRatingToItems(children))
{
@@ -649,7 +660,8 @@ namespace MediaBrowser.Providers.Manager
return type == typeof(TItemType);
}
- protected virtual async Task<RefreshResult> RefreshWithProviders(MetadataResult<TItemType> metadata,
+ protected virtual async Task<RefreshResult> RefreshWithProviders(
+ MetadataResult<TItemType> metadata,
TIdType id,
MetadataRefreshOptions options,
List<IMetadataProvider> providers,
@@ -715,7 +727,7 @@ namespace MediaBrowser.Providers.Manager
userDataList.AddRange(localItem.UserDataList);
}
- MergeData(localItem, temp, new MetadataFields[] { }, !options.ReplaceAllMetadata, true);
+ MergeData(localItem, temp, Array.Empty<MetadataField>(), !options.ReplaceAllMetadata, true);
refreshResult.UpdateType = refreshResult.UpdateType | ItemUpdateType.MetadataImport;
// Only one local provider allowed per item
@@ -723,6 +735,7 @@ namespace MediaBrowser.Providers.Manager
{
hasLocalMetadata = true;
}
+
break;
}
@@ -763,20 +776,20 @@ namespace MediaBrowser.Providers.Manager
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, new MetadataFields[] { }, false, false);
+ MergeData(metadata, temp, Array.Empty<MetadataField>(), false, false);
MergeData(temp, metadata, item.LockedFields, true, false);
}
}
}
- //var isUnidentified = failedProviderCount > 0 && successfulProviderCount == 0;
+ // 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);
+ // ImportUserData(item, userDataList, cancellationToken);
return refreshResult;
}
@@ -797,7 +810,7 @@ namespace MediaBrowser.Providers.Manager
try
{
- refreshResult.UpdateType = refreshResult.UpdateType | await provider.FetchAsync(item, options, cancellationToken).ConfigureAwait(false);
+ refreshResult.UpdateType |= await provider.FetchAsync(item, options, cancellationToken).ConfigureAwait(false);
}
catch (OperationCanceledException)
{
@@ -840,7 +853,7 @@ namespace MediaBrowser.Providers.Manager
{
result.Provider = provider.Name;
- MergeData(result, temp, new MetadataFields[] { }, false, false);
+ MergeData(result, temp, Array.Empty<MetadataField>(), false, false);
MergeNewData(temp.Item, id);
refreshResult.UpdateType = refreshResult.UpdateType | ItemUpdateType.MetadataDownload;
@@ -865,15 +878,6 @@ namespace MediaBrowser.Providers.Manager
return refreshResult;
}
- private string NormalizeLanguage(string language)
- {
- if (string.IsNullOrWhiteSpace(language))
- {
- return "en";
- }
- return language;
- }
-
private void MergeNewData(TItemType source, TIdType lookupInfo)
{
// Copy new provider id's that may have been obtained
@@ -889,24 +893,23 @@ namespace MediaBrowser.Providers.Manager
}
}
- protected abstract void MergeData(MetadataResult<TItemType> source,
+ protected abstract void MergeData(
+ MetadataResult<TItemType> source,
MetadataResult<TItemType> target,
- MetadataFields[] lockedFields,
+ MetadataField[] lockedFields,
bool replaceData,
bool mergeMetadataSettings);
- public virtual int Order => 0;
-
private bool HasChanged(BaseItem item, IHasItemChangeMonitor changeMonitor, IDirectoryService directoryService)
{
try
{
var hasChanged = changeMonitor.HasChanged(item, directoryService);
- //if (hasChanged)
- //{
- // logger.LogDebug("{0} reports change to {1}", changeMonitor.GetType().Name, item.Path ?? item.Name);
- //}
+ if (hasChanged)
+ {
+ Logger.LogDebug("{0} reports change to {1}", changeMonitor.GetType().Name, item.Path ?? item.Name);
+ }
return hasChanged;
}
@@ -917,11 +920,4 @@ namespace MediaBrowser.Providers.Manager
}
}
}
-
- public class RefreshResult
- {
- public ItemUpdateType UpdateType { get; set; }
- public string ErrorMessage { get; set; }
- public int Failures { get; set; }
- }
}
diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs
index cfff897672..a0c7d4ad09 100644
--- a/MediaBrowser.Providers/Manager/ProviderManager.cs
+++ b/MediaBrowser.Providers/Manager/ProviderManager.cs
@@ -1,13 +1,15 @@
-#pragma warning disable CS1591
-
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
+using System.Net;
+using System.Net.Http;
+using System.Net.Mime;
using System.Threading;
using System.Threading.Tasks;
+using Jellyfin.Data.Events;
using MediaBrowser.Common.Net;
using MediaBrowser.Common.Progress;
using MediaBrowser.Controller;
@@ -16,109 +18,118 @@ using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.Movies;
-using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Subtitles;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Events;
using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Net;
using MediaBrowser.Model.Providers;
-using MediaBrowser.Model.Serialization;
using Microsoft.Extensions.Logging;
using Priority_Queue;
+using Book = MediaBrowser.Controller.Entities.Book;
+using Episode = MediaBrowser.Controller.Entities.TV.Episode;
+using Movie = MediaBrowser.Controller.Entities.Movies.Movie;
+using MusicAlbum = MediaBrowser.Controller.Entities.Audio.MusicAlbum;
+using Season = MediaBrowser.Controller.Entities.TV.Season;
+using Series = MediaBrowser.Controller.Entities.TV.Series;
namespace MediaBrowser.Providers.Manager
{
/// <summary>
- /// Class ProviderManager
+ /// Class ProviderManager.
/// </summary>
public class ProviderManager : IProviderManager, IDisposable
{
- private readonly ILogger _logger;
- private readonly IHttpClient _httpClient;
+ private readonly object _refreshQueueLock = new object();
+ private readonly ILogger<ProviderManager> _logger;
+ private readonly IHttpClientFactory _httpClientFactory;
private readonly ILibraryMonitor _libraryMonitor;
private readonly IFileSystem _fileSystem;
private readonly IServerApplicationPaths _appPaths;
- private readonly IJsonSerializer _json;
private readonly ILibraryManager _libraryManager;
private readonly ISubtitleManager _subtitleManager;
private readonly IServerConfigurationManager _configurationManager;
+ private readonly ConcurrentDictionary<Guid, double> _activeRefreshes = new ConcurrentDictionary<Guid, double>();
+ private readonly CancellationTokenSource _disposeCancellationTokenSource = new CancellationTokenSource();
+ private readonly SimplePriorityQueue<Tuple<Guid, MetadataRefreshOptions>> _refreshQueue =
+ new SimplePriorityQueue<Tuple<Guid, MetadataRefreshOptions>>();
- private IImageProvider[] ImageProviders { get; set; }
-
- private IMetadataService[] _metadataServices = { };
- private IMetadataProvider[] _metadataProviders = { };
+ private IMetadataService[] _metadataServices = Array.Empty<IMetadataService>();
+ private IMetadataProvider[] _metadataProviders = Array.Empty<IMetadataProvider>();
private IEnumerable<IMetadataSaver> _savers;
-
private IExternalId[] _externalIds;
-
- private CancellationTokenSource _disposeCancellationTokenSource = new CancellationTokenSource();
-
- public event EventHandler<GenericEventArgs<BaseItem>> RefreshStarted;
- public event EventHandler<GenericEventArgs<BaseItem>> RefreshCompleted;
- public event EventHandler<GenericEventArgs<Tuple<BaseItem, double>>> RefreshProgress;
+ private bool _isProcessingRefreshQueue;
+ private bool _disposed;
/// <summary>
- /// Initializes a new instance of the <see cref="ProviderManager" /> class.
+ /// Initializes a new instance of the <see cref="ProviderManager"/> class.
/// </summary>
+ /// <param name="httpClientFactory">The Http client factory.</param>
+ /// <param name="subtitleManager">The subtitle manager.</param>
+ /// <param name="configurationManager">The configuration manager.</param>
+ /// <param name="libraryMonitor">The library monitor.</param>
+ /// <param name="logger">The logger.</param>
+ /// <param name="fileSystem">The filesystem.</param>
+ /// <param name="appPaths">The server application paths.</param>
+ /// <param name="libraryManager">The library manager.</param>
public ProviderManager(
- IHttpClient httpClient,
+ IHttpClientFactory httpClientFactory,
ISubtitleManager subtitleManager,
IServerConfigurationManager configurationManager,
ILibraryMonitor libraryMonitor,
ILogger<ProviderManager> logger,
IFileSystem fileSystem,
IServerApplicationPaths appPaths,
- ILibraryManager libraryManager,
- IJsonSerializer json)
+ ILibraryManager libraryManager)
{
_logger = logger;
- _httpClient = httpClient;
+ _httpClientFactory = httpClientFactory;
_configurationManager = configurationManager;
_libraryMonitor = libraryMonitor;
_fileSystem = fileSystem;
_appPaths = appPaths;
_libraryManager = libraryManager;
- _json = json;
_subtitleManager = subtitleManager;
}
- /// <summary>
- /// Adds the metadata providers.
- /// </summary>
- public void AddParts(IEnumerable<IImageProvider> imageProviders, IEnumerable<IMetadataService> metadataServices,
- IEnumerable<IMetadataProvider> metadataProviders, IEnumerable<IMetadataSaver> metadataSavers,
- IEnumerable<IExternalId> externalIds)
+ /// <inheritdoc/>
+ public event EventHandler<GenericEventArgs<BaseItem>> RefreshStarted;
+
+ /// <inheritdoc/>
+ public event EventHandler<GenericEventArgs<BaseItem>> RefreshCompleted;
+
+ /// <inheritdoc/>
+ public event EventHandler<GenericEventArgs<Tuple<BaseItem, double>>> RefreshProgress;
+
+ private IImageProvider[] ImageProviders { get; set; }
+
+ /// <inheritdoc/>
+ public void AddParts(
+ IEnumerable<IImageProvider> imageProviders,
+ IEnumerable<IMetadataService> metadataServices,
+ IEnumerable<IMetadataProvider> metadataProviders,
+ IEnumerable<IMetadataSaver> metadataSavers,
+ IEnumerable<IExternalId> externalIds)
{
ImageProviders = imageProviders.ToArray();
_metadataServices = metadataServices.OrderBy(i => i.Order).ToArray();
_metadataProviders = metadataProviders.ToArray();
- _externalIds = externalIds.OrderBy(i => i.Name).ToArray();
+ _externalIds = externalIds.OrderBy(i => i.ProviderName).ToArray();
- _savers = metadataSavers.Where(i =>
- {
- var configurable = i as IConfigurableProvider;
-
- return configurable == null || configurable.IsEnabled;
- }).ToArray();
+ _savers = metadataSavers
+ .Where(i => !(i is IConfigurableProvider configurable) || configurable.IsEnabled)
+ .ToArray();
}
+ /// <inheritdoc/>
public Task<ItemUpdateType> RefreshSingleItem(BaseItem item, MetadataRefreshOptions options, CancellationToken cancellationToken)
{
- IMetadataService service = null;
var type = item.GetType();
- foreach (var current in _metadataServices)
- {
- if (current.CanRefreshPrimary(type))
- {
- service = current;
- break;
- }
- }
+ var service = _metadataServices.FirstOrDefault(current => current.CanRefreshPrimary(type));
if (service == null)
{
@@ -141,35 +152,58 @@ namespace MediaBrowser.Providers.Manager
return Task.FromResult(ItemUpdateType.None);
}
+ /// <inheritdoc/>
public async Task SaveImage(BaseItem item, string url, ImageType type, int? imageIndex, CancellationToken cancellationToken)
{
- using (var response = await _httpClient.GetResponse(new HttpRequestOptions
+ var httpClient = _httpClientFactory.CreateClient(NamedClient.Default);
+ using var response = await httpClient.GetAsync(url, cancellationToken).ConfigureAwait(false);
+
+ if (response.StatusCode != HttpStatusCode.OK)
{
- CancellationToken = cancellationToken,
- Url = url,
- BufferContent = false
+ throw new HttpException("Invalid image received.")
+ {
+ StatusCode = response.StatusCode
+ };
+ }
+
+ var contentType = response.Content.Headers.ContentType.MediaType;
- }).ConfigureAwait(false))
+ // Workaround for tvheadend channel icons
+ // TODO: Isolate this hack into the tvh plugin
+ if (string.IsNullOrEmpty(contentType))
{
- // Workaround for tvheadend channel icons
- // TODO: Isolate this hack into the tvh plugin
- if (string.IsNullOrEmpty(response.ContentType))
+ if (url.IndexOf("/imagecache/", StringComparison.OrdinalIgnoreCase) != -1)
{
- if (url.IndexOf("/imagecache/", StringComparison.OrdinalIgnoreCase) != -1)
- {
- response.ContentType = "image/png";
- }
+ contentType = "image/png";
}
+ }
- await SaveImage(item, response.Content, response.ContentType, type, imageIndex, cancellationToken).ConfigureAwait(false);
+ // thetvdb will sometimes serve a rubbish 404 html page with a 200 OK code, because reasons...
+ if (contentType.Equals(MediaTypeNames.Text.Html, StringComparison.OrdinalIgnoreCase))
+ {
+ throw new HttpException("Invalid image received.")
+ {
+ StatusCode = HttpStatusCode.NotFound
+ };
}
+
+ await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+ await SaveImage(
+ item,
+ stream,
+ contentType,
+ type,
+ imageIndex,
+ cancellationToken).ConfigureAwait(false);
}
+ /// <inheritdoc/>
public Task SaveImage(BaseItem item, Stream source, string mimeType, ImageType type, int? imageIndex, CancellationToken cancellationToken)
{
return new ImageSaver(_configurationManager, _libraryMonitor, _fileSystem, _logger).SaveImage(item, source, mimeType, type, imageIndex, cancellationToken);
}
+ /// <inheritdoc/>
public Task SaveImage(BaseItem item, string source, string mimeType, ImageType type, int? imageIndex, bool? saveLocallyWithMedia, CancellationToken cancellationToken)
{
if (string.IsNullOrWhiteSpace(source))
@@ -182,6 +216,14 @@ namespace MediaBrowser.Providers.Manager
return new ImageSaver(_configurationManager, _libraryMonitor, _fileSystem, _logger).SaveImage(item, fileStream, mimeType, type, imageIndex, saveLocallyWithMedia, cancellationToken);
}
+ /// <inheritdoc/>
+ public Task SaveImage(Stream source, string mimeType, string path)
+ {
+ return new ImageSaver(_configurationManager, _libraryMonitor, _fileSystem, _logger)
+ .SaveImage(source, path);
+ }
+
+ /// <inheritdoc/>
public async Task<IEnumerable<RemoteImageInfo>> GetAvailableRemoteImages(BaseItem item, RemoteImageQuery query, CancellationToken cancellationToken)
{
var providers = GetRemoteImageProviders(item, query.IncludeDisabledProviders);
@@ -201,7 +243,7 @@ namespace MediaBrowser.Providers.Manager
languages.Add(preferredLanguage);
}
- var tasks = providers.Select(i => GetImages(item, cancellationToken, i, languages, query.ImageType));
+ var tasks = providers.Select(i => GetImages(item, i, languages, cancellationToken, query.ImageType));
var results = await Task.WhenAll(tasks).ConfigureAwait(false);
@@ -212,12 +254,17 @@ namespace MediaBrowser.Providers.Manager
/// Gets the images.
/// </summary>
/// <param name="item">The item.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
/// <param name="provider">The provider.</param>
/// <param name="preferredLanguages">The preferred languages.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
/// <param name="type">The type.</param>
/// <returns>Task{IEnumerable{RemoteImageInfo}}.</returns>
- private async Task<IEnumerable<RemoteImageInfo>> GetImages(BaseItem item, CancellationToken cancellationToken, IRemoteImageProvider provider, List<string> preferredLanguages, ImageType? type = null)
+ private async Task<IEnumerable<RemoteImageInfo>> GetImages(
+ BaseItem item,
+ IRemoteImageProvider provider,
+ IReadOnlyCollection<string> preferredLanguages,
+ CancellationToken cancellationToken,
+ ImageType? type = null)
{
try
{
@@ -243,25 +290,23 @@ namespace MediaBrowser.Providers.Manager
}
catch (Exception ex)
{
- _logger.LogError(ex, "{0} failed in GetImageInfos for type {1}", provider.GetType().Name, item.GetType().Name);
+ _logger.LogError(ex, "{ProviderName} failed in GetImageInfos for type {ItemType} at {ItemPath}", provider.GetType().Name, item.GetType().Name, item.Path);
return new List<RemoteImageInfo>();
}
}
- /// <summary>
- /// Gets the supported image providers.
- /// </summary>
- /// <param name="item">The item.</param>
- /// <returns>IEnumerable{IImageProvider}.</returns>
+ /// <inheritdoc/>
public IEnumerable<ImageProviderInfo> GetRemoteImageProviderInfo(BaseItem item)
{
- return GetRemoteImageProviders(item, true).Select(i => new ImageProviderInfo
- {
- Name = i.Name,
- SupportedImages = i.GetSupportedImages(item).ToArray()
- });
+ return GetRemoteImageProviders(item, true).Select(i => new ImageProviderInfo(i.Name, i.GetSupportedImages(item).ToArray()));
}
+ /// <summary>
+ /// Gets the image providers for the provided item.
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <param name="refreshOptions">The image refresh options.</param>
+ /// <returns>The image providers for the item.</returns>
public IEnumerable<IImageProvider> GetImageProviders(BaseItem item, ImageRefreshOptions refreshOptions)
{
return GetImageProviders(item, _libraryManager.GetLibraryOptions(item), GetMetadataOptions(item), refreshOptions, false);
@@ -275,7 +320,7 @@ namespace MediaBrowser.Providers.Manager
var typeOptions = libraryOptions.GetTypeOptions(item.GetType().Name);
var typeFetcherOrder = typeOptions?.ImageFetcherOrder;
- return ImageProviders.Where(i => CanRefresh(i, item, libraryOptions, options, refreshOptions, includeDisabled))
+ return ImageProviders.Where(i => CanRefresh(i, item, libraryOptions, refreshOptions, includeDisabled))
.OrderBy(i =>
{
// See if there's a user-defined order
@@ -296,6 +341,13 @@ namespace MediaBrowser.Providers.Manager
.ThenBy(GetOrder);
}
+ /// <summary>
+ /// Gets the metadata providers for the provided item.
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <param name="libraryOptions">The library options.</param>
+ /// <typeparam name="T">The type of metadata provider.</typeparam>
+ /// <returns>The metadata providers.</returns>
public IEnumerable<IMetadataProvider<T>> GetMetadataProviders<T>(BaseItem item, LibraryOptions libraryOptions)
where T : BaseItem
{
@@ -311,7 +363,7 @@ namespace MediaBrowser.Providers.Manager
var currentOptions = globalMetadataOptions;
return _metadataProviders.OfType<IMetadataProvider<T>>()
- .Where(i => CanRefresh(i, item, libraryOptions, currentOptions, includeDisabled, forceEnableInternetMetadata))
+ .Where(i => CanRefresh(i, item, libraryOptions, includeDisabled, forceEnableInternetMetadata))
.OrderBy(i => GetConfiguredOrder(item, i, libraryOptions, globalMetadataOptions))
.ThenBy(GetDefaultOrder);
}
@@ -321,14 +373,20 @@ namespace MediaBrowser.Providers.Manager
var options = GetMetadataOptions(item);
var libraryOptions = _libraryManager.GetLibraryOptions(item);
- return GetImageProviders(item, libraryOptions, options,
- new ImageRefreshOptions(
- new DirectoryService(_fileSystem)),
- includeDisabled)
- .OfType<IRemoteImageProvider>();
+ return GetImageProviders(
+ item,
+ libraryOptions,
+ options,
+ new ImageRefreshOptions(new DirectoryService(_fileSystem)),
+ includeDisabled).OfType<IRemoteImageProvider>();
}
- private bool CanRefresh(IMetadataProvider provider, BaseItem item, LibraryOptions libraryOptions, MetadataOptions options, bool includeDisabled, bool forceEnableInternetMetadata)
+ private bool CanRefresh(
+ IMetadataProvider provider,
+ BaseItem item,
+ LibraryOptions libraryOptions,
+ bool includeDisabled,
+ bool forceEnableInternetMetadata)
{
if (!includeDisabled)
{
@@ -364,7 +422,12 @@ namespace MediaBrowser.Providers.Manager
return true;
}
- private bool CanRefresh(IImageProvider provider, BaseItem item, LibraryOptions libraryOptions, MetadataOptions options, ImageRefreshOptions refreshOptions, bool includeDisabled)
+ private bool CanRefresh(
+ IImageProvider provider,
+ BaseItem item,
+ LibraryOptions libraryOptions,
+ ImageRefreshOptions refreshOptions,
+ bool includeDisabled)
{
if (!includeDisabled)
{
@@ -392,7 +455,7 @@ namespace MediaBrowser.Providers.Manager
}
catch (Exception ex)
{
- _logger.LogError(ex, "{0} failed in Supports for type {1}", provider.GetType().Name, item.GetType().Name);
+ _logger.LogError(ex, "{ProviderName} failed in Supports for type {ItemType} at {ItemPath}", provider.GetType().Name, item.GetType().Name, item.Path);
return false;
}
}
@@ -404,9 +467,7 @@ namespace MediaBrowser.Providers.Manager
/// <returns>System.Int32.</returns>
private int GetOrder(IImageProvider provider)
{
- var hasOrder = provider as IHasOrder;
-
- if (hasOrder == null)
+ if (!(provider is IHasOrder hasOrder))
{
return 0;
}
@@ -433,7 +494,7 @@ namespace MediaBrowser.Providers.Manager
if (provider is IRemoteMetadataProvider)
{
var typeOptions = libraryOptions.GetTypeOptions(item.GetType().Name);
- var typeFetcherOrder = typeOptions == null ? null : typeOptions.MetadataFetcherOrder;
+ var typeFetcherOrder = typeOptions?.MetadataFetcherOrder;
var fetcherOrder = typeFetcherOrder ?? globalMetadataOptions.MetadataFetcherOrder;
@@ -451,9 +512,7 @@ namespace MediaBrowser.Providers.Manager
private int GetDefaultOrder(IMetadataProvider provider)
{
- var hasOrder = provider as IHasOrder;
-
- if (hasOrder != null)
+ if (provider is IHasOrder hasOrder)
{
return hasOrder.Order;
}
@@ -461,9 +520,10 @@ namespace MediaBrowser.Providers.Manager
return 0;
}
+ /// <inheritdoc/>
public MetadataPluginSummary[] GetAllMetadataPlugins()
{
- return new MetadataPluginSummary[]
+ return new[]
{
GetPluginSummary<Movie>(),
GetPluginSummary<BoxSet>(),
@@ -485,7 +545,7 @@ namespace MediaBrowser.Providers.Manager
where T : BaseItem, new()
{
// Give it a dummy path just so that it looks like a file system item
- var dummy = new T()
+ var dummy = new T
{
Path = Path.Combine(_appPaths.InternalMetadataPath, "dummy"),
ParentId = Guid.NewGuid()
@@ -500,16 +560,17 @@ namespace MediaBrowser.Providers.Manager
var libraryOptions = new LibraryOptions();
- var imageProviders = GetImageProviders(dummy, libraryOptions, options,
- new ImageRefreshOptions(
- new DirectoryService(_fileSystem)),
- true)
- .ToList();
+ var imageProviders = GetImageProviders(
+ dummy,
+ libraryOptions,
+ options,
+ new ImageRefreshOptions(new DirectoryService(_fileSystem)),
+ true).ToList();
var pluginList = summary.Plugins.ToList();
AddMetadataPlugins(pluginList, dummy, libraryOptions, options);
- AddImagePlugins(pluginList, dummy, imageProviders);
+ AddImagePlugins(pluginList, imageProviders);
var subtitleProviders = _subtitleManager.GetSupportedProviders(dummy);
@@ -540,14 +601,14 @@ namespace MediaBrowser.Providers.Manager
var providers = GetMetadataProvidersInternal<T>(item, libraryOptions, options, true, true).ToList();
// Locals
- list.AddRange(providers.Where(i => (i is ILocalMetadataProvider)).Select(i => new MetadataPlugin
+ list.AddRange(providers.Where(i => i is ILocalMetadataProvider).Select(i => new MetadataPlugin
{
Name = i.Name,
Type = MetadataPluginType.LocalMetadataProvider
}));
// Fetchers
- list.AddRange(providers.Where(i => (i is IRemoteMetadataProvider)).Select(i => new MetadataPlugin
+ list.AddRange(providers.Where(i => i is IRemoteMetadataProvider).Select(i => new MetadataPlugin
{
Name = i.Name,
Type = MetadataPluginType.MetadataFetcher
@@ -561,12 +622,10 @@ namespace MediaBrowser.Providers.Manager
}));
}
- private void AddImagePlugins<T>(List<MetadataPlugin> list, T item, List<IImageProvider> imageProviders)
- where T : BaseItem
+ private void AddImagePlugins(List<MetadataPlugin> list, List<IImageProvider> imageProviders)
{
-
// Locals
- list.AddRange(imageProviders.Where(i => (i is ILocalImageProvider)).Select(i => new MetadataPlugin
+ list.AddRange(imageProviders.Where(i => i is ILocalImageProvider).Select(i => new MetadataPlugin
{
Name = i.Name,
Type = MetadataPluginType.LocalImageProvider
@@ -580,6 +639,7 @@ namespace MediaBrowser.Providers.Manager
}));
}
+ /// <inheritdoc/>
public MetadataOptions GetMetadataOptions(BaseItem item)
{
var type = item.GetType().Name;
@@ -589,17 +649,13 @@ namespace MediaBrowser.Providers.Manager
new MetadataOptions();
}
- /// <summary>
- /// Saves the metadata.
- /// </summary>
+ /// <inheritdoc/>
public void SaveMetadata(BaseItem item, ItemUpdateType updateType)
{
SaveMetadata(item, updateType, _savers);
}
- /// <summary>
- /// Saves the metadata.
- /// </summary>
+ /// <inheritdoc/>
public void SaveMetadata(BaseItem item, ItemUpdateType updateType, IEnumerable<string> savers)
{
SaveMetadata(item, updateType, _savers.Where(i => savers.Contains(i.Name, StringComparer.OrdinalIgnoreCase)));
@@ -611,7 +667,6 @@ namespace MediaBrowser.Providers.Manager
/// <param name="item">The item.</param>
/// <param name="updateType">Type of the update.</param>
/// <param name="savers">The savers.</param>
- /// <returns>Task.</returns>
private void SaveMetadata(BaseItem item, ItemUpdateType updateType, IEnumerable<IMetadataSaver> savers)
{
var libraryOptions = _libraryManager.GetLibraryOptions(item);
@@ -620,11 +675,9 @@ namespace MediaBrowser.Providers.Manager
{
_logger.LogDebug("Saving {0} to {1}.", item.Path ?? item.Name, saver.Name);
- var fileSaver = saver as IMetadataFileSaver;
-
- if (fileSaver != null)
+ if (saver is IMetadataFileSaver fileSaver)
{
- string path = null;
+ string path;
try
{
@@ -691,11 +744,9 @@ namespace MediaBrowser.Providers.Manager
{
if (updateType >= ItemUpdateType.MetadataEdit)
{
- var fileSaver = saver as IMetadataFileSaver;
-
// Manual edit occurred
// Even if save local is off, save locally anyway if the metadata file already exists
- if (fileSaver == null || !File.Exists(fileSaver.GetSavePath(item)))
+ if (!(saver is IMetadataFileSaver fileSaver) || !File.Exists(fileSaver.GetSavePath(item)))
{
return false;
}
@@ -726,6 +777,7 @@ namespace MediaBrowser.Providers.Manager
}
}
+ /// <inheritdoc/>
public Task<IEnumerable<RemoteSearchResult>> GetRemoteSearchResults<TItemType, TLookupType>(RemoteSearchQuery<TLookupType> searchInfo, CancellationToken cancellationToken)
where TItemType : BaseItem, new()
where TLookupType : ItemLookupInfo
@@ -740,7 +792,7 @@ namespace MediaBrowser.Providers.Manager
return GetRemoteSearchResults<TItemType, TLookupType>(searchInfo, referenceItem, cancellationToken);
}
- public async Task<IEnumerable<RemoteSearchResult>> GetRemoteSearchResults<TItemType, TLookupType>(RemoteSearchQuery<TLookupType> searchInfo, BaseItem referenceItem, CancellationToken cancellationToken)
+ private async Task<IEnumerable<RemoteSearchResult>> GetRemoteSearchResults<TItemType, TLookupType>(RemoteSearchQuery<TLookupType> searchInfo, BaseItem referenceItem, CancellationToken cancellationToken)
where TItemType : BaseItem, new()
where TLookupType : ItemLookupInfo
{
@@ -779,6 +831,7 @@ namespace MediaBrowser.Providers.Manager
{
searchInfo.SearchInfo.MetadataLanguage = _configurationManager.Configuration.PreferredMetadataLanguage;
}
+
if (string.IsNullOrWhiteSpace(searchInfo.SearchInfo.MetadataCountryCode))
{
searchInfo.SearchInfo.MetadataCountryCode = _configurationManager.Configuration.MetadataCountryCode;
@@ -823,12 +876,14 @@ namespace MediaBrowser.Providers.Manager
}
}
- //_logger.LogDebug("Returning search results {0}", _json.SerializeToString(resultList));
+ // _logger.LogDebug("Returning search results {0}", _json.SerializeToString(resultList));
return resultList;
}
- private async Task<IEnumerable<RemoteSearchResult>> GetSearchResults<TLookupType>(IRemoteSearchProvider<TLookupType> provider, TLookupType searchInfo,
+ private async Task<IEnumerable<RemoteSearchResult>> GetSearchResults<TLookupType>(
+ IRemoteSearchProvider<TLookupType> provider,
+ TLookupType searchInfo,
CancellationToken cancellationToken)
where TLookupType : ItemLookupInfo
{
@@ -844,7 +899,8 @@ namespace MediaBrowser.Providers.Manager
return list;
}
- public Task<HttpResponseInfo> GetSearchImage(string providerName, string url, CancellationToken cancellationToken)
+ /// <inheritdoc/>
+ public Task<HttpResponseMessage> GetSearchImage(string providerName, string url, CancellationToken cancellationToken)
{
var provider = _metadataProviders.OfType<IRemoteSearchProvider>().FirstOrDefault(i => string.Equals(i.Name, providerName, StringComparison.OrdinalIgnoreCase));
@@ -856,7 +912,7 @@ namespace MediaBrowser.Providers.Manager
return provider.GetImageResponse(url, cancellationToken);
}
- public IEnumerable<IExternalId> GetExternalIds(IHasProviderIds item)
+ private IEnumerable<IExternalId> GetExternalIds(IHasProviderIds item)
{
return _externalIds.Where(i =>
{
@@ -872,6 +928,7 @@ namespace MediaBrowser.Providers.Manager
});
}
+ /// <inheritdoc/>
public IEnumerable<ExternalUrl> GetExternalUrls(BaseItem item)
{
return GetExternalIds(item)
@@ -891,29 +948,29 @@ namespace MediaBrowser.Providers.Manager
return new ExternalUrl
{
- Name = i.Name,
+ Name = i.ProviderName,
Url = string.Format(
CultureInfo.InvariantCulture,
i.UrlFormatString,
value)
};
-
}).Where(i => i != null).Concat(item.GetRelatedUrls());
}
+ /// <inheritdoc/>
public IEnumerable<ExternalIdInfo> GetExternalIdInfos(IHasProviderIds item)
{
return GetExternalIds(item)
.Select(i => new ExternalIdInfo
{
- Name = i.Name,
+ Name = i.ProviderName,
Key = i.Key,
+ Type = i.Type,
UrlFormatString = i.UrlFormatString
});
}
- private ConcurrentDictionary<Guid, double> _activeRefreshes = new ConcurrentDictionary<Guid, double>();
-
+ /// <inheritdoc/>
public Dictionary<Guid, Guid> GetRefreshQueue()
{
lock (_refreshQueueLock)
@@ -929,22 +986,25 @@ namespace MediaBrowser.Providers.Manager
}
}
+ /// <inheritdoc/>
public void OnRefreshStart(BaseItem item)
{
- _logger.LogInformation("OnRefreshStart {0}", item.Id.ToString("N", CultureInfo.InvariantCulture));
+ _logger.LogDebug("OnRefreshStart {0}", item.Id.ToString("N", CultureInfo.InvariantCulture));
_activeRefreshes[item.Id] = 0;
RefreshStarted?.Invoke(this, new GenericEventArgs<BaseItem>(item));
}
+ /// <inheritdoc/>
public void OnRefreshComplete(BaseItem item)
{
- _logger.LogInformation("OnRefreshComplete {0}", item.Id.ToString("N", CultureInfo.InvariantCulture));
+ _logger.LogDebug("OnRefreshComplete {0}", item.Id.ToString("N", CultureInfo.InvariantCulture));
_activeRefreshes.Remove(item.Id, out _);
RefreshCompleted?.Invoke(this, new GenericEventArgs<BaseItem>(item));
}
+ /// <inheritdoc/>
public double? GetRefreshProgress(Guid id)
{
if (_activeRefreshes.TryGetValue(id, out double value))
@@ -955,6 +1015,7 @@ namespace MediaBrowser.Providers.Manager
return null;
}
+ /// <inheritdoc/>
public void OnRefreshProgress(BaseItem item, double progress)
{
var id = item.Id;
@@ -974,12 +1035,7 @@ namespace MediaBrowser.Providers.Manager
RefreshProgress?.Invoke(this, new GenericEventArgs<Tuple<BaseItem, double>>(new Tuple<BaseItem, double>(item, progress)));
}
- private readonly SimplePriorityQueue<Tuple<Guid, MetadataRefreshOptions>> _refreshQueue =
- new SimplePriorityQueue<Tuple<Guid, MetadataRefreshOptions>>();
-
- private readonly object _refreshQueueLock = new object();
- private bool _isProcessingRefreshQueue;
-
+ /// <inheritdoc/>
public void QueueRefresh(Guid id, MetadataRefreshOptions options, RefreshPriority priority)
{
if (_disposed)
@@ -1023,7 +1079,7 @@ namespace MediaBrowser.Providers.Manager
if (item != null)
{
// Try to throttle this a little bit.
- await Task.Delay(100).ConfigureAwait(false);
+ await Task.Delay(100, cancellationToken).ConfigureAwait(false);
var task = item is MusicArtist artist
? RefreshArtist(artist, refreshItem.Item2, cancellationToken)
@@ -1053,17 +1109,14 @@ namespace MediaBrowser.Providers.Manager
await item.RefreshMetadata(options, cancellationToken).ConfigureAwait(false);
// Collection folders don't validate their children so we'll have to simulate that here
-
- if (item is CollectionFolder collectionFolder)
+ switch (item)
{
- await RefreshCollectionFolderChildren(options, collectionFolder, cancellationToken).ConfigureAwait(false);
- }
- else
- {
- if (item is Folder folder)
- {
+ case CollectionFolder collectionFolder:
+ await RefreshCollectionFolderChildren(options, collectionFolder, cancellationToken).ConfigureAwait(false);
+ break;
+ case Folder folder:
await folder.ValidateChildren(new SimpleProgress<double>(), cancellationToken, options).ConfigureAwait(false);
- }
+ break;
}
}
@@ -1073,7 +1126,7 @@ namespace MediaBrowser.Providers.Manager
{
await child.RefreshMetadata(options, cancellationToken).ConfigureAwait(false);
- await child.ValidateChildren(new SimpleProgress<double>(), cancellationToken, options, true).ConfigureAwait(false);
+ await child.ValidateChildren(new SimpleProgress<double>(), cancellationToken, options).ConfigureAwait(false);
}
}
@@ -1109,20 +1162,41 @@ namespace MediaBrowser.Providers.Manager
}
}
+ /// <inheritdoc/>
public Task RefreshFullItem(BaseItem item, MetadataRefreshOptions options, CancellationToken cancellationToken)
{
return RefreshItem(item, options, cancellationToken);
}
- private bool _disposed;
+ /// <inheritdoc/>
public void Dispose()
{
- _disposed = true;
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ /// <summary>
+ /// Releases unmanaged and optionally managed resources.
+ /// </summary>
+ /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
+ protected virtual void Dispose(bool disposing)
+ {
+ if (_disposed)
+ {
+ return;
+ }
if (!_disposeCancellationTokenSource.IsCancellationRequested)
{
_disposeCancellationTokenSource.Cancel();
}
+
+ if (disposing)
+ {
+ _disposeCancellationTokenSource.Dispose();
+ }
+
+ _disposed = true;
}
}
}
diff --git a/MediaBrowser.Providers/Manager/ProviderUtils.cs b/MediaBrowser.Providers/Manager/ProviderUtils.cs
index 8d1588c4eb..70a5a6ac13 100644
--- a/MediaBrowser.Providers/Manager/ProviderUtils.cs
+++ b/MediaBrowser.Providers/Manager/ProviderUtils.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.Linq;
@@ -14,7 +16,7 @@ namespace MediaBrowser.Providers.Manager
public static void MergeBaseItemData<T>(
MetadataResult<T> sourceResult,
MetadataResult<T> targetResult,
- MetadataFields[] lockedFields,
+ MetadataField[] lockedFields,
bool replaceData,
bool mergeMetadataSettings)
where T : BaseItem
@@ -24,14 +26,15 @@ namespace MediaBrowser.Providers.Manager
if (source == null)
{
- throw new ArgumentNullException(nameof(source));
+ throw new ArgumentException("Item cannot be null.", nameof(sourceResult));
}
+
if (target == null)
{
- throw new ArgumentNullException(nameof(target));
+ throw new ArgumentException("Item cannot be null.", nameof(targetResult));
}
- if (!lockedFields.Contains(MetadataFields.Name))
+ if (!lockedFields.Contains(MetadataField.Name))
{
if (replaceData || string.IsNullOrEmpty(target.Name))
{
@@ -62,7 +65,7 @@ namespace MediaBrowser.Providers.Manager
target.EndDate = source.EndDate;
}
- if (!lockedFields.Contains(MetadataFields.Genres))
+ if (!lockedFields.Contains(MetadataField.Genres))
{
if (replaceData || target.Genres.Length == 0)
{
@@ -75,7 +78,7 @@ namespace MediaBrowser.Providers.Manager
target.IndexNumber = source.IndexNumber;
}
- if (!lockedFields.Contains(MetadataFields.OfficialRating))
+ if (!lockedFields.Contains(MetadataField.OfficialRating))
{
if (replaceData || string.IsNullOrEmpty(target.OfficialRating))
{
@@ -93,7 +96,7 @@ namespace MediaBrowser.Providers.Manager
target.Tagline = source.Tagline;
}
- if (!lockedFields.Contains(MetadataFields.Overview))
+ if (!lockedFields.Contains(MetadataField.Overview))
{
if (replaceData || string.IsNullOrEmpty(target.Overview))
{
@@ -106,12 +109,11 @@ namespace MediaBrowser.Providers.Manager
target.ParentIndexNumber = source.ParentIndexNumber;
}
- if (!lockedFields.Contains(MetadataFields.Cast))
+ if (!lockedFields.Contains(MetadataField.Cast))
{
if (replaceData || targetResult.People == null || targetResult.People.Count == 0)
{
targetResult.People = sourceResult.People;
-
}
else if (targetResult.People != null && sourceResult.People != null)
{
@@ -129,7 +131,7 @@ namespace MediaBrowser.Providers.Manager
target.ProductionYear = source.ProductionYear;
}
- if (!lockedFields.Contains(MetadataFields.Runtime))
+ if (!lockedFields.Contains(MetadataField.Runtime))
{
if (replaceData || !target.RunTimeTicks.HasValue)
{
@@ -140,7 +142,7 @@ namespace MediaBrowser.Providers.Manager
}
}
- if (!lockedFields.Contains(MetadataFields.Studios))
+ if (!lockedFields.Contains(MetadataField.Studios))
{
if (replaceData || target.Studios.Length == 0)
{
@@ -148,7 +150,7 @@ namespace MediaBrowser.Providers.Manager
}
}
- if (!lockedFields.Contains(MetadataFields.Tags))
+ if (!lockedFields.Contains(MetadataField.Tags))
{
if (replaceData || target.Tags.Length == 0)
{
@@ -156,7 +158,7 @@ namespace MediaBrowser.Providers.Manager
}
}
- if (!lockedFields.Contains(MetadataFields.ProductionLocations))
+ if (!lockedFields.Contains(MetadataField.ProductionLocations))
{
if (replaceData || target.ProductionLocations.Length == 0)
{
diff --git a/MediaBrowser.Providers/Manager/RefreshResult.cs b/MediaBrowser.Providers/Manager/RefreshResult.cs
new file mode 100644
index 0000000000..72fc61e424
--- /dev/null
+++ b/MediaBrowser.Providers/Manager/RefreshResult.cs
@@ -0,0 +1,15 @@
+#pragma warning disable CS1591
+
+using MediaBrowser.Controller.Library;
+
+namespace MediaBrowser.Providers.Manager
+{
+ public class RefreshResult
+ {
+ public ItemUpdateType UpdateType { get; set; }
+
+ public string ErrorMessage { get; set; }
+
+ public int Failures { get; set; }
+ }
+}