whatsapp-crm-common
Version:
Componentes compartidos para servicios de WhatsApp CRM - Common utilities and types for WhatsApp CRM system
209 lines • 9.7 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.WhatsAppDataService = void 0;
const chat_repository_1 = require("./chat-repository");
const contact_repository_1 = require("./contact-repository");
const group_repository_1 = require("./group-repository");
const message_repository_1 = require("./message-repository");
const sync_repository_1 = require("./sync-repository");
class WhatsAppDataService {
constructor(pool) {
// Extraer connectionString del pool inyectado
const connectionString = pool.options.connectionString;
this.messageRepo = new message_repository_1.MessageRepository(connectionString);
this.chatRepo = new chat_repository_1.ChatRepository(connectionString);
this.contactRepo = new contact_repository_1.ContactRepository(connectionString);
this.groupRepo = new group_repository_1.GroupRepository(connectionString);
this.syncRepo = new sync_repository_1.SyncRepository(connectionString);
// ✅ Usar pool inyectado en lugar de crear uno nuevo
this.pool = pool;
}
// Message-related methods
async bulkInsertMessages(messages, tenantId, agentId) {
return this.messageRepo.bulkInsertMessages(messages, tenantId, agentId);
}
async handleMessageUpdate(tenantId, agentId, messageUpdate) {
return this.messageRepo.handleMessageUpdate(tenantId, agentId, messageUpdate);
}
async handleBulkMessageUpdates(tenantId, agentId, messageUpdates) {
return this.messageRepo.handleBulkMessageUpdates(tenantId, agentId, messageUpdates);
}
async handleMessageDelete(tenantId, agentId, deleteEvent) {
return this.messageRepo.handleMessageDelete(tenantId, agentId, deleteEvent);
}
async handleMessageReactions(tenantId, agentId, reactions) {
return this.messageRepo.handleMessageReactions(tenantId, agentId, reactions);
}
async handleMessageReceiptUpdates(updates, tenantId, agentId) {
return this.messageRepo.handleMessageReceiptUpdates(updates, tenantId, agentId);
}
// Chat-related methods
async handleChatUpserts(chats, tenantId, agentId) {
return this.chatRepo.handleChatUpserts(chats, tenantId, agentId);
}
async handleChatUpdates(tenantId, agentId, updates) {
return this.chatRepo.handleChatUpdates(tenantId, agentId, updates);
}
// Contact-related methods
async handleContactUpserts(contacts, tenantId, agentId) {
return this.contactRepo.handleContactUpserts(contacts, tenantId, agentId);
}
async handleContactUpdates(tenantId, agentId, updates) {
return this.contactRepo.handleContactUpdates(tenantId, agentId, updates);
}
// Bulk insert methods for workers
async bulkInsertContacts(contacts, tenantId, agentId) {
const client = await this.pool.connect();
try {
await client.query("BEGIN");
await this.contactRepo.guardarContactosBulk(client, contacts, tenantId, agentId);
await client.query("COMMIT");
}
catch (error) {
await client.query("ROLLBACK");
throw error;
}
finally {
client.release();
}
}
async bulkInsertChats(chats, tenantId, agentId) {
const client = await this.pool.connect();
try {
await client.query("BEGIN");
await this.chatRepo.guardarChatsBulk(client, chats, tenantId, agentId);
await client.query("COMMIT");
}
catch (error) {
await client.query("ROLLBACK");
throw error;
}
finally {
client.release();
}
}
// Main sync-related method
async guardarChatsEnBD(resultado, tenantId, agentId) {
const client = await this.pool.connect();
try {
await client.query("BEGIN");
// First save sync metadata
await this.syncRepo.guardarMetadatos(client, resultado.metadatos, tenantId, agentId);
// Prepare data collections for bulk processing
const chats = [];
const chatContactRelations = [];
const groupParticipants = [];
const messages = [];
const allReferencedContactIds = new Set();
// Add special "self" contact for messages sent by the user
allReferencedContactIds.add("self");
// Collect all data for bulk insertion
for (const chatId in resultado) {
if (chatId !== "todosLosContactos" && chatId !== "metadatos") {
const chatInfo = resultado[chatId];
chats.push(chatInfo);
// Chat-contact relations for individual chats
if (!chatInfo.esGrupo && chatInfo.contacto?.id) {
const contactId = chatInfo.contacto.id;
chatContactRelations.push({ chatId, contactId });
allReferencedContactIds.add(contactId);
}
// Group participants
if (chatInfo.esGrupo && chatInfo.participantes) {
for (const participanteId in chatInfo.participantes) {
groupParticipants.push({
groupId: chatId,
contactId: participanteId,
});
allReferencedContactIds.add(participanteId);
}
}
// Messages
for (const mensaje of chatInfo.mensajes) {
messages.push({ message: mensaje, chatId });
// Track message sender if it's a contact
if (mensaje.key?.participant) {
allReferencedContactIds.add(mensaje.key.participant);
}
}
}
}
// Create a map of known contacts
const knownContacts = new Map();
if (resultado.todosLosContactos) {
for (const contactId in resultado.todosLosContactos) {
knownContacts.set(contactId, resultado.todosLosContactos[contactId]);
}
}
// Detect missing contact IDs
const missingContactIds = [];
for (const contactId of allReferencedContactIds) {
if (!knownContacts.has(contactId)) {
missingContactIds.push(contactId);
// Create placeholder contacts
if (contactId === "self") {
knownContacts.set(contactId, {
id: contactId,
name: "Me (Self)",
notify: "Me",
});
}
else {
const phoneNumber = contactId.split("@")[0];
knownContacts.set(contactId, {
id: contactId,
name: phoneNumber,
notify: phoneNumber,
});
}
}
}
// Create placeholder contacts for missing IDs
if (missingContactIds.length > 0) {
const placeholderContacts = Array.from(missingContactIds, (id) => knownContacts.get(id));
await this.contactRepo.guardarContactosBulk(client, placeholderContacts, tenantId, agentId);
}
// Save all remaining contacts (placeholders already saved)
const contactosRestantes = Array.from(knownContacts.values()).filter((contact) => !missingContactIds.includes(contact.id));
if (contactosRestantes.length > 0) {
await this.contactRepo.guardarContactosBulk(client, contactosRestantes, tenantId, agentId);
}
// Execute bulk operations in correct order
await this.chatRepo.guardarChatsBulk(client, chats, tenantId, agentId);
await this.contactRepo.guardarChatContactRelationsBulk(client, chatContactRelations, tenantId, agentId);
await this.contactRepo.guardarGroupParticipantsBulk(client, groupParticipants, tenantId, agentId);
const flatMessages = messages.map((m) => m.message);
await this.messageRepo.bulkInsertMessages(flatMessages, tenantId, agentId);
await client.query("COMMIT");
}
catch (error) {
await client.query("ROLLBACK");
console.error("Error al guardar chats en la base de datos:", error);
throw error;
}
finally {
client.release();
}
}
/**
* Actualiza el estado de conexión para un tenant/agente
*/
async updateConnectionStatus(tenantId, agentId, connected, reason) {
const client = await this.pool.connect();
try {
await client.query(`INSERT INTO connection_status (tenant_id, agent_id, connected, reason, updated_at)
VALUES ($1, $2, $3, $4, NOW())
ON CONFLICT (tenant_id, agent_id)
DO UPDATE SET connected = $3, reason = $4, updated_at = NOW()`, [tenantId, agentId, connected, reason || null]);
}
catch (error) {
console.error("Error updating connection status:", error);
throw error;
}
finally {
client.release();
}
}
}
exports.WhatsAppDataService = WhatsAppDataService;
//# sourceMappingURL=whatsapp-data-service.js.map