Small joys: Quote of the Day + Word of the Day engines

- quote.py: curated public-domain quote pool (16 seeded, admin-grows), deterministic daily
  pick, lazy AI "what it means" explainer of the real quote (cached). No LLM-invented quotes.
- wotd.py: LLM proposes positive words → validated/enriched against dictionaryapi.dev (real
  definition, IPA, examples, audio) → audio clip cached to our origin (TTS fallback) →
  deterministic daily pick. Tops the pool up toward 30/day.
- db.py: quote_pool/daily_quote + wotd_pool/daily_wotd tables.
- api.py: /api/quote/today, /api/word/today, /api/word/audio/{word} (GET+HEAD).
- cli.py: cycle steps for both (under --no-joys), shared LLM client.
- tests: test_quote.py (6) + test_wotd.py (5). 393 backend tests green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
jay
2026-06-22 17:28:55 -04:00
parent a7da8362ab
commit 67d4bc32cb
7 changed files with 550 additions and 4 deletions
+49
View File
@@ -304,6 +304,55 @@ CREATE TABLE IF NOT EXISTS daily_onthisday (
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
);
-- Quote of the Day: curated public-domain quotes; one picked per day. `meaning` is an
-- AI explainer of the (real) quote, filled lazily the first time it's shown.
CREATE TABLE IF NOT EXISTS quote_pool (
id INTEGER PRIMARY KEY AUTOINCREMENT,
source TEXT NOT NULL DEFAULT 'curated',
ckey TEXT NOT NULL UNIQUE,
text TEXT NOT NULL,
author TEXT,
work TEXT,
year TEXT,
meaning TEXT,
shown_at TEXT,
blocked INTEGER NOT NULL DEFAULT 0,
featured INTEGER NOT NULL DEFAULT 0,
added_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS daily_quote (
feature_date TEXT PRIMARY KEY,
pool_id INTEGER NOT NULL,
source TEXT NOT NULL DEFAULT 'curated',
text TEXT, author TEXT, work TEXT, year TEXT, meaning TEXT,
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
);
-- Word of the Day: LLM-proposed positive words, validated/enriched against a real
-- dictionary (definition, IPA, examples, cached audio clip); one picked per day.
CREATE TABLE IF NOT EXISTS wotd_pool (
id INTEGER PRIMARY KEY AUTOINCREMENT,
source TEXT NOT NULL DEFAULT 'llm',
word TEXT NOT NULL UNIQUE,
part_of_speech TEXT,
phonetic TEXT, -- IPA
audio_file TEXT, -- our cached pronunciation clip (or null → browser TTS)
audio_url TEXT, -- source clip URL
definition TEXT NOT NULL,
examples TEXT, -- JSON array of example sentences
shown_at TEXT,
blocked INTEGER NOT NULL DEFAULT 0,
featured INTEGER NOT NULL DEFAULT 0,
added_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS daily_wotd (
feature_date TEXT PRIMARY KEY,
pool_id INTEGER NOT NULL,
word TEXT, part_of_speech TEXT, phonetic TEXT, audio_file TEXT,
definition TEXT, examples TEXT,
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
);
-- Privacy-respecting, first-party analytics. NO IP / user-agent / referrer / raw
-- URL. visitor_hash is a hash of a random localStorage token (never email/IP).
-- The UNIQUE key dedups to one row per (kind, article, visitor, day) — that both