UNPKG

skailan-conversations

Version:

Servicio de conversaciones y mensajería para Skailan

259 lines 10.2 kB
import { StartConversation } from "../../app/use-cases/StartConversation"; import { CreateMessage } from "../../app/use-cases/CreateMessage"; import { Message } from "../entities/Message"; import { v4 as uuidv4 } from "uuid"; export class TelegramChannelService { telegramService; messageRepository; conversationRepository; channelRepository; constructor(telegramService, messageRepository, conversationRepository, channelRepository) { this.telegramService = telegramService; this.messageRepository = messageRepository; this.conversationRepository = conversationRepository; this.channelRepository = channelRepository; } async processIncomingMessage(organizationId, channelId, message) { try { console.log(`📥 Procesando mensaje de Telegram: ${message.id}`); // 1. Iniciar o encontrar conversación const startConversationUseCase = new StartConversation(this.conversationRepository, this.channelRepository); const conversation = await startConversationUseCase.execute({ organizationId, channelId, contactExternalId: message.from, contactName: message.metadata?.contactName, contactPhone: message.from, // En Telegram, el from es el chat_id }); // 2. Crear mensaje en la base de datos const createMessageUseCase = new CreateMessage(this.messageRepository, this.conversationRepository); const savedMessage = await createMessageUseCase.execute({ organizationId, conversationId: conversation.id, senderType: "contact", senderId: message.from, type: message.type, content: message.content, mediaUrl: message.mediaUrl, externalMessageId: message.id, timestamp: message.timestamp, }); console.log(`✅ Mensaje de Telegram procesado: ${savedMessage.id}`); return { conversation, message: savedMessage }; } catch (error) { console.error("❌ Error procesando mensaje de Telegram:", error); throw error; } } async sendMessage(request) { try { console.log(`📤 Enviando mensaje de Telegram a: ${request.to}`); // Obtener configuración del canal const channel = await this.channelRepository.findById(request.channelId); if (!channel) { throw new Error("Canal no encontrado"); } const config = channel.config; if (!config.botToken) { throw new Error("Bot token no configurado"); } // Enviar mensaje a Telegram const telegramResponse = await this.telegramService.sendMessage(parseInt(request.to), request.content, request.options); // Crear mensaje en la base de datos const message = new Message(uuidv4(), request.organizationId, request.conversationId, "system", "telegram_system", request.type || "text", request.content, request.mediaUrl || null, telegramResponse.message_id?.toString() || null, "sent", new Date(), new Date()); const savedMessage = await this.messageRepository.save(message); console.log(`✅ Mensaje de Telegram enviado: ${savedMessage.id}`); return savedMessage; } catch (error) { console.error("❌ Error enviando mensaje de Telegram:", error); throw error; } } async validateConfig(config) { try { const telegramConfig = config; if (!telegramConfig.botToken) { throw new Error("Bot token de Telegram requerido"); } if (telegramConfig.botToken.length < 10) { throw new Error("Bot token de Telegram inválido"); } if (!telegramConfig.botToken.includes(":")) { throw new Error("Formato de bot token de Telegram inválido"); } console.log(`✅ Configuración de Telegram válida`); return true; } catch (error) { console.error("❌ Error validando configuración de Telegram:", error); return false; } } async getContactInfo(organizationId, channelId, contactId) { try { console.log(`👤 Obteniendo información de contacto: ${contactId}`); // Obtener información del bot desde Telegram const channel = await this.channelRepository.findById(channelId); if (!channel) { throw new Error("Canal no encontrado"); } const config = channel.config; // Aquí podrías hacer una llamada a la API de Telegram para obtener información del usuario // Por ahora, retornamos información básica return { id: contactId, externalId: contactId, name: `Usuario ${contactId}`, phone: contactId, metadata: { platform: "telegram", chatId: contactId, }, }; } catch (error) { console.error("❌ Error obteniendo información de contacto:", error); throw error; } } async verifyWebhook(payload, signature, config) { try { console.log(`🔐 Verificando webhook de Telegram`); // Telegram no usa firmas como WhatsApp, pero podemos verificar el bot token const telegramConfig = config; if (!telegramConfig.botToken) { console.error("❌ Bot token no encontrado en configuración"); return false; } // Verificar que el payload contiene un update válido if (!payload || !payload.update_id) { console.error("❌ Payload de Telegram inválido"); return false; } console.log(`✅ Webhook de Telegram verificado`); return true; } catch (error) { console.error("❌ Error verificando webhook de Telegram:", error); return false; } } getChannelType() { return "telegram"; } /** * Procesa un update de Telegram */ async processTelegramUpdate(organizationId, channelId, update) { try { console.log(`📥 Procesando update de Telegram: ${update.update_id}`); // Extraer mensaje del update const message = this.extractMessageFromUpdate(update); if (!message) { console.log(`⚠️ Update de Telegram sin mensaje válido: ${update.update_id}`); return null; } return await this.processIncomingMessage(organizationId, channelId, message); } catch (error) { console.error("❌ Error procesando update de Telegram:", error); throw error; } } /** * Extrae un mensaje del update de Telegram */ extractMessageFromUpdate(update) { // Manejar diferentes tipos de updates if (update.message) { return this.extractMessageFromMessage(update.message); } else if (update.edited_message) { return this.extractMessageFromMessage(update.edited_message); } else if (update.callback_query) { return this.extractMessageFromCallbackQuery(update.callback_query); } return null; } /** * Extrae mensaje de un objeto message de Telegram */ extractMessageFromMessage(message) { if (!message.text && !message.photo && !message.video && !message.audio && !message.document) { return null; } let content = ""; let type = "text"; let mediaUrl; if (message.text) { content = message.text; type = "text"; } else if (message.photo) { content = message.caption || "(Imagen)"; type = "image"; mediaUrl = message.photo[0]?.file_id; } else if (message.video) { content = message.caption || "(Video)"; type = "video"; mediaUrl = message.video.file_id; } else if (message.audio) { content = "(Audio)"; type = "audio"; mediaUrl = message.audio.file_id; } else if (message.document) { content = message.document.file_name || "(Documento)"; type = "document"; mediaUrl = message.document.file_id; } return { id: message.message_id.toString(), from: message.from.id.toString(), to: message.chat.id.toString(), type, content, mediaUrl, timestamp: new Date(message.date * 1000), metadata: { contactName: message.from.first_name, lastName: message.from.last_name, username: message.from.username, isBot: message.from.is_bot, chatType: message.chat.type, }, }; } /** * Extrae mensaje de un callback query de Telegram */ extractMessageFromCallbackQuery(callbackQuery) { if (!callbackQuery.data) { return null; } return { id: callbackQuery.id, from: callbackQuery.from.id.toString(), to: callbackQuery.message?.chat.id.toString() || "", type: "text", content: callbackQuery.data, timestamp: new Date(), metadata: { callbackQuery: true, messageId: callbackQuery.message?.message_id, contactName: callbackQuery.from.first_name, username: callbackQuery.from.username, }, }; } } //# sourceMappingURL=TelegramChannelService.js.map