aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Providers/Manager/MetadataService.cs
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Providers/Manager/MetadataService.cs')
-rw-r--r--MediaBrowser.Providers/Manager/MetadataService.cs182
1 files changed, 129 insertions, 53 deletions
diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs
index 45f66f85f..f220ec4a1 100644
--- a/MediaBrowser.Providers/Manager/MetadataService.cs
+++ b/MediaBrowser.Providers/Manager/MetadataService.cs
@@ -12,7 +12,9 @@ using Jellyfin.Extensions;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
@@ -26,13 +28,22 @@ namespace MediaBrowser.Providers.Manager
where TItemType : BaseItem, IHasLookupInfo<TIdType>, new()
where TIdType : ItemLookupInfo, new()
{
- protected MetadataService(IServerConfigurationManager serverConfigurationManager, ILogger<MetadataService<TItemType, TIdType>> logger, IProviderManager providerManager, IFileSystem fileSystem, ILibraryManager libraryManager)
+ protected MetadataService(
+ IServerConfigurationManager serverConfigurationManager,
+ ILogger<MetadataService<TItemType, TIdType>> logger,
+ IProviderManager providerManager,
+ IFileSystem fileSystem,
+ ILibraryManager libraryManager,
+ IExternalDataManager externalDataManager,
+ IItemRepository itemRepository)
{
ServerConfigurationManager = serverConfigurationManager;
Logger = logger;
ProviderManager = providerManager;
FileSystem = fileSystem;
LibraryManager = libraryManager;
+ ExternalDataManager = externalDataManager;
+ ItemRepository = itemRepository;
ImageProvider = new ItemImageProvider(Logger, ProviderManager, FileSystem);
}
@@ -48,6 +59,10 @@ namespace MediaBrowser.Providers.Manager
protected ILibraryManager LibraryManager { get; }
+ protected IExternalDataManager ExternalDataManager { get; }
+
+ protected IItemRepository ItemRepository { get; }
+
protected virtual bool EnableUpdatingPremiereDateFromChildren => false;
protected virtual bool EnableUpdatingGenresFromChildren => false;
@@ -58,11 +73,11 @@ namespace MediaBrowser.Providers.Manager
public virtual int Order => 0;
- private FileSystemMetadata TryGetFile(string path, IDirectoryService directoryService)
+ private FileSystemMetadata TryGetFileSystemMetadata(string path, IDirectoryService directoryService)
{
try
{
- return directoryService.GetFile(path);
+ return directoryService.GetFileSystemEntry(path);
}
catch (Exception ex)
{
@@ -75,8 +90,9 @@ namespace MediaBrowser.Providers.Manager
{
var itemOfType = (TItemType)item;
var updateType = ItemUpdateType.None;
+
var libraryOptions = LibraryManager.GetLibraryOptions(item);
- var isFirstRefresh = item.DateLastRefreshed == default;
+ var isFirstRefresh = item.DateLastRefreshed == DateTime.MinValue;
var hasRefreshedMetadata = true;
var hasRefreshedImages = true;
@@ -128,14 +144,17 @@ namespace MediaBrowser.Providers.Manager
var metadataResult = new MetadataResult<TItemType>
{
- Item = itemOfType,
- People = LibraryManager.GetPeople(item)
+ Item = itemOfType
};
- var beforeSaveResult = BeforeSave(itemOfType, isFirstRefresh || refreshOptions.ReplaceAllMetadata || refreshOptions.MetadataRefreshMode == MetadataRefreshMode.FullRefresh || requiresRefresh || refreshOptions.ForceSave, updateType);
+ var beforeSaveResult = await BeforeSave(itemOfType, isFirstRefresh || refreshOptions.ReplaceAllMetadata || refreshOptions.MetadataRefreshMode == MetadataRefreshMode.FullRefresh || requiresRefresh || refreshOptions.ForceSave, updateType)
+ .ConfigureAwait(false);
updateType |= beforeSaveResult;
- updateType = await SaveInternal(item, refreshOptions, updateType, isFirstRefresh, requiresRefresh, metadataResult, cancellationToken).ConfigureAwait(false);
+ if (!isFirstRefresh)
+ {
+ updateType = await SaveInternal(item, refreshOptions, updateType, isFirstRefresh, requiresRefresh, metadataResult, cancellationToken).ConfigureAwait(false);
+ }
// Next run metadata providers
if (refreshOptions.MetadataRefreshMode != MetadataRefreshMode.None)
@@ -209,10 +228,15 @@ namespace MediaBrowser.Providers.Manager
{
if (item.IsFileProtocol)
{
- var file = TryGetFile(item.Path, refreshOptions.DirectoryService);
+ var file = TryGetFileSystemMetadata(item.Path, refreshOptions.DirectoryService);
if (file is not null)
{
item.DateModified = file.LastWriteTimeUtc;
+
+ if (!file.IsDirectory)
+ {
+ item.Size = file.Length;
+ }
}
}
@@ -253,14 +277,13 @@ namespace MediaBrowser.Providers.Manager
protected async Task SaveItemAsync(MetadataResult<TItemType> result, ItemUpdateType reason, CancellationToken cancellationToken)
{
- if (result.Item.SupportsPeople)
+ await result.Item.UpdateToRepositoryAsync(reason, cancellationToken).ConfigureAwait(false);
+ if (result.Item.SupportsPeople && result.People is not null)
{
var baseItem = result.Item;
await LibraryManager.UpdatePeopleAsync(baseItem, result.People, cancellationToken).ConfigureAwait(false);
}
-
- await result.Item.UpdateToRepositoryAsync(reason, cancellationToken).ConfigureAwait(false);
}
protected virtual Task AfterMetadataRefresh(TItemType item, MetadataRefreshOptions refreshOptions, CancellationToken cancellationToken)
@@ -276,12 +299,20 @@ namespace MediaBrowser.Providers.Manager
/// <param name="isFullRefresh">if set to <c>true</c> [is full refresh].</param>
/// <param name="currentUpdateType">Type of the current update.</param>
/// <returns>ItemUpdateType.</returns>
- private ItemUpdateType BeforeSave(TItemType item, bool isFullRefresh, ItemUpdateType currentUpdateType)
+ private async Task<ItemUpdateType> BeforeSave(TItemType item, bool isFullRefresh, ItemUpdateType currentUpdateType)
{
var updateType = BeforeSaveInternal(item, isFullRefresh, currentUpdateType);
updateType |= item.OnMetadataChanged();
+ if (updateType == ItemUpdateType.None)
+ {
+ if (!await ItemRepository.ItemExistsAsync(item.Id).ConfigureAwait(false))
+ {
+ return ItemUpdateType.MetadataImport;
+ }
+ }
+
return updateType;
}
@@ -289,12 +320,8 @@ namespace MediaBrowser.Providers.Manager
{
if (EnableUpdateMetadataFromChildren(item, isFullRefresh, updateType))
{
- if (isFullRefresh || updateType > ItemUpdateType.None)
- {
- var children = GetChildrenForMetadataUpdates(item);
-
- updateType = UpdateMetadataFromChildren(item, children, isFullRefresh, updateType);
- }
+ var children = GetChildrenForMetadataUpdates(item);
+ updateType = UpdateMetadataFromChildren(item, children, isFullRefresh, updateType);
}
var presentationUniqueKey = item.CreatePresentationUniqueKey();
@@ -304,21 +331,57 @@ namespace MediaBrowser.Providers.Manager
updateType |= ItemUpdateType.MetadataImport;
}
+ // Cleanup extracted files if source file was modified
+ var itemPath = item.Path;
+ if (!string.IsNullOrEmpty(itemPath))
+ {
+ var info = FileSystem.GetFileSystemInfo(itemPath);
+ if (info.Exists && item.HasChanged(info.LastWriteTimeUtc))
+ {
+ Logger.LogDebug("File modification time changed from {Then} to {Now}: {Path}", item.DateModified, info.LastWriteTimeUtc, itemPath);
+
+ item.DateModified = info.LastWriteTimeUtc;
+ if (ServerConfigurationManager.GetMetadataConfiguration().UseFileCreationTimeForDateAdded)
+ {
+ if (info.CreationTimeUtc > DateTime.MinValue)
+ {
+ item.DateCreated = info.CreationTimeUtc;
+ }
+ }
+
+ if (item is Video video)
+ {
+ Logger.LogInformation("File changed, pruning extracted data: {Path}", item.Path);
+ ExternalDataManager.DeleteExternalItemDataAsync(video, CancellationToken.None).GetAwaiter().GetResult();
+ }
+
+ updateType |= ItemUpdateType.MetadataImport;
+ }
+ }
+
return updateType;
}
protected virtual bool EnableUpdateMetadataFromChildren(TItemType item, bool isFullRefresh, ItemUpdateType currentUpdateType)
{
- if (isFullRefresh || currentUpdateType > ItemUpdateType.None)
+ if (item is Folder folder)
{
- if (EnableUpdatingPremiereDateFromChildren || EnableUpdatingGenresFromChildren || EnableUpdatingStudiosFromChildren || EnableUpdatingOfficialRatingFromChildren)
+ if (!isFullRefresh && currentUpdateType == ItemUpdateType.None)
{
- return true;
+ return folder.SupportsDateLastMediaAdded;
}
- if (item is Folder folder)
+ if (isFullRefresh || currentUpdateType > ItemUpdateType.None)
{
- return folder.SupportsDateLastMediaAdded || folder.SupportsCumulativeRunTimeTicks;
+ if (EnableUpdatingPremiereDateFromChildren || EnableUpdatingGenresFromChildren || EnableUpdatingStudiosFromChildren || EnableUpdatingOfficialRatingFromChildren)
+ {
+ return true;
+ }
+
+ if (folder.SupportsDateLastMediaAdded || folder.SupportsCumulativeRunTimeTicks)
+ {
+ return true;
+ }
}
}
@@ -339,36 +402,42 @@ namespace MediaBrowser.Providers.Manager
{
var updateType = ItemUpdateType.None;
- if (isFullRefresh || currentUpdateType > ItemUpdateType.None)
+ if (item is Folder folder)
{
- updateType |= UpdateCumulativeRunTimeTicks(item, children);
- updateType |= UpdateDateLastMediaAdded(item, children);
-
- // don't update user-changeable metadata for locked items
- if (item.IsLocked)
+ if (folder.SupportsDateLastMediaAdded)
{
- return updateType;
+ updateType |= UpdateDateLastMediaAdded(item, children);
}
- if (EnableUpdatingPremiereDateFromChildren)
+ if ((isFullRefresh || currentUpdateType > ItemUpdateType.None) && folder.SupportsCumulativeRunTimeTicks)
{
- updateType |= UpdatePremiereDate(item, children);
+ updateType |= UpdateCumulativeRunTimeTicks(item, children);
}
+ }
- if (EnableUpdatingGenresFromChildren)
- {
- updateType |= UpdateGenres(item, children);
- }
+ if (!(isFullRefresh || currentUpdateType > ItemUpdateType.None) || item.IsLocked)
+ {
+ return updateType;
+ }
- if (EnableUpdatingStudiosFromChildren)
- {
- updateType |= UpdateStudios(item, children);
- }
+ if (EnableUpdatingPremiereDateFromChildren)
+ {
+ updateType |= UpdatePremiereDate(item, children);
+ }
- if (EnableUpdatingOfficialRatingFromChildren)
- {
- updateType |= UpdateOfficialRating(item, children);
- }
+ if (EnableUpdatingGenresFromChildren)
+ {
+ updateType |= UpdateGenres(item, children);
+ }
+
+ if (EnableUpdatingStudiosFromChildren)
+ {
+ updateType |= UpdateStudios(item, children);
+ }
+
+ if (EnableUpdatingOfficialRatingFromChildren)
+ {
+ updateType |= UpdateOfficialRating(item, children);
}
return updateType;
@@ -614,7 +683,7 @@ namespace MediaBrowser.Providers.Manager
var dateLastImageRefresh = item.DateLastRefreshed;
// Run all if either of these flags are true
- var runAllProviders = options.ImageRefreshMode == MetadataRefreshMode.FullRefresh || dateLastImageRefresh == default(DateTime);
+ var runAllProviders = options.ImageRefreshMode == MetadataRefreshMode.FullRefresh || dateLastImageRefresh.Date == DateTime.MinValue.Date;
if (!runAllProviders)
{
@@ -781,7 +850,9 @@ namespace MediaBrowser.Providers.Manager
}
else
{
- var shouldReplace = options.MetadataRefreshMode > MetadataRefreshMode.ValidationOnly || options.ReplaceAllMetadata;
+ var shouldReplace = (options.MetadataRefreshMode > MetadataRefreshMode.ValidationOnly && options.ReplaceAllMetadata)
+ // Case for Scan for new and updated files
+ || (options.MetadataRefreshMode == MetadataRefreshMode.Default && !options.ReplaceAllMetadata);
MergeData(temp, metadata, item.LockedFields, shouldReplace, true);
}
}
@@ -1042,7 +1113,7 @@ namespace MediaBrowser.Providers.Manager
}
else
{
- target.Studios = target.Studios.Concat(source.Studios).Distinct().ToArray();
+ target.Studios = target.Studios.Concat(source.Studios).Distinct(StringComparer.OrdinalIgnoreCase).ToArray();
}
}
@@ -1054,7 +1125,7 @@ namespace MediaBrowser.Providers.Manager
}
else
{
- target.Tags = target.Tags.Concat(source.Tags).Distinct().ToArray();
+ target.Tags = target.Tags.Concat(source.Tags).Distinct(StringComparer.OrdinalIgnoreCase).ToArray();
}
}
@@ -1066,7 +1137,7 @@ namespace MediaBrowser.Providers.Manager
}
else
{
- target.ProductionLocations = target.ProductionLocations.Concat(source.ProductionLocations).Distinct().ToArray();
+ target.ProductionLocations = target.ProductionLocations.Concat(source.ProductionLocations).Distinct(StringComparer.OrdinalIgnoreCase).ToArray();
}
}
@@ -1128,11 +1199,16 @@ namespace MediaBrowser.Providers.Manager
target.LockedFields = target.LockedFields.Concat(source.LockedFields).Distinct().ToArray();
}
- if (source.DateCreated != default)
+ if (source.DateCreated != DateTime.MinValue)
{
target.DateCreated = source.DateCreated;
}
+ if (replaceData || source.DateModified != DateTime.MinValue)
+ {
+ target.DateModified = source.DateModified;
+ }
+
if (replaceData || string.IsNullOrEmpty(target.PreferredMetadataCountryCode))
{
target.PreferredMetadataCountryCode = source.PreferredMetadataCountryCode;
@@ -1215,7 +1291,7 @@ namespace MediaBrowser.Providers.Manager
}
else if (sourceHasAlbumArtist.AlbumArtists.Count > 0)
{
- targetHasAlbumArtist.AlbumArtists = targetHasAlbumArtist.AlbumArtists.Concat(sourceHasAlbumArtist.AlbumArtists).Distinct().ToArray();
+ targetHasAlbumArtist.AlbumArtists = targetHasAlbumArtist.AlbumArtists.Concat(sourceHasAlbumArtist.AlbumArtists).Distinct(StringComparer.OrdinalIgnoreCase).ToArray();
}
}
}
@@ -1224,7 +1300,7 @@ namespace MediaBrowser.Providers.Manager
{
if (source is Video sourceCast && target is Video targetCast)
{
- if (replaceData || !targetCast.Video3DFormat.HasValue)
+ if (sourceCast.Video3DFormat.HasValue && (replaceData || !targetCast.Video3DFormat.HasValue))
{
targetCast.Video3DFormat = sourceCast.Video3DFormat;
}