diff options
| author | Bond-009 <bond.009@outlook.com> | 2026-05-06 20:49:19 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-05-06 20:49:19 +0200 |
| commit | 33ed52b8ee25e1fae4763a26337b838dc9782b26 (patch) | |
| tree | ee68da202f604eef267254ea8c689965098b1c3e /Emby.Server.Implementations/Library/Validators | |
| parent | aa96ff42e616ecf5638a8f1e2e8459b94513c528 (diff) | |
| parent | d1ab428476f961426841a0561036c59c3b93878e (diff) | |
Merge branch 'master' into feature/season-provider-id-from-path
Diffstat (limited to 'Emby.Server.Implementations/Library/Validators')
6 files changed, 106 insertions, 41 deletions
diff --git a/Emby.Server.Implementations/Library/Validators/ArtistsValidator.cs b/Emby.Server.Implementations/Library/Validators/ArtistsValidator.cs index 7cc851b73b..fa7112eb90 100644 --- a/Emby.Server.Implementations/Library/Validators/ArtistsValidator.cs +++ b/Emby.Server.Implementations/Library/Validators/ArtistsValidator.cs @@ -50,21 +50,40 @@ public class ArtistsValidator public async Task Run(IProgress<double> progress, CancellationToken cancellationToken) { var names = _itemRepo.GetAllArtistNames(); + var existingArtistIds = _libraryManager.GetItemIds(new InternalItemsQuery + { + IncludeItemTypes = [BaseItemKind.MusicArtist] + }).ToHashSet(); + + var existingArtists = _libraryManager.GetArtists(names); var numComplete = 0; var count = names.Count; + var refreshed = 0; foreach (var name in names) { try { - var item = _libraryManager.GetArtist(name); + MusicArtist? item = null; + if (existingArtists.TryGetValue(name, out var artists) && artists.Length > 0) + { + item = artists.OrderBy(i => i.IsAccessedByName ? 1 : 0).First(); + } - await item.RefreshMetadata(cancellationToken).ConfigureAwait(false); + // Fall back to GetArtist if not found (creates new item if needed) + item ??= _libraryManager.GetArtist(name); + var isNew = !existingArtistIds.Contains(item.Id); + var neverRefreshed = item.DateLastRefreshed == default; + + if (isNew || neverRefreshed) + { + await item.RefreshMetadata(cancellationToken).ConfigureAwait(false); + refreshed++; + } } catch (OperationCanceledException) { - // Don't clutter the log throw; } catch (Exception ex) @@ -80,31 +99,24 @@ public class ArtistsValidator progress.Report(percent); } + _logger.LogInformation("Refreshed metadata for {RefreshedCount} new artists out of {TotalCount} total", refreshed, count); + var deadEntities = _libraryManager.GetItemList(new InternalItemsQuery { IncludeItemTypes = [BaseItemKind.MusicArtist], IsDeadArtist = true, IsLocked = false - }).Cast<MusicArtist>().ToList(); + }).Cast<MusicArtist>() + .Where(item => item.IsAccessedByName) + .ToList(); foreach (var item in deadEntities) { - if (!item.IsAccessedByName) - { - continue; - } - _logger.LogInformation("Deleting dead {ItemType} {ItemId} {ItemName}", item.GetType().Name, item.Id.ToString("N", CultureInfo.InvariantCulture), item.Name); - - _libraryManager.DeleteItem( - item, - new DeleteOptions - { - DeleteFileLocation = false - }, - false); } + _libraryManager.DeleteItemsUnsafeFast(deadEntities, deleteSourceFiles: true); + progress.Report(100); } } diff --git a/Emby.Server.Implementations/Library/Validators/CollectionPostScanTask.cs b/Emby.Server.Implementations/Library/Validators/CollectionPostScanTask.cs index e62c638ed6..e3ef75b9ee 100644 --- a/Emby.Server.Implementations/Library/Validators/CollectionPostScanTask.cs +++ b/Emby.Server.Implementations/Library/Validators/CollectionPostScanTask.cs @@ -74,7 +74,7 @@ public class CollectionPostScanTask : ILibraryPostScanTask foreach (var m in movies) { - if (m is Movie movie && !string.IsNullOrEmpty(movie.CollectionName)) + if (m is Movie movie && !string.IsNullOrEmpty(movie.CollectionName) && !movie.PrimaryVersionId.HasValue) { if (collectionNameMoviesMap.TryGetValue(movie.CollectionName, out var movieList)) { diff --git a/Emby.Server.Implementations/Library/Validators/GenresValidator.cs b/Emby.Server.Implementations/Library/Validators/GenresValidator.cs index fbfc9f7d54..fc5a2fa0c5 100644 --- a/Emby.Server.Implementations/Library/Validators/GenresValidator.cs +++ b/Emby.Server.Implementations/Library/Validators/GenresValidator.cs @@ -1,5 +1,6 @@ using System; using System.Globalization; +using System.Linq; using System.Threading; using System.Threading.Tasks; using Jellyfin.Data.Enums; @@ -48,17 +49,40 @@ public class GenresValidator public async Task Run(IProgress<double> progress, CancellationToken cancellationToken) { var names = _itemRepo.GetGenreNames(); + var existingGenreIds = _libraryManager.GetItemIds(new InternalItemsQuery + { + IncludeItemTypes = [BaseItemKind.Genre] + }).ToHashSet(); + + var existingGenres = _libraryManager.GetItemList(new InternalItemsQuery + { + IncludeItemTypes = [BaseItemKind.Genre] + }).Cast<Genre>() + .GroupBy(g => g.Name, StringComparer.OrdinalIgnoreCase) + .ToDictionary(g => g.Key, g => g.First(), StringComparer.OrdinalIgnoreCase); var numComplete = 0; var count = names.Count; + var refreshed = 0; foreach (var name in names) { try { - var item = _libraryManager.GetGenre(name); + Genre? item = null; + if (existingGenres.TryGetValue(name, out var existingGenre)) + { + item = existingGenre; + } + + // Fall back to GetGenre if not found (creates new item if needed) + item ??= _libraryManager.GetGenre(name); - await item.RefreshMetadata(cancellationToken).ConfigureAwait(false); + if (!existingGenreIds.Contains(item.Id)) + { + await item.RefreshMetadata(cancellationToken).ConfigureAwait(false); + refreshed++; + } } catch (OperationCanceledException) { @@ -78,6 +102,8 @@ public class GenresValidator progress.Report(percent); } + _logger.LogInformation("Refreshed metadata for {RefreshedCount} new genres out of {TotalCount} total", refreshed, count); + var deadEntities = _libraryManager.GetItemList(new InternalItemsQuery { IncludeItemTypes = [BaseItemKind.Genre, BaseItemKind.MusicGenre], @@ -88,16 +114,10 @@ public class GenresValidator foreach (var item in deadEntities) { _logger.LogInformation("Deleting dead {ItemType} {ItemId} {ItemName}", item.GetType().Name, item.Id.ToString("N", CultureInfo.InvariantCulture), item.Name); - - _libraryManager.DeleteItem( - item, - new DeleteOptions - { - DeleteFileLocation = false - }, - false); } + _libraryManager.DeleteItemsUnsafeFast(deadEntities, deleteSourceFiles: true); + progress.Report(100); } } diff --git a/Emby.Server.Implementations/Library/Validators/MusicGenresValidator.cs b/Emby.Server.Implementations/Library/Validators/MusicGenresValidator.cs index 6203bce2bc..4365707529 100644 --- a/Emby.Server.Implementations/Library/Validators/MusicGenresValidator.cs +++ b/Emby.Server.Implementations/Library/Validators/MusicGenresValidator.cs @@ -1,6 +1,9 @@ using System; +using System.Linq; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Data.Enums; +using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Persistence; using Microsoft.Extensions.Logging; @@ -45,17 +48,25 @@ public class MusicGenresValidator public async Task Run(IProgress<double> progress, CancellationToken cancellationToken) { var names = _itemRepo.GetMusicGenreNames(); + var existingMusicGenreIds = _libraryManager.GetItemIds(new InternalItemsQuery + { + IncludeItemTypes = [BaseItemKind.MusicGenre] + }).ToHashSet(); var numComplete = 0; var count = names.Count; + var refreshed = 0; foreach (var name in names) { try { var item = _libraryManager.GetMusicGenre(name); - - await item.RefreshMetadata(cancellationToken).ConfigureAwait(false); + if (!existingMusicGenreIds.Contains(item.Id)) + { + await item.RefreshMetadata(cancellationToken).ConfigureAwait(false); + refreshed++; + } } catch (OperationCanceledException) { @@ -75,6 +86,8 @@ public class MusicGenresValidator progress.Report(percent); } + _logger.LogInformation("Refreshed metadata for {RefreshedCount} new music genres out of {TotalCount} total", refreshed, count); + progress.Report(100); } } diff --git a/Emby.Server.Implementations/Library/Validators/PeopleValidator.cs b/Emby.Server.Implementations/Library/Validators/PeopleValidator.cs index f9a6f0d19e..dacef102dd 100644 --- a/Emby.Server.Implementations/Library/Validators/PeopleValidator.cs +++ b/Emby.Server.Implementations/Library/Validators/PeopleValidator.cs @@ -109,7 +109,7 @@ public class PeopleValidator var i = 0; foreach (var item in deadEntities.Chunk(500)) { - _libraryManager.DeleteItemsUnsafeFast(item); + _libraryManager.DeleteItemsUnsafeFast(item, true); subProgress.Report(100f / deadEntities.Count * (i++ * 100)); } diff --git a/Emby.Server.Implementations/Library/Validators/StudiosValidator.cs b/Emby.Server.Implementations/Library/Validators/StudiosValidator.cs index 5b87e4d9d0..88f86ae6ca 100644 --- a/Emby.Server.Implementations/Library/Validators/StudiosValidator.cs +++ b/Emby.Server.Implementations/Library/Validators/StudiosValidator.cs @@ -1,5 +1,6 @@ using System; using System.Globalization; +using System.Linq; using System.Threading; using System.Threading.Tasks; using Jellyfin.Data.Enums; @@ -49,17 +50,40 @@ public class StudiosValidator public async Task Run(IProgress<double> progress, CancellationToken cancellationToken) { var names = _itemRepo.GetStudioNames(); + var existingStudioIds = _libraryManager.GetItemIds(new InternalItemsQuery + { + IncludeItemTypes = [BaseItemKind.Studio] + }).ToHashSet(); + + var existingStudios = _libraryManager.GetItemList(new InternalItemsQuery + { + IncludeItemTypes = [BaseItemKind.Studio] + }).Cast<Studio>() + .GroupBy(s => s.Name, StringComparer.OrdinalIgnoreCase) + .ToDictionary(g => g.Key, g => g.First(), StringComparer.OrdinalIgnoreCase); var numComplete = 0; var count = names.Count; + var refreshed = 0; foreach (var name in names) { try { - var item = _libraryManager.GetStudio(name); + Studio? item = null; + if (existingStudios.TryGetValue(name, out var existingStudio)) + { + item = existingStudio; + } + + // Fall back to GetStudio if not found (creates new item if needed) + item ??= _libraryManager.GetStudio(name); - await item.RefreshMetadata(cancellationToken).ConfigureAwait(false); + if (!existingStudioIds.Contains(item.Id)) + { + await item.RefreshMetadata(cancellationToken).ConfigureAwait(false); + refreshed++; + } } catch (OperationCanceledException) { @@ -79,6 +103,8 @@ public class StudiosValidator progress.Report(percent); } + _logger.LogInformation("Refreshed metadata for {RefreshedCount} new studios out of {TotalCount} total", refreshed, count); + var deadEntities = _libraryManager.GetItemList(new InternalItemsQuery { IncludeItemTypes = [BaseItemKind.Studio], @@ -89,16 +115,10 @@ public class StudiosValidator foreach (var item in deadEntities) { _logger.LogInformation("Deleting dead {ItemType} {ItemId} {ItemName}", item.GetType().Name, item.Id.ToString("N", CultureInfo.InvariantCulture), item.Name); - - _libraryManager.DeleteItem( - item, - new DeleteOptions - { - DeleteFileLocation = false - }, - false); } + _libraryManager.DeleteItemsUnsafeFast(deadEntities, deleteSourceFiles: true); + progress.Report(100); } } |
