UNPKG

skailan-conversations

Version:

Servicio de conversaciones y mensajería para Skailan

240 lines 8.39 kB
export class MessageDisplayService { /** * Convierte un mensaje de la base de datos a formato de visualización */ formatMessageForDisplay(message) { const isOutgoing = message.senderType === "system" || message.senderType === "bot"; // Determinar el tipo de mensaje basado en el contenido y metadata const messageType = this.determineMessageType(message); // Obtener información del remitente const senderInfo = this.getSenderInfo(message); // Extraer metadata específica del canal const metadata = this.extractChannelMetadata(message); return { id: message.id, content: message.content || "", type: messageType, senderType: message.senderType, senderId: message.senderId, senderName: senderInfo.name, senderAvatar: senderInfo.avatar, timestamp: message.timestamp, status: message.status, isOutgoing, channelType: this.determineChannelType(message), metadata, }; } /** * Convierte una conversación a formato de visualización */ formatConversationForDisplay(conversation, lastMessage, unreadCount = 0) { const participants = this.getConversationParticipants(conversation); return { id: conversation.id, title: `Conversación ${conversation.id.slice(0, 8)}`, status: conversation.status, lastMessage: lastMessage ? this.formatMessageForDisplay(lastMessage) : undefined, unreadCount, participants, channelType: this.determineChannelTypeFromConversation(conversation), createdAt: conversation.createdAt, updatedAt: conversation.updatedAt, }; } /** * Determina el tipo de mensaje basado en el contenido */ determineMessageType(message) { // Si hay mediaUrl, determinar tipo por extensión if (message.mediaUrl) { const extension = message.mediaUrl.split(".").pop()?.toLowerCase(); if (["jpg", "jpeg", "png", "gif", "webp"].includes(extension || "")) { return "image"; } if (["mp4", "avi", "mov", "wmv"].includes(extension || "")) { return "video"; } if (["mp3", "wav", "ogg", "m4a"].includes(extension || "")) { return "audio"; } return "document"; } // Si el contenido es JSON, podría ser un mensaje especial try { const parsed = JSON.parse(message.content || ""); if (parsed.type === "location") return "location"; if (parsed.type === "contact") return "contact"; } catch { // No es JSON, continuar } return "text"; } /** * Obtiene información del remitente */ getSenderInfo(message) { switch (message.senderType) { case "system": return { name: "Sistema", avatar: "/avatars/system.png", }; case "bot": return { name: "Bot de Telegram", avatar: "/avatars/bot.png", }; case "user": return { name: `Usuario ${message.senderId.slice(0, 8)}`, avatar: `/avatars/user-${message.senderId.slice(0, 8)}.png`, }; default: return { name: "Usuario", avatar: "/avatars/default.png", }; } } /** * Extrae metadata específica del canal */ extractChannelMetadata(message) { const metadata = {}; // Extraer Telegram Message ID si existe if (message.externalMessageId) { metadata.telegramMessageId = parseInt(message.externalMessageId); } // Si el contenido es JSON, extraer metadata adicional try { const parsed = JSON.parse(message.content || ""); if (parsed.replyToMessageId) { metadata.replyToMessageId = parsed.replyToMessageId; } if (parsed.inlineKeyboard) { metadata.inlineKeyboard = parsed.inlineKeyboard; } if (parsed.fileUrl) { metadata.fileUrl = parsed.fileUrl; } if (parsed.fileName) { metadata.fileName = parsed.fileName; } if (parsed.fileSize) { metadata.fileSize = parsed.fileSize; } if (parsed.mimeType) { metadata.mimeType = parsed.mimeType; } } catch { // No es JSON, continuar } return metadata; } /** * Determina el tipo de canal basado en el mensaje */ determineChannelType(message) { // Basado en el senderId o metadata if (message.senderId.includes("telegram") || message.senderId.includes("bot")) { return "telegram"; } if (message.senderId.includes("whatsapp")) { return "whatsapp"; } if (message.senderId.includes("email")) { return "email"; } return "web"; } /** * Determina el tipo de canal basado en la conversación */ determineChannelTypeFromConversation(conversation) { // Basado en el channelId o metadata de la conversación if (conversation.channelId?.includes("telegram")) { return "telegram"; } if (conversation.channelId?.includes("whatsapp")) { return "whatsapp"; } if (conversation.channelId?.includes("email")) { return "email"; } return "web"; } /** * Obtiene los participantes de una conversación */ getConversationParticipants(conversation) { const participants = []; // Agregar usuario asignado si existe if (conversation.assignedToUserId) { participants.push({ id: conversation.assignedToUserId, name: `Agente ${conversation.assignedToUserId.slice(0, 8)}`, avatar: `/avatars/agent-${conversation.assignedToUserId.slice(0, 8)}.png`, type: "user", }); } // Agregar bot del canal participants.push({ id: "bot", name: "Bot de Telegram", avatar: "/avatars/bot.png", type: "bot", }); return participants; } /** * Formatea timestamp para visualización */ formatTimestamp(timestamp) { const now = new Date(); const diff = now.getTime() - timestamp.getTime(); const minutes = Math.floor(diff / 60000); const hours = Math.floor(diff / 3600000); const days = Math.floor(diff / 86400000); if (minutes < 1) return "Ahora"; if (minutes < 60) return `Hace ${minutes} min`; if (hours < 24) return `Hace ${hours} h`; if (days < 7) return `Hace ${days} días`; return timestamp.toLocaleDateString("es-ES", { day: "2-digit", month: "2-digit", year: "2-digit", }); } /** * Obtiene el estado visual del mensaje */ getMessageStatusDisplay(status) { switch (status) { case "sent": return { text: "Enviado", icon: "✓", color: "text-gray-500" }; case "delivered": return { text: "Entregado", icon: "✓✓", color: "text-blue-500" }; case "read": return { text: "Leído", icon: "✓✓", color: "text-green-500" }; case "failed": return { text: "Error", icon: "✗", color: "text-red-500" }; case "pending": return { text: "Enviando...", icon: "⏳", color: "text-yellow-500" }; default: return { text: "Desconocido", icon: "?", color: "text-gray-400" }; } } } //# sourceMappingURL=MessageDisplayService.js.map