mirror of
https://github.com/PR0M3TH3AN/unredact.git
synced 2026-11-05 21:20:30 +00:00
feat: add separate V (victim) badge independent of associate tiers
Victim names are stored as a flat set of lowercased name variants with no person details — the V badge appears but is not clickable, protecting victim identities. A result can show both T1/T2/T3 and V badges simultaneously. - 15 known victims from public court records → 43 name variants - Enabler/perpetrator categories promoted to T2 - Purple V badge with pointer-events disabled - Victim matching uses prefix/suffix combination like associate matching Co-Authored-By: Claude Opus 4.6 <[email protected]>
This commit is contained in:
1 parent
d0e6a7c47a
commit
2268e8549e
5 files changed
+109
-6
No files matched your search
@@ -62,6 +62,23 @@ NICKNAMES = {
|
||||
# Tier 2 categories (staff/financial get auto-promoted)
|
||||
TIER2_CATEGORIES = {"staff", "financial"}
|
||||
|
||||
# Known victims from public court records and reporting (Giuffre v. Maxwell, etc.)
|
||||
# Stored as a separate name set — no person details exposed in the UI.
|
||||
KNOWN_VICTIMS = {
|
||||
"Virginia Giuffre", "VIRGINIA ROBERTS", "Virginia Roberts",
|
||||
"Courtney Wild",
|
||||
"Sarah Ransome",
|
||||
"Maria Farmer", "Annie Farmer",
|
||||
"Chauntae Davies",
|
||||
"Johanna Sjoberg",
|
||||
"Michelle Licata",
|
||||
"Carolyn Andriano",
|
||||
"Priscilla Doe",
|
||||
"Teresa Helm",
|
||||
"Anouska De Georgiou",
|
||||
"Haley Robson",
|
||||
}
|
||||
|
||||
|
||||
def _compute_tiers(registry: list[dict], relationships: list[dict]) -> dict[str, int]:
|
||||
"""Compute tier for each person name.
|
||||
@@ -91,7 +108,7 @@ def _compute_tiers(registry: list[dict], relationships: list[dict]) -> dict[str,
|
||||
|
||||
if name in traveled:
|
||||
tiers[name] = 1
|
||||
elif category in TIER2_CATEGORIES or rel_counts.get(name, 0) >= 3:
|
||||
elif category in TIER2_CATEGORIES or category in {"enabler", "perpetrator"} or rel_counts.get(name, 0) >= 3:
|
||||
tiers[name] = 2
|
||||
else:
|
||||
tiers[name] = 3
|
||||
@@ -154,13 +171,42 @@ def _generate_lookups_for_name(
|
||||
_add_name_entries(names, f"{nick} {last}", person_id, tier, "nickname_full")
|
||||
|
||||
|
||||
def _build_victim_names() -> set[str]:
|
||||
"""Build a flat set of lowercased victim name variants for matching.
|
||||
|
||||
No person details — just strings to check against. This keeps victim
|
||||
identities private in the UI (the V badge shows but is not clickable).
|
||||
"""
|
||||
victim_names: set[str] = set()
|
||||
|
||||
for full_name in KNOWN_VICTIMS:
|
||||
low = full_name.lower().strip()
|
||||
if len(low) < 2:
|
||||
continue
|
||||
victim_names.add(low)
|
||||
|
||||
parts = low.split()
|
||||
if len(parts) >= 2:
|
||||
first, last = parts[0], parts[-1]
|
||||
victim_names.add(first)
|
||||
victim_names.add(last)
|
||||
|
||||
# Nicknames
|
||||
if first in NICKNAMES:
|
||||
for nick in NICKNAMES[first]:
|
||||
victim_names.add(nick)
|
||||
victim_names.add(f"{nick} {last}")
|
||||
|
||||
return victim_names
|
||||
|
||||
|
||||
def process_associates(
|
||||
registry: list[dict],
|
||||
relationships: list[dict],
|
||||
) -> dict:
|
||||
"""Process raw registry + relationships into the associates lookup format.
|
||||
|
||||
Returns: {"names": {str: [...]}, "persons": {str: {...}}}
|
||||
Returns: {"names": {str: [...]}, "persons": {str: {...}}, "victim_names": [str, ...]}
|
||||
"""
|
||||
tiers = _compute_tiers(registry, relationships)
|
||||
|
||||
@@ -193,7 +239,9 @@ def process_associates(
|
||||
for alias in person.get("aliases", []):
|
||||
_generate_lookups_for_name(names, alias, person_id, tier)
|
||||
|
||||
return {"names": names, "persons": persons}
|
||||
victim_names = sorted(_build_victim_names())
|
||||
|
||||
return {"names": names, "persons": persons, "victim_names": victim_names}
|
||||
|
||||
|
||||
def download_data(data_dir: Path) -> tuple[list, list]:
|
||||
|
||||
Reference in new issue
Block a user