185 lines
5.6 KiB
JavaScript
185 lines
5.6 KiB
JavaScript
const path = require("path");
|
|
require("dotenv").config({
|
|
path: path.resolve(process.cwd(), `.env.${process.env.NODE_ENV || "development"}`)
|
|
});
|
|
|
|
const client = require("../graphql-client/graphql-client").client;
|
|
const queries = require("../graphql-client/queries");
|
|
const { phone } = require("phone");
|
|
const { admin } = require("../firebase/firebase-handler");
|
|
const logger = require("../utils/logger");
|
|
const InstanceManager = require("../utils/instanceMgr").default;
|
|
|
|
exports.receive = async (req, res) => {
|
|
const {
|
|
ioRedis,
|
|
ioHelpers: { getBodyshopRoom, getBodyshopConversationRoom }
|
|
} = req;
|
|
|
|
const loggerData = {
|
|
msid: req.body.SmsMessageSid,
|
|
text: req.body.Body,
|
|
image: !!req.body.MediaUrl0,
|
|
image_path: generateMediaArray(req.body)
|
|
};
|
|
|
|
logger.log("sms-inbound", "DEBUG", "api", null, loggerData);
|
|
|
|
if (!req.body || !req.body.MessagingServiceSid || !req.body.SmsMessageSid) {
|
|
logger.log("sms-inbound-error", "ERROR", "api", null, {
|
|
...loggerData,
|
|
type: "malformed-request"
|
|
});
|
|
return res.status(400).json({ success: false, error: "Malformed Request" });
|
|
}
|
|
|
|
try {
|
|
const response = await client.request(queries.FIND_BODYSHOP_BY_MESSAGING_SERVICE_SID, {
|
|
mssid: req.body.MessagingServiceSid,
|
|
phone: phone(req.body.From).phoneNumber
|
|
});
|
|
|
|
if (!response.bodyshops[0]) {
|
|
return res.status(400).json({ success: false, error: "No matching bodyshop" });
|
|
}
|
|
|
|
const bodyshop = response.bodyshops[0];
|
|
const isNewConversation = bodyshop.conversations.length === 0;
|
|
const isDuplicate = bodyshop.conversations.length > 1;
|
|
|
|
let newMessage = {
|
|
msid: req.body.SmsMessageSid,
|
|
text: req.body.Body,
|
|
image: !!req.body.MediaUrl0,
|
|
image_path: generateMediaArray(req.body)
|
|
};
|
|
|
|
if (isDuplicate) {
|
|
logger.log("sms-inbound-error", "ERROR", "api", null, {
|
|
...loggerData,
|
|
messagingServiceSid: req.body.MessagingServiceSid,
|
|
type: "duplicate-phone"
|
|
});
|
|
return res.status(400).json({ success: false, error: "Duplicate phone number" });
|
|
}
|
|
|
|
if (isNewConversation) {
|
|
newMessage.conversation = {
|
|
data: {
|
|
bodyshopid: bodyshop.id,
|
|
phone_num: phone(req.body.From).phoneNumber,
|
|
archived: false
|
|
}
|
|
};
|
|
} else {
|
|
const existingConversation = bodyshop.conversations[0];
|
|
|
|
// Update the conversation to unarchive it
|
|
if (existingConversation.archived) {
|
|
await client.request(queries.UNARCHIVE_CONVERSATION, {
|
|
id: existingConversation.id,
|
|
archived: false
|
|
});
|
|
}
|
|
|
|
newMessage.conversationid = existingConversation.id;
|
|
}
|
|
|
|
const query = isNewConversation ? queries.RECEIVE_MESSAGE : queries.INSERT_MESSAGE;
|
|
const variables = isNewConversation
|
|
? { msg: newMessage }
|
|
: { msg: newMessage, conversationid: newMessage.conversationid };
|
|
|
|
const insertresp = await client.request(query, variables);
|
|
const message = insertresp?.insert_messages?.returning?.[0];
|
|
const conversation = message?.conversation || null;
|
|
|
|
if (!conversation) {
|
|
throw new Error("Conversation data is missing from the response.");
|
|
}
|
|
|
|
const broadcastRoom = getBodyshopRoom(conversation.bodyshop.id);
|
|
const conversationRoom = getBodyshopConversationRoom({
|
|
bodyshopId: conversation.bodyshop.id,
|
|
conversationId: conversation.id
|
|
});
|
|
|
|
const commonPayload = {
|
|
isoutbound: false,
|
|
conversationId: conversation.id,
|
|
updated_at: message.updated_at,
|
|
msid: message.sid
|
|
};
|
|
|
|
ioRedis.to(broadcastRoom).emit("new-message-summary", {
|
|
...commonPayload,
|
|
existingConversation: !isNewConversation,
|
|
newConversation: isNewConversation ? conversation : null,
|
|
summary: true
|
|
});
|
|
|
|
ioRedis.to(conversationRoom).emit("new-message-detailed", {
|
|
newMessage: message,
|
|
...commonPayload,
|
|
newConversation: isNewConversation ? conversation : null,
|
|
existingConversation: !isNewConversation,
|
|
summary: false
|
|
});
|
|
|
|
const fcmresp = await admin.messaging().send({
|
|
topic: `${message.conversation.bodyshop.imexshopid}-messaging`,
|
|
notification: {
|
|
title: InstanceManager({
|
|
imex: `ImEX Online Message - ${message.conversation.phone_num}`,
|
|
rome: `Rome Online Message - ${message.conversation.phone_num}`,
|
|
promanager: `ProManager Message - ${message.conversation.phone_num}`
|
|
}),
|
|
body: message.image_path ? `Image ${message.text}` : message.text
|
|
},
|
|
data: {
|
|
type: "messaging-inbound",
|
|
conversationid: message.conversationid || "",
|
|
text: message.text || "",
|
|
messageid: message.id || "",
|
|
phone_num: message.conversation.phone_num || ""
|
|
}
|
|
});
|
|
|
|
logger.log("sms-inbound-success", "DEBUG", "api", null, {
|
|
newMessage,
|
|
fcmresp
|
|
});
|
|
|
|
res.status(200).send("");
|
|
} catch (e) {
|
|
handleError(req, e, res, "RECEIVE_MESSAGE");
|
|
}
|
|
};
|
|
|
|
const generateMediaArray = (body) => {
|
|
const { NumMedia } = body;
|
|
if (parseInt(NumMedia) > 0) {
|
|
const ret = [];
|
|
for (let i = 0; i < parseInt(NumMedia); i++) {
|
|
ret.push(body[`MediaUrl${i}`]);
|
|
}
|
|
return ret;
|
|
} else {
|
|
return null;
|
|
}
|
|
};
|
|
|
|
const handleError = (req, error, res, context) => {
|
|
logger.log("sms-inbound-error", "ERROR", "api", null, {
|
|
msid: req.body.SmsMessageSid,
|
|
text: req.body.Body,
|
|
image: !!req.body.MediaUrl0,
|
|
image_path: generateMediaArray(req.body),
|
|
messagingServiceSid: req.body.MessagingServiceSid,
|
|
context,
|
|
error
|
|
});
|
|
|
|
res.status(500).json({ error: error.message || "Internal Server Error" });
|
|
};
|