corregidas imcompativilidades despues del merge
All checks were successful
Deploy conversation layer / deploy (push) Successful in 2m4s
All checks were successful
Deploy conversation layer / deploy (push) Successful in 2m4s
This commit is contained in:
@@ -41,4 +41,4 @@ export function registerConversationRoutes(app: Application, openWaUrl: string |
|
|||||||
const deleted = deleteConversation(req.params.id);
|
const deleted = deleteConversation(req.params.id);
|
||||||
res.json({ success: deleted });
|
res.json({ success: deleted });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -3,81 +3,108 @@ import { WhatsAppMessage, Conversation, Msg, Participant } from '../types';
|
|||||||
|
|
||||||
const conversations = new Map<string, Conversation>();
|
const conversations = new Map<string, Conversation>();
|
||||||
|
|
||||||
// ──────────────────────────── Helpers ─────────────────────────────
|
async function loadMessages(
|
||||||
|
chatId: string,
|
||||||
async function fetchChatMessages(chatId: string, openWaUrl: string): Promise<WhatsAppMessage[]> {
|
openWaUrl: string
|
||||||
|
): Promise<WhatsAppMessage[]> {
|
||||||
|
console.log(`[conversationStore] Loading messages for ${chatId}`);
|
||||||
const { data } = await axios.post(`${openWaUrl}/loadAndGetAllMessagesInChat`, {
|
const { data } = await axios.post(`${openWaUrl}/loadAndGetAllMessagesInChat`, {
|
||||||
args: { chatId, includeMe: true, includeNotifications: true },
|
args: {
|
||||||
|
chatId,
|
||||||
|
includeMe: true,
|
||||||
|
includeNotifications: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
return data?.response ?? data ?? [];
|
const msgs: WhatsAppMessage[] = data?.response || data || [];
|
||||||
|
return msgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
function toMsg(m: WhatsAppMessage): Msg {
|
function mapMessage(m: WhatsAppMessage): Msg {
|
||||||
const anyMsg = m as any;
|
|
||||||
return {
|
return {
|
||||||
id: m.id,
|
id: m.id,
|
||||||
from: m.from,
|
from: m.from,
|
||||||
to: m.to,
|
to: m.to,
|
||||||
ts: anyMsg.timestamp ?? anyMsg.t ?? Date.now(),
|
ts: (m as any).timestamp || (m as any).t,
|
||||||
type: anyMsg.type ?? 'chat',
|
type: ((m as any).type as any) || 'chat',
|
||||||
text: anyMsg.text ?? anyMsg.caption ?? anyMsg.body ?? '',
|
text: (m as any).text || (m as any).caption || (m as any).body,
|
||||||
mediaUrl: anyMsg.cloudUrl ?? anyMsg.clientUrl,
|
mediaUrl: (m as any).cloudUrl || (m as any).clientUrl,
|
||||||
mentions: anyMsg.mentionedJidList ?? [],
|
mentions: ((m as any).mentionedJidList as any) || [],
|
||||||
meta: {
|
meta: {
|
||||||
ack: anyMsg.ack ?? 0,
|
ack: (m as any).ack || 0,
|
||||||
hasReaction: Boolean(anyMsg.hasReaction),
|
hasReaction: (m as any).hasReaction || false,
|
||||||
isQuoted: Boolean(anyMsg.quotedMsg),
|
isQuoted: !!(m as any).quotedMsg,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildParticipants(messages: WhatsAppMessage[], chat?: any): Participant[] {
|
export async function getConversation(
|
||||||
const map = new Map<string, Participant>();
|
chatId: string,
|
||||||
|
openWaUrl: string
|
||||||
|
): Promise<Conversation> {
|
||||||
|
console.log(`[conversationStore] Retrieving conversation for ${chatId}`);
|
||||||
|
let conv = conversations.get(chatId);
|
||||||
|
if (!conv) {
|
||||||
|
conv = await buildConversation(chatId, openWaUrl);
|
||||||
|
}
|
||||||
|
return conv;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function listConversations(): Conversation[] {
|
||||||
|
console.log('[conversationStore] Listing conversations');
|
||||||
|
return Array.from(conversations.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function buildConversation(
|
||||||
|
chatId: string,
|
||||||
|
openWaUrl: string
|
||||||
|
): Promise<Conversation> {
|
||||||
|
console.log(`[conversationStore] Building conversation for ${chatId}`);
|
||||||
|
const rawMessages = await loadMessages(chatId, openWaUrl);
|
||||||
|
const now = Date.now();
|
||||||
|
|
||||||
|
const first = rawMessages[0];
|
||||||
|
const chat = first?.chat;
|
||||||
|
const title = chat?.formattedTitle || chat?.name || chatId;
|
||||||
|
const isGroup = chat?.isGroup || false;
|
||||||
|
const unreadCount = chat?.unreadCount || 0;
|
||||||
|
|
||||||
|
const participantsMap = new Map<string, Participant>();
|
||||||
if (chat?.contact) {
|
if (chat?.contact) {
|
||||||
const c = chat.contact;
|
const c = chat.contact;
|
||||||
map.set(c.id, {
|
participantsMap.set(c.id, {
|
||||||
id: c.id,
|
id: c.id,
|
||||||
name: c.pushname || c.name || '',
|
name: c.pushname || c.name || '',
|
||||||
isMe: Boolean(c.isMe),
|
isMe: c.isMe,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (isGroup && chat?.groupMetadata?.participants) {
|
||||||
if (chat?.isGroup && chat.groupMetadata?.participants) {
|
|
||||||
for (const p of chat.groupMetadata.participants as any[]) {
|
for (const p of chat.groupMetadata.participants as any[]) {
|
||||||
const c = p.contact || {};
|
const c = p.contact || {};
|
||||||
const id = c.id || p.id;
|
const id = c.id || p.id;
|
||||||
map.set(id, {
|
participantsMap.set(id, {
|
||||||
id,
|
id,
|
||||||
name: c.pushname || c.name || '',
|
name: c.pushname || c.name || '',
|
||||||
isMe: Boolean(c.isMe),
|
isMe: c.isMe || false,
|
||||||
isAdmin: Boolean(p.isAdmin || p.isSuperAdmin),
|
isAdmin: p.isAdmin || p.isSuperAdmin,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const m of messages) {
|
for (const m of rawMessages) {
|
||||||
const s = m.sender;
|
const s = m.sender;
|
||||||
if (s && !map.has(s.id)) {
|
if (s && !participantsMap.has(s.id)) {
|
||||||
map.set(s.id, {
|
participantsMap.set(s.id, {
|
||||||
id: s.id,
|
id: s.id,
|
||||||
name: s.pushname || s.name || '',
|
name: s.pushname || s.name || '',
|
||||||
isMe: Boolean(s.isMe),
|
isMe: s.isMe,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return [...map.values()];
|
const messages: Msg[] = rawMessages.slice(-20).map(mapMessage);
|
||||||
}
|
messages.sort((a, b) => a.ts - b.ts);
|
||||||
|
|
||||||
// ──────────────────────────── Public API ─────────────────────────────
|
const conv: Conversation = {
|
||||||
|
|
||||||
export async function buildConversation(chatId: string, openWaUrl: string): Promise<Conversation> {
|
|
||||||
const raw = await fetchChatMessages(chatId, openWaUrl);
|
|
||||||
const chat = raw[0]?.chat;
|
|
||||||
const now = Date.now();
|
|
||||||
|
|
||||||
const conversation: Conversation = {
|
|
||||||
chatId,
|
chatId,
|
||||||
title,
|
title,
|
||||||
isGroup,
|
isGroup,
|
||||||
@@ -87,21 +114,12 @@ export async function buildConversation(chatId: string, openWaUrl: string): Prom
|
|||||||
createdAt: conversations.get(chatId)?.createdAt || now,
|
createdAt: conversations.get(chatId)?.createdAt || now,
|
||||||
};
|
};
|
||||||
|
|
||||||
conversations.set(chatId, conversation);
|
conversations.set(chatId, conv);
|
||||||
return conversation;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getConversation(chatId: string, openWaUrl: string): Promise<Conversation> {
|
|
||||||
let conv = conversations.get(chatId);
|
|
||||||
if (!conv) conv = await buildConversation(chatId, openWaUrl);
|
|
||||||
return conv;
|
return conv;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function listConversations(): Conversation[] {
|
|
||||||
return [...conversations.values()];
|
|
||||||
}
|
|
||||||
|
|
||||||
export function deleteConversation(chatId: string): boolean {
|
export function deleteConversation(chatId: string): boolean {
|
||||||
|
console.log(`[conversationStore] Deleting conversation ${chatId}`);
|
||||||
return conversations.delete(chatId);
|
return conversations.delete(chatId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,8 +128,10 @@ export async function addMessageToConversation(
|
|||||||
msg: WhatsAppMessage,
|
msg: WhatsAppMessage,
|
||||||
openWaUrl: string
|
openWaUrl: string
|
||||||
): Promise<Conversation> {
|
): Promise<Conversation> {
|
||||||
|
console.log(`[conversationStore] Adding message to ${chatId}`);
|
||||||
const conv = await getConversation(chatId, openWaUrl);
|
const conv = await getConversation(chatId, openWaUrl);
|
||||||
const mapped = toMsg(msg);
|
const mapped = mapMessage(msg);
|
||||||
|
// avoid duplicates if multiple webhook events deliver the same message
|
||||||
if (!conv.messages.some((m) => m.id === mapped.id)) {
|
if (!conv.messages.some((m) => m.id === mapped.id)) {
|
||||||
conv.messages.push(mapped);
|
conv.messages.push(mapped);
|
||||||
if (conv.messages.length > 20) conv.messages.shift();
|
if (conv.messages.length > 20) conv.messages.shift();
|
||||||
@@ -121,9 +141,9 @@ export async function addMessageToConversation(
|
|||||||
conv.participants.push({
|
conv.participants.push({
|
||||||
id: s.id,
|
id: s.id,
|
||||||
name: s.pushname || s.name || '',
|
name: s.pushname || s.name || '',
|
||||||
isMe: Boolean(s.isMe),
|
isMe: s.isMe,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return conv;
|
return conv;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user