Added notifications for actual news
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import crypto from 'crypto'
|
||||
import { promises as fs } from 'fs'
|
||||
import path from 'path'
|
||||
import { readUsers, writeUsers, isHiddenUser } from './auth.js'
|
||||
import { readUsers, writeUsers, isHiddenUser, migrateUserRoles } from './auth.js'
|
||||
import { notificationSettingsForUser } from './notification-settings.js'
|
||||
|
||||
const FCM_SCOPE = 'https://www.googleapis.com/auth/firebase.messaging'
|
||||
@@ -132,11 +132,25 @@ async function sendFcmMessage({ serviceAccount, accessToken, token, title, body,
|
||||
}
|
||||
}
|
||||
|
||||
export async function sendNewNewsPush(news) {
|
||||
function notificationIdFor(value) {
|
||||
return String(value || Date.now()).split('').reduce((acc, char) => acc + char.charCodeAt(0), 0).toString()
|
||||
}
|
||||
|
||||
function userRoles(user) {
|
||||
const migrated = migrateUserRoles({ ...(user || {}) })
|
||||
return Array.isArray(migrated.roles) ? migrated.roles : []
|
||||
}
|
||||
|
||||
function isVorstandUser(user) {
|
||||
const roles = userRoles(user)
|
||||
return roles.includes('admin') || roles.includes('vorstand')
|
||||
}
|
||||
|
||||
export async function sendPushToUsers({ title, body, data = {}, predicate, failureLabel = 'FCM-Push' }) {
|
||||
const serviceAccount = await readServiceAccount()
|
||||
if (!serviceAccount) {
|
||||
console.warn('FCM nicht konfiguriert: FCM_SERVICE_ACCOUNT_JSON oder GOOGLE_APPLICATION_CREDENTIALS fehlt.')
|
||||
return { sent: 0, skipped: true }
|
||||
return { sent: 0, failed: 0, removed: 0, recipients: 0, tokenCount: 0, skipped: true }
|
||||
}
|
||||
const accessToken = await getAccessToken(serviceAccount)
|
||||
const users = await readUsers()
|
||||
@@ -146,32 +160,29 @@ export async function sendNewNewsPush(news) {
|
||||
let recipients = 0
|
||||
let tokenCount = 0
|
||||
let changed = false
|
||||
const title = 'Neue News'
|
||||
const body = String(news.title || 'Neue Nachricht vom Harheimer TC').slice(0, 120)
|
||||
const data = {
|
||||
type: 'news',
|
||||
newsId: String(news.id || ''),
|
||||
title,
|
||||
body,
|
||||
notificationId: String(news.id || Date.now()).split('').reduce((acc, char) => acc + char.charCodeAt(0), 0).toString()
|
||||
const payload = {
|
||||
...Object.fromEntries(Object.entries(data).map(([key, value]) => [key, String(value ?? '')])),
|
||||
title: String(title || 'Harheimer TC'),
|
||||
body: String(body || '').slice(0, 240),
|
||||
notificationId: String(data.notificationId || notificationIdFor(`${data.type || 'push'}:${title}:${body}`))
|
||||
}
|
||||
|
||||
for (const user of users) {
|
||||
if (isHiddenUser(user)) continue
|
||||
const settings = notificationSettingsForUser(user)
|
||||
if (!settings.newNews) continue
|
||||
if (predicate && !predicate(user, settings)) continue
|
||||
recipients += 1
|
||||
const tokens = pushTokensForUser(user)
|
||||
tokenCount += tokens.length
|
||||
const validTokens = []
|
||||
for (const entry of tokens) {
|
||||
try {
|
||||
await sendFcmMessage({ serviceAccount, accessToken, token: entry.token, title, body, data })
|
||||
await sendFcmMessage({ serviceAccount, accessToken, token: entry.token, title, body, data: payload })
|
||||
sent += 1
|
||||
validTokens.push(entry)
|
||||
} catch (error) {
|
||||
failed += 1
|
||||
console.error('FCM News-Push fehlgeschlagen:', error.message)
|
||||
console.error(`${failureLabel} fehlgeschlagen:`, error.message)
|
||||
if (!/UNREGISTERED|NOT_FOUND|INVALID_ARGUMENT/.test(String(error.message))) {
|
||||
validTokens.push(entry)
|
||||
} else {
|
||||
@@ -188,3 +199,66 @@ export async function sendNewNewsPush(news) {
|
||||
if (changed) await writeUsers(users)
|
||||
return { sent, failed, removed, recipients, tokenCount, skipped: false }
|
||||
}
|
||||
|
||||
export async function sendNewNewsPush(news) {
|
||||
const title = 'Neue News'
|
||||
const body = String(news.title || 'Neue Nachricht vom Harheimer TC').slice(0, 120)
|
||||
return sendPushToUsers({
|
||||
title,
|
||||
body,
|
||||
data: {
|
||||
type: 'news',
|
||||
newsId: String(news.id || ''),
|
||||
notificationId: notificationIdFor(news.id || Date.now())
|
||||
},
|
||||
predicate: (_user, settings) => settings.newNews,
|
||||
failureLabel: 'FCM News-Push'
|
||||
})
|
||||
}
|
||||
|
||||
export async function sendNewEventPush(termin) {
|
||||
const title = 'Neuer Termin'
|
||||
const body = String(termin?.titel || 'Ein neuer Termin wurde eingetragen.').slice(0, 120)
|
||||
return sendPushToUsers({
|
||||
title,
|
||||
body,
|
||||
data: {
|
||||
type: 'event',
|
||||
date: termin?.datum || '',
|
||||
notificationId: notificationIdFor(`event:${termin?.datum || ''}:${termin?.titel || ''}`)
|
||||
},
|
||||
predicate: (_user, settings) => settings.newEvents,
|
||||
failureLabel: 'FCM Termin-Push'
|
||||
})
|
||||
}
|
||||
|
||||
export async function sendNewContactRequestPush(contactRequest) {
|
||||
const title = 'Neue Kontaktanfrage'
|
||||
const body = String(contactRequest?.subject || contactRequest?.name || 'Eine neue Kontaktanfrage ist eingegangen.').slice(0, 120)
|
||||
return sendPushToUsers({
|
||||
title,
|
||||
body,
|
||||
data: {
|
||||
type: 'contact_request',
|
||||
notificationId: notificationIdFor(`contact:${contactRequest?.email || ''}:${contactRequest?.subject || ''}:${Date.now()}`)
|
||||
},
|
||||
predicate: (user, settings) => isVorstandUser(user) && settings.newContactRequest,
|
||||
failureLabel: 'FCM Kontaktanfrage-Push'
|
||||
})
|
||||
}
|
||||
|
||||
export async function sendNewUserRegistrationPush(registration) {
|
||||
const title = 'Neue Benutzerregistrierung'
|
||||
const body = String(registration?.name || registration?.email || 'Eine neue Registrierung wartet auf Freigabe.').slice(0, 120)
|
||||
return sendPushToUsers({
|
||||
title,
|
||||
body,
|
||||
data: {
|
||||
type: 'user_registration',
|
||||
userId: registration?.id || '',
|
||||
notificationId: notificationIdFor(`registration:${registration?.id || registration?.email || Date.now()}`)
|
||||
},
|
||||
predicate: (user, settings) => isVorstandUser(user) && settings.newUserRegistration,
|
||||
failureLabel: 'FCM Registrierungs-Push'
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user