Initial commit
This commit is contained in:
75
utils/pushService.js
Normal file
75
utils/pushService.js
Normal file
@@ -0,0 +1,75 @@
|
||||
// utils/pushService.js
|
||||
const webpush = require('web-push');
|
||||
const db = require('../db');
|
||||
|
||||
const hasVapid =
|
||||
!!process.env.VAPID_PUBLIC_KEY && !!process.env.VAPID_PRIVATE_KEY;
|
||||
|
||||
if (!hasVapid) {
|
||||
console.warn('[Push] VAPID keys não definidas. Push desativado.');
|
||||
} else {
|
||||
webpush.setVapidDetails(
|
||||
process.env.VAPID_SUBJECT || 'mailto:admin@evstation.local',
|
||||
process.env.VAPID_PUBLIC_KEY,
|
||||
process.env.VAPID_PRIVATE_KEY
|
||||
);
|
||||
}
|
||||
|
||||
// retry simples p/ 429 e 5xx
|
||||
async function sendWithRetry(subscription, message, tries = 2) {
|
||||
try {
|
||||
return await webpush.sendNotification(subscription, message);
|
||||
} catch (err) {
|
||||
const code = err?.statusCode;
|
||||
if ((code === 429 || code >= 500) && tries > 1) {
|
||||
await new Promise((r) => setTimeout(r, 1000));
|
||||
return sendWithRetry(subscription, message, tries - 1);
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
async function sendPushToUser(userId, payload) {
|
||||
if (!hasVapid) return;
|
||||
|
||||
const subs = await db('push_subscriptions')
|
||||
.where({ user_id: userId })
|
||||
.select('id', 'endpoint', 'p256dh', 'auth');
|
||||
|
||||
if (!subs.length) return;
|
||||
|
||||
const message = JSON.stringify(payload);
|
||||
|
||||
await Promise.allSettled(
|
||||
subs.map(async (s) => {
|
||||
const subscription = {
|
||||
endpoint: s.endpoint,
|
||||
keys: {
|
||||
p256dh: s.p256dh,
|
||||
auth: s.auth,
|
||||
},
|
||||
};
|
||||
|
||||
try {
|
||||
await sendWithRetry(subscription, message);
|
||||
|
||||
// TTL opcional (default 15min)
|
||||
// se quiseres usar TTL do payload, descomenta e passa options no sendWithRetry
|
||||
// await webpush.sendNotification(subscription, message, {
|
||||
// TTL: payload.ttl ?? 60 * 15,
|
||||
// });
|
||||
} catch (err) {
|
||||
const code = err?.statusCode;
|
||||
|
||||
// remove subscriptions mortas
|
||||
if (code === 404 || code === 410) {
|
||||
await db('push_subscriptions').where({ id: s.id }).del();
|
||||
} else {
|
||||
console.error('[Push] erro ao enviar:', err.message);
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = { sendPushToUser };
|
||||
Reference in New Issue
Block a user