using System; using System.Collections.Generic; using Jellyfin.Plugin.JRay.Models; namespace Jellyfin.Plugin.JRay.Services; /// /// Resolves the effective prioritise/ignore action for an item from the /// configured rules. More specific scopes win: an Item rule overrides a /// Series rule, which overrides a Genre rule. Because a given scope+value can /// hold only one action, the only conflicts possible are across scopes, and /// specificity resolves those. /// public static class PolicyResolver { /// /// Computes the effective action for an item, or null if no rule matches. /// /// The configured rules. /// The item's id. /// The item's series id, or if it is not an episode. /// The item's genres. /// The effective , or null when unruled. public static PolicyAction? Resolve( IReadOnlyList rules, Guid itemId, Guid seriesId, IReadOnlyList genres) { ArgumentNullException.ThrowIfNull(rules); PolicyAction? itemAction = null; PolicyAction? seriesAction = null; PolicyAction? genreAction = null; var itemIdStr = itemId.ToString("D"); var seriesIdStr = seriesId == Guid.Empty ? null : seriesId.ToString("D"); foreach (var rule in rules) { switch (rule.Scope) { case PolicyScope.Item: if (string.Equals(rule.Value, itemIdStr, StringComparison.OrdinalIgnoreCase)) { itemAction = rule.Action; } break; case PolicyScope.Series: if (seriesIdStr is not null && string.Equals(rule.Value, seriesIdStr, StringComparison.OrdinalIgnoreCase)) { seriesAction = rule.Action; } break; case PolicyScope.Genre: if (genres is not null && MatchesGenre(genres, rule.Value)) { genreAction = rule.Action; } break; } } return itemAction ?? seriesAction ?? genreAction; } private static bool MatchesGenre(IReadOnlyList genres, string value) { for (var i = 0; i < genres.Count; i++) { if (string.Equals(genres[i], value, StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } }