diff --git a/src/bot/handler.js b/src/bot/handler.js index ea47351..a208685 100644 --- a/src/bot/handler.js +++ b/src/bot/handler.js @@ -2330,10 +2330,11 @@ Digite /help para ver todos os comandos disponíveis! if (result.success && result.readyForRemoval) { // ONU encontrada - mostrar informações e pedir confirmação + // O service-port NÃO é incluído no callback_data pois removeOnu busca todos automaticamente const keyboard = { inline_keyboard: [ [ - { text: '✅ CONFIRMAR REMOÇÃO', callback_data: `confirm_remove_${oltId}_${result.slot.replace(/\//g, '-')}_${result.onuId}_${result.servicePort}_${serialNumber}` } + { text: '✅ CONFIRMAR REMOÇÃO', callback_data: `confirm_remove_${oltId}_${result.slot.replace(/\//g, '-')}_${result.onuId}_${serialNumber}` } ], [ { text: '❌ Cancelar', callback_data: 'cancel_action' } @@ -2341,11 +2342,15 @@ Digite /help para ver todos os comandos disponíveis! ] }; + const servicePortsInfo = result.servicePorts && result.servicePorts.length > 1 + ? `🔌 **Service-ports:** ${result.servicePorts.join(', ')} *(${result.servicePorts.length} encontrados — todos serão removidos)*` + : `🔌 **Service-port:** ${result.servicePort}`; + await this.bot.editMessageText( `⚠️ **CONFIRMAÇÃO DE REMOÇÃO**\n\n` + `📱 **Serial:** ${serialNumber}\n` + `📍 **Localização:** Slot ${result.slot}, ONU ${result.onuId}\n` + - `🔌 **Service-port:** ${result.servicePort}\n` + + `${servicePortsInfo}\n` + `🏢 **OLT:** ${oltId.replace('olt_', '').replace(/_/g, '\\_').toUpperCase()}\n\n` + `⚠️ **ATENÇÃO:** Esta ação não pode ser desfeita!\n` + `A ONU será completamente removida da OLT.\n\n` + @@ -2393,35 +2398,33 @@ Digite /help para ver todos os comandos disponíveis! const chatId = callbackQuery.message.chat.id; console.log(`🔍 handleConfirmRemoveCallback chamado com data: ${data}`); - const parts = data.split('_'); // confirm_remove_olt_dito_[slot]_[onuId]_[servicePort]_[serialNumber] + // Novo formato (sem servicePort): confirm_remove_olt_dito_[slot]_[onuId]_[serialNumber] + const parts = data.split('_'); console.log(`🔍 Parts: ${JSON.stringify(parts)}`); - let oltId, slot, onuId, servicePort, serialNumber; + let oltId, slot, onuId, serialNumber; - if (parts.length >= 9 && parts[3] === 'pedro' && parts[4] === 'afonso') { - // Caso: confirm_remove_olt_pedro_afonso_slot_onuId_servicePort_serialNumber + if (parts.length >= 8 && parts[3] === 'pedro' && parts[4] === 'afonso') { + // Caso: confirm_remove_olt_pedro_afonso_slot_onuId_serialNumber oltId = parts[2] + '_' + parts[3] + '_' + parts[4]; // "olt_pedro_afonso" - slot = parts[5].replace(/-/g, '/'); // Converter de volta: "1-1-3" -> "1/1/3" + slot = parts[5].replace(/-/g, '/'); onuId = parts[6]; - servicePort = parts[7]; - serialNumber = parts.slice(8).join('_'); // Serial pode ter underscores - } else if (parts.length >= 8) { - // Caso: confirm_remove_olt_dito_slot_onuId_servicePort_serialNumber + serialNumber = parts.slice(7).join('_'); + } else if (parts.length >= 7) { + // Caso: confirm_remove_olt_dito_slot_onuId_serialNumber oltId = parts[2] + '_' + parts[3]; // "olt_dito" - slot = parts[4].replace(/-/g, '/'); // Converter de volta: "1-1-3" -> "1/1/3" + slot = parts[4].replace(/-/g, '/'); onuId = parts[5]; - servicePort = parts[6]; - serialNumber = parts.slice(7).join('_'); // Serial pode ter underscores - } else { - // Fallback - caso não siga o padrão esperado - oltId = parts[2]; - slot = parts[3].replace(/-/g, '/'); // Converter de volta também no fallback - onuId = parts[4]; - servicePort = parts[5]; serialNumber = parts.slice(6).join('_'); + } else { + // Fallback + oltId = parts[2]; + slot = parts[3].replace(/-/g, '/'); + onuId = parts[4]; + serialNumber = parts.slice(5).join('_'); } - console.log(`🔍 Parsed - oltId: ${oltId}, slot: ${slot}, onuId: ${onuId}, servicePort: ${servicePort}, serialNumber: ${serialNumber}`); + console.log(`🔍 Parsed - oltId: ${oltId}, slot: ${slot}, onuId: ${onuId}, serialNumber: ${serialNumber}`); await this.bot.answerCallbackQuery(callbackQuery.id); @@ -2429,9 +2432,8 @@ Digite /help para ver todos os comandos disponíveis! `🗑️ **Removendo ONU...**\n\n` + `📱 **Serial:** ${serialNumber}\n` + `📍 **Localização:** Slot ${slot}, ONU ${onuId}\n` + - `🔌 **Service-port:** ${servicePort}\n` + `🏢 **OLT:** ${oltId.replace('olt_', '').replace(/_/g, '\\_').toUpperCase()}\n\n` + - `⏳ Executando comandos de remoção...`, + `⏳ Buscando e removendo todos os service-ports...`, { chat_id: chatId, message_id: callbackQuery.message.message_id, @@ -2440,19 +2442,25 @@ Digite /help para ver todos os comandos disponíveis! ); try { - const result = await this.ssh.removeOnu(oltId, slot, onuId, servicePort); + const result = await this.ssh.removeOnu(oltId, slot, onuId); if (result.success) { + const portsRemovidos = result.servicePorts && result.servicePorts.length > 0 + ? result.servicePorts.join(', ') + : 'N/A'; + const portsLabel = result.servicePorts && result.servicePorts.length > 1 + ? `• Removidos ${result.servicePorts.length} service-ports (${portsRemovidos})` + : `• Removido service-port ${portsRemovidos}`; + await this.bot.editMessageText( `✅ **ONU Removida com Sucesso!**\n\n` + `📱 **Serial:** ${serialNumber}\n` + `📍 **Localização:** Slot ${slot}, ONU ${onuId}\n` + - `🔌 **Service-port:** ${servicePort}\n` + `🏢 **OLT:** ${oltId.replace('olt_', '').replace(/_/g, '\\_').toUpperCase()}\n\n` + `✅ **Status:** ONU removida completamente\n` + `🗑️ **Ações realizadas:**\n` + `• Removida interface ONU\n` + - `• Removido service-port\n` + + `${portsLabel}\n` + `• Configuração commitada\n\n` + `💡 A ONU pode ser reconfigurada quando necessário`, { @@ -2466,7 +2474,6 @@ Digite /help para ver todos os comandos disponíveis! `❌ **Erro na Remoção**\n\n` + `📱 **Serial:** ${serialNumber}\n` + `📍 **Localização:** Slot ${slot}, ONU ${onuId}\n` + - `🔌 **Service-port:** ${servicePort}\n` + `🏢 **OLT:** ${oltId.replace('olt_', '').replace(/_/g, '\\_').toUpperCase()}\n\n` + `❌ **Erro:** ${result.message}\n\n` + `🔄 Verifique o status da ONU ou tente novamente`, diff --git a/src/ssh/manager.js b/src/ssh/manager.js index 1691bf4..4427a66 100644 --- a/src/ssh/manager.js +++ b/src/ssh/manager.js @@ -958,10 +958,10 @@ class SSHManager { }; } - // Extrair service-port da saída - const servicePort = this.parseServicePort(result.output); + // Extrair todos os service-ports da saída + const servicePorts = this.parseServicePorts(result.output); - if (!servicePort) { + if (servicePorts.length === 0) { return { success: false, message: `Service-port não encontrado para ONU ${onuId} no slot ${slot}`, @@ -971,8 +971,9 @@ class SSHManager { return { success: true, - message: `Service-port encontrado: ${servicePort}`, - servicePort: servicePort, + message: `Service-port(s) encontrado(s): ${servicePorts.join(', ')}`, + servicePort: servicePorts[0], // compatibilidade retroativa + servicePorts: servicePorts, slot: slot, onuId: onuId, output: result.output @@ -989,34 +990,47 @@ class SSHManager { } /** - * Extrai o service-port da saída do comando + * Extrai o service-port da saída do comando (retorna apenas o primeiro) * @param {string} output - Saída do comando show running-config service-port * @returns {string|null} - Service-port encontrado ou null */ parseServicePort(output) { + const ports = this.parseServicePorts(output); + return ports.length > 0 ? ports[0] : null; + } + + /** + * Extrai todos os service-ports da saída do comando + * @param {string} output - Saída do comando show running-config service-port + * @returns {string[]} - Array com todos os service-ports encontrados + */ + parseServicePorts(output) { const lines = output.split('\n'); - + const ports = []; + for (const line of lines) { - // Procurar por "service-port" seguido de número const match = line.match(/service-port\s+(\d+)/); if (match) { - return match[1]; + const port = match[1]; + if (!ports.includes(port)) { + ports.push(port); + } } } - - return null; + + return ports; } /** * Remove uma ONU específica (processo completo) + * Busca automaticamente todos os service-ports e remove cada um deles. * @param {string} equipmentId - ID do equipamento OLT * @param {string} slot - Slot da ONU (ex: 1/1/1) * @param {string} onuId - ID da ONU - * @param {string} servicePort - Service-port da ONU * @returns {Promise} - Promise com resultado da operação */ - async removeOnu(equipmentId, slot, onuId, servicePort) { - console.log(`🗑️ Iniciando remoção de ONU - OLT: ${equipmentId}, Slot: ${slot}, ONU: ${onuId}, Service-port: ${servicePort}`); + async removeOnu(equipmentId, slot, onuId) { + console.log(`🗑️ Iniciando remoção de ONU - OLT: ${equipmentId}, Slot: ${slot}, ONU: ${onuId}`); return new Promise(async (resolve, reject) => { try { @@ -1029,6 +1043,24 @@ class SSHManager { } console.log(`✅ Conectado! ConnectionId: ${connection.connectionId}`); + + // Buscar todos os service-ports antes de abrir o shell interativo + const searchCommand = `show running-config service-port | context-match "gpon ${slot} onu ${onuId}"`; + console.log(`🔍 Buscando service-ports: ${searchCommand}`); + const spResult = await this.executeCommand(connection.connectionId, searchCommand); + const servicePorts = spResult.success ? this.parseServicePorts(spResult.output) : []; + + if (servicePorts.length === 0) { + this.disconnect(connection.connectionId); + return resolve({ + success: false, + message: `Nenhum service-port encontrado para ONU ${onuId} no slot ${slot}`, + slot: slot, + onuId: onuId + }); + } + + console.log(`🔌 Service-port(s) encontrado(s): ${servicePorts.join(', ')}`); const conn = this.connections.get(connection.connectionId); @@ -1044,24 +1076,36 @@ class SSHManager { let step = 0; let isComplete = false; + // Construir lista de comandos dinamicamente para N service-ports + // 0: config + // 1: interface gpon + // 2: no onu + // 3: top + // 4..4+n-1: no service-port (um por service-port) + // 4+n: commit + // 4+n+1: top + // 4+n+2: exit + // 4+n+3: exit const commands = [ 'config', `interface gpon ${slot}`, `no onu ${onuId}`, 'top', - `no service-port ${servicePort}`, + ...servicePorts.map(sp => `no service-port ${sp}`), 'commit', 'top', 'exit', 'exit' ]; + // Índice do comando commit (usado como referência para os demais) + const commitIdx = 4 + servicePorts.length; + stream.on('data', (data) => { const dataStr = data.toString(); output += dataStr; console.log(`📨 Recebido: ${dataStr.trim()}`); - // Detectar prompts e enviar próximo comando if (step < commands.length) { let shouldSendCommand = false; @@ -1072,30 +1116,21 @@ class SSHManager { // No modo config - enviar interface shouldSendCommand = true; } else if (step === 2 && dataStr.includes('(config-gpon')) { - // No modo interface - enviar no onu + // No modo interface gpon - enviar no onu shouldSendCommand = true; } else if (step === 3 && dataStr.includes('(config-gpon')) { // Após no onu - enviar top shouldSendCommand = true; - } else if (step === 4 && dataStr.includes('(config)#')) { - // De volta ao config - enviar no service-port + } else if (step >= 4 && step <= commitIdx + 2 && dataStr.includes('(config)#')) { + // Remove todos os service-ports + commit + top + primeiro exit shouldSendCommand = true; - } else if (step === 5 && dataStr.includes('(config)#')) { - // Após service-port - enviar commit - shouldSendCommand = true; - } else if (step === 6 && dataStr.includes('(config)#')) { - // Após commit - enviar top - shouldSendCommand = true; - } else if (step === 7 && dataStr.includes('(config)#')) { - // Após top - enviar exit - shouldSendCommand = true; - } else if (step === 8 && dataStr.includes('#') && !dataStr.includes('(config')) { - // Último exit - enviar exit final + } else if (step === commitIdx + 3 && dataStr.includes('#') && !dataStr.includes('(config')) { + // Último exit shouldSendCommand = true; } if (shouldSendCommand) { - console.log(`📝 Enviando comando ${step + 1}: ${commands[step]}`); + console.log(`📝 Enviando comando ${step + 1}/${commands.length}: ${commands[step]}`); stream.write(commands[step] + '\n'); step++; } @@ -1118,7 +1153,7 @@ class SSHManager { output: output.trim(), slot: slot, onuId: onuId, - servicePort: servicePort + servicePorts: servicePorts }); }); @@ -1145,7 +1180,6 @@ class SSHManager { } }); } - /** * Processo completo de remoção de ONU pelo serial number * @param {string} equipmentId - ID do equipamento OLT @@ -1190,7 +1224,8 @@ class SSHManager { serialNumber: serialNumber, slot: findResult.onuInfo.slot, onuId: findResult.onuInfo.onuId, - servicePort: servicePortResult.servicePort, + servicePort: servicePortResult.servicePorts[0], // compatibilidade retroativa + servicePorts: servicePortResult.servicePorts, findOutput: findResult.output, servicePortOutput: servicePortResult.output, readyForRemoval: true