Adventure news: fix posting gates, digest counts, and section gating

- Don't post adventure beats when posting.enabled=false (PostNow ignores the flag)
- Keep the adventure channel out of the round-robin rotation so it can't steal bulletins from the digest
- no_push now retires a fact against the digest, not just the live post
- Default a missing occurred_at to now instead of the Unix epoch
- Keep protocol-relative image URLs on the guarded thumbnailer
- Make digest_hour=0 (midnight UTC) settable
- Quote the true window total in the digest, not the truncated slice
- Hide the Adventure section entirely when it's disabled
This commit is contained in:
prosolis
2026-07-11 08:07:40 -07:00
parent 9bf56cbb4e
commit 8e0d6aff3e
8 changed files with 137 additions and 63 deletions

View File

@@ -256,29 +256,37 @@ func GetNewestPostableStoryByChannel(channel string) (*Story, error) {
// that have never been posted to Matrix (no post_log row). PRIORITY beats post
// live and so carry a post_log row; the ones left are exactly the BULLETINs the
// daily digest collects. Oldest first so the digest reads chronologically.
func UnpostedAdventureSince(since int64, limit int) ([]Story, error) {
rows, err := Get().Query(
`SELECT guid, headline, lede, article_url, seen_at
FROM stories
WHERE classified = 1
//
// At most `limit` rows come back, but total is how many match in all — the digest
// quotes it to readers, so it must count the window rather than the returned page.
func UnpostedAdventureSince(since int64, limit int) (stories []Story, total int, err error) {
const where = `WHERE classified = 1
AND channel = 'adventure'
AND seen_at >= ?
AND guid NOT IN (SELECT guid FROM post_log)
AND guid NOT IN (SELECT guid FROM post_log)`
if err := Get().QueryRow(`SELECT COUNT(*) FROM stories `+where, since).Scan(&total); err != nil {
return nil, 0, err
}
rows, err := Get().Query(
`SELECT guid, headline, lede, article_url, seen_at
FROM stories `+where+`
ORDER BY seen_at ASC
LIMIT ?`, since, limit)
if err != nil {
return nil, err
return nil, 0, err
}
defer rows.Close()
var out []Story
for rows.Next() {
var s Story
if err := rows.Scan(&s.GUID, &s.Headline, &s.Lede, &s.ArticleURL, &s.SeenAt); err != nil {
return nil, err
return nil, 0, err
}
out = append(out, s)
}
return out, rows.Err()
return out, total, rows.Err()
}
// MarkAdventureDigested records each bulletin guid as posted (in a shared digest