kink-discovery / scripts /prune_noise.py
Perplexed7675's picture
Sync from kink_cli (Docker Space)
6ff91d6 verified
Raw
History Blame Contribute Delete
3.55 kB
#!/usr/bin/env python3
"""Remove zero-popularity noise kinks that have no edges, no preferences, and unclean names."""
from __future__ import annotations
import re
import sqlite3
import sys
from pathlib import Path
DB_PATH = Path(__file__).resolve().parent.parent / "data" / "store.db"
MAX_NAME_WORDS = 6
MAX_NAME_CHARS = 50
PUNCT_REGEX = re.compile(r"[^\w\s/&-]", re.UNICODE)
def name_is_clean(name: str) -> bool:
stripped = name.strip()
if not stripped:
return False
word_count = len(stripped.split())
if word_count > MAX_NAME_WORDS or len(stripped) > MAX_NAME_CHARS:
return False
if PUNCT_REGEX.search(stripped):
return False
if any(char.isdigit() for char in stripped):
return False
return True
def main():
if not DB_PATH.exists():
print(f"Database not found: {DB_PATH}")
sys.exit(1)
conn = sqlite3.connect(DB_PATH, timeout=30)
conn.row_factory = sqlite3.Row
conn.execute("PRAGMA journal_mode=WAL")
conn.execute("PRAGMA busy_timeout=30000")
conn.execute("PRAGMA foreign_keys=ON")
before = conn.execute("SELECT COUNT(*) AS n FROM kink").fetchone()["n"]
print(f"Kinks before: {before}")
zero_pop = conn.execute("""
SELECT k.id, k.name FROM kink k
LEFT JOIN fetlifekinkmeta m ON k.id = m.kink_id
WHERE COALESCE(m.popularity, 0) = 0
AND k.id NOT IN (SELECT DISTINCT left_kink_id FROM similarityedge)
AND k.id NOT IN (SELECT DISTINCT right_kink_id FROM similarityedge)
AND k.id NOT IN (SELECT DISTINCT kink_id FROM playpreference)
""").fetchall()
ids_to_delete = []
for row in zero_pop:
if not name_is_clean(row["name"]):
ids_to_delete.append(row["id"])
print(f"Zero-pop candidates: {len(zero_pop)}")
print(f"Failing name_is_clean: {len(ids_to_delete)}")
if not ids_to_delete:
print("Nothing to prune.")
conn.close()
return
batch_size = 500
for i in range(0, len(ids_to_delete), batch_size):
batch = ids_to_delete[i : i + batch_size]
placeholders = ",".join("?" * len(batch))
conn.execute(f"DELETE FROM alias WHERE kink_id IN ({placeholders})", batch)
conn.execute(f"DELETE FROM definition WHERE kink_id IN ({placeholders})", batch)
conn.execute(f"DELETE FROM kinkexample WHERE kink_id IN ({placeholders})", batch)
conn.execute(f"DELETE FROM asset WHERE kink_id IN ({placeholders})", batch)
conn.execute(f"DELETE FROM kinkfacet WHERE kink_id IN ({placeholders})", batch)
conn.execute(f"DELETE FROM kinkcontenttype WHERE kink_id IN ({placeholders})", batch)
conn.execute(f"DELETE FROM fetlifepictureref WHERE kink_id IN ({placeholders})", batch)
conn.execute(f"DELETE FROM fetlifekinkmeta WHERE kink_id IN ({placeholders})", batch)
conn.execute(f"DELETE FROM kink WHERE id IN ({placeholders})", batch)
if (i + batch_size) % 5000 == 0:
conn.commit()
print(f" deleted {min(i + batch_size, len(ids_to_delete))} / {len(ids_to_delete)}")
conn.commit()
after = conn.execute("SELECT COUNT(*) AS n FROM kink").fetchone()["n"]
print(f"Kinks after: {after} (removed {before - after})")
print("Rebuilding FTS index...")
conn.execute("DELETE FROM play_fts")
conn.commit()
print("FTS cleared (will rebuild on next catalog load).")
conn.execute("PRAGMA wal_checkpoint(TRUNCATE)")
conn.close()
print("Done.")
if __name__ == "__main__":
main()