feature/IO-3182-Phone-Number-Consent - Checkpoint
This commit is contained in:
@@ -1,16 +1,61 @@
|
|||||||
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 client = require("../graphql-client/graphql-client").client;
|
||||||
const queries = require("../graphql-client/queries");
|
const {
|
||||||
|
FIND_BODYSHOP_BY_MESSAGING_SERVICE_SID,
|
||||||
|
UNARCHIVE_CONVERSATION,
|
||||||
|
CREATE_CONVERSATION,
|
||||||
|
INSERT_MESSAGE
|
||||||
|
} = require("../graphql-client/queries");
|
||||||
const { phone } = require("phone");
|
const { phone } = require("phone");
|
||||||
const { admin } = require("../firebase/firebase-handler");
|
const { admin } = require("../firebase/firebase-handler");
|
||||||
const logger = require("../utils/logger");
|
const logger = require("../utils/logger");
|
||||||
const InstanceManager = require("../utils/instanceMgr").default;
|
const InstanceManager = require("../utils/instanceMgr").default;
|
||||||
|
|
||||||
exports.receive = async (req, res) => {
|
/**
|
||||||
|
* Generate an array of media URLs from the request body
|
||||||
|
* @param body
|
||||||
|
* @returns {null|*[]}
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle errors during the message receiving process
|
||||||
|
* @param req
|
||||||
|
* @param error
|
||||||
|
* @param res
|
||||||
|
* @param context
|
||||||
|
*/
|
||||||
|
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" });
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Receive an inbound SMS message
|
||||||
|
* @param req
|
||||||
|
* @param res
|
||||||
|
* @returns {Promise<*>}
|
||||||
|
*/
|
||||||
|
const receive = async (req, res) => {
|
||||||
const {
|
const {
|
||||||
ioRedis,
|
ioRedis,
|
||||||
ioHelpers: { getBodyshopRoom, getBodyshopConversationRoom }
|
ioHelpers: { getBodyshopRoom, getBodyshopConversationRoom }
|
||||||
@@ -35,7 +80,7 @@ exports.receive = async (req, res) => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// Step 1: Find the bodyshop and existing conversation
|
// Step 1: Find the bodyshop and existing conversation
|
||||||
const response = await client.request(queries.FIND_BODYSHOP_BY_MESSAGING_SERVICE_SID, {
|
const response = await client.request(FIND_BODYSHOP_BY_MESSAGING_SERVICE_SID, {
|
||||||
mssid: req.body.MessagingServiceSid,
|
mssid: req.body.MessagingServiceSid,
|
||||||
phone: phone(req.body.From).phoneNumber
|
phone: phone(req.body.From).phoneNumber
|
||||||
});
|
});
|
||||||
@@ -68,14 +113,14 @@ exports.receive = async (req, res) => {
|
|||||||
|
|
||||||
// Unarchive the conversation if necessary
|
// Unarchive the conversation if necessary
|
||||||
if (existingConversation.archived) {
|
if (existingConversation.archived) {
|
||||||
await client.request(queries.UNARCHIVE_CONVERSATION, {
|
await client.request(UNARCHIVE_CONVERSATION, {
|
||||||
id: conversationid,
|
id: conversationid,
|
||||||
archived: false
|
archived: false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Create a new conversation
|
// Create a new conversation
|
||||||
const newConversationResponse = await client.request(queries.CREATE_CONVERSATION, {
|
const newConversationResponse = await client.request(CREATE_CONVERSATION, {
|
||||||
conversation: {
|
conversation: {
|
||||||
bodyshopid: bodyshop.id,
|
bodyshopid: bodyshop.id,
|
||||||
phone_num: phone(req.body.From).phoneNumber,
|
phone_num: phone(req.body.From).phoneNumber,
|
||||||
@@ -90,7 +135,7 @@ exports.receive = async (req, res) => {
|
|||||||
newMessage.conversationid = conversationid;
|
newMessage.conversationid = conversationid;
|
||||||
|
|
||||||
// Step 3: Insert the message into the conversation
|
// Step 3: Insert the message into the conversation
|
||||||
const insertresp = await client.request(queries.INSERT_MESSAGE, {
|
const insertresp = await client.request(INSERT_MESSAGE, {
|
||||||
msg: newMessage,
|
msg: newMessage,
|
||||||
conversationid: conversationid
|
conversationid: conversationid
|
||||||
});
|
});
|
||||||
@@ -137,7 +182,7 @@ exports.receive = async (req, res) => {
|
|||||||
notification: {
|
notification: {
|
||||||
title: InstanceManager({
|
title: InstanceManager({
|
||||||
imex: `ImEX Online Message - ${message.conversation.phone_num}`,
|
imex: `ImEX Online Message - ${message.conversation.phone_num}`,
|
||||||
rome: `Rome Online Message - ${message.conversation.phone_num}`,
|
rome: `Rome Online Message - ${message.conversation.phone_num}`
|
||||||
}),
|
}),
|
||||||
body: message.image_path ? `Image ${message.text}` : message.text
|
body: message.image_path ? `Image ${message.text}` : message.text
|
||||||
},
|
},
|
||||||
@@ -161,29 +206,6 @@ exports.receive = async (req, res) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const generateMediaArray = (body) => {
|
module.exports = {
|
||||||
const { NumMedia } = body;
|
receive
|
||||||
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" });
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
const path = require("path");
|
|
||||||
require("dotenv").config({
|
|
||||||
path: path.resolve(process.cwd(), `.env.${process.env.NODE_ENV || "development"}`)
|
|
||||||
});
|
|
||||||
|
|
||||||
const twilio = require("twilio");
|
const twilio = require("twilio");
|
||||||
const { phone } = require("phone");
|
const { phone } = require("phone");
|
||||||
const queries = require("../graphql-client/queries");
|
const { INSERT_MESSAGE } = require("../graphql-client/queries");
|
||||||
const logger = require("../utils/logger");
|
const logger = require("../utils/logger");
|
||||||
const client = twilio(process.env.TWILIO_AUTH_TOKEN, process.env.TWILIO_AUTH_KEY);
|
const client = twilio(process.env.TWILIO_AUTH_TOKEN, process.env.TWILIO_AUTH_KEY);
|
||||||
const gqlClient = require("../graphql-client/graphql-client").client;
|
const gqlClient = require("../graphql-client/graphql-client").client;
|
||||||
|
|
||||||
exports.send = async (req, res) => {
|
/**
|
||||||
|
* Send an outbound SMS message
|
||||||
|
* @param req
|
||||||
|
* @param res
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
const send = async (req, res) => {
|
||||||
const { to, messagingServiceSid, body, conversationid, selectedMedia, imexshopid } = req.body;
|
const { to, messagingServiceSid, body, conversationid, selectedMedia, imexshopid } = req.body;
|
||||||
const {
|
const {
|
||||||
ioRedis,
|
ioRedis,
|
||||||
@@ -64,7 +65,10 @@ exports.send = async (req, res) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const gqlResponse = await gqlClient.request(queries.INSERT_MESSAGE, { msg: newMessage, conversationid });
|
const gqlResponse = await gqlClient.request(INSERT_MESSAGE, {
|
||||||
|
msg: newMessage,
|
||||||
|
conversationid
|
||||||
|
});
|
||||||
|
|
||||||
logger.log("sms-outbound-success", "DEBUG", req.user.email, null, {
|
logger.log("sms-outbound-success", "DEBUG", req.user.email, null, {
|
||||||
msid: message.sid,
|
msid: message.sid,
|
||||||
@@ -111,3 +115,7 @@ exports.send = async (req, res) => {
|
|||||||
res.status(500).json({ success: false, message: "Failed to send message through Twilio." });
|
res.status(500).json({ success: false, message: "Failed to send message through Twilio." });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
send
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
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 client = require("../graphql-client/graphql-client").client;
|
||||||
const queries = require("../graphql-client/queries");
|
const { UPDATE_MESSAGE_STATUS, MARK_MESSAGES_AS_READ } = require("../graphql-client/queries");
|
||||||
const logger = require("../utils/logger");
|
const logger = require("../utils/logger");
|
||||||
|
|
||||||
exports.status = async (req, res) => {
|
/**
|
||||||
|
* Handle the status of an SMS message
|
||||||
|
* @param req
|
||||||
|
* @param res
|
||||||
|
* @returns {Promise<*>}
|
||||||
|
*/
|
||||||
|
const status = async (req, res) => {
|
||||||
const { SmsSid, SmsStatus } = req.body;
|
const { SmsSid, SmsStatus } = req.body;
|
||||||
const {
|
const {
|
||||||
ioRedis,
|
ioRedis,
|
||||||
@@ -21,7 +22,7 @@ exports.status = async (req, res) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update message status in the database
|
// Update message status in the database
|
||||||
const response = await client.request(queries.UPDATE_MESSAGE_STATUS, {
|
const response = await client.request(UPDATE_MESSAGE_STATUS, {
|
||||||
msid: SmsSid,
|
msid: SmsSid,
|
||||||
fields: { status: SmsStatus }
|
fields: { status: SmsStatus }
|
||||||
});
|
});
|
||||||
@@ -65,7 +66,13 @@ exports.status = async (req, res) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.markConversationRead = async (req, res) => {
|
/**
|
||||||
|
* Mark a conversation as read
|
||||||
|
* @param req
|
||||||
|
* @param res
|
||||||
|
* @returns {Promise<*>}
|
||||||
|
*/
|
||||||
|
const markConversationRead = async (req, res) => {
|
||||||
const {
|
const {
|
||||||
ioRedis,
|
ioRedis,
|
||||||
ioHelpers: { getBodyshopRoom, getBodyshopConversationRoom }
|
ioHelpers: { getBodyshopRoom, getBodyshopConversationRoom }
|
||||||
@@ -80,7 +87,7 @@ exports.markConversationRead = async (req, res) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await client.request(queries.MARK_MESSAGES_AS_READ, {
|
const response = await client.request(MARK_MESSAGES_AS_READ, {
|
||||||
conversationId
|
conversationId
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -104,3 +111,8 @@ exports.markConversationRead = async (req, res) => {
|
|||||||
res.status(500).json({ error: "Failed to mark conversation as read." });
|
res.status(500).json({ error: "Failed to mark conversation as read." });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
status,
|
||||||
|
markConversationRead
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,3 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* @module ioHelpers
|
||||||
|
* @param app
|
||||||
|
* @param api
|
||||||
|
* @param io
|
||||||
|
* @param logger
|
||||||
|
* @returns {{getBodyshopRoom: (function(*): string), getBodyshopConversationRoom: (function({bodyshopId: *, conversationId: *}): string)}}
|
||||||
|
*/
|
||||||
const applyIOHelpers = ({ app, api, io, logger }) => {
|
const applyIOHelpers = ({ app, api, io, logger }) => {
|
||||||
// Global Bodyshop Room
|
// Global Bodyshop Room
|
||||||
const getBodyshopRoom = (bodyshopId) => `bodyshop-broadcast-room:${bodyshopId}`;
|
const getBodyshopRoom = (bodyshopId) => `bodyshop-broadcast-room:${bodyshopId}`;
|
||||||
|
|||||||
Reference in New Issue
Block a user