Files
nfoguard/NFOGuard.Emby.Plugin/NFOGuardScheduledTask.cs
T
2025-09-12 10:30:12 -04:00

226 lines
10 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Tasks;
namespace NFOGuard.Emby.Plugin
{
public class NFOGuardScheduledTask : IScheduledTask
{
private readonly ILibraryManager _libraryManager;
private readonly ILogger _logger;
private readonly FreeTierManager _freeTierManager;
public string Name => "DateSync Task";
public string Key => "NFOGuardSync";
public string Description => "Synchronizes PremiereDate to DateCreated for all TV episodes and movies";
public string Category => "Library";
public NFOGuardScheduledTask(ILibraryManager libraryManager, ILogManager logManager)
{
_libraryManager = libraryManager;
_logger = logManager.GetLogger("NFOGuard");
_freeTierManager = new FreeTierManager(_logger);
}
public async Task Execute(CancellationToken cancellationToken, IProgress<double> progress)
{
if (!Plugin.Instance.Configuration.EnableScheduledTask)
{
_logger.Info("NFOGuard :: Scheduled task is disabled in configuration");
return;
}
_logger.Info("NFOGuard :: Starting scheduled task execution");
try
{
// Get all TV episodes and movies
var episodes = _libraryManager.GetItemList(new InternalItemsQuery
{
IncludeItemTypes = new[] { "Episode" },
Recursive = true
}).OfType<Episode>().ToList();
var movies = _libraryManager.GetItemList(new InternalItemsQuery
{
IncludeItemTypes = new[] { "Movie" },
Recursive = true
}).OfType<Movie>().ToList();
var totalItems = episodes.Count + movies.Count;
_logger.Info($"NFOGuard :: Found {episodes.Count} episodes and {movies.Count} movies to process ({totalItems} total)");
// Calculate items that need processing
var itemsNeedingSync = episodes.Where(e => e.PremiereDate.HasValue && e.DateCreated != e.PremiereDate.Value).Count() +
movies.Where(m => m.PremiereDate.HasValue && m.DateCreated != m.PremiereDate.Value).Count();
_logger.Info($"NFOGuard :: {itemsNeedingSync} items need date synchronization");
// Check free tier limits
if (!_freeTierManager.CanProcessItems(itemsNeedingSync, out string reason))
{
_logger.Info($"NFOGuard :: {reason}");
// In free tier, process only what we can
var pluginConfig = Plugin.Instance.Configuration;
if (pluginConfig.MonthlyProcessingLimit > 0 && !pluginConfig.LicenseValid)
{
var allowedCount = Math.Max(0, pluginConfig.MonthlyProcessingLimit - pluginConfig.ProcessedThisMonth);
_logger.Info($"NFOGuard :: Free tier: Processing {allowedCount} items only");
if (allowedCount == 0)
{
_logger.Info("NFOGuard :: Free tier limit reached. No items will be processed this month.");
return;
}
}
}
var processedCount = 0;
var updatedCount = 0;
var config = Plugin.Instance.Configuration;
var remainingQuota = config.MonthlyProcessingLimit > 0 && !config.LicenseValid
? Math.Max(0, config.MonthlyProcessingLimit - config.ProcessedThisMonth)
: int.MaxValue;
// Process episodes
for (int i = 0; i < episodes.Count && (config.LicenseValid || remainingQuota > 0); i++)
{
cancellationToken.ThrowIfCancellationRequested();
var episode = episodes[i];
try
{
// Always log detailed info to diagnose the issue
if (Plugin.Instance.Configuration.LogVerbose)
_logger.Info($"NFOGuard :: Episode: {episode.Name} :: " +
$"PremiereDate: {episode.PremiereDate?.ToString("yyyy-MM-dd HH:mm:ss") ?? "NULL"}, " +
$"DateCreated: {episode.DateCreated.ToString("yyyy-MM-dd HH:mm:ss")}");
if (episode.PremiereDate.HasValue &&
episode.DateCreated != episode.PremiereDate.Value)
{
_logger.Info($"NFOGuard :: SYNCING episode: {episode.Name} :: " +
$"PremiereDate: {episode.PremiereDate.Value}, DateCreated: {episode.DateCreated}");
episode.DateCreated = episode.PremiereDate.Value;
episode.UpdateToRepository(ItemUpdateType.MetadataEdit);
updatedCount++;
// Track usage and decrement quota
_freeTierManager.RecordProcessedItems(1);
if (!config.LicenseValid && config.MonthlyProcessingLimit > 0)
{
remainingQuota--;
}
}
else if (!episode.PremiereDate.HasValue)
{
if (Plugin.Instance.Configuration.LogVerbose)
_logger.Info($"NFOGuard :: Episode {episode.Name} has no PremiereDate - skipping");
}
else
{
if (Plugin.Instance.Configuration.LogVerbose)
_logger.Info($"NFOGuard :: Episode {episode.Name} dates already match - no sync needed");
}
processedCount++;
var progressPercentage = (double)processedCount / totalItems * 100;
progress?.Report(progressPercentage);
}
catch (Exception ex)
{
_logger.ErrorException($"NFOGuard :: Error processing episode {episode.Name}", ex);
}
}
// Process movies
for (int i = 0; i < movies.Count && (config.LicenseValid || remainingQuota > 0); i++)
{
cancellationToken.ThrowIfCancellationRequested();
var movie = movies[i];
try
{
// Always log detailed info to diagnose the issue
if (Plugin.Instance.Configuration.LogVerbose)
_logger.Info($"NFOGuard :: Movie: {movie.Name} :: " +
$"PremiereDate: {movie.PremiereDate?.ToString("yyyy-MM-dd HH:mm:ss") ?? "NULL"}, " +
$"DateCreated: {movie.DateCreated.ToString("yyyy-MM-dd HH:mm:ss")}");
if (movie.PremiereDate.HasValue &&
movie.DateCreated != movie.PremiereDate.Value)
{
_logger.Info($"NFOGuard :: SYNCING movie: {movie.Name} :: " +
$"PremiereDate: {movie.PremiereDate.Value}, DateCreated: {movie.DateCreated}");
movie.DateCreated = movie.PremiereDate.Value;
movie.UpdateToRepository(ItemUpdateType.MetadataEdit);
updatedCount++;
// Track usage and decrement quota
_freeTierManager.RecordProcessedItems(1);
if (!config.LicenseValid && config.MonthlyProcessingLimit > 0)
{
remainingQuota--;
}
}
else if (!movie.PremiereDate.HasValue)
{
if (Plugin.Instance.Configuration.LogVerbose)
_logger.Info($"NFOGuard :: Movie {movie.Name} has no PremiereDate - skipping");
}
else
{
if (Plugin.Instance.Configuration.LogVerbose)
_logger.Info($"NFOGuard :: Movie {movie.Name} dates already match - no sync needed");
}
processedCount++;
var progressPercentage = (double)processedCount / totalItems * 100;
progress?.Report(progressPercentage);
}
catch (Exception ex)
{
_logger.ErrorException($"NFOGuard :: Error processing movie {movie.Name}", ex);
}
}
_logger.Info($"NFOGuard :: Scheduled task completed. Processed: {processedCount} items ({episodes.Count} episodes, {movies.Count} movies), Updated: {updatedCount}");
}
catch (Exception ex)
{
_logger.ErrorException("NFOGuard :: Scheduled task failed", ex);
throw;
}
}
public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
{
// Default to run weekly at 3 AM on Sunday
return new[]
{
new TaskTriggerInfo
{
Type = TaskTriggerInfo.TriggerWeekly,
DayOfWeek = DayOfWeek.Sunday,
TimeOfDayTicks = TimeSpan.FromHours(3).Ticks
}
};
}
}
}