feature/IO-3000-messaging-sockets-migration2 - Final fixes around sync / archive / receive
Signed-off-by: Dave Richer <dave@imexsystems.ca>
This commit is contained in:
@@ -42,10 +42,13 @@ export function* openChatByPhone({ payload }) {
|
|||||||
} = yield client.query({
|
} = yield client.query({
|
||||||
query: CONVERSATION_ID_BY_PHONE,
|
query: CONVERSATION_ID_BY_PHONE,
|
||||||
variables: { phone: p.number },
|
variables: { phone: p.number },
|
||||||
fetchPolicy: "network-only"
|
// THIS NEEDS TO REMAIN NO CACHE, IT CHECKS FOR NEW MESSAGES FOR SYNC
|
||||||
|
fetchPolicy: "no-cache"
|
||||||
});
|
});
|
||||||
|
|
||||||
if (conversations.length === 0) {
|
const existingConversation = conversations?.find((c) => c.phone_num === phone_num);
|
||||||
|
|
||||||
|
if (!existingConversation) {
|
||||||
// No conversation exists, create a new one
|
// No conversation exists, create a new one
|
||||||
const {
|
const {
|
||||||
data: {
|
data: {
|
||||||
@@ -75,18 +78,17 @@ export function* openChatByPhone({ payload }) {
|
|||||||
|
|
||||||
// Set the newly created conversation as selected
|
// Set the newly created conversation as selected
|
||||||
yield put(setSelectedConversation(createdConversation.id));
|
yield put(setSelectedConversation(createdConversation.id));
|
||||||
} else if (conversations.length === 1) {
|
} else {
|
||||||
const conversation = conversations[0];
|
let updatedConversation = existingConversation;
|
||||||
let updatedConversation = conversation;
|
|
||||||
|
|
||||||
if (conversation.archived) {
|
if (existingConversation.archived) {
|
||||||
// Conversation is archived, unarchive it in the DB
|
// Conversation is archived, unarchive it in the DB
|
||||||
const {
|
const {
|
||||||
data: { update_conversations_by_pk: unarchivedConversation }
|
data: { update_conversations_by_pk: unarchivedConversation }
|
||||||
} = yield client.mutate({
|
} = yield client.mutate({
|
||||||
mutation: TOGGLE_CONVERSATION_ARCHIVE,
|
mutation: TOGGLE_CONVERSATION_ARCHIVE,
|
||||||
variables: {
|
variables: {
|
||||||
id: conversation.id,
|
id: existingConversation.id,
|
||||||
archived: false
|
archived: false
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -115,10 +117,6 @@ export function* openChatByPhone({ payload }) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// Multiple conversations found
|
|
||||||
console.error("ERROR: Multiple conversations found.");
|
|
||||||
yield put(setSelectedConversation(null));
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error in openChatByPhone saga.", error);
|
console.error("Error in openChatByPhone saga.", error);
|
||||||
|
|||||||
@@ -2577,3 +2577,34 @@ exports.MARK_MESSAGES_AS_READ = `mutation MARK_MESSAGES_AS_READ($conversationId:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports.CREATE_CONVERSATION = `mutation CREATE_CONVERSATION($conversation: [conversations_insert_input!]!) {
|
||||||
|
insert_conversations(objects: $conversation) {
|
||||||
|
returning {
|
||||||
|
id
|
||||||
|
phone_num
|
||||||
|
archived
|
||||||
|
label
|
||||||
|
unreadcnt
|
||||||
|
job_conversations {
|
||||||
|
jobid
|
||||||
|
conversationid
|
||||||
|
job {
|
||||||
|
id
|
||||||
|
ro_number
|
||||||
|
ownr_fn
|
||||||
|
ownr_ln
|
||||||
|
ownr_co_nm
|
||||||
|
}
|
||||||
|
}
|
||||||
|
messages_aggregate(where: { read: { _eq: false }, isoutbound: { _eq: false } }) {
|
||||||
|
aggregate {
|
||||||
|
count
|
||||||
|
}
|
||||||
|
}
|
||||||
|
created_at
|
||||||
|
updated_at
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ exports.receive = async (req, res) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// 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(queries.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
|
||||||
@@ -44,53 +45,51 @@ exports.receive = async (req, res) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const bodyshop = response.bodyshops[0];
|
const bodyshop = response.bodyshops[0];
|
||||||
const isNewConversation = bodyshop.conversations.length === 0;
|
const existingConversation = bodyshop.conversations[0]; // Expect only one conversation per phone number per bodyshop
|
||||||
const isDuplicate = bodyshop.conversations.length > 1;
|
|
||||||
|
|
||||||
|
let conversationid;
|
||||||
let newMessage = {
|
let newMessage = {
|
||||||
msid: req.body.SmsMessageSid,
|
msid: req.body.SmsMessageSid,
|
||||||
text: req.body.Body,
|
text: req.body.Body,
|
||||||
image: !!req.body.MediaUrl0,
|
image: !!req.body.MediaUrl0,
|
||||||
image_path: generateMediaArray(req.body)
|
image_path: generateMediaArray(req.body),
|
||||||
|
isoutbound: false,
|
||||||
|
userid: null // Add additional fields as necessary
|
||||||
};
|
};
|
||||||
|
|
||||||
if (isDuplicate) {
|
if (existingConversation) {
|
||||||
logger.log("sms-inbound-error", "ERROR", "api", null, {
|
// Use the existing conversation
|
||||||
...loggerData,
|
conversationid = existingConversation.id;
|
||||||
messagingServiceSid: req.body.MessagingServiceSid,
|
|
||||||
type: "duplicate-phone"
|
|
||||||
});
|
|
||||||
return res.status(400).json({ success: false, error: "Duplicate phone number" });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isNewConversation) {
|
// Unarchive the conversation if necessary
|
||||||
newMessage.conversation = {
|
if (existingConversation.archived) {
|
||||||
data: {
|
await client.request(queries.UNARCHIVE_CONVERSATION, {
|
||||||
|
id: conversationid,
|
||||||
|
archived: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Create a new conversation
|
||||||
|
const newConversationResponse = await client.request(queries.CREATE_CONVERSATION, {
|
||||||
|
conversation: {
|
||||||
bodyshopid: bodyshop.id,
|
bodyshopid: bodyshop.id,
|
||||||
phone_num: phone(req.body.From).phoneNumber,
|
phone_num: phone(req.body.From).phoneNumber,
|
||||||
archived: false
|
archived: false
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
} else {
|
const createdConversation = newConversationResponse.insert_conversations.returning[0];
|
||||||
const existingConversation = bodyshop.conversations[0];
|
conversationid = createdConversation.id;
|
||||||
|
|
||||||
// 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;
|
// Ensure `conversationid` is added to the message
|
||||||
const variables = isNewConversation
|
newMessage.conversationid = conversationid;
|
||||||
? { msg: newMessage }
|
|
||||||
: { msg: newMessage, conversationid: newMessage.conversationid };
|
// Step 3: Insert the message into the conversation
|
||||||
|
const insertresp = await client.request(queries.INSERT_MESSAGE, {
|
||||||
|
msg: newMessage,
|
||||||
|
conversationid: conversationid
|
||||||
|
});
|
||||||
|
|
||||||
const insertresp = await client.request(query, variables);
|
|
||||||
const message = insertresp?.insert_messages?.returning?.[0];
|
const message = insertresp?.insert_messages?.returning?.[0];
|
||||||
const conversation = message?.conversation || null;
|
const conversation = message?.conversation || null;
|
||||||
|
|
||||||
@@ -98,6 +97,7 @@ exports.receive = async (req, res) => {
|
|||||||
throw new Error("Conversation data is missing from the response.");
|
throw new Error("Conversation data is missing from the response.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Step 4: Notify clients through Redis
|
||||||
const broadcastRoom = getBodyshopRoom(conversation.bodyshop.id);
|
const broadcastRoom = getBodyshopRoom(conversation.bodyshop.id);
|
||||||
const conversationRoom = getBodyshopConversationRoom({
|
const conversationRoom = getBodyshopConversationRoom({
|
||||||
bodyshopId: conversation.bodyshop.id,
|
bodyshopId: conversation.bodyshop.id,
|
||||||
@@ -113,19 +113,20 @@ exports.receive = async (req, res) => {
|
|||||||
|
|
||||||
ioRedis.to(broadcastRoom).emit("new-message-summary", {
|
ioRedis.to(broadcastRoom).emit("new-message-summary", {
|
||||||
...commonPayload,
|
...commonPayload,
|
||||||
existingConversation: !isNewConversation,
|
existingConversation: !!existingConversation,
|
||||||
newConversation: isNewConversation ? conversation : null,
|
newConversation: !existingConversation ? conversation : null,
|
||||||
summary: true
|
summary: true
|
||||||
});
|
});
|
||||||
|
|
||||||
ioRedis.to(conversationRoom).emit("new-message-detailed", {
|
ioRedis.to(conversationRoom).emit("new-message-detailed", {
|
||||||
newMessage: message,
|
newMessage: message,
|
||||||
...commonPayload,
|
...commonPayload,
|
||||||
newConversation: isNewConversation ? conversation : null,
|
newConversation: !existingConversation ? conversation : null,
|
||||||
existingConversation: !isNewConversation,
|
existingConversation: !!existingConversation,
|
||||||
summary: false
|
summary: false
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Step 5: Send FCM notification
|
||||||
const fcmresp = await admin.messaging().send({
|
const fcmresp = await admin.messaging().send({
|
||||||
topic: `${message.conversation.bodyshop.imexshopid}-messaging`,
|
topic: `${message.conversation.bodyshop.imexshopid}-messaging`,
|
||||||
notification: {
|
notification: {
|
||||||
|
|||||||
Reference in New Issue
Block a user