fix: preserve brief notification preferences
All checks were successful
CI / Lint, test, typecheck and build (push) Successful in 10m45s
All checks were successful
CI / Lint, test, typecheck and build (push) Successful in 10m45s
This commit is contained in:
@@ -54,12 +54,24 @@ export async function GET(request: Request) {
|
|||||||
|
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const briefTime = normalizeTime(process.env.NOTIFICATIONS_MORNING_BRIEF_TIME, DEFAULT_MORNING_BRIEF_TIME);
|
const briefTime = normalizeTime(process.env.NOTIFICATIONS_MORNING_BRIEF_TIME, DEFAULT_MORNING_BRIEF_TIME);
|
||||||
const subscriptions = getPushSubscriptions().filter(
|
const allSubscriptions = getPushSubscriptions();
|
||||||
|
const subscriptions = allSubscriptions.filter(
|
||||||
(subscription) =>
|
(subscription) =>
|
||||||
subscription.morningBriefEnabled &&
|
subscription.morningBriefEnabled &&
|
||||||
Number.isFinite(subscription.latitude) &&
|
Number.isFinite(subscription.latitude) &&
|
||||||
Number.isFinite(subscription.longitude),
|
Number.isFinite(subscription.longitude),
|
||||||
);
|
);
|
||||||
|
const skippedReasons = {
|
||||||
|
disabled: allSubscriptions.filter((subscription) => !subscription.morningBriefEnabled).length,
|
||||||
|
missingLocation: allSubscriptions.filter(
|
||||||
|
(subscription) =>
|
||||||
|
subscription.morningBriefEnabled &&
|
||||||
|
(!Number.isFinite(subscription.latitude) || !Number.isFinite(subscription.longitude)),
|
||||||
|
).length,
|
||||||
|
beforeTime: 0,
|
||||||
|
alreadySent: 0,
|
||||||
|
noBrief: 0,
|
||||||
|
};
|
||||||
let warningsUnavailable = false;
|
let warningsUnavailable = false;
|
||||||
const hasPolishSubscriptions = subscriptions.some((subscription) => subscription.region === "PL");
|
const hasPolishSubscriptions = subscriptions.some((subscription) => subscription.region === "PL");
|
||||||
const warnings = hasPolishSubscriptions
|
const warnings = hasPolishSubscriptions
|
||||||
@@ -76,11 +88,13 @@ export async function GET(request: Request) {
|
|||||||
const localTime = getLocalDateParts(subscription.timezone, now);
|
const localTime = getLocalDateParts(subscription.timezone, now);
|
||||||
if (localTime.time < briefTime) {
|
if (localTime.time < briefTime) {
|
||||||
skipped += 1;
|
skipped += 1;
|
||||||
|
skippedReasons.beforeTime += 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const dateKey = localTime.dateKey;
|
const dateKey = localTime.dateKey;
|
||||||
if (hasSentMorningBrief(subscription.endpoint, dateKey)) {
|
if (hasSentMorningBrief(subscription.endpoint, dateKey)) {
|
||||||
skipped += 1;
|
skipped += 1;
|
||||||
|
skippedReasons.alreadySent += 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,6 +117,7 @@ export async function GET(request: Request) {
|
|||||||
});
|
});
|
||||||
if (!brief) {
|
if (!brief) {
|
||||||
skipped += 1;
|
skipped += 1;
|
||||||
|
skippedReasons.noBrief += 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
await sendMorningBriefNotification(subscription, brief);
|
await sendMorningBriefNotification(subscription, brief);
|
||||||
@@ -119,10 +134,12 @@ export async function GET(request: Request) {
|
|||||||
return NextResponse.json({
|
return NextResponse.json({
|
||||||
ok: true,
|
ok: true,
|
||||||
time: briefTime,
|
time: briefTime,
|
||||||
subscriptions: subscriptions.length,
|
subscriptions: allSubscriptions.length,
|
||||||
|
eligibleSubscriptions: subscriptions.length,
|
||||||
warningsUnavailable,
|
warningsUnavailable,
|
||||||
sent,
|
sent,
|
||||||
skipped,
|
skipped,
|
||||||
|
skippedReasons,
|
||||||
failed,
|
failed,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,12 +66,24 @@ export async function GET(request: Request) {
|
|||||||
|
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const briefTime = normalizeTime(process.env.NOTIFICATIONS_TOMORROW_BRIEF_TIME, DEFAULT_TOMORROW_BRIEF_TIME);
|
const briefTime = normalizeTime(process.env.NOTIFICATIONS_TOMORROW_BRIEF_TIME, DEFAULT_TOMORROW_BRIEF_TIME);
|
||||||
const subscriptions = getPushSubscriptions().filter(
|
const allSubscriptions = getPushSubscriptions();
|
||||||
|
const subscriptions = allSubscriptions.filter(
|
||||||
(subscription) =>
|
(subscription) =>
|
||||||
subscription.tomorrowBriefEnabled &&
|
subscription.tomorrowBriefEnabled &&
|
||||||
Number.isFinite(subscription.latitude) &&
|
Number.isFinite(subscription.latitude) &&
|
||||||
Number.isFinite(subscription.longitude),
|
Number.isFinite(subscription.longitude),
|
||||||
);
|
);
|
||||||
|
const skippedReasons = {
|
||||||
|
disabled: allSubscriptions.filter((subscription) => !subscription.tomorrowBriefEnabled).length,
|
||||||
|
missingLocation: allSubscriptions.filter(
|
||||||
|
(subscription) =>
|
||||||
|
subscription.tomorrowBriefEnabled &&
|
||||||
|
(!Number.isFinite(subscription.latitude) || !Number.isFinite(subscription.longitude)),
|
||||||
|
).length,
|
||||||
|
beforeTime: 0,
|
||||||
|
alreadySent: 0,
|
||||||
|
noBrief: 0,
|
||||||
|
};
|
||||||
let warningsUnavailable = false;
|
let warningsUnavailable = false;
|
||||||
const hasPolishSubscriptions = subscriptions.some((subscription) => subscription.region === "PL");
|
const hasPolishSubscriptions = subscriptions.some((subscription) => subscription.region === "PL");
|
||||||
const warnings = hasPolishSubscriptions
|
const warnings = hasPolishSubscriptions
|
||||||
@@ -88,11 +100,13 @@ export async function GET(request: Request) {
|
|||||||
const localToday = getLocalDateParts(subscription.timezone, now);
|
const localToday = getLocalDateParts(subscription.timezone, now);
|
||||||
if (localToday.time < briefTime) {
|
if (localToday.time < briefTime) {
|
||||||
skipped += 1;
|
skipped += 1;
|
||||||
|
skippedReasons.beforeTime += 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const targetDateKey = getLocalDateParts(subscription.timezone, now, 1).dateKey;
|
const targetDateKey = getLocalDateParts(subscription.timezone, now, 1).dateKey;
|
||||||
if (hasSentTomorrowBrief(subscription.endpoint, targetDateKey)) {
|
if (hasSentTomorrowBrief(subscription.endpoint, targetDateKey)) {
|
||||||
skipped += 1;
|
skipped += 1;
|
||||||
|
skippedReasons.alreadySent += 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,6 +129,7 @@ export async function GET(request: Request) {
|
|||||||
});
|
});
|
||||||
if (!brief) {
|
if (!brief) {
|
||||||
skipped += 1;
|
skipped += 1;
|
||||||
|
skippedReasons.noBrief += 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
await sendTomorrowBriefNotification(subscription, brief);
|
await sendTomorrowBriefNotification(subscription, brief);
|
||||||
@@ -131,10 +146,12 @@ export async function GET(request: Request) {
|
|||||||
return NextResponse.json({
|
return NextResponse.json({
|
||||||
ok: true,
|
ok: true,
|
||||||
time: briefTime,
|
time: briefTime,
|
||||||
subscriptions: subscriptions.length,
|
subscriptions: allSubscriptions.length,
|
||||||
|
eligibleSubscriptions: subscriptions.length,
|
||||||
warningsUnavailable,
|
warningsUnavailable,
|
||||||
sent,
|
sent,
|
||||||
skipped,
|
skipped,
|
||||||
|
skippedReasons,
|
||||||
failed,
|
failed,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -428,14 +428,15 @@ export function SettingsPage() {
|
|||||||
setMorningBriefEnabled(enabled);
|
setMorningBriefEnabled(enabled);
|
||||||
if (!notificationsEnabled || !canUsePush || notificationStatus !== "granted") return;
|
if (!notificationsEnabled || !canUsePush || notificationStatus !== "granted") return;
|
||||||
try {
|
try {
|
||||||
|
const preferences = useWeatherStore.getState();
|
||||||
const registration = await navigator.serviceWorker?.getRegistration();
|
const registration = await navigator.serviceWorker?.getRegistration();
|
||||||
const subscription = await registration?.pushManager.getSubscription();
|
const subscription = await registration?.pushManager.getSubscription();
|
||||||
if (!subscription) return;
|
if (!subscription) return;
|
||||||
await savePushSubscription(subscription, effectiveProvince, language, {
|
await savePushSubscription(subscription, effectiveProvince, language, {
|
||||||
region: selectedRegion,
|
region: selectedRegion,
|
||||||
officialWarningsEnabled: canUseOfficialWarnings && notificationsEnabled,
|
officialWarningsEnabled: canUseOfficialWarnings && notificationsEnabled,
|
||||||
morningBriefEnabled: enabled,
|
morningBriefEnabled: preferences.morningBriefNotificationsEnabled,
|
||||||
tomorrowBriefEnabled,
|
tomorrowBriefEnabled: preferences.tomorrowBriefNotificationsEnabled,
|
||||||
latitude: notificationLatitude,
|
latitude: notificationLatitude,
|
||||||
longitude: notificationLongitude,
|
longitude: notificationLongitude,
|
||||||
locationName: notificationLocationName,
|
locationName: notificationLocationName,
|
||||||
@@ -453,14 +454,15 @@ export function SettingsPage() {
|
|||||||
setTomorrowBriefEnabled(enabled);
|
setTomorrowBriefEnabled(enabled);
|
||||||
if (!notificationsEnabled || !canUsePush || notificationStatus !== "granted") return;
|
if (!notificationsEnabled || !canUsePush || notificationStatus !== "granted") return;
|
||||||
try {
|
try {
|
||||||
|
const preferences = useWeatherStore.getState();
|
||||||
const registration = await navigator.serviceWorker?.getRegistration();
|
const registration = await navigator.serviceWorker?.getRegistration();
|
||||||
const subscription = await registration?.pushManager.getSubscription();
|
const subscription = await registration?.pushManager.getSubscription();
|
||||||
if (!subscription) return;
|
if (!subscription) return;
|
||||||
await savePushSubscription(subscription, effectiveProvince, language, {
|
await savePushSubscription(subscription, effectiveProvince, language, {
|
||||||
region: selectedRegion,
|
region: selectedRegion,
|
||||||
officialWarningsEnabled: canUseOfficialWarnings && notificationsEnabled,
|
officialWarningsEnabled: canUseOfficialWarnings && notificationsEnabled,
|
||||||
morningBriefEnabled,
|
morningBriefEnabled: preferences.morningBriefNotificationsEnabled,
|
||||||
tomorrowBriefEnabled: enabled,
|
tomorrowBriefEnabled: preferences.tomorrowBriefNotificationsEnabled,
|
||||||
latitude: notificationLatitude,
|
latitude: notificationLatitude,
|
||||||
longitude: notificationLongitude,
|
longitude: notificationLongitude,
|
||||||
locationName: notificationLocationName,
|
locationName: notificationLocationName,
|
||||||
|
|||||||
@@ -102,6 +102,15 @@ Worker:
|
|||||||
|
|
||||||
Endpointy harmonogramu nie uruchamiają się same bez workera albo zewnętrznego crona.
|
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
|
## Zewnętrzny Cron
|
||||||
|
|
||||||
Jeśli nie używasz `npm run notifications:worker`, zewnętrzny cron powinien wywoływać:
|
Jeśli nie używasz `npm run notifications:worker`, zewnętrzny cron powinien wywoływać:
|
||||||
|
|||||||
Reference in New Issue
Block a user