using System; using System.Linq; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Logging; namespace NFOGuard.Emby.Plugin { public class FreeTierManager { private readonly ILogger _logger; private readonly ILibraryManager _libraryManager; public FreeTierManager(ILogger logger, ILibraryManager libraryManager = null) { _logger = logger; _libraryManager = libraryManager; } public bool CanProcessItems(int itemCount, out string reason) { var config = Plugin.Instance.Configuration; reason = string.Empty; // If licensed or no limit set, allow processing if (config.LicenseValid || config.MonthlyProcessingLimit == 0) { return true; } // Check if month has rolled over ResetMonthlyCounterIfNeeded(); // Check if this processing would exceed the limit var wouldExceed = config.ProcessedThisMonth + itemCount > config.MonthlyProcessingLimit; if (wouldExceed) { var remaining = Math.Max(0, config.MonthlyProcessingLimit - config.ProcessedThisMonth); reason = $"Free tier limit reached. {remaining} items remaining this month of {config.MonthlyProcessingLimit} allowed. Upgrade to process unlimited items."; _logger.Info($"NFOGuard :: {reason}"); return false; } return true; } public void RecordProcessedItems(int count) { var config = Plugin.Instance.Configuration; // Only track if using free tier limits if (config.MonthlyProcessingLimit > 0 && !config.LicenseValid) { config.ProcessedThisMonth += count; Plugin.Instance.SaveConfiguration(); _logger.Info($"NFOGuard :: Free tier usage: {config.ProcessedThisMonth}/{config.MonthlyProcessingLimit} items this month"); } } public void SetFreeTierLimits(int monthlyLimit) { var config = Plugin.Instance.Configuration; config.MonthlyProcessingLimit = monthlyLimit; config.LicenseValid = false; if (config.InstallDate == DateTime.MinValue) { config.InstallDate = DateTime.UtcNow; } ResetMonthlyCounterIfNeeded(); Plugin.Instance.SaveConfiguration(); _logger.Info($"NFOGuard :: Free tier configured: {monthlyLimit} items per month"); } public void SetPercentageBasedLimits() { if (_libraryManager == null) { _logger.Warn("NFOGuard :: Cannot calculate percentage limits without LibraryManager"); SetFreeTierLimits(500); // Fallback to fixed limit return; } try { // Get library counts var episodes = _libraryManager.GetItemList(new InternalItemsQuery { IncludeItemTypes = new[] { "Episode" }, Recursive = true }).OfType().Count(); var movies = _libraryManager.GetItemList(new InternalItemsQuery { IncludeItemTypes = new[] { "Movie" }, Recursive = true }).OfType().Count(); // Calculate 2% of TV episodes + 5% of movies var episodeLimit = Math.Max(1, (int)(episodes * 0.02)); // At least 1 episode var movieLimit = Math.Max(1, (int)(movies * 0.05)); // At least 1 movie var totalLimit = episodeLimit + movieLimit; _logger.Info($"NFOGuard :: Library analysis - Episodes: {episodes}, Movies: {movies}"); _logger.Info($"NFOGuard :: Free tier limits - Episodes: {episodeLimit} (2%), Movies: {movieLimit} (5%), Total: {totalLimit}"); var config = Plugin.Instance.Configuration; config.MonthlyProcessingLimit = totalLimit; config.LicenseValid = false; if (config.InstallDate == DateTime.MinValue) { config.InstallDate = DateTime.UtcNow; } ResetMonthlyCounterIfNeeded(); Plugin.Instance.SaveConfiguration(); } catch (Exception ex) { _logger.ErrorException("NFOGuard :: Error calculating percentage limits", ex); SetFreeTierLimits(500); // Fallback } } public void EnableFullVersion() { var config = Plugin.Instance.Configuration; config.LicenseValid = true; config.MonthlyProcessingLimit = 0; Plugin.Instance.SaveConfiguration(); _logger.Info("NFOGuard :: Full version enabled - unlimited processing"); } private void ResetMonthlyCounterIfNeeded() { var config = Plugin.Instance.Configuration; var now = DateTime.UtcNow; // Reset if last reset was more than a month ago or never set if (config.LastProcessingReset == DateTime.MinValue || now > config.LastProcessingReset.AddMonths(1)) { config.ProcessedThisMonth = 0; config.LastProcessingReset = new DateTime(now.Year, now.Month, 1); // First of current month Plugin.Instance.SaveConfiguration(); _logger.Info("NFOGuard :: Monthly processing counter reset"); } } public string GetUsageInfo() { var config = Plugin.Instance.Configuration; if (config.LicenseValid || config.MonthlyProcessingLimit == 0) { return "Full version - unlimited processing"; } ResetMonthlyCounterIfNeeded(); var remaining = Math.Max(0, config.MonthlyProcessingLimit - config.ProcessedThisMonth); return $"Free tier: {remaining} items remaining this month (of {config.MonthlyProcessingLimit} allowed)"; } } }