fix(messages): normalize webhook reply references
This commit is contained in:
@@ -52,6 +52,16 @@ const currentChat = useMapGetter('getSelectedChat');
|
||||
|
||||
// Cache for fetched reply messages to avoid duplicate API calls
|
||||
const fetchedReplyMessages = reactive(new Map());
|
||||
const pendingReplyMessageFetches = new Map();
|
||||
|
||||
const replyMessageMatches = (message, referenceId) => {
|
||||
const normalizedReferenceId = String(referenceId);
|
||||
return (
|
||||
String(message.id) === normalizedReferenceId ||
|
||||
message.source_id === normalizedReferenceId ||
|
||||
message.sourceId === normalizedReferenceId
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Fetches a specific message from the API by trying to get messages around it
|
||||
@@ -60,33 +70,58 @@ const fetchedReplyMessages = reactive(new Map());
|
||||
* @returns {Promise<Object|null>} - The fetched message or null if not found/error
|
||||
*/
|
||||
const fetchReplyMessage = async (messageId, conversationId) => {
|
||||
const cacheKey = String(messageId);
|
||||
|
||||
// Return cached result if already fetched
|
||||
if (fetchedReplyMessages.has(messageId)) {
|
||||
return fetchedReplyMessages.get(messageId);
|
||||
if (fetchedReplyMessages.has(cacheKey)) {
|
||||
return fetchedReplyMessages.get(cacheKey);
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await MessageApi.getPreviousMessages({
|
||||
conversationId,
|
||||
before: messageId + 100,
|
||||
after: messageId - 100,
|
||||
});
|
||||
const numericMessageId = Number(messageId);
|
||||
if (!Number.isSafeInteger(numericMessageId) || numericMessageId <= 0) {
|
||||
// Legacy provider payloads may contain an external source ID here. Never
|
||||
// pass those strings to the numeric before/after cursor endpoint.
|
||||
fetchedReplyMessages.set(cacheKey, null);
|
||||
return null;
|
||||
}
|
||||
|
||||
const messages = response.data?.payload || [];
|
||||
const targetMessage = messages.find(msg => msg.id === messageId);
|
||||
if (pendingReplyMessageFetches.has(cacheKey)) {
|
||||
return pendingReplyMessageFetches.get(cacheKey);
|
||||
}
|
||||
|
||||
if (targetMessage) {
|
||||
const camelCaseMessage = useCamelCase(targetMessage);
|
||||
fetchedReplyMessages.set(messageId, camelCaseMessage);
|
||||
return camelCaseMessage;
|
||||
const request = (async () => {
|
||||
try {
|
||||
const response = await MessageApi.getPreviousMessages({
|
||||
conversationId,
|
||||
before: numericMessageId + 100,
|
||||
after: numericMessageId - 100,
|
||||
});
|
||||
|
||||
const messages = response.data?.payload || [];
|
||||
const targetMessage = messages.find(
|
||||
message => Number(message.id) === numericMessageId
|
||||
);
|
||||
|
||||
if (targetMessage) {
|
||||
const camelCaseMessage = useCamelCase(targetMessage);
|
||||
fetchedReplyMessages.set(cacheKey, camelCaseMessage);
|
||||
return camelCaseMessage;
|
||||
}
|
||||
|
||||
// Cache null result to avoid repeated API calls
|
||||
fetchedReplyMessages.set(cacheKey, null);
|
||||
return null;
|
||||
} catch (error) {
|
||||
fetchedReplyMessages.set(cacheKey, null);
|
||||
return null;
|
||||
}
|
||||
})();
|
||||
|
||||
// Cache null result to avoid repeated API calls
|
||||
fetchedReplyMessages.set(messageId, null);
|
||||
return null;
|
||||
} catch (error) {
|
||||
fetchedReplyMessages.set(messageId, null);
|
||||
return null;
|
||||
pendingReplyMessageFetches.set(cacheKey, request);
|
||||
try {
|
||||
return await request;
|
||||
} finally {
|
||||
pendingReplyMessageFetches.delete(cacheKey);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -137,19 +172,23 @@ const getInReplyToMessage = parentMessage => {
|
||||
|
||||
if (!inReplyToMessageId) return null;
|
||||
|
||||
const cacheKey = String(inReplyToMessageId);
|
||||
|
||||
// Try to find in current messages first
|
||||
let replyMessage = props.messages?.find(msg => msg.id === inReplyToMessageId);
|
||||
let replyMessage = props.messages?.find(message =>
|
||||
replyMessageMatches(message, inReplyToMessageId)
|
||||
);
|
||||
|
||||
// Then try store messages
|
||||
if (!replyMessage && currentChat.value?.messages) {
|
||||
replyMessage = currentChat.value.messages.find(
|
||||
msg => msg.id === inReplyToMessageId
|
||||
replyMessage = currentChat.value.messages.find(message =>
|
||||
replyMessageMatches(message, inReplyToMessageId)
|
||||
);
|
||||
}
|
||||
|
||||
// Then check fetch cache
|
||||
if (!replyMessage && fetchedReplyMessages.has(inReplyToMessageId)) {
|
||||
replyMessage = fetchedReplyMessages.get(inReplyToMessageId);
|
||||
if (!replyMessage && fetchedReplyMessages.has(cacheKey)) {
|
||||
replyMessage = fetchedReplyMessages.get(cacheKey);
|
||||
}
|
||||
|
||||
// If still not found and we have conversation context, fetch it
|
||||
|
||||
Reference in New Issue
Block a user