141 lines
4.6 KiB
JavaScript
141 lines
4.6 KiB
JavaScript
const twilio = require("twilio");
|
|
const { phone } = require("phone");
|
|
const { INSERT_MESSAGE, GET_PHONE_NUMBER_CONSENT } = require("../graphql-client/queries");
|
|
const client = twilio(process.env.TWILIO_AUTH_TOKEN, process.env.TWILIO_AUTH_KEY);
|
|
const gqlClient = require("../graphql-client/graphql-client").client;
|
|
|
|
const send = async (req, res) => {
|
|
const { to, messagingServiceSid, body, conversationid, selectedMedia, imexshopid, bodyshopid } = req.body;
|
|
const {
|
|
ioRedis,
|
|
logger,
|
|
ioHelpers: { getBodyshopRoom, getBodyshopConversationRoom },
|
|
sessionUtils: { getBodyshopFromRedis }
|
|
} = req;
|
|
|
|
logger.log("sms-outbound", "DEBUG", req.user.email, null, {
|
|
messagingServiceSid,
|
|
to: phone(to).phoneNumber,
|
|
mediaUrl: selectedMedia.map((i) => i.src),
|
|
text: body,
|
|
conversationid,
|
|
isoutbound: true,
|
|
userid: req.user.email,
|
|
image: selectedMedia.length > 0,
|
|
image_path: selectedMedia.length > 0 ? selectedMedia.map((i) => i.src) : []
|
|
});
|
|
|
|
if (!to || !messagingServiceSid || (!body && selectedMedia.length === 0) || !conversationid || !bodyshopid) {
|
|
logger.log("sms-outbound-error", "ERROR", req.user.email, null, {
|
|
type: "missing-parameters",
|
|
messagingServiceSid,
|
|
to: phone(to).phoneNumber,
|
|
text: body,
|
|
conversationid,
|
|
isoutbound: true,
|
|
userid: req.user.email,
|
|
image: selectedMedia.length > 0,
|
|
image_path: selectedMedia.length > 0 ? selectedMedia.map((i) => i.src) : []
|
|
});
|
|
res.status(400).json({ success: false, message: "Missing required parameter(s)." });
|
|
return;
|
|
}
|
|
|
|
try {
|
|
// Check bodyshop's enforce_sms_consent setting
|
|
const bodyShopData = await getBodyshopFromRedis(bodyshopid);
|
|
const enforceConsent = bodyShopData?.enforce_sms_consent ?? false;
|
|
|
|
// Check consent only if enforcement is enabled
|
|
if (enforceConsent) {
|
|
const normalizedPhone = phone(to, "CA").phoneNumber.replace(/^\+1/, "");
|
|
const consentResponse = await gqlClient.request(GET_PHONE_NUMBER_CONSENT, {
|
|
bodyshopid,
|
|
phone_number: normalizedPhone
|
|
});
|
|
if (!consentResponse.phone_number_consent?.length || !consentResponse.phone_number_consent[0].consent_status) {
|
|
logger.log("sms-outbound-error", "ERROR", req.user.email, null, {
|
|
type: "no-consent",
|
|
phone_number: normalizedPhone,
|
|
conversationid
|
|
});
|
|
return res.status(403).json({
|
|
success: false,
|
|
message: "Phone number has not consented to messaging."
|
|
});
|
|
}
|
|
}
|
|
|
|
const message = await client.messages.create({
|
|
body,
|
|
messagingServiceSid,
|
|
to: phone(to).phoneNumber,
|
|
mediaUrl: selectedMedia.map((i) => i.src)
|
|
});
|
|
|
|
const newMessage = {
|
|
msid: message.sid,
|
|
text: body,
|
|
conversationid,
|
|
isoutbound: true,
|
|
userid: req.user.email,
|
|
image: selectedMedia.length > 0,
|
|
image_path: selectedMedia.length > 0 ? selectedMedia.map((i) => i.src) : []
|
|
};
|
|
|
|
try {
|
|
const gqlResponse = await gqlClient.request(INSERT_MESSAGE, {
|
|
msg: newMessage,
|
|
conversationid
|
|
});
|
|
|
|
logger.log("sms-outbound-success", "DEBUG", req.user.email, null, {
|
|
msid: message.sid,
|
|
conversationid
|
|
});
|
|
|
|
const insertedMessage = gqlResponse.insert_messages.returning[0];
|
|
const broadcastRoom = getBodyshopRoom(insertedMessage.conversation.bodyshop.id);
|
|
const conversationRoom = getBodyshopConversationRoom({
|
|
bodyshopId: insertedMessage.conversation.bodyshop.id,
|
|
conversationId: insertedMessage.conversation.id
|
|
});
|
|
|
|
ioRedis.to(broadcastRoom).emit("new-message-summary", {
|
|
isoutbound: true,
|
|
conversationId: conversationid,
|
|
updated_at: insertedMessage.updated_at,
|
|
msid: message.sid,
|
|
summary: true
|
|
});
|
|
|
|
ioRedis.to(conversationRoom).emit("new-message-detailed", {
|
|
newMessage: insertedMessage,
|
|
conversationId: conversationid,
|
|
summary: false
|
|
});
|
|
|
|
res.sendStatus(200);
|
|
} catch (gqlError) {
|
|
logger.log("sms-outbound-error", "ERROR", req.user.email, null, {
|
|
msid: message.sid,
|
|
conversationid,
|
|
error: gqlError.message,
|
|
stack: gqlError.stack
|
|
});
|
|
res.status(500).json({ success: false, message: "Failed to insert message into database." });
|
|
}
|
|
} catch (twilioError) {
|
|
logger.log("sms-outbound-error", "ERROR", req.user.email, null, {
|
|
conversationid,
|
|
error: twilioError.message,
|
|
stack: twilioError.stack
|
|
});
|
|
res.status(500).json({ success: false, message: "Failed to send message through Twilio." });
|
|
}
|
|
};
|
|
|
|
module.exports = {
|
|
send
|
|
};
|