Skip to content

feat: notifications & cookie-health monitoring#40

Open
bin101 wants to merge 4 commits into
mainfrom
feat/notifications
Open

feat: notifications & cookie-health monitoring#40
bin101 wants to merge 4 commits into
mainfrom
feat/notifications

Conversation

@bin101

@bin101 bin101 commented Jul 1, 2026

Copy link
Copy Markdown
Owner

Summary

  • notify.py β€” new pure/testable module: send_notification(url, payload, *, post_fn) with an injected HTTP POST function (no network in tests), plus build_run_payload and build_auth_error_payload helpers. Supports ntfy, Telegram bots, or any generic HTTP endpoint.
  • AppSettings extended with notifyWebhookUrl (validated http/https URL or empty), notifyOnRun (default False), notifyOnAuthError (default True)
  • RunStatus extended with authOk: bool | None β€” None = no run yet, True = last run succeeded auth, False = last run hit AuthError
  • _run_job in app.py now sets _app_state["auth_ok"], catches AuthError (cookie expired) so the scheduler stays alive, and fires webhook notifications after run-complete or auth-failure events
  • Auth warning banner β€” shown across all tabs when authOk === false; dismissed automatically on the next successful run
  • Settings tab β€” new Notifications card with webhook URL input + two toggle switches

Test plan

  • ruff check src tests β€” zero errors
  • ruff format --check src tests β€” zero issues
  • mypy src β€” zero type errors
  • pytest --cov=kudosy β€” 400 tests pass, 86% coverage
  • Set notifyWebhookUrl to a local ntfy instance and trigger a dry-run β†’ notification arrives
  • Set an invalid cookie and trigger a run β†’ authOk becomes false, warning banner appears, auth-error webhook fires
  • Fix the cookie β†’ banner disappears after next poll
  • Leave notifyWebhookUrl empty β†’ no notifications sent (noop)
  • AppSettings(notifyWebhookUrl="not-a-url") raises ValidationError

πŸ€– Generated with Claude Code

bin101 and others added 4 commits July 1, 2026 17:43
The 1450-line app.js is replaced by 12 focused ES modules:
state.js, dom.js, api.js, format.js, schedule-matrix.js,
athletes.js, config.js, settings.js, feed.js, status.js,
tabs.js, main.js.

The importmap in routes.py::serve_index now covers all local
modules so every module is cache-busted on release. Entry
point changes from app.js to main.js.

No behaviour change β€” all 380 tests pass, coverage 87 %.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a rolling run-history store (capped at 500 entries, newest-first) and
a Statistics tab that aggregates kudos per day, summary cards, and a
last-20-runs detail table rendered with a pure-canvas bar chart.

- store.py: append_run_history / read_run_history (atomic JSON writes)
- app.py: persist compact RunResult entry after every scheduler job
- routes.py: GET /api/history?limit= endpoint + ./stats.js in importmap
- static/stats.js: loadStats() + drawBarChart() (no CDN, CSP-safe)
- static/tabs.js: 'stats' added to validTabs; first-visit loadStats() call
- static/main.js: initStatsTab() wired in init()
- static/state.js: statsLoaded flag
- static/index.html: Statistics tab nav button + tab-pane (inside <main>)
- static/i18n.js: DE + EN keys for stats tab
- tests/unit/test_run_history.py: 7 unit tests (TDD)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add webhook notifications (ntfy/Telegram/any HTTP POST) and a visible
auth-error banner when the Strava session cookie expires.

Backend:
- notify.py: send_notification() with injected post_fn (testable without
  network); build_run_payload() and build_auth_error_payload() helpers
- models.py: AppSettings + notifyWebhookUrl (http/https validated),
  notifyOnRun, notifyOnAuthError; RunStatus + authOk (bool | None)
- app.py: _run_job tracks auth_ok state, sends webhook on run-complete
  (if notifyOnRun) and on AuthError (if notifyOnAuthError); AuthError
  is now caught so a bad cookie no longer leaves the scheduler broken
- routes.py: GET /api/status includes authOk from _app_state

Frontend:
- index.html: auth-error banner (hidden by default) + Notifications
  settings card (webhook URL, onRun toggle, onAuthError toggle)
- status.js: show/hide banner based on s.authOk === false
- settings.js: load/save notifyWebhookUrl, notifyOnRun, notifyOnAuthError
- i18n.js: DE/EN/FR/ES/IT keys for notify settings + status.authError
- styles.css: .auth-error-banner styling (error-bg / error colors)

Tests:
- tests/unit/test_notify.py: 13 unit tests (TDD β€” written first)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant