Crisp hero (prefer og:image), 7-card Highlights, no-recycle Replace + session History
- Hero blur fix: brief enrichment now prefers a page's og:image even when a feed thumbnail exists (feed thumbs are often tiny; the hero is shown large). Verified: BBC hero upgrades to the 1024px share image, ScienceDaily to 1920px. - Today is now 'Highlights from Today' — hero + 6 (brief size 7), which also makes the secondary grid a balanced 3+3 instead of an orphaned 3+1. - Replace now excludes every article seen this session (a client-side seen-set), so it never cycles back to something already shown. - New session History panel (this tab only, no account): lists everything seen, including swapped-away stories, so they stay recoverable. Persistent history/favorites are tabled for sign-in later. Tests: og:image upgrade of an existing feed image (86 total). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+2
-2
@@ -9,7 +9,7 @@ from .paywall import is_paywalled
|
||||
def build_daily_brief(
|
||||
conn: sqlite3.Connection,
|
||||
brief_date: str | None = None,
|
||||
limit: int = 5,
|
||||
limit: int = 7,
|
||||
replace: bool = False,
|
||||
window_days: int = 3,
|
||||
) -> int:
|
||||
@@ -22,7 +22,7 @@ def build_daily_brief(
|
||||
|
||||
brief_id = conn.execute(
|
||||
"INSERT INTO daily_briefs (brief_date, title) VALUES (?, ?)",
|
||||
(target_date, f"Five Good Things Today - {target_date}"),
|
||||
(target_date, f"Highlights from Today - {target_date}"),
|
||||
).lastrowid
|
||||
|
||||
rows = _candidate_articles(conn, target_date, window_days)
|
||||
|
||||
+3
-3
@@ -139,7 +139,7 @@ def main() -> None:
|
||||
|
||||
brief_parser = subparsers.add_parser("build-brief", help="Build/freeze a daily brief")
|
||||
brief_parser.add_argument("--date", help="Brief date in YYYY-MM-DD format; defaults to today")
|
||||
brief_parser.add_argument("--limit", type=int, default=5)
|
||||
brief_parser.add_argument("--limit", type=int, default=7)
|
||||
brief_parser.add_argument("--replace", action="store_true")
|
||||
|
||||
show_brief_parser = subparsers.add_parser("show-brief", help="Show a stored daily brief")
|
||||
@@ -446,7 +446,7 @@ def _run_cycle_locked(conn: sqlite3.Connection, args: argparse.Namespace) -> Non
|
||||
if not args.no_brief:
|
||||
today = date.today().isoformat()
|
||||
try:
|
||||
brief_id = build_daily_brief(conn, brief_date=today, limit=5, replace=True)
|
||||
brief_id = build_daily_brief(conn, brief_date=today, limit=7, replace=True)
|
||||
found = enrich_brief_images(conn, today)
|
||||
print(f"brief: rebuilt {today} (id {brief_id}); {found} hero image(s) enriched")
|
||||
except Exception as exc:
|
||||
@@ -672,7 +672,7 @@ def print_brief(rows: list[sqlite3.Row]) -> None:
|
||||
print("No brief items found.")
|
||||
return
|
||||
date = rows[0]["brief_date"]
|
||||
print(f"Five Good Things Today - {date}")
|
||||
print(f"Highlights from Today - {date}")
|
||||
for row in rows:
|
||||
print(f"{row['rank']}. {row['title']}")
|
||||
print(f" {row['source_name']} | {row['default_category']} | {row['model_name']}")
|
||||
|
||||
+4
-1
@@ -127,13 +127,16 @@ def enrich_brief_images(conn: sqlite3.Connection, brief_date: str, fetch=fetch_o
|
||||
stamps image_checked_at either way so failures are not retried forever.
|
||||
Returns how many images were newly found.
|
||||
"""
|
||||
# Brief items not yet checked. We fetch even when a feed image exists,
|
||||
# because feed thumbnails are often tiny and the hero is shown large — a
|
||||
# page's og:image (the social-share image) is the better hero visual.
|
||||
rows = conn.execute(
|
||||
"""
|
||||
SELECT a.id, a.canonical_url
|
||||
FROM daily_briefs b
|
||||
JOIN daily_brief_items bi ON bi.brief_id = b.id
|
||||
JOIN articles a ON a.id = bi.article_id
|
||||
WHERE b.brief_date = ? AND a.image_url IS NULL AND a.image_checked_at IS NULL
|
||||
WHERE b.brief_date = ? AND a.image_checked_at IS NULL
|
||||
ORDER BY bi.rank
|
||||
LIMIT ?
|
||||
""",
|
||||
|
||||
Reference in New Issue
Block a user