diff --git a/CHANGELOG.md b/CHANGELOG.md index f12c281..0fae182 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,10 +23,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 map, and left alone. - Audience tagging. Applies a configurable tag (default `grandma`) to titles - that pass a genre and rating rule, so a user account can be narrowed with - Allowed Tags. Because Allowed Tags fails closed, new content is invisible to - that account until tagged, which is why this runs on a schedule rather than - once. + that clear a genre rule, a rating ceiling and a community-rating floor, so a + user account can be narrowed with Allowed Tags. The floor applies to rated and + unrated titles alike, through separate settings, because a ceiling on its own + admits poorly reviewed titles that happen to carry a mild rating, and the + point of the tag is to make an overwhelming library smaller rather than to + reproduce it. Unrated titles are judged on reputation alone, which is what + keeps the older classics TMDB holds no US certification for. Because Allowed + Tags fails closed, new content is invisible to that account until tagged, + which is why this runs on a schedule rather than once. - A curation ledger at `tagged-ids.txt` in the plugin data folder. An item whose id is in the ledger but which no longer carries the tag was untagged by a diff --git a/Jellyfin.Plugin.Audience/AudienceRules.cs b/Jellyfin.Plugin.Audience/AudienceRules.cs index 4027860..3a5df85 100644 --- a/Jellyfin.Plugin.Audience/AudienceRules.cs +++ b/Jellyfin.Plugin.Audience/AudienceRules.cs @@ -130,15 +130,22 @@ public static class AudienceRules return false; } - // A usable rating is judged on the rating. Anything at or below the ceiling is in. + // A usable rating must clear the ceiling AND the quality floor. The floor matters + // as much as the ceiling: the point of this tag is to make an overwhelming library + // smaller, and a poorly reviewed film that happens to be rated PG adds noise rather + // than removing it. An item with no community rating at all fails here, which is + // deliberate - without a rating and without a score there is nothing to judge on. if (ratingScore.HasValue) { - return ratingScore.Value <= config.MaxRatingScore; + return ratingScore.Value <= config.MaxRatingScore + && item.CommunityRating.HasValue + && item.CommunityRating.Value >= config.MinCommunityRating; } - // No usable rating: fall back to reputation. This is what keeps the older - // classics, which are exactly what this audience wants and which TMDB - // frequently has no US certification for. + // No usable rating: fall back to reputation alone, against its own floor. This is + // what keeps the older classics, which are exactly what this audience wants and + // which TMDB frequently has no US certification for. The floor is separate because + // an unrated item is carrying more risk, so it may warrant a higher bar. return item.CommunityRating.HasValue && item.CommunityRating.Value >= config.MinCommunityRatingWhenUnrated; } diff --git a/Jellyfin.Plugin.Audience/Configuration/PluginConfiguration.cs b/Jellyfin.Plugin.Audience/Configuration/PluginConfiguration.cs index 3e0011f..75143a6 100644 --- a/Jellyfin.Plugin.Audience/Configuration/PluginConfiguration.cs +++ b/Jellyfin.Plugin.Audience/Configuration/PluginConfiguration.cs @@ -51,6 +51,15 @@ public class PluginConfiguration : BasePluginConfiguration /// public int MaxRatingScore { get; set; } = 14; + /// + /// Gets or sets the community rating an item must reach to be tagged when it DOES have a + /// usable official rating. The ceiling alone is not enough: this tag exists to make an + /// overwhelming library smaller, and a poorly reviewed film that happens to be rated PG + /// adds noise rather than removing it. An item carrying no community rating at all fails + /// this check, which is deliberate. + /// + public double MinCommunityRating { get; set; } = 6.0; + /// /// Gets or sets the minimum community rating for an item with no usable parental rating. /// diff --git a/Jellyfin.Plugin.Audience/Configuration/configPage.html b/Jellyfin.Plugin.Audience/Configuration/configPage.html index 52d4b04..f8493c1 100644 --- a/Jellyfin.Plugin.Audience/Configuration/configPage.html +++ b/Jellyfin.Plugin.Audience/Configuration/configPage.html @@ -84,6 +84,17 @@ +
+ + +
+ A rated item must clear this as well as the ceiling. The point of the tag + is to make an overwhelming library smaller, and a poorly reviewed film + that happens to be rated PG adds noise rather than removing it. An item + with no community rating at all fails this check. +
+
+
@@ -129,6 +140,7 @@ document.querySelector('#ApplyTags').checked = config.ApplyTags; document.querySelector('#TagName').value = config.TagName; document.querySelector('#MaxRatingScore').value = config.MaxRatingScore; + document.querySelector('#MinCommunityRating').value = config.MinCommunityRating; document.querySelector('#MinCommunityRatingWhenUnrated').value = config.MinCommunityRatingWhenUnrated; document.querySelector('#RespectManualUntag').checked = config.RespectManualUntag; Dashboard.hideLoadingMsg(); @@ -145,6 +157,7 @@ config.ApplyTags = document.querySelector('#ApplyTags').checked; config.TagName = document.querySelector('#TagName').value; config.MaxRatingScore = parseInt(document.querySelector('#MaxRatingScore').value, 10); + config.MinCommunityRating = parseFloat(document.querySelector('#MinCommunityRating').value); config.MinCommunityRatingWhenUnrated = parseFloat(document.querySelector('#MinCommunityRatingWhenUnrated').value); config.RespectManualUntag = document.querySelector('#RespectManualUntag').checked;