130 lines
3.8 KiB
JavaScript
130 lines
3.8 KiB
JavaScript
const { Pool } = require('pg');
|
|
const webpush = require('web-push');
|
|
|
|
// Database connection
|
|
const pool = new Pool({
|
|
user: 'postgres',
|
|
host: 'localhost',
|
|
database: 'ninjacross',
|
|
password: 'postgres',
|
|
port: 5432,
|
|
});
|
|
|
|
// VAPID Keys (generate with: webpush.generateVAPIDKeys())
|
|
const vapidKeys = {
|
|
publicKey: 'BEl62iUYgUivxIkv69yViEuiBIa40HI6F2B5L4h7Q8Y',
|
|
privateKey: 'your-private-key-here'
|
|
};
|
|
|
|
webpush.setVapidDetails(
|
|
'mailto:admin@ninjacross.es',
|
|
vapidKeys.publicKey,
|
|
vapidKeys.privateKey
|
|
);
|
|
|
|
// Store subscription endpoint for each player
|
|
async function storePlayerSubscription(playerId, subscription) {
|
|
try {
|
|
await pool.query(`
|
|
INSERT INTO player_subscriptions (player_id, endpoint, p256dh, auth)
|
|
VALUES ($1, $2, $3, $4)
|
|
`, [
|
|
playerId,
|
|
subscription.endpoint,
|
|
subscription.keys.p256dh,
|
|
subscription.keys.auth
|
|
]);
|
|
console.log(`✅ Subscription stored for player ${playerId}`);
|
|
} catch (error) {
|
|
console.error('Error storing subscription:', error);
|
|
}
|
|
}
|
|
|
|
// Send push notification to player
|
|
async function sendPushNotification(playerId, title, message, icon = '🏆') {
|
|
try {
|
|
const result = await pool.query(`
|
|
SELECT endpoint, p256dh, auth
|
|
FROM player_subscriptions
|
|
WHERE player_id = $1
|
|
`, [playerId]);
|
|
|
|
if (result.rows.length === 0) {
|
|
console.log(`No subscription found for player ${playerId}`);
|
|
return;
|
|
}
|
|
|
|
const subscription = {
|
|
endpoint: result.rows[0].endpoint,
|
|
keys: {
|
|
p256dh: result.rows[0].p256dh,
|
|
auth: result.rows[0].auth
|
|
}
|
|
};
|
|
|
|
const payload = JSON.stringify({
|
|
title: title,
|
|
body: message,
|
|
icon: '/pictures/favicon.ico',
|
|
badge: '/pictures/favicon.ico',
|
|
data: {
|
|
url: '/dashboard.html'
|
|
}
|
|
});
|
|
|
|
await webpush.sendNotification(subscription, payload);
|
|
console.log(`✅ Push notification sent to player ${playerId}`);
|
|
|
|
} catch (error) {
|
|
console.error('Error sending push notification:', error);
|
|
}
|
|
}
|
|
|
|
// Send best time notifications
|
|
async function sendBestTimeNotifications() {
|
|
try {
|
|
console.log('🔔 Sending best time notifications...');
|
|
|
|
// Get daily best
|
|
const dailyResult = await pool.query(`
|
|
WITH daily_best AS (
|
|
SELECT
|
|
t.player_id,
|
|
MIN(t.recorded_time) as best_time,
|
|
CONCAT(p.firstname, ' ', p.lastname) as player_name
|
|
FROM times t
|
|
JOIN players p ON t.player_id = p.id
|
|
WHERE DATE(t.created_at AT TIME ZONE 'Europe/Berlin') = CURRENT_DATE
|
|
GROUP BY t.player_id, p.firstname, p.lastname
|
|
)
|
|
SELECT
|
|
player_id,
|
|
player_name,
|
|
best_time
|
|
FROM daily_best
|
|
WHERE best_time = (SELECT MIN(best_time) FROM daily_best)
|
|
LIMIT 1
|
|
`);
|
|
|
|
if (dailyResult.rows.length > 0) {
|
|
const daily = dailyResult.rows[0];
|
|
await sendPushNotification(
|
|
daily.player_id,
|
|
'🏆 Tageskönig!',
|
|
`Glückwunsch ${daily.player_name}! Du hast die beste Zeit des Tages mit ${daily.best_time} erreicht!`
|
|
);
|
|
}
|
|
|
|
console.log('✅ Best time notifications sent');
|
|
|
|
} catch (error) {
|
|
console.error('❌ Error sending best time notifications:', error);
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
storePlayerSubscription,
|
|
sendPushNotification,
|
|
sendBestTimeNotifications
|
|
};
|