Initial
This commit is contained in:
@@ -3,7 +3,7 @@ const router = express.Router();
|
|||||||
const twilio = require("twilio");
|
const twilio = require("twilio");
|
||||||
const { receive } = require("../sms/receive");
|
const { receive } = require("../sms/receive");
|
||||||
const { send } = require("../sms/send");
|
const { send } = require("../sms/send");
|
||||||
const { status, markConversationRead } = require("../sms/status");
|
const { status, markConversationRead, markLastMessageUnread } = require("../sms/status");
|
||||||
const validateFirebaseIdTokenMiddleware = require("../middleware/validateFirebaseIdTokenMiddleware");
|
const validateFirebaseIdTokenMiddleware = require("../middleware/validateFirebaseIdTokenMiddleware");
|
||||||
|
|
||||||
// Twilio Webhook Middleware for production
|
// Twilio Webhook Middleware for production
|
||||||
@@ -14,5 +14,6 @@ router.post("/receive", twilioWebhookMiddleware, receive);
|
|||||||
router.post("/send", validateFirebaseIdTokenMiddleware, send);
|
router.post("/send", validateFirebaseIdTokenMiddleware, send);
|
||||||
router.post("/status", twilioWebhookMiddleware, status);
|
router.post("/status", twilioWebhookMiddleware, status);
|
||||||
router.post("/markConversationRead", validateFirebaseIdTokenMiddleware, markConversationRead);
|
router.post("/markConversationRead", validateFirebaseIdTokenMiddleware, markConversationRead);
|
||||||
|
router.post("/markLastMessageUnread", validateFirebaseIdTokenMiddleware, markLastMessageUnread);
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|||||||
@@ -8,6 +8,46 @@ const {
|
|||||||
const logger = require("../utils/logger");
|
const logger = require("../utils/logger");
|
||||||
const { phone } = require("phone");
|
const { phone } = require("phone");
|
||||||
|
|
||||||
|
// Local GraphQL for “mark unread” (kept here to avoid requiring edits to graphql-client/queries.js)
|
||||||
|
const GET_LAST_INBOUND_NON_SYSTEM_MESSAGE = `
|
||||||
|
query GetLastInboundNonSystemMessage($conversationId: uuid!) {
|
||||||
|
messages(
|
||||||
|
where: {
|
||||||
|
conversationid: { _eq: $conversationId }
|
||||||
|
isoutbound: { _eq: false }
|
||||||
|
is_system: { _eq: false }
|
||||||
|
}
|
||||||
|
order_by: { created_at: desc }
|
||||||
|
limit: 1
|
||||||
|
) {
|
||||||
|
id
|
||||||
|
created_at
|
||||||
|
read
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const MARK_LAST_INBOUND_MESSAGE_UNREAD_MAX_ONE = `
|
||||||
|
mutation MarkLastInboundMessageUnreadMaxOne($conversationId: uuid!, $lastId: uuid!) {
|
||||||
|
markOthersRead: update_messages(
|
||||||
|
_set: { read: true }
|
||||||
|
where: {
|
||||||
|
conversationid: { _eq: $conversationId }
|
||||||
|
isoutbound: { _eq: false }
|
||||||
|
is_system: { _eq: false }
|
||||||
|
id: { _neq: $lastId }
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
affected_rows
|
||||||
|
returning { id }
|
||||||
|
}
|
||||||
|
|
||||||
|
markLastUnread: update_messages_by_pk(pk_columns: { id: $lastId }, _set: { read: false }) {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle the status of an SMS message
|
* Handle the status of an SMS message
|
||||||
* @param req
|
* @param req
|
||||||
@@ -176,7 +216,80 @@ const markConversationRead = async (req, res) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark last inbound (customer) non-system message as unread.
|
||||||
|
* Enforces: max unread inbound non-system messages per thread = 1
|
||||||
|
*
|
||||||
|
* Body: { conversationId, imexshopid, bodyshopid }
|
||||||
|
*/
|
||||||
|
const markLastMessageUnread = async (req, res) => {
|
||||||
|
const {
|
||||||
|
ioRedis,
|
||||||
|
ioHelpers: { getBodyshopRoom }
|
||||||
|
} = req;
|
||||||
|
|
||||||
|
const { conversationId, imexshopid, bodyshopid } = req.body;
|
||||||
|
|
||||||
|
if (!conversationId || !imexshopid || !bodyshopid) {
|
||||||
|
return res.status(400).json({ error: "Invalid conversation data provided." });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const lastResp = await client.request(GET_LAST_INBOUND_NON_SYSTEM_MESSAGE, { conversationId });
|
||||||
|
const last = lastResp?.messages?.[0];
|
||||||
|
|
||||||
|
if (!last?.id) {
|
||||||
|
// No inbound message to mark unread
|
||||||
|
const broadcastRoom = getBodyshopRoom(bodyshopid);
|
||||||
|
ioRedis.to(broadcastRoom).emit("conversation-changed", {
|
||||||
|
type: "conversation-marked-unread",
|
||||||
|
conversationId,
|
||||||
|
lastUnreadMessageId: null,
|
||||||
|
messageIdsMarkedRead: [],
|
||||||
|
unreadCount: 0
|
||||||
|
});
|
||||||
|
|
||||||
|
return res.status(200).json({
|
||||||
|
success: true,
|
||||||
|
conversationId,
|
||||||
|
lastUnreadMessageId: null,
|
||||||
|
messageIdsMarkedRead: [],
|
||||||
|
unreadCount: 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const mutResp = await client.request(MARK_LAST_INBOUND_MESSAGE_UNREAD_MAX_ONE, {
|
||||||
|
conversationId,
|
||||||
|
lastId: last.id
|
||||||
|
});
|
||||||
|
|
||||||
|
const messageIdsMarkedRead = mutResp?.markOthersRead?.returning?.map((m) => m.id) || [];
|
||||||
|
|
||||||
|
const broadcastRoom = getBodyshopRoom(bodyshopid);
|
||||||
|
|
||||||
|
ioRedis.to(broadcastRoom).emit("conversation-changed", {
|
||||||
|
type: "conversation-marked-unread",
|
||||||
|
conversationId,
|
||||||
|
lastUnreadMessageId: last.id,
|
||||||
|
messageIdsMarkedRead,
|
||||||
|
unreadCount: 1
|
||||||
|
});
|
||||||
|
|
||||||
|
return res.status(200).json({
|
||||||
|
success: true,
|
||||||
|
conversationId,
|
||||||
|
lastUnreadMessageId: last.id,
|
||||||
|
messageIdsMarkedRead,
|
||||||
|
unreadCount: 1
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error marking last message unread:", error);
|
||||||
|
return res.status(500).json({ error: "Failed to mark last message unread." });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
status,
|
status,
|
||||||
markConversationRead
|
markConversationRead,
|
||||||
|
markLastMessageUnread
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user