Notificaciones push a dispositivos

This commit is contained in:
David Arranz 2023-04-20 14:20:09 +02:00
parent 0a56da7c7a
commit 2bef00a3c0
6 changed files with 163 additions and 104 deletions

View File

@ -303,7 +303,7 @@ const extraControllers = {
try {
let notification = notificationHelper.createNotificationValidatedInscription(inscription);
console.log(notification);
let result = notificationService.sendNotification(notification, [inscription.user.id]);
let result = notificationService.sendNotificationToUsers(notification, [inscription.user.id]);
console.log(result);
} catch (error) {

View File

@ -322,7 +322,7 @@ module.exports = function (sequelize, DataTypes) {
model: sequelize.models.MultimediaFile,
as: "multimediaFile"
}],
order: [["type", "asc"]],
order: [["type", "ASC"]], // <- esto no funciona por ahora en Sequelize
},
]
}

View File

@ -21,7 +21,7 @@ const controllerOptions = { MODULE_NAME };
async function _sendNotificationAllActiveUsers(notification) {
let limit = 4;
let limit = 33;
let page = 1;
let totalRows = 0;
@ -38,7 +38,7 @@ async function _sendNotificationAllActiveUsers(notification) {
page = page + 1;
let ids = result.rows.map(function (item) { return item.id });
notificationService.sendNotification(notification, ids);
notificationService.sendNotificationToUsers(notification, ids);
} while (page <= totalPages);
@ -46,6 +46,32 @@ async function _sendNotificationAllActiveUsers(notification) {
return 'OK';
}
async function _sendNotificationAllActiveDevices(notification) {
let limit = 33;
let page = 1;
let totalRows = 0;
let totalPages = -1;
do {
let offset = (page - 1) * limit;
let result = await userDeviceService._getActiveDeviceIds(offset, limit);
console.log(result);
if (totalPages == -1) {
totalPages = Math.ceil(result.count / limit);
}
page = page + 1;
notificationService.sendNotificationToDevices(notification, result.rows);
} while (page <= totalPages);
return 'OK';
}
async function _getUserIdsForEventId(eventId, segment) {
let userIds = [];
@ -80,8 +106,8 @@ const extraControllers = {
/**
* notificationSample = {
* "tittle": "título de la notificación",
* "message": "cuerpo de la notificación",
* "title": "título de la notificación",
* "body": "cuerpo de la notificación",
* "recipients": {
* OPCION 1- Unos usuarios determinados
* "userIds": ["*" | "f428a317-6d1f-4eda-aa3e-22baff3f48d7", ...]
@ -92,6 +118,8 @@ const extraControllers = {
* "segment": "ALL" | "ALL_VALIDATED" | "ALL_NOT_VALIDATED" |
* "PARTNERS_ALL" | "PARTNERS_VALIDATED" | "PARTNERS_NOT_VALIDATED" |
* "COLLEGE_ALL" | "COLLEGE_VALIDATED" | "COLLEGE_NOT_VALIDATED"
* OPCION 3 - A todos los dispositivos activos
* "deviceIds": ["*" | "ExponentPushToken[YbOS1AIZjQbchZbxNaVRqC]", ...]
* },
* "data": {
* "type": "message",
@ -117,6 +145,7 @@ const extraControllers = {
let receipt = undefined;
let userIds = undefined;
let deviceIds = undefined;
let eventId = undefined;
let segment = undefined;
const { body } = req;
@ -129,6 +158,7 @@ const extraControllers = {
return handleErrorResponse(controllerOptions.MODULE_NAME, 'sendNotification', new Error('Missing body content'), res)
}
// Evento?
if (body.recipients.eventId) {
eventId = body.recipients.eventId;
@ -136,13 +166,14 @@ const extraControllers = {
} else if (body.recipients.userIds) {
userIds = body.recipients.userIds;
segment = body.recipients.segment;
} else if (body.recipients.deviceIds) {
deviceIds = body.recipients.deviceIds;
} else {
return handleErrorResponse(controllerOptions.MODULE_NAME, 'sendNotification', new Error('Missing user Ids or event Ids'), res)
return handleErrorResponse(controllerOptions.MODULE_NAME, 'sendNotification', new Error('Missing user Ids or event Ids or devices Ids'), res)
}
try {
let notification = notificationHelper.createNotification({
...body,
userId: context.user.id
@ -150,6 +181,8 @@ const extraControllers = {
if ((userIds) && (userIds.length == 1) && (userIds[0] == "*")) {
receipt = _sendNotificationAllActiveUsers(notification);
} else if ((deviceIds) && (deviceIds.length == 1) && (deviceIds[0] == "*")) {
receipt = _sendNotificationAllActiveDevices(notification);
} else {
let _userIds = null;
@ -165,45 +198,10 @@ const extraControllers = {
}
if (_userIds) {
receipt = notificationService.sendNotification(notification, _userIds);
receipt = notificationService.sendNotificationToUsers(notification, _userIds);
}
}
/*let getUserIds = async () => {
if (userIds) {
return new Promise(function(resolve) { resolve(userIds) } );
} else if (eventId) {
switch (segment) {
//Todos los inscritos tanto invitados como libres
case 'ALL_VALIDATED':
userIds = await eventInscriptionService._getInscriptionByEventAndValidated(eventId, true);
break;
//Todos los de lista de espera tanto invitados como libres (Actualmente en invitados no hay lista de espera)
case 'ALL_NOT_VALIDATED':
userIds = await eventInscriptionService._getInscriptionByEventAndValidated(eventId, false);
break;
//Solo invitados como actualmente no se usa codigo de reserva para los coles, vale con filtrar por aquellos que tengan codigo de reserva
case 'PARTNERS_ALL':
userIds = await eventInscriptionService._getInscriptionByEventFromPartner(eventId);
break;
//Todos los inscritos al evento, tanto validados como en lista de espera
default: //ALL
userIds = await eventInscriptionService._getInscriptionByEvent(eventId);
break;
}
return new Promise(function (resolve) { resolve(usersIdsComposer(userIds)); });
} else {
return handleErrorResponse(controllerOptions.MODULE_NAME, 'sendNotification', new Error('Missing event and segment'), res)
}
} */
//receipt = notificationService.sendNotification(notification, await getUserIds());
return handleResultResponse(receipt, null, null, res, httpStatus.OK);
} catch (error) {
console.error(error);

View File

@ -6,9 +6,67 @@ const notificationDetailService = require('./notification_detail.service');
const pushHelper = require('../../helpers/push.helper');
const models = require('../../core/models');
const saveNotification = (notification) => extraMethods.saveNotification(notification);
const getUserDevices = async (userId) => {
const result = await userDeviceService.fetchAll({ params: { userId: userId } }, {});
return result.rows;
};
const disableUserDevice = (token) => userDeviceService.update({
params: {
token: token,
}
}, { valid: 0, invalidated: moment() }, {});
const disableInvalidUserDevices = async (devices) => {
console.log(devices);
const okDevices = [];
devices.forEach(async (device) => {
if (!userDeviceService.isValidPushToken(device.token)) {
await disableUserDevice(device.token);
} else {
okDevices.push(device);
}
});
return okDevices;
};
const buildPushMessages = (notification, devices) => {
let messages = [];
devices.forEach(async function (device) {
messages.push(pushHelper.createPushMessage({
...notification,
userId: device.userId,
to: device.token,
}));
});
return messages;
};
const disableUserDevicesWithErrorStatus = (messages, tickets) => {
tickets.forEach(async function (ticket, index) {
if ((ticket.status === 'error') && (ticket.details.error === 'DeviceNotRegistered')) {
disableUserDevice(messages[index].to)
}
});
}
let saveResponseStatusPromise = (messages, tickets) => notificationDetailService.saveNotificationDetails(messages, tickets);
const extraMethods = {
createNotification: (data) => {
/*createNotification: (data) => {
return {
date: data.date,
title: data.title,
@ -19,7 +77,7 @@ const extraMethods = {
data: data.data,
userId: data.userId,
}
},
},*/
saveNotification: ({ date, title, body, ttl, priority, recipients, data, userId }) => {
return models.Notification.create({
@ -35,67 +93,11 @@ const extraMethods = {
},
sendNotification: (notification, userIds) => {
/*sendNotificationToUsers: (notification, userIds) => {
console.log('sendNofitication -----------------------------------------------');
console.log('sendNotificationToUsers -----------------------------------------------');
console.log(notification, userIds);
let getUserDevicesPromise = (userId) => userDeviceService.fetchAll({ params: { userId: userId } }, {}).then(function (result) {
return new Promise(function (resolve) { resolve(result.rows) });
});
let saveNotificationPromise = (notification) => extraMethods.saveNotification(notification);
let sendNotificationsPromise = (messages) => pushHelper.sendPushMessage(messages);
let disableUserDevicePromise = (token) => userDeviceService.update({
params: {
token: token,
}
}, { valid: 0, invalidated: moment() }, {});
let disableInvalidUserDevicesPromise = (userDevices) => {
return new Promise(function (resolve) {
let _userDevices = [];
userDevices.forEach(async function (userDevice) {
if (!userDeviceService.isValidPushToken(userDevice.token)) {
await disableUserDevicePromise(userDevice.token);
} else {
_userDevices.push(userDevice);
}
});
resolve(_userDevices)
});
};
let disableUserDevicesWithErrorStatus = (messages, tickets) => {
return new Promise(function (resolve) {
tickets.forEach(async function (ticket, index) {
if ((ticket.status === 'error') && (ticket.details.error === 'DeviceNotRegistered')) {
await disableUserDevicePromise(messages[index].to)
}
});
resolve(true);
});
}
let saveResponseStatusPromise = (messages, tickets) => notificationDetailService.saveNotificationDetails(messages, tickets);
let buildMessagesPromise = (userDevices) => {
return new Promise(function (resolve) {
let messages = [];
userDevices.forEach(async function (userDevice) {
messages.push(pushHelper.createPushMessage({
...notification,
userId: userDevice.userId,
to: userDevice.token,
}));
});
resolve(messages)
});
};
let getUserDevicesList = [];
saveNotificationPromise(notification)
@ -128,9 +130,56 @@ const extraMethods = {
console.log(details);
return details;
});
},*/
sendNotificationToUsers: async (notification, userIds) => {
console.log('sendNotificationToUsers -----------------------------------------------');
console.log(notification);
const savedNotification = (await saveNotification(notification)).toJSON();
const userDevicesList = await Promise.all(userIds.map((userId) => getUserDevices(userId)));
const allDevices = userDevicesList.flat();
const validDevices = await disableInvalidUserDevices(allDevices);
const pushMessages = buildPushMessages(savedNotification, validDevices);
const { messages, tickets } = await pushHelper.sendPushMessage(pushMessages);
saveResponseStatusPromise(messages, tickets);
disableUserDevicesWithErrorStatus(messages, tickets);
return;
},
sendNotificationToDevices: async (notification, devicesIds) => {
console.log('sendNotificationToDevices -----------------------------------------------');
console.log(notification);
const savedNotification = (await saveNotification(notification)).toJSON();
const validDevices = await disableInvalidUserDevices(devicesIds);
const pushMessages = buildPushMessages(savedNotification, validDevices);
const { messages, tickets } = await pushHelper.sendPushMessage(pushMessages);
saveResponseStatusPromise(messages, tickets);
disableUserDevicesWithErrorStatus(messages, tickets);
return;
},
getNotificationsWithoutReceipt: async () => {

View File

@ -17,6 +17,7 @@ const pushSendEvent = Joi.object().keys({
body: Joi.string().required(),
recipients: Joi.object().keys({
userIds: Joi.array().optional(),
deviceIds: Joi.array().optional(),
eventId: Joi.string().optional(),
segment: Joi.string().optional(),
}),

View File

@ -28,6 +28,17 @@ const extraMethods = {
where: params,
});
},
_getActiveDeviceIds: async (offset = 0, limit = 10) => {
return models.UserDevice.findAndCountAll({
where: {
valid: 1,
},
raw: true,
limit: limit,
offset: offset,
});
},
};
module.exports = generateService(models.UserDevice, extraMethods);