|   |  | 1 |  | using System; | 
|   |  | 2 |  | using System.Linq; | 
|   |  | 3 |  | using System.Threading; | 
|   |  | 4 |  |  | 
|   |  | 5 |  | using Jellyfin.Data.Enums; | 
|   |  | 6 |  | using MediaBrowser.Controller.Entities; | 
|   |  | 7 |  | using MediaBrowser.Controller.Library; | 
|   |  | 8 |  | using MediaBrowser.Controller.Playlists; | 
|   |  | 9 |  | using Microsoft.Extensions.Logging; | 
|   |  | 10 |  |  | 
|   |  | 11 |  | namespace Jellyfin.Server.Migrations.Routines; | 
|   |  | 12 |  |  | 
|   |  | 13 |  | /// <summary> | 
|   |  | 14 |  | /// Properly set playlist owner. | 
|   |  | 15 |  | /// </summary> | 
|   |  | 16 |  | #pragma warning disable CS0618 // Type or member is obsolete | 
|   |  | 17 |  | [JellyfinMigration("2025-04-20T15:00:00", nameof(FixPlaylistOwner), "615DFA9E-2497-4DBB-A472-61938B752C5B")] | 
|   |  | 18 |  | internal class FixPlaylistOwner : IMigrationRoutine | 
|   |  | 19 |  | #pragma warning restore CS0618 // Type or member is obsolete | 
|   |  | 20 |  | { | 
|   |  | 21 |  |     private readonly ILogger<FixPlaylistOwner> _logger; | 
|   |  | 22 |  |     private readonly ILibraryManager _libraryManager; | 
|   |  | 23 |  |     private readonly IPlaylistManager _playlistManager; | 
|   |  | 24 |  |  | 
|   |  | 25 |  |     public FixPlaylistOwner( | 
|   |  | 26 |  |         ILogger<FixPlaylistOwner> logger, | 
|   |  | 27 |  |         ILibraryManager libraryManager, | 
|   |  | 28 |  |         IPlaylistManager playlistManager) | 
|   |  | 29 |  |     { | 
|   | 0 | 30 |  |         _logger = logger; | 
|   | 0 | 31 |  |         _libraryManager = libraryManager; | 
|   | 0 | 32 |  |         _playlistManager = playlistManager; | 
|   | 0 | 33 |  |     } | 
|   |  | 34 |  |  | 
|   |  | 35 |  |     /// <inheritdoc/> | 
|   |  | 36 |  |     public void Perform() | 
|   |  | 37 |  |     { | 
|   | 0 | 38 |  |         var playlists = _libraryManager.GetItemList(new InternalItemsQuery | 
|   | 0 | 39 |  |         { | 
|   | 0 | 40 |  |             IncludeItemTypes = new[] { BaseItemKind.Playlist } | 
|   | 0 | 41 |  |         }) | 
|   | 0 | 42 |  |         .Cast<Playlist>() | 
|   | 0 | 43 |  |         .Where(x => x.OwnerUserId.Equals(Guid.Empty)) | 
|   | 0 | 44 |  |         .ToArray(); | 
|   |  | 45 |  |  | 
|   | 0 | 46 |  |         if (playlists.Length > 0) | 
|   |  | 47 |  |         { | 
|   | 0 | 48 |  |             foreach (var playlist in playlists) | 
|   |  | 49 |  |             { | 
|   | 0 | 50 |  |                 var shares = playlist.Shares; | 
|   | 0 | 51 |  |                 if (shares.Count > 0) | 
|   |  | 52 |  |                 { | 
|   | 0 | 53 |  |                     var firstEditShare = shares.First(x => x.CanEdit); | 
|   | 0 | 54 |  |                     if (firstEditShare is not null) | 
|   |  | 55 |  |                     { | 
|   | 0 | 56 |  |                         playlist.OwnerUserId = firstEditShare.UserId; | 
|   | 0 | 57 |  |                         playlist.Shares = shares.Where(x => x != firstEditShare).ToArray(); | 
|   | 0 | 58 |  |                         playlist.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).GetAwaiter | 
|   | 0 | 59 |  |                         _playlistManager.SavePlaylistFile(playlist); | 
|   |  | 60 |  |                     } | 
|   |  | 61 |  |                 } | 
|   |  | 62 |  |                 else | 
|   |  | 63 |  |                 { | 
|   | 0 | 64 |  |                     playlist.OpenAccess = true; | 
|   | 0 | 65 |  |                     playlist.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).GetAwaiter().G | 
|   |  | 66 |  |                 } | 
|   |  | 67 |  |             } | 
|   |  | 68 |  |         } | 
|   | 0 | 69 |  |     } | 
|   |  | 70 |  | } |