mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-26 23:48:52 -03:00
Add new setting 'mature_blur_level' with options PG13/R/X/XXX to control which NSFW rating level triggers blur filtering when NSFW blur is enabled. - Backend: update preview selection logic to respect threshold - Frontend: update UI components to use configurable threshold - Settings: add validation and normalization for mature_blur_level - Tests: add coverage for new threshold behavior - Translations: add keys for all supported languages Fixes #867
86 lines
2.6 KiB
Python
86 lines
2.6 KiB
Python
"""Utilities for selecting preview media from Civitai image metadata."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any, Mapping, Optional, Sequence, Tuple
|
|
|
|
from .constants import NSFW_LEVELS
|
|
|
|
PreviewMedia = Mapping[str, object]
|
|
VALID_MATURE_BLUR_LEVELS = ("PG13", "R", "X", "XXX")
|
|
|
|
|
|
def _extract_nsfw_level(entry: Mapping[str, object]) -> int:
|
|
"""Return a normalized NSFW level value for the supplied media entry."""
|
|
|
|
value = entry.get("nsfwLevel", 0)
|
|
try:
|
|
return int(value) # type: ignore[return-value]
|
|
except (TypeError, ValueError):
|
|
return 0
|
|
|
|
|
|
def resolve_mature_threshold(settings: Mapping[str, Any] | None) -> int:
|
|
"""Resolve the configured mature blur threshold from settings.
|
|
|
|
Allowed values are ``PG13``, ``R``, ``X``, and ``XXX``. Any invalid or
|
|
missing value falls back to ``R``.
|
|
"""
|
|
|
|
if not isinstance(settings, Mapping):
|
|
return NSFW_LEVELS.get("R", 4)
|
|
|
|
raw_level = settings.get("mature_blur_level", "R")
|
|
normalized = str(raw_level).strip().upper()
|
|
if normalized not in VALID_MATURE_BLUR_LEVELS:
|
|
normalized = "R"
|
|
return NSFW_LEVELS.get(normalized, NSFW_LEVELS.get("R", 4))
|
|
|
|
|
|
def select_preview_media(
|
|
images: Sequence[Mapping[str, object]] | None,
|
|
*,
|
|
blur_mature_content: bool,
|
|
mature_threshold: int | None = None,
|
|
) -> Tuple[Optional[PreviewMedia], int]:
|
|
"""Select the most appropriate preview media entry.
|
|
|
|
When ``blur_mature_content`` is enabled we first try to return the first media
|
|
item with an ``nsfwLevel`` lower than the configured mature threshold
|
|
(defaults to :pydata:`NSFW_LEVELS["R"]`). If none are available we return
|
|
the media entry with the lowest NSFW level. When the setting is disabled we
|
|
simply return the first entry.
|
|
"""
|
|
|
|
if not images:
|
|
return None, 0
|
|
|
|
candidates = [item for item in images if isinstance(item, Mapping)]
|
|
if not candidates:
|
|
return None, 0
|
|
|
|
selected = candidates[0]
|
|
selected_level = _extract_nsfw_level(selected)
|
|
|
|
if not blur_mature_content:
|
|
return selected, selected_level
|
|
|
|
safe_threshold = (
|
|
mature_threshold if isinstance(mature_threshold, int) else NSFW_LEVELS.get("R", 4)
|
|
)
|
|
for candidate in candidates:
|
|
level = _extract_nsfw_level(candidate)
|
|
if level < safe_threshold:
|
|
return candidate, level
|
|
|
|
for candidate in candidates[1:]:
|
|
level = _extract_nsfw_level(candidate)
|
|
if level < selected_level:
|
|
selected = candidate
|
|
selected_level = level
|
|
|
|
return selected, selected_level
|
|
|
|
|
|
__all__ = ["resolve_mature_threshold", "select_preview_media", "VALID_MATURE_BLUR_LEVELS"]
|