diff --git a/Jellyfin.Plugin.MediaCleaner/Controllers/StateController.cs b/Jellyfin.Plugin.MediaCleaner/Controllers/StateController.cs new file mode 100644 index 0000000..c66c6be --- /dev/null +++ b/Jellyfin.Plugin.MediaCleaner/Controllers/StateController.cs @@ -0,0 +1,22 @@ +using Jellyfin.Plugin.MediaCleaner.Data; +using Jellyfin.Plugin.MediaCleaner.Models; +using Microsoft.AspNetCore.Mvc; + +namespace Jellyfin.Plugin.MediaCleaner.Controllers; + +[Route("mediacleaner/state")] +public class StateController : Controller +{ + private readonly PluginState _state; + public StateController(PluginState state) => _state = state; + + [HttpGet] + public IActionResult Get() => Ok(_state.GetSeriesInfo()); + + [HttpPost("add")] + public IActionResult AddSeriesInfo([FromBody] SeriesInfo seriesInfo) + { + _state.AddSeriesInfo(seriesInfo); + return Ok(); + } +} diff --git a/Jellyfin.Plugin.MediaCleaner/Data/PluginState.cs b/Jellyfin.Plugin.MediaCleaner/Data/PluginState.cs new file mode 100644 index 0000000..53f038f --- /dev/null +++ b/Jellyfin.Plugin.MediaCleaner/Data/PluginState.cs @@ -0,0 +1,29 @@ +using System.Collections.Generic; +using Jellyfin.Plugin.MediaCleaner.Models; + +namespace Jellyfin.Plugin.MediaCleaner.Data; + +public class PluginState +{ + private readonly object _lock = new(); + private List _seriesInfo = new List + { + new SeriesInfo { SeriesName = "TestName", Id = System.Guid.NewGuid() } + }; + + public void AddSeriesInfo(SeriesInfo seriesInfo) + { + lock (_lock) + { + _seriesInfo.Add(seriesInfo); + } + } + + public IEnumerable GetSeriesInfo() + { + lock (_lock) + { + return _seriesInfo; + } + } +} diff --git a/Jellyfin.Plugin.MediaCleaner/Helpers/LoggingHelper.cs b/Jellyfin.Plugin.MediaCleaner/Helpers/LoggingHelper.cs index 9ac7b8b..c78aadf 100644 --- a/Jellyfin.Plugin.MediaCleaner/Helpers/LoggingHelper.cs +++ b/Jellyfin.Plugin.MediaCleaner/Helpers/LoggingHelper.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using Jellyfin.Plugin.MediaCleaner.Configuration; using Jellyfin.Plugin.MediaCleaner.Models; @@ -10,150 +11,25 @@ using Microsoft.Extensions.Logging; namespace Jellyfin.Plugin.MediaCleaner.Helpers; -public class LoggingHelper +public class LoggingHelper(ILogger logger) { - private readonly ILogger _logger; + private readonly ILogger _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - public LoggingHelper(ILogger logger) + [SuppressMessage("Microsoft.Performance", "CA2254:TemplateShouldBeConstant", Justification = "Message parameter is intentionally variable for flexible debug logging")] + public void LogDebugInformation(string message, params object?[] args) { - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + if (Configuration.DebugMode) + { + _logger.LogInformation(message, args); + } + } + + [SuppressMessage("Microsoft.Performance", "CA2254:TemplateShouldBeConstant", Justification = "Message parameter is intentionally variable for flexible logging")] + public void LogInformation(string message, params object?[] args) + { + _logger.LogInformation(message, args); } private static PluginConfiguration Configuration => Plugin.Instance!.Configuration; - - public void StartLogging() - { - if (Configuration.DebugMode) - { - _logger.LogInformation("--DEBUG MODE ACTIVE--"); - } - - _logger.LogInformation("-------------------------------------------------"); - _logger.LogInformation("Starting stale media scan..."); - } - - public void EndLogging() - { - _logger.LogInformation("Ending stale media scan..."); - _logger.LogInformation("-------------------------------------------------"); - } - - public void PrintDebugEndOfScanningForSeries(BaseItem item) - { - if (Configuration.DebugMode) - { - _logger.LogInformation("End of scanning for series: {Series}", item); - _logger.LogInformation("-------------------------------------------------"); - } - } - - - public void StartScanningSeriesItems() - { - _logger.LogInformation("-------------------------------------------------"); - _logger.LogInformation("Starting scan of series items."); - _logger.LogInformation("-------------------------------------------------"); - } - - public void StartScanningMoviesItems() - { - _logger.LogInformation("-------------------------------------------------"); - _logger.LogInformation("Starting scan of movies items."); - _logger.LogInformation("-------------------------------------------------"); - } - - public void PrintItemsInformation(IReadOnlyCollection items) - { - ArgumentNullException.ThrowIfNull(items); - - _logger.LogInformation("Total items: {ItemCount}", items.Count); - _logger.LogInformation("Stale items found: {AllItems}", items); - } - - public void PrintStaleMoviesInformation(IReadOnlyCollection staleMovies) - { - ArgumentNullException.ThrowIfNull(staleMovies); - - _logger.LogInformation("-------------------------------------------------"); - _logger.LogInformation("Stale Movies found: {StaleMovies}", staleMovies.Count); - - if (staleMovies.Count > 0 && Configuration.DebugMode) - { - foreach (var movieInfo in staleMovies) - { - _logger.LogInformation("Movie Info: ID: {Id} | Movie Name: {MovieName}", [movieInfo.Id, movieInfo.Name]); - } - } - } - - public void PrintStaleEpisodesInformation(Func, List> findSeriesInfoFromEpisodes, IReadOnlyCollection staleEpisodes) - { - ArgumentNullException.ThrowIfNull(staleEpisodes); - ArgumentNullException.ThrowIfNull(findSeriesInfoFromEpisodes); - - _logger.LogInformation("-------------------------------------------------"); - _logger.LogInformation("Stale Episodes found: {StaleEpisodes}", staleEpisodes.Count); - - if (staleEpisodes.Count > 0 && Configuration.DebugMode) - { - if (findSeriesInfoFromEpisodes == null) - { - throw new ArgumentNullException(nameof(findSeriesInfoFromEpisodes), "The method to find series information cannot be null."); - } - - List seriesInfoList = findSeriesInfoFromEpisodes(staleEpisodes); - - foreach (var seriesInfo in seriesInfoList) - { - _logger.LogInformation("Series Info: ID: {Id} | Series Name: {SeriesName} | Stale Seasons: {Seasons}", [seriesInfo.Id, seriesInfo.SeriesName, string.Join(", ", seriesInfo.Seasons)]); - } - } - - _logger.LogInformation("-------------------------------------------------"); - } - - public void PrintDebugDataForSeries(BaseItem item) - { - ArgumentNullException.ThrowIfNull(item); - - if (Configuration.DebugMode) - { - _logger.LogInformation("-------------------------------------------------"); - _logger.LogInformation("Debug data for series: {SeriesName}", item.Name); - _logger.LogInformation("-------------------------------------------------"); - } - } - - public void PrintDebugSeasonInfo() - { - if (Configuration.DebugMode) - { - _logger.LogInformation("Season debug information:"); - } - } - - public void PrintDebugEpisodesWithUserData(IReadOnlyCollection episodesWithUserData) - { - if(Configuration.DebugMode){ - _logger.LogInformation("Episodes with user data: {EpisodesWithUserData}", episodesWithUserData); - _logger.LogInformation("-------------------------------------------------"); - } - } - - public void PrintDebugEpisodeCreationInfo(IReadOnlyCollection episodes) - { - ArgumentNullException.ThrowIfNull(episodes); - - if(Configuration.DebugMode){ - _logger.LogInformation("-------------------------------------------------"); - _logger.LogInformation("Episode creation dates:"); - _logger.LogInformation("-------------------------------------------------"); - foreach(BaseItem episode in episodes) - { - _logger.LogInformation("Episode: {EpisodeName} | Date Created: {EpisodeDateCreated}", [episode.Name, episode.DateCreated]); - } - _logger.LogInformation("-------------------------------------------------"); - } - } } diff --git a/Jellyfin.Plugin.MediaCleaner/Helpers/MovieHelper.cs b/Jellyfin.Plugin.MediaCleaner/Helpers/MovieHelper.cs index 3793ad1..429ed1c 100644 --- a/Jellyfin.Plugin.MediaCleaner/Helpers/MovieHelper.cs +++ b/Jellyfin.Plugin.MediaCleaner/Helpers/MovieHelper.cs @@ -8,26 +8,17 @@ using Microsoft.Extensions.Logging; namespace Jellyfin.Plugin.MediaCleaner.Helpers; -public class MovieHelper +public class MovieHelper(ILogger logger) { - private readonly ILogger _logger; - - public MovieHelper(ILogger logger) - { - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - } + private readonly LoggingHelper _loggingHelper = new(logger); private static PluginConfiguration Configuration => Plugin.Instance!.Configuration; public bool IsMovieStale(BaseItem movie) { - if (Configuration.DebugMode) - { - _logger.LogInformation("-------------------------------------------------"); - _logger.LogInformation("Start of scanning for movie: {Movie}", movie); - _logger.LogInformation("-------------------------------------------------"); - } + _loggingHelper.LogDebugInformation("Start of scanning for movie: {Movie}", movie); + _loggingHelper.LogDebugInformation("-------------------------------------------------"); bool movieIsStale = false; @@ -38,40 +29,33 @@ public class MovieHelper { var mostRecentUserData = movie.UserData.OrderByDescending(data => data.LastPlayedDate).First(data => data.LastPlayedDate != null); - if (Configuration.DebugMode){ - _logger.LogInformation("Most recent user data: {Movie}", movie); + _loggingHelper.LogDebugInformation("Most recent user data: {Movie}", movie); - foreach (var property in typeof(UserData).GetProperties()) - { - _logger.LogInformation("{PropertyName}: {PropertyValue}", property.Name, property.GetValue(mostRecentUserData)); - } - _logger.LogInformation("-------------------------------------------------"); + foreach (var property in typeof(UserData).GetProperties()) + { + _loggingHelper.LogDebugInformation("{PropertyName}: {PropertyValue}", property.Name, property.GetValue(mostRecentUserData)); } + _loggingHelper.LogDebugInformation("-------------------------------------------------"); + if (mostRecentUserData.LastPlayedDate < DateTime.Now.AddDays(-Configuration.StaleMediaCutoff)) { - if (Configuration.DebugMode) - { - _logger.LogInformation("Most recent user data last played date is outside of cutoff. Adding {Movie} to stale movies.", movie); - } + _loggingHelper.LogDebugInformation("Most recent user data has last played date that is outside of cutoff."); + _loggingHelper.LogDebugInformation("Adding {Movie} to stale movies.", movie); + _loggingHelper.LogDebugInformation("With Last Played Date: {LastPlayedDate}", mostRecentUserData.LastPlayedDate); + movieIsStale = true; } } else if (createdOutsideCutoff) { - if (Configuration.DebugMode) - { - _logger.LogInformation("Movie has no user data and was created outside of cutoff: {DateCreated}. Adding {Movie} to stale movies.", [movie.DateCreated, movie]); - } + _loggingHelper.LogDebugInformation("Movie has no user data and was created outside of cutoff: {DateCreated}.", movie.DateCreated); + _loggingHelper.LogDebugInformation("Adding {Movie} to stale movies.", movie); movieIsStale = true; } - if (Configuration.DebugMode) - { - _logger.LogInformation("-------------------------------------------------"); - _logger.LogInformation("End of scanning for movie: {Movie}", movie); - _logger.LogInformation("-------------------------------------------------"); - } + _loggingHelper.LogDebugInformation("-------------------------------------------------"); + _loggingHelper.LogDebugInformation("End of scanning for movie: {Movie}", movie); return movieIsStale; } diff --git a/Jellyfin.Plugin.MediaCleaner/Helpers/SeriesHelper.cs b/Jellyfin.Plugin.MediaCleaner/Helpers/SeriesHelper.cs index f53630b..51d2950 100644 --- a/Jellyfin.Plugin.MediaCleaner/Helpers/SeriesHelper.cs +++ b/Jellyfin.Plugin.MediaCleaner/Helpers/SeriesHelper.cs @@ -11,71 +11,80 @@ using Microsoft.Extensions.Logging; namespace Jellyfin.Plugin.MediaCleaner.Helpers; -public class SeriesHelper +public class SeriesHelper(ILogger logger) { - private readonly ILogger _logger; - private readonly LoggingHelper _loggingHelper; - - public SeriesHelper(ILogger logger) - { - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - _loggingHelper = new LoggingHelper(logger); - } + private readonly LoggingHelper _loggingHelper = new(logger); private static PluginConfiguration Configuration => Plugin.Instance!.Configuration; - public bool IsSeasonUserDataStale(IReadOnlyList episodes) + private List ProcessEpisodes(IReadOnlyCollection episodes) { - bool seasonIsStale = false; - - List staleEpisodes = []; - - var episodesWithUserData = episodes.Where(episode => episode.UserData.Where(data => data.LastPlayedDate != null).ToList().Count > 0).ToList(); - - _loggingHelper.PrintDebugEpisodesWithUserData(episodesWithUserData); - - foreach (var episode in episodesWithUserData) + List staleEpisodes = [.. episodes + .Where(episode => { bool episodeIsStale = false; - var mostRecentUserData = episode.UserData.OrderByDescending(data => data.LastPlayedDate).First(data => data.LastPlayedDate != null); - var staleLastPlayedDate = mostRecentUserData.LastPlayedDate < DateTime.Now.AddDays(-Configuration.StaleMediaCutoff); var staleCreationDate = episode.DateCreated < DateTime.Now.AddDays(-Configuration.StaleMediaCutoff); + var hasUserDataWithLastPlayedDate = episode.UserData.Any(data => data.LastPlayedDate != null); + + _loggingHelper.LogDebugInformation("-------------------------------------------------"); + _loggingHelper.LogDebugInformation("Debug data for episode: {Episode}", episode); + _loggingHelper.LogDebugInformation("-------------------------------------------------"); + + if (staleCreationDate && !hasUserDataWithLastPlayedDate){ + _loggingHelper.LogDebugInformation("Creation date is stale, and no user data for episode {Episode}.", episode); + _loggingHelper.LogDebugInformation("Date created: {DateCreated}", episode.DateCreated); + episodeIsStale = true; + } + + if (hasUserDataWithLastPlayedDate){ + UserData mostRecentUserData = episode.UserData + .OrderByDescending(data => data.LastPlayedDate) + .First(); - if(Configuration.DebugMode){ - _logger.LogInformation("User data for episode: {Episode}", episode); - _logger.LogInformation("-------------------------------------------------"); foreach (var property in typeof(UserData).GetProperties()) { - _logger.LogInformation("{PropertyName}: {PropertyValue}", property.Name, property.GetValue(mostRecentUserData)); + _loggingHelper.LogDebugInformation("{PropertyName}: {PropertyValue}", property.Name, property.GetValue(mostRecentUserData)); } - _logger.LogInformation("-------------------------------------------------"); - } - if (staleLastPlayedDate && staleCreationDate) - { - episodeIsStale = true; - if(Configuration.DebugMode){ - _logger.LogInformation("Most recent user data has a last played date of: {LastPlayedDate}.", [mostRecentUserData.LastPlayedDate]); - _logger.LogInformation("And episode created {DateCreated}.", episode.DateCreated); + _loggingHelper.LogDebugInformation("-------------------------------------------------"); + + bool staleLastPlayedDate = mostRecentUserData.LastPlayedDate < DateTime.Now.AddDays(-Configuration.StaleMediaCutoff); + + if (staleLastPlayedDate && staleCreationDate) + { + episodeIsStale = true; + _loggingHelper.LogDebugInformation("Most recent user data has a last played date of: {LastPlayedDate}.", [mostRecentUserData.LastPlayedDate]); + _loggingHelper.LogDebugInformation("Episode created {DateCreated}.", episode.DateCreated); + _loggingHelper.LogDebugInformation("Episode is marked as stale."); } } - if (episodeIsStale) - { - staleEpisodes.Add(episode); - if(Configuration.DebugMode){ - _logger.LogInformation("Episode is stale."); - } - } + return episodeIsStale; + })]; + + return staleEpisodes; + } + + public bool IsSeasonDataStale(IReadOnlyList episodes) + { + if(episodes == null) + { + ArgumentNullException.ThrowIfNull(episodes); } + bool seasonIsStale = false; + + List staleEpisodes = ProcessEpisodes(episodes); + if(staleEpisodes.Count == episodes.Count) { seasonIsStale = true; - _logger.LogInformation("Stale episodes count matches all episode count. Season is stale."); - _logger.LogInformation("-------------------------------------------------"); + + _loggingHelper.LogDebugInformation("-------------------------------------------------"); + _loggingHelper.LogDebugInformation("Stale episodes count matches season episode count. Season is stale."); + _loggingHelper.LogDebugInformation("-------------------------------------------------"); } return seasonIsStale; diff --git a/Jellyfin.Plugin.MediaCleaner/Jellyfin.Plugin.MediaCleaner.csproj b/Jellyfin.Plugin.MediaCleaner/Jellyfin.Plugin.MediaCleaner.csproj index aa5bdaa..68b496e 100644 --- a/Jellyfin.Plugin.MediaCleaner/Jellyfin.Plugin.MediaCleaner.csproj +++ b/Jellyfin.Plugin.MediaCleaner/Jellyfin.Plugin.MediaCleaner.csproj @@ -22,8 +22,8 @@ - - + + diff --git a/Jellyfin.Plugin.MediaCleaner/Models/SeriesInfo.cs b/Jellyfin.Plugin.MediaCleaner/Models/SeriesInfo.cs index 90ecf95..59ff805 100644 --- a/Jellyfin.Plugin.MediaCleaner/Models/SeriesInfo.cs +++ b/Jellyfin.Plugin.MediaCleaner/Models/SeriesInfo.cs @@ -22,9 +22,5 @@ public class SeriesInfo /// /// Gets or sets seasons. /// -#pragma warning disable CA2227 // Collection properties should be read only -#pragma warning disable CA1002 // Do not expose generic lists - public List Seasons { get; set; } = []; -#pragma warning restore CA1002 // Do not expose generic lists -#pragma warning restore CA2227 // Collection properties should be read only + public IEnumerable Seasons { get; set; } = []; } diff --git a/Jellyfin.Plugin.MediaCleaner/Pages/home.html b/Jellyfin.Plugin.MediaCleaner/Pages/home.html index 8d53c40..e5971e0 100644 --- a/Jellyfin.Plugin.MediaCleaner/Pages/home.html +++ b/Jellyfin.Plugin.MediaCleaner/Pages/home.html @@ -1,4 +1,5 @@ -
+
@@ -6,6 +7,15 @@ Settings

Media Cleaner

+ + + + + + + + +
IDSeries Name
diff --git a/Jellyfin.Plugin.MediaCleaner/Pages/media_cleaner_table.js b/Jellyfin.Plugin.MediaCleaner/Pages/media_cleaner_table.js new file mode 100644 index 0000000..a56f7ba --- /dev/null +++ b/Jellyfin.Plugin.MediaCleaner/Pages/media_cleaner_table.js @@ -0,0 +1,27 @@ +var table = document.getElementById("seriesTable"); + + + +const getMediaCleanerState = async () => { + const response = await fetch('/mediacleaner/state'); + + if(!response.ok){ + throw new Error(`Response status: ${response.status}`) + } + + return response.json(); +} + +var state = await getMediaCleanerState(); + +console.log("State: ", state); + +for(let i = 0; i < state.length; i++){ + var row = table.insertRow(-1); + var cell1 = row.insertCell(0); + var cell2 = row.insertCell(1); + var cell3 = row.insertCell(2); + cell1.innerHTML = state[i].Id; + cell2.innerHTML = state[i].SeriesName; + cell3.innerHTML = state[i].Seasons.length; +} diff --git a/Jellyfin.Plugin.MediaCleaner/Plugin.cs b/Jellyfin.Plugin.MediaCleaner/Plugin.cs index 170a572..5e4271d 100644 --- a/Jellyfin.Plugin.MediaCleaner/Plugin.cs +++ b/Jellyfin.Plugin.MediaCleaner/Plugin.cs @@ -2,11 +2,13 @@ using System; using System.Collections.Generic; using System.Globalization; using Jellyfin.Plugin.MediaCleaner.Configuration; +using Jellyfin.Plugin.MediaCleaner.Data; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Plugins; using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Plugins; using MediaBrowser.Model.Serialization; +using Microsoft.Extensions.DependencyInjection; namespace Jellyfin.Plugin.MediaCleaner; @@ -53,6 +55,11 @@ public class Plugin : BasePlugin, IHasWebPages EmbeddedResourcePath = string.Format(CultureInfo.InvariantCulture, "{0}.Pages.home.html", GetType().Namespace), EnableInMainMenu = true, }, + new PluginPageInfo + { + Name = "media_cleaner_table.js", + EmbeddedResourcePath = string.Format(CultureInfo.InvariantCulture, "{0}.Pages.media_cleaner_table.js", GetType().Namespace), + } ]; } } diff --git a/Jellyfin.Plugin.MediaCleaner/PluginServiceRegistrator.cs b/Jellyfin.Plugin.MediaCleaner/PluginServiceRegistrator.cs new file mode 100644 index 0000000..e5b2db9 --- /dev/null +++ b/Jellyfin.Plugin.MediaCleaner/PluginServiceRegistrator.cs @@ -0,0 +1,13 @@ +using Jellyfin.Plugin.MediaCleaner.Data; +using MediaBrowser.Controller; +using MediaBrowser.Controller.Plugins; +using Microsoft.Extensions.DependencyInjection; + +namespace Jellyfin.Plugin.MediaCleaner; +public class PluginServiceRegistrator : IPluginServiceRegistrator +{ + public void RegisterServices(IServiceCollection serviceCollection, IServerApplicationHost applicationHost) + { + serviceCollection.AddSingleton(); + } +} diff --git a/Jellyfin.Plugin.MediaCleaner/ScheduledTasks/StaleMediaTask.cs b/Jellyfin.Plugin.MediaCleaner/ScheduledTasks/StaleMediaTask.cs index 1c232a3..7c9f3d1 100644 --- a/Jellyfin.Plugin.MediaCleaner/ScheduledTasks/StaleMediaTask.cs +++ b/Jellyfin.Plugin.MediaCleaner/ScheduledTasks/StaleMediaTask.cs @@ -60,7 +60,10 @@ public sealed class StaleMediaTask : IScheduledTask Task IScheduledTask.ExecuteAsync(IProgress progress, CancellationToken cancellationToken) { - _loggingHelper.StartLogging(); + _loggingHelper.LogDebugInformation("--DEBUG MODE ACTIVE--"); + _loggingHelper.LogInformation("-------------------------------------------------"); + _loggingHelper.LogInformation("Starting stale media scan..."); + _loggingHelper.LogInformation("-------------------------------------------------"); var query = new InternalItemsQuery { @@ -70,21 +73,50 @@ public sealed class StaleMediaTask : IScheduledTask List allItems = [.. _libraryManager.GetItemsResult(query).Items]; - _loggingHelper.PrintItemsInformation(allItems); + _loggingHelper.LogInformation("Total items: {ItemCount}", allItems.Count); + _loggingHelper.LogInformation("Stale items found: {AllItems}", allItems); List series = [.. allItems.Where(item => item.GetBaseItemKind() == BaseItemKind.Series)]; List movies = [.. allItems.Where(item => item.GetBaseItemKind() == BaseItemKind.Movie)]; - _loggingHelper.StartScanningSeriesItems(); - List staleEpisodes = [.. series.SelectMany(GetStaleEpisodes)]; + _loggingHelper.LogInformation("-------------------------------------------------"); + _loggingHelper.LogInformation("Starting scan of series items."); + _loggingHelper.LogInformation("-------------------------------------------------"); + + List staleSeasons = [.. series.SelectMany(GetStaleSeasons)]; + + _loggingHelper.LogInformation("Starting scan of movies items."); + _loggingHelper.LogInformation("-------------------------------------------------"); - _loggingHelper.StartScanningMoviesItems(); List staleMovies = [.. GetStaleMovies(movies)]; - _loggingHelper.PrintStaleMoviesInformation(staleMovies); - _loggingHelper.PrintStaleEpisodesInformation(FindSeriesInfoFromEpisodes, staleEpisodes); + _loggingHelper.LogInformation("-------------------------------------------------"); + _loggingHelper.LogInformation("Stale Movies found: {StaleMovies}", staleMovies.Count); - _loggingHelper.EndLogging(); + if (staleMovies.Count > 0 && Configuration.DebugMode) + { + foreach (var movieInfo in staleMovies) + { + _loggingHelper.LogDebugInformation("Movie Info: ID: {Id} | Movie Name: {MovieName}", [movieInfo.Id, movieInfo.Name]); + } + } + + _loggingHelper.LogInformation("-------------------------------------------------"); + _loggingHelper.LogInformation("Stale seasons found: {StaleSeasons}", staleSeasons.Count); + + if (staleSeasons.Count > 0 && Configuration.DebugMode) + { + IEnumerable staleSeriesInfo = FindSeriesInfo(staleSeasons); + + foreach (var seriesInfo in staleSeriesInfo) + { + _loggingHelper.LogDebugInformation("Series Info: ID: {Id} | Series Name: {SeriesName} | Stale Seasons: {Seasons}", [seriesInfo.Id, seriesInfo.SeriesName, string.Join(", ", seriesInfo.Seasons)]); + } + } + + _loggingHelper.LogInformation("-------------------------------------------------"); + _loggingHelper.LogInformation("Ending stale media scan..."); + _loggingHelper.LogInformation("-------------------------------------------------"); return Task.CompletedTask; } @@ -99,9 +131,10 @@ public sealed class StaleMediaTask : IScheduledTask } - private List GetStaleEpisodes(BaseItem item) + private List GetStaleSeasons(BaseItem item) { - List staleEpisodes = []; + _loggingHelper.LogDebugInformation("Debug data for series: {SeriesName}", item.Name); + _loggingHelper.LogDebugInformation("-------------------------------------------------"); // Gets each season in a show var seasons = _libraryManager.GetItemList(new InternalItemsQuery @@ -110,66 +143,48 @@ public sealed class StaleMediaTask : IScheduledTask Recursive = false }); - _loggingHelper.PrintDebugDataForSeries(item); - - foreach (var season in seasons) - { - // Gets each episode, to access user data. + List staleSeasons = [ ..seasons + .Where(season => { var episodes = _libraryManager.GetItemList(new InternalItemsQuery { ParentId = season.Id, Recursive = false }); - _loggingHelper.PrintDebugSeasonInfo(); + _loggingHelper.LogDebugInformation("Season debug information for {SeasonNumber}:", season); - bool seasonHasUserData = episodes.Any(episode => episode.UserData.Count > 0); - bool seasonIsStale = seasonHasUserData && _seriesHelper.IsSeasonUserDataStale(episodes); + bool isSeasonDataStale = _seriesHelper.IsSeasonDataStale(episodes); - if (seasonIsStale) - { - if (!seasonHasUserData) - { - _loggingHelper.PrintDebugEpisodeCreationInfo(episodes); - } + _loggingHelper.LogDebugInformation("End of season debug information for {SeasonNumber}.", season); - staleEpisodes.AddRange(episodes); - } - } + return isSeasonDataStale; + })]; - _loggingHelper.PrintDebugEndOfScanningForSeries(item); - return staleEpisodes; + _loggingHelper.LogDebugInformation("-------------------------------------------------"); + _loggingHelper.LogDebugInformation("End of scanning for series: {Series}", item); + _loggingHelper.LogDebugInformation("-------------------------------------------------"); + + return staleSeasons; } - private List FindSeriesInfoFromEpisodes(IReadOnlyCollection episodes) + private IEnumerable FindSeriesInfo(IReadOnlyCollection seasons) { - Guid[] seasonIds = [.. episodes.Select(episode => episode.ParentId).Distinct()]; - - var seasons = _libraryManager.GetItemList(new InternalItemsQuery - { - ItemIds = seasonIds - }); - Guid[] seriesIds = [.. seasons.Select(season => season.ParentId).Distinct()]; - var series = _libraryManager.GetItemList(new InternalItemsQuery + IReadOnlyCollection series = _libraryManager.GetItemList(new InternalItemsQuery { ItemIds = seriesIds - }).ToList(); + }); - List seriesNames = [.. series.Select(series => series.Name).Distinct()]; - - List seriesInfoList = []; - - series.ForEach(series => + IEnumerable seriesInfoList = series.Select(series => { - seriesInfoList.Add(new SeriesInfo + return new SeriesInfo { Id = series.Id, SeriesName = series.Name, Seasons = [.. seasons.Where(season => season.ParentId == series.Id).Select(season => season.Name)] - }); + }; }); return seriesInfoList;