import moment from 'moment' import * as UserController from '../../controllers/user' import { prismaClient as prisma } from '../../prismaClient' import { logger } from '../logger' import * as Twilio from '../twilio' import { EventWebhook } from './types' export const handleEmailNotification = async (req, res) => { res.status(200).end() const notifications: EventWebhook[] = req.body try { if (notifications?.length > 0) { for await (const notification of notifications) { const { reason, event, email, emailTemplate } = notification try { const user = await UserController.querySingleUser({ email, }) if (!user) { return } if (event === 'spamreport') { await prisma.user.update({ where: { id: user.id, }, data: { cantDeliverEmail: true, cantDeliverEmailReason: 'SPAM', cantDeliverEmailFullReason: reason, }, }) } if (event === 'unsubscribe') { await prisma.user.update({ where: { id: user.id, }, data: { cantDeliverEmail: true, cantDeliverEmailReason: 'BLOCKED', cantDeliverEmailFullReason: reason, }, }) } if (event === 'delivered') { if (notification.notificationId) { const walterNotification = await prisma.notification.update({ where: { id: notification.notificationId, }, data: { delivered: true, deliveredByEmail: true, deliveredByEmailAt: moment().toDate(), }, }) if (!walterNotification.deliveredAt) { await prisma.notification.update({ where: { id: walterNotification.id, }, data: { deliveredAt: moment().toDate(), }, }) } } if (user.cantDeliverEmail) { await prisma.user.update({ where: { id: user.id, }, data: { cantDeliverEmail: false, cantDeliverEmailReason: null, }, }) } } if (event === 'open') { // Notification seen if (notification.notificationId) { const walterNotification = await prisma.notification.findOne({ where: { id: notification.notificationId }, }) if ( !walterNotification.hasBeenSeen || !walterNotification.hasBeenSeenAt || !walterNotification.hasBeenSeenByEmail || !walterNotification.hasBeenSeenByEmailAt ) { await prisma.notification.update({ where: { id: walterNotification.id, }, data: { ...(!walterNotification.hasBeenSeenByEmail && { hasBeenSeenByEmail: true }), ...(!walterNotification.hasBeenSeen && { hasBeenSeen: true }), ...(!walterNotification.hasBeenSeenAt && { hasBeenSeenAt: moment().toDate() }), ...(!walterNotification.hasBeenSeenByEmailAt && { hasBeenSeenByEmailAt: moment().toDate(), }), }, }) } } // Walter Invitation if ( (emailTemplate === 'RESIDENT_FIRST_INVITE' || emailTemplate === 'RESIDENT_FIRST_INVITE_FR') && !user.hasOpenedEmailInvitationAt ) { await prisma.user.update({ where: { id: user.id }, data: { hasOpenedEmailInvitation: true, hasOpenedEmailInvitationAt: new Date(), }, }) } else if ( emailTemplate === 'RESIDENT_SECOND_INVITE' && !user.hasOpenedSecondEmailInvitation ) { await prisma.user.update({ where: { id: user.id }, data: { hasOpenedSecondEmailInvitation: true, hasOpenedSecondEmailInvitationAt: new Date(), }, }) } // New message email mark as read. } if (event === 'dropped') { if (notification.notificationId) { await prisma.notification.update({ where: { id: notification.notificationId, }, data: { deliveryErrorMessageEmail: "Email couldn't be delivered (User might have unsubscribed from the email list)", }, }) } } if (event === 'bounce') { // Cant deliver email + if there's a postId we need to send it another way if (!user.cantDeliverEmail) { await prisma.user.update({ where: { id: user.id, }, data: { cantDeliverEmail: true, cantDeliverEmailReason: 'BOUNCED', cantDeliverEmailFullReason: reason, }, }) } // Send the post as a SMS if the email bounced if (notification.postId) { const [post, userPhone] = await Promise.all([ prisma.post.findOne({ where: { id: notification.postId } }), prisma.user.findOne({ where: { id: user.id } }).phone(), ]) const postNotifications = await prisma.post .findOne({ where: { id: post.id } }) .notifications({ where: { user: { id: user.id } } }) if (userPhone && user.hasSMSNotificationEnable) { await Twilio.sendSMS({ to: userPhone.number, body: `Nouvel avis / New announcement\n\n${ !user.hasInstalledApp && user.role === 'RESIDENT' ? `\n\n${await UserController.getDownloadWalterMessage({ user, projectId: user.currentProjectId, })}` : '' }`, itemId: postNotifications[0]?.id, }) } } if (notification.notificationId) { await prisma.notification.update({ where: { id: notification.notificationId, }, data: { deliveryErrorMessageEmail: 'User email is invalid. The email bounced when we tried to send it.', }, }) } } if (event === 'click') { if ( (emailTemplate === 'RESIDENT_FIRST_INVITE' || emailTemplate === 'RESIDENT_FIRST_INVITE_FR') && !user.hasClickedOnCTAInEmailInvitation ) { await prisma.user.update({ where: { id: user.id }, data: { hasClickedOnCTAInEmailInvitation: true, hasClickedOnCTAInEmailInvitationAt: new Date(), }, }) } else if ( emailTemplate === 'RESIDENT_SECOND_INVITE' && !user.hasClickedOnCTAInSecondEmailInvitation ) { await prisma.user.update({ where: { id: user.id }, data: { hasClickedOnCTAInSecondEmailInvitation: true, hasClickedOnCTAInSecondEmailInvitationAt: new Date(), }, }) } } } catch (error) { logger.error(error) } } } else { logger.error( `req.body is not an array when receiving notification with Sendgrid? ${JSON.stringify( req.body )}` ) } } catch (error) { logger.error(error) } }