125 lines
3.8 KiB
JavaScript
125 lines
3.8 KiB
JavaScript
const webpush = require('web-push');
|
|
|
|
// VAPID Keys (sollten in Umgebungsvariablen gespeichert werden)
|
|
const vapidKeys = {
|
|
publicKey: 'BJmNVx0C3XeVxeKGTP9c-Z4HcuZNmdk6QdiLocZgCmb-miCS0ESFO3W2TvJlRhhNAShV63pWA5p36BTVSetyTds',
|
|
privateKey: 'HBdRCtmZUAzsWpVjZ2LDaoWliIPHldAb5ExAt8bvDeg'
|
|
};
|
|
|
|
// Configure web-push
|
|
webpush.setVapidDetails(
|
|
'mailto:ninjacross@example.com',
|
|
vapidKeys.publicKey,
|
|
vapidKeys.privateKey
|
|
);
|
|
|
|
class PushService {
|
|
constructor() {
|
|
this.subscriptions = new Map(); // In production: use database
|
|
}
|
|
|
|
// Subscribe user to push notifications
|
|
subscribe(userId, subscription) {
|
|
this.subscriptions.set(userId, subscription);
|
|
console.log(`User ${userId} subscribed to push notifications`);
|
|
}
|
|
|
|
// Unsubscribe user from push notifications
|
|
unsubscribe(userId) {
|
|
this.subscriptions.delete(userId);
|
|
console.log(`User ${userId} unsubscribed from push notifications`);
|
|
}
|
|
|
|
// Send push notification to specific user
|
|
async sendToUser(userId, payload) {
|
|
const subscription = this.subscriptions.get(userId);
|
|
if (!subscription) {
|
|
console.log(`No subscription found for user ${userId}`);
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
await webpush.sendNotification(subscription, JSON.stringify(payload));
|
|
console.log(`Push notification sent to user ${userId}`);
|
|
return true;
|
|
} catch (error) {
|
|
console.error(`Error sending push notification to user ${userId}:`, error);
|
|
|
|
// If subscription is invalid, remove it
|
|
if (error.statusCode === 410) {
|
|
this.unsubscribe(userId);
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Send push notification to all subscribed users
|
|
async sendToAll(payload) {
|
|
const results = [];
|
|
for (const [userId, subscription] of this.subscriptions) {
|
|
const result = await this.sendToUser(userId, payload);
|
|
results.push({ userId, success: result });
|
|
}
|
|
return results;
|
|
}
|
|
|
|
// Send achievement notification
|
|
async sendAchievementNotification(userId, achievementName) {
|
|
const payload = {
|
|
title: '🏆 Neues Achievement!',
|
|
body: `Du hast "${achievementName}" erreicht!`,
|
|
icon: '/pictures/icon-192.png',
|
|
badge: '/pictures/icon-192.png',
|
|
data: {
|
|
type: 'achievement',
|
|
achievement: achievementName,
|
|
timestamp: Date.now()
|
|
},
|
|
actions: [
|
|
{
|
|
action: 'view',
|
|
title: 'Dashboard öffnen'
|
|
}
|
|
]
|
|
};
|
|
|
|
return await this.sendToUser(userId, payload);
|
|
}
|
|
|
|
// Send best time notification
|
|
async sendBestTimeNotification(userId, timeType, locationName) {
|
|
const payload = {
|
|
title: `🏁 ${timeType} Bestzeit!`,
|
|
body: `Du hast die beste Zeit in ${locationName} erreicht!`,
|
|
icon: '/pictures/icon-192.png',
|
|
badge: '/pictures/icon-192.png',
|
|
data: {
|
|
type: 'best_time',
|
|
timeType: timeType,
|
|
location: locationName,
|
|
timestamp: Date.now()
|
|
},
|
|
actions: [
|
|
{
|
|
action: 'view',
|
|
title: 'Dashboard öffnen'
|
|
}
|
|
]
|
|
};
|
|
|
|
return await this.sendToUser(userId, payload);
|
|
}
|
|
|
|
// Get subscription count
|
|
getSubscriptionCount() {
|
|
return this.subscriptions.size;
|
|
}
|
|
|
|
// Get all user IDs with subscriptions
|
|
getSubscribedUsers() {
|
|
return Array.from(this.subscriptions.keys());
|
|
}
|
|
}
|
|
|
|
module.exports = new PushService();
|