Files
wtr/docs/notifications.md
zv f15ebd28dc
All checks were successful
CI / Lint, test, typecheck and build (push) Successful in 10m45s
fix: preserve brief notification preferences
2026-07-04 15:28:58 +02:00

142 lines
4.5 KiB
Markdown

# Powiadomienia Web Push
Powiadomienia obejmują:
- nowe ostrzeżenia meteorologiczne IMGW dla Polski,
- poranny brief dnia,
- wieczorny brief z prognozą na jutro,
- testowe powiadomienie wysyłane z `/settings`.
Konfiguracja użytkownika znajduje się w widoku `/settings`.
## Wymagania
Do wysyłki Web Push potrzebne są klucze VAPID:
```bash
WEB_PUSH_VAPID_PUBLIC_KEY=
WEB_PUSH_VAPID_PRIVATE_KEY=
WEB_PUSH_VAPID_SUBJECT=mailto:admin@example.com
```
Klucze można wygenerować poleceniem:
```bash
npx web-push generate-vapid-keys
```
Endpointy harmonogramu wymagają też sekretu crona w produkcji:
```bash
NOTIFICATIONS_CRON_SECRET=
```
Subskrypcje Web Push i historia wysyłek są zapisywane w SQLite:
```bash
WTR_DATABASE_PATH=./data/wtr.sqlite
```
Jeśli zmienna nie jest ustawiona, aplikacja używa `./data/wtr.sqlite` względem katalogu projektu.
## Preferencje Subskrypcji
Subskrypcja Web Push zapisuje:
- endpoint subskrypcji przeglądarki,
- region pogodowy `PL` albo `GLOBAL`,
- województwo dla oficjalnych ostrzeżeń IMGW w Polsce,
- język interfejsu,
- czy ostrzeżenia są aktywne,
- czy aktywny jest brief poranny,
- czy aktywny jest brief na jutro,
- współrzędne i nazwę lokalizacji,
- opcjonalny powiat TERYT,
- wybraną jednostkę temperatury dla briefów wysyłanych z serwera,
- wybraną jednostkę wiatru dla briefów wysyłanych z serwera.
Ostrzeżenia meteo są filtrowane po powiecie TERYT, jeśli lokalizacja go dostarcza. W przeciwnym razie używany jest fallback wojewódzki.
Dla subskrypcji `GLOBAL` oficjalne ostrzeżenia IMGW są wyłączone, `province` może być puste, a powiadomienia mogą obejmować brief poranny i brief na jutro oparte o prognozę modelową Open-Meteo.
## Worker Self-Hosted
Worker powiadomień uruchamia się osobno od aplikacji:
```bash
npm run notifications:worker
```
Wymaga równolegle działającej aplikacji Next.js. Domyślnie odpytuje:
```bash
http://127.0.0.1:3000
```
Jeśli aplikacja działa pod innym adresem albo portem, ustaw:
```bash
WTR_APP_URL=http://127.0.0.1:4000
```
Worker wczytuje `.env` i `.env.local`. Zmienne ustawione bezpośrednio w shellu mają pierwszeństwo.
## Harmonogram
Domyślna konfiguracja:
```bash
NOTIFICATIONS_WARNING_INTERVAL_MINUTES=5
NOTIFICATIONS_BRIEF_INTERVAL_MINUTES=5
NOTIFICATIONS_MORNING_BRIEF_TIME=07:00
NOTIFICATIONS_TOMORROW_BRIEF_TIME=18:00
```
Worker:
- sprawdza nowe ostrzeżenia co 5 minut,
- co 5 minut odpytuje endpointy briefów,
- endpoint `/api/notifications/daily-brief` wysyła po 07:00 lokalnego czasu zapisanego w subskrypcji,
- endpoint `/api/notifications/tomorrow-brief` wysyła po 18:00 lokalnego czasu zapisanego w subskrypcji,
- nie blokuje jednego harmonogramu błędem drugiego.
Endpointy harmonogramu nie uruchamiają się same bez workera albo zewnętrznego crona.
Endpointy briefów zwracają diagnostykę JSON z polami `subscriptions`, `eligibleSubscriptions`, `sent`, `skipped`,
`failed` oraz `skippedReasons`. Dla problemów z harmonogramem najważniejsze powody to:
- `disabled` - subskrypcja istnieje, ale dany brief nie jest włączony w zapisanym stanie serwera,
- `missingLocation` - brief jest włączony, ale subskrypcja nie ma współrzędnych,
- `beforeTime` - lokalny czas subskrypcji jest jeszcze przed skonfigurowaną godziną,
- `alreadySent` - brief dla tej lokalnej daty został już oznaczony jako wysłany,
- `noBrief` - prognoza nie pozwoliła zbudować treści briefu.
## Zewnętrzny Cron
Jeśli nie używasz `npm run notifications:worker`, zewnętrzny cron powinien wywoływać:
```text
GET /api/notifications/check
GET /api/notifications/daily-brief
GET /api/notifications/tomorrow-brief
```
W produkcji dodaj jeden z nagłówków:
```http
Authorization: Bearer <NOTIFICATIONS_CRON_SECRET>
x-cron-secret: <NOTIFICATIONS_CRON_SECRET>
```
## Platformy
- iOS/iPadOS wymaga dodania PWA do ekranu początkowego i uruchomienia aplikacji z ikony.
- Android i desktop nie są blokowane wymogiem `standalone`, jeśli przeglądarka obsługuje Web Push.
- GPS i powiadomienia wymagają bezpiecznego kontekstu HTTPS poza wyjątkami typu `localhost`.
## Ograniczenia
`lib/push-store.ts` przechowuje subskrypcje i historię wysyłek w lokalnym SQLite przez `better-sqlite3`. Dane przetrwają restart procesu, jeśli plik wskazany przez `WTR_DATABASE_PATH` znajduje się w trwałym katalogu. Na self-hostingu warto backupować plik bazy razem z plikami `-wal` i `-shm`, jeśli istnieją.
Powiadomienie testowe jest wysyłane na konkretny endpoint subskrypcji przekazany z `/settings`, a nie broadcastowane do wszystkich urządzeń.