Ship name corpus lookup/spin, nickname suggestions, significance UX, site-ideas SMTP, and remove the Logo concepts page and assets.
109 lines
4.5 KiB
Python
109 lines
4.5 KiB
Python
#!/usr/bin/env python3
|
|
"""Backfill empty locale fields + optional nicknames from name_meta.
|
|
|
|
Usage (on stork host / in container):
|
|
python scripts/backfill_name_meta.py --board b_UDKbqtB8cXw
|
|
python scripts/backfill_name_meta.py --board b_UDKbqtB8cXw --dry-run
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import os
|
|
import sqlite3
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
sys.path.insert(0, str(ROOT))
|
|
|
|
from stork.name_meta import lookup_name_meta # noqa: E402
|
|
from stork.nicknames import nicknames_for_new_name # noqa: E402
|
|
|
|
|
|
def main() -> int:
|
|
ap = argparse.ArgumentParser()
|
|
ap.add_argument("--board", required=True)
|
|
ap.add_argument("--db", default=os.environ.get("STORK_DATA", "/data") + "/stork.sqlite3")
|
|
ap.add_argument("--dry-run", action="store_true")
|
|
ap.add_argument("--force-empty-only", action="store_true", default=True)
|
|
args = ap.parse_args()
|
|
db = Path(args.db)
|
|
if not db.is_file():
|
|
print(f"missing db {db}", file=sys.stderr)
|
|
return 1
|
|
con = sqlite3.connect(db)
|
|
con.row_factory = sqlite3.Row
|
|
names = con.execute(
|
|
"SELECT id, spelling, nicknames FROM names WHERE board_id = ? ORDER BY id",
|
|
(args.board,),
|
|
).fetchall()
|
|
changed = 0
|
|
for n in names:
|
|
meta = lookup_name_meta(n["spelling"])
|
|
locs = con.execute(
|
|
"SELECT lang, pronunciation, origin, meaning FROM locales WHERE name_id = ?",
|
|
(n["id"],),
|
|
).fetchall()
|
|
by_lang = {r["lang"]: dict(r) for r in locs}
|
|
for lang in ("en", "ru", "he"):
|
|
cur = by_lang.get(lang) or {"pronunciation": "", "origin": "", "meaning": ""}
|
|
hint = meta["locales"].get(lang) or {}
|
|
new_p = (cur["pronunciation"] or "").strip() or (hint.get("pronunciation") or "").strip()
|
|
new_o = (cur["origin"] or "").strip() or (hint.get("origin") or "").strip()
|
|
new_m = (cur["meaning"] or "").strip() or (hint.get("meaning") or "").strip()
|
|
if (new_p, new_o, new_m) == (
|
|
(cur["pronunciation"] or "").strip(),
|
|
(cur["origin"] or "").strip(),
|
|
(cur["meaning"] or "").strip(),
|
|
):
|
|
continue
|
|
print(f" {n['spelling']} [{lang}]: fill origin/meaning/pron")
|
|
changed += 1
|
|
if not args.dry_run:
|
|
con.execute(
|
|
"""
|
|
INSERT INTO locales (name_id, lang, pronunciation, origin, meaning)
|
|
VALUES (?, ?, ?, ?, ?)
|
|
ON CONFLICT(name_id, lang) DO UPDATE SET
|
|
pronunciation = excluded.pronunciation,
|
|
origin = excluded.origin,
|
|
meaning = excluded.meaning
|
|
""",
|
|
(n["id"], lang, new_p[:200], new_o[:200], new_m[:500]),
|
|
)
|
|
# nicknames if empty
|
|
if not (n["nicknames"] or "").strip():
|
|
filled = nicknames_for_new_name(n["spelling"], "")
|
|
# For slash spellings try first token
|
|
if not filled and "/" in n["spelling"]:
|
|
filled = nicknames_for_new_name(n["spelling"].split("/")[0].strip(), "")
|
|
if filled:
|
|
print(f" {n['spelling']}: nicknames -> {filled}")
|
|
changed += 1
|
|
if not args.dry_run:
|
|
con.execute("UPDATE names SET nicknames = ? WHERE id = ?", (filled, n["id"]))
|
|
# strip nickname equal to full spelling when present
|
|
elif n["spelling"].casefold() in {
|
|
x.strip().casefold() for x in (n["nicknames"] or "").replace(";", ",").split(",")
|
|
}:
|
|
from stork.nicknames import nicknames_excluding_spelling
|
|
|
|
cleaned = nicknames_excluding_spelling(n["spelling"], n["nicknames"])
|
|
# also try primary token for Rivka-style
|
|
primary = n["spelling"].split("/")[0].strip()
|
|
cleaned = nicknames_excluding_spelling(primary, cleaned or n["nicknames"])
|
|
if cleaned != (n["nicknames"] or "").strip():
|
|
print(f" {n['spelling']}: nicknames clean {n['nicknames']!r} -> {cleaned!r}")
|
|
changed += 1
|
|
if not args.dry_run:
|
|
con.execute("UPDATE names SET nicknames = ? WHERE id = ?", (cleaned, n["id"]))
|
|
if not args.dry_run:
|
|
con.commit()
|
|
print(f"{'dry-run ' if args.dry_run else ''}updates touching {changed} fields/rows")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|