Files

2.3 KiB

Family Waters Bonus + Join League Fix (Jul 9, 2026)

Changes

1. Join League 500 Error Fix

Root cause: sqlite3.Row has no .get() method. The join_league endpoint at line 584 called league.get("max_players") on a sqlite3.Row object.

Fix: Added league = dict(league) after fetchone() but before accessing values.

# Before:
league = conn.execute("SELECT * FROM leagues WHERE invite_code = ?", (code,)).fetchone()
if league["status"] != "draft":  # works because bracket access IS supported on sqlite3.Row
    ...
max_p = league.get("max_players") or 6  # AttributeError - sqlite3.Row has no .get()

# After:
league = conn.execute("SELECT * FROM leagues WHERE invite_code = ?", (code,)).fetchone()
if not league:
    raise HTTPException(404, "Invalid invite code")
league = dict(league)  # <--- THE FIX
if league["status"] != "draft":
    ...
max_p = league.get("max_players", 6)  # now works, and uses the default arg properly

Lesson: Compare with get_league_or_404() helper that already does dict(league). The join endpoint was the only place that skipped this conversion.

2. Family Waters +30 Bonus

New feature: Score events can be marked personal (is_personal: true) to earn +30 bonus points.

API change:

POST /api/scores/events
{
    "region_id": 1,
    "event_type": "bite",
    "is_personal": true      ← new
}
→ { "points": 35, "family_waters_bonus": 30, "is_personal": true, ... }

Leaderboard change:

{
    "user_id": 34,
    "display_name": "HostUser",
    "total_points": 52,
    "family_waters_bonus": 60,
    "family_waters_count": 2,
    "regions": [...]
}

Push notification format change:

"+5 pts + 30 Family Waters — 🏖️ Florida East Coast"
(vs normal: "+5 pts — 🏖️ Florida East Coast")

Migration SQL (run in on_startup):

conn.execute("ALTER TABLE scores ADD COLUMN is_personal INTEGER DEFAULT 0")
conn.execute("ALTER TABLE users ADD COLUMN family_waters_bonus INTEGER DEFAULT 0")
conn.execute("ALTER TABLE users ADD COLUMN family_waters_count INTEGER DEFAULT 0")

Key files changed: server.py only — CreateScoreEvent model, create_score_event endpoint, recalculate_user_scores helper, leaderboard query, push notification body builder.