Files
mwitnessing/pages/api/notify.ts
Dobromir Popov 3ef9738266 fix prima
2024-12-14 04:26:39 +02:00

214 lines
8.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const webPush = require('web-push')
import common from '../../src/helpers/common';
//generate and store VAPID keys in .env.local if not already done
if (!process.env.NEXT_PUBLIC_WEB_PUSH_PUBLIC_KEY || !process.env.WEB_PUSH_PRIVATE_KEY) {
const { publicKey, privateKey } = webPush.generateVAPIDKeys()
console.log('VAPID keys generated:')
console.log('Public key:', publicKey)
console.log('Private key:', privateKey)
console.log('Store these keys in your .env.local file:')
console.log('NEXT_PUBLIC_WEB_PUSH_PUBLIC_KEY=', publicKey)
console.log('WEB_PUSH_PRIVATE_KEY=', privateKey)
process.exit(0)
}
webPush.setVapidDetails(
`mailto:${process.env.WEB_PUSH_EMAIL}`,
process.env.NEXT_PUBLIC_WEB_PUSH_PUBLIC_KEY,
process.env.WEB_PUSH_PRIVATE_KEY
)
const Notification = async (req, res) => {
if (req.method == 'GET') {
res.statusCode = 200
res.setHeader('Allow', 'POST')
let subs = 0
if (req.query && req.query.id) {
const prisma = common.getPrismaClient();
const publisher = await prisma.publisher.findUnique({
where: { id: req.query.id },
select: { pushSubscription: true }
});
subs = Array.isArray(publisher.pushSubscription) ? publisher.pushSubscription.length : (publisher.pushSubscription ? 1 : 0);
res.send({ subs })
res.end()
return
} else {
// send the public key in the response headers
//res.setHeader('Content-Type', 'text/plain')
res.send({ pk: process.env.NEXT_PUBLIC_WEB_PUSH_PUBLIC_KEY, subs })
res.end()
}
}
if (req.method == 'PUT') {
// store the subscription object in the database
// publisher.pushSubscription = subscription
const prisma = common.getPrismaClient();
const { subscription, id, name } = req.body
const publisher = await prisma.publisher.findUnique({
where: { id },
select: { pushSubscription: true }
});
if (!publisher) {
res.statusCode = 404
res.end()
return
}
let subscriptions = Array.isArray(publisher.pushSubscription) ? publisher.pushSubscription : (publisher.pushSubscription ? [publisher.pushSubscription] : []);
const index = subscriptions.findIndex(sub => sub.endpoint === subscription.endpoint);
if (index !== -1) {
subscriptions[index] = subscription; // Update existing subscription
console.log('Subscription for publisher', id, 'updated.')
} else {
subscriptions.push(subscription); // Add new subscription
console.log('Subscription for publisher', id, 'saved.')
}
await prisma.publisher.update({
where: { id },
data: { pushSubscription: subscriptions }
});
console.log('Subscription update successful', subscription.keys.auth, ". Total subscriptions:", subscriptions.length)
res.send({ subs: subscriptions.length })
res.statusCode = 200
res.end()
}
if (req.method == 'DELETE') {
// remove the subscription object from the database
// publisher.pushSubscription = null
const prisma = common.getPrismaClient();
const { subscriptionId, id } = req.body;
const publisher = await prisma.publisher.findUnique({
where: { id },
select: { pushSubscription: true }
});
let subscriptions = Array.isArray(publisher.pushSubscription) ? publisher.pushSubscription : (publisher.pushSubscription ? [publisher.pushSubscription] : []);
try {
subscriptions = subscriptionId ? subscriptions.filter(sub => sub.endpoint !== subscriptionId) : [];
await prisma.publisher.update({
where: { id },
data: { pushSubscription: subscriptions }
});
} catch (e) {
console.log(e)
await prisma.publisher.update({
where: { id },
data: { pushSubscription: null }
});
}
console.log('Subscription for publisher', id, 'deleted')
res.send({ subs: subscriptions.length })
res.statusCode = 200
res.end()
}
if (req.method == 'POST') {//title = "ССС", message = "Ще получите уведомление по този начин.")
const { subscription, id, ids, broadcast, title = 'ССОМ', message = 'Ще получавате уведомления така.', actions } = req.body
if (broadcast) {
await broadcastPush(title, message, actions)
res.statusCode = 200
res.end()
return
} else if (ids && ids.length) {
console.log('Sending push notifications to publishers ', ids);
await Promise.all(ids.map(_id => sendPush(_id, title, message, actions)));
res.statusCode = 200;
res.end();
return;
} else if (id) {
console.log('Sending push notification to publisher ', id)
await sendPush(id, title, message, actions)
res.statusCode = 200
res.end()
return
} else if (subscription) {
await webPush
.sendNotification(
subscription,
JSON.stringify({ title, message, actions })
)
.then(response => {
res.writeHead(response.statusCode, response.headers).end(response.body)
})
.catch(err => {
if ('statusCode' in err) {
res.writeHead(err.statusCode, err.headers).end(err.body)
} else {
console.error(err)
res.statusCode = 500
res.end()
}
})
}
} else {
res.statusCode = 405
res.end()
}
}
export default Notification
//export pushNotification(userId or email) for use in other files
export const sendPush = async (id, title, message, actions) => {
const prisma = common.getPrismaClient();
const publisher = await prisma.publisher.findUnique({
where: { id }
})
if (publisher.pushSubscription && Array.isArray(publisher.pushSubscription) && publisher.pushSubscription.length) {
for (const subscription of publisher.pushSubscription) {
await webPush
.sendNotification(
subscription,
JSON.stringify({ title, message, actions })
)
.then(response => {
console.log('Push notification sent to publisher', id)
})
.catch(err => {
console.error('Error sending push notification to publisher', id, ':', err)
})
}
} else {
console.log('No valid subscriptions found for publisher', id)
}
}
//export breoadcastNotification for use in other files
export const broadcastPush = async (title, message, actions) => {
const prisma = common.getPrismaClient();
const publishers = await prisma.publisher.findMany({
where: { pushSubscription: { not: null } }
})
for (const publisher of publishers) {
if (Array.isArray(publisher.pushSubscription) && publisher.pushSubscription.length) {
for (const subscription of publisher.pushSubscription) {
await webPush.sendNotification(
subscription, // Here subscription is each individual subscription object
JSON.stringify({ title, message, actions })
)
.then(response => {
console.log('Push notification sent to device', subscription.endpoint, 'of publisher', publisher.id);
})
.catch(err => {
console.error('Error sending push notification to device', subscription.endpoint, 'of publisher', publisher.id, ':', err);
// Optionally handle failed subscriptions, e.g., remove outdated or invalid subscriptions
});
}
} else {
console.log('No valid subscriptions found for publisher', publisher.id);
}
}
}