using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Querying; using Jellyfin.Data.Enums; using Microsoft.Extensions.Logging; namespace Jellyfin.Plugin.MovieNight.Services; /// /// Service for synchronizing the Jellyfin library with MovieNight. /// public class MovieNightSyncService { private readonly MovieNightBackendClient _backendClient; private readonly ILibraryManager _libraryManager; private readonly IUserManager _userManager; private readonly IUserDataManager _userDataManager; private readonly ILogger _logger; /// /// Initializes a new instance of the class. /// public MovieNightSyncService( MovieNightBackendClient backendClient, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager, ILogger logger) { _backendClient = backendClient; _libraryManager = libraryManager; _userManager = userManager; _userDataManager = userDataManager; _logger = logger; } /// /// Performs a full library sync. /// public async Task PerformSyncAsync(CancellationToken cancellationToken) { _logger.LogInformation("Starting MovieNight library sync"); var config = Plugin.Instance?.Configuration; var enabledLibraryIds = config?.EnabledLibraryIds ?? new List(); var query = new InternalItemsQuery { IncludeItemTypes = new[] { BaseItemKind.Movie }, Recursive = true }; if (enabledLibraryIds.Count > 0) { query.AncestorIds = enabledLibraryIds.Select(Guid.Parse).ToArray(); } var items = _libraryManager.GetItemList(query); var users = _userManager.Users; var syncUsers = users.Select(u => new { jellyfinUserId = u.Id.ToString("N"), name = u.Username }).ToList(); var syncItems = new List(); foreach (var item in items) { if (item is not Movie movie) continue; var jellyfinItemId = movie.Id.ToString("N"); var title = string.IsNullOrWhiteSpace(movie.Name) ? jellyfinItemId : movie.Name; var itemData = new Dictionary { ["jellyfinItemId"] = jellyfinItemId, ["title"] = title, ["originalTitle"] = movie.OriginalTitle, ["description"] = movie.Overview, ["year"] = movie.ProductionYear, ["duration"] = movie.RunTimeTicks, ["genres"] = movie.Genres, ["posterUrl"] = $"/Items/{jellyfinItemId}/Images/Primary", ["imdbId"] = movie.GetProviderId(MetadataProvider.Imdb), ["tmdbId"] = movie.GetProviderId(MetadataProvider.Tmdb), ["userStates"] = users.Select(u => { var userData = _userDataManager.GetUserData(u, movie); return new { jellyfinUserId = u.Id.ToString("N"), isViewed = userData?.Played ?? false, playCount = userData?.PlayCount ?? 0, lastPlayedAt = userData?.LastPlayedDate, userRating = userData?.Rating }; }).ToList() }; syncItems.Add(itemData); } await _backendClient.SyncAsync(new { users = syncUsers, items = syncItems }, cancellationToken).ConfigureAwait(false); _logger.LogInformation("MovieNight library sync completed"); } }