RemoveDuplicatePlaylistChildren.cs 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. using System;
  2. using System.Linq;
  3. using System.Threading;
  4. using Jellyfin.Data.Enums;
  5. using MediaBrowser.Controller.Entities;
  6. using MediaBrowser.Controller.Library;
  7. using MediaBrowser.Controller.Playlists;
  8. namespace Jellyfin.Server.Migrations.Routines;
  9. /// <summary>
  10. /// Remove duplicate playlist entries.
  11. /// </summary>
  12. #pragma warning disable CS0618 // Type or member is obsolete
  13. [JellyfinMigration("2025-04-20T19:00:00", nameof(RemoveDuplicatePlaylistChildren), "96C156A2-7A13-4B3B-A8B8-FB80C94D20C0")]
  14. internal class RemoveDuplicatePlaylistChildren : IMigrationRoutine
  15. #pragma warning restore CS0618 // Type or member is obsolete
  16. {
  17. private readonly ILibraryManager _libraryManager;
  18. private readonly IPlaylistManager _playlistManager;
  19. public RemoveDuplicatePlaylistChildren(
  20. ILibraryManager libraryManager,
  21. IPlaylistManager playlistManager)
  22. {
  23. _libraryManager = libraryManager;
  24. _playlistManager = playlistManager;
  25. }
  26. /// <inheritdoc/>
  27. public void Perform()
  28. {
  29. var playlists = _libraryManager.GetItemList(new InternalItemsQuery
  30. {
  31. IncludeItemTypes = [BaseItemKind.Playlist]
  32. })
  33. .Cast<Playlist>()
  34. .Where(p => !p.OpenAccess || !p.OwnerUserId.Equals(Guid.Empty))
  35. .ToArray();
  36. if (playlists.Length > 0)
  37. {
  38. foreach (var playlist in playlists)
  39. {
  40. var linkedChildren = playlist.LinkedChildren;
  41. if (linkedChildren.Length > 0)
  42. {
  43. var nullItemChildren = linkedChildren.Where(c => c.ItemId is null);
  44. var deduplicatedChildren = linkedChildren.DistinctBy(c => c.ItemId);
  45. var newLinkedChildren = nullItemChildren.Concat(deduplicatedChildren);
  46. playlist.LinkedChildren = linkedChildren;
  47. playlist.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).GetAwaiter().GetResult();
  48. _playlistManager.SavePlaylistFile(playlist);
  49. }
  50. }
  51. }
  52. }
  53. }