Update
This commit is contained in:
162
lib/push-service.js
Normal file
162
lib/push-service.js
Normal file
@@ -0,0 +1,162 @@
|
||||
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:admin@reptilfpv.de',
|
||||
vapidKeys.publicKey,
|
||||
vapidKeys.privateKey
|
||||
);
|
||||
|
||||
class PushService {
|
||||
constructor() {
|
||||
this.subscriptions = new Map(); // Map<playerId, Set<subscription>>
|
||||
}
|
||||
|
||||
// Subscribe user to push notifications
|
||||
subscribe(userId, subscription) {
|
||||
if (!this.subscriptions.has(userId)) {
|
||||
this.subscriptions.set(userId, new Set());
|
||||
}
|
||||
this.subscriptions.get(userId).add(subscription);
|
||||
console.log(`User ${userId} subscribed to push notifications (${this.subscriptions.get(userId).size} total subscriptions)`);
|
||||
}
|
||||
|
||||
// Unsubscribe user from push notifications
|
||||
unsubscribe(userId) {
|
||||
this.subscriptions.delete(userId);
|
||||
console.log(`User ${userId} unsubscribed from push notifications`);
|
||||
}
|
||||
|
||||
// Unsubscribe specific device from push notifications
|
||||
unsubscribeDevice(userId, endpoint) {
|
||||
const subscriptions = this.subscriptions.get(userId);
|
||||
if (!subscriptions) {
|
||||
console.log(`No subscriptions found for user ${userId}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find and remove the specific subscription by endpoint
|
||||
let removed = false;
|
||||
for (const subscription of subscriptions) {
|
||||
if (subscription.endpoint === endpoint) {
|
||||
subscriptions.delete(subscription);
|
||||
removed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If no subscriptions left, remove the user entirely
|
||||
if (subscriptions.size === 0) {
|
||||
this.subscriptions.delete(userId);
|
||||
console.log(`User ${userId} unsubscribed from push notifications (all devices)`);
|
||||
} else {
|
||||
console.log(`Device ${endpoint} unsubscribed from push notifications for user ${userId} (${subscriptions.size} devices remaining)`);
|
||||
}
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
||||
// Send push notification to specific user
|
||||
async sendToUser(userId, payload) {
|
||||
const subscriptions = this.subscriptions.get(userId);
|
||||
if (!subscriptions || subscriptions.size === 0) {
|
||||
console.log(`No subscriptions found for user ${userId}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
let successCount = 0;
|
||||
let totalCount = subscriptions.size;
|
||||
|
||||
for (const subscription of subscriptions) {
|
||||
try {
|
||||
await webpush.sendNotification(subscription, JSON.stringify(payload));
|
||||
successCount++;
|
||||
} catch (error) {
|
||||
console.error(`Error sending push notification to user ${userId}:`, error);
|
||||
|
||||
// If subscription is invalid, remove it
|
||||
if (error.statusCode === 410) {
|
||||
subscriptions.delete(subscription);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Push notification sent to ${successCount}/${totalCount} subscriptions for user ${userId}`);
|
||||
return successCount > 0;
|
||||
}
|
||||
|
||||
// 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();
|
||||
Reference in New Issue
Block a user