diagnostico: adicionada função (TESTING)

Signed-off-by: Rodrigo Bertoldo de Sousa Martins <rodrigo.sousa.577@gmail.com>
This commit is contained in:
rodrigo committed 2026-03-30 21:52:13 -03:00
1 parent 7f38d16821
commit 0dbab52aa1
3 files changed
+430 -1

No files matched your search

+360
View File
@@ -226,6 +226,11 @@ class BotHandler {
await this.handleListarServicos(chatId, target);
break;
case 'diagnosticar':
console.log(`🩺 Executando handleDiagnosticarCliente com target: ${target}`);
await this.handleDiagnosticarCliente(chatId, target);
break;
case 'dados_cliente':
case 'dados_cadastrais':
console.log(`📋 Executando handleDadosClientePorBusca com target: ${target}`);
@@ -871,6 +876,355 @@ Digite /help para ver todos os comandos disponíveis!
}
}
/**
* Diagnóstico completo de um cliente: TopSapp + Juniper PPPoE + ONU
*/
async handleDiagnosticarCliente(chatId, query) {
if (!query) {
await this.bot.sendMessage(chatId,
`🩺 *Diagnóstico de Cliente*\n\n` +
`💡 *Como usar:*\n` +
`• "diagnosticar João da Silva"\n` +
`• "diagnosticar 123.456.789-10"\n\n` +
`O diagnóstico verifica: status no TopSapp, sessão PPPoE no concentrador e status da ONU.`,
{ parse_mode: 'Markdown' }
);
return;
}
try {
await this.bot.sendMessage(chatId, '🔍 Buscando cliente...');
let location = '';
let searchQuery = query;
if (/guarai|colmeia/i.test(query)) {
location = 'Guarai/Colmeia';
searchQuery = query.replace(/(guarai|colmeia)/gi, '').trim();
} else if (/pedro afonso/i.test(query)) {
location = 'Pedro Afonso';
searchQuery = query.replace(/pedro afonso/gi, '').trim();
}
const resultado = await this.topsapp.buscarCliente(searchQuery, location);
if (!resultado.success) {
await this.bot.sendMessage(chatId, `❌ Erro na busca: ${resultado.error}`);
return;
}
if (!resultado.clientes || resultado.clientes.length === 0) {
await this.bot.sendMessage(chatId, `🔍 Nenhum cliente encontrado para: "${searchQuery}"`);
return;
}
const instancia = resultado.instancia || location;
if (resultado.clientes.length === 1) {
await this._mostrarServicosParaDiagnostico(chatId, resultado.clientes[0].id, instancia);
return;
}
// Múltiplos clientes → exibir teclado de seleção
let message = `🔍 *${resultado.clientes.length} clientes encontrados*\n\n`;
const keyboard = [];
resultado.clientes.slice(0, 8).forEach((cliente, index) => {
message += `*${index + 1}.* ${cliente.nome}`;
if (cliente.cpf) message += ` — CPF: \`${cliente.cpf}\``;
message += `\n`;
keyboard.push([{
text: `🩺 Diagnosticar: ${cliente.nome.substring(0, 30)}`,
callback_data: `diag_cliente_${cliente.id}_${instancia}`
}]);
});
await this.bot.sendMessage(chatId, message, {
parse_mode: 'Markdown',
reply_markup: { inline_keyboard: keyboard }
});
} catch (error) {
console.error('❌ Erro em handleDiagnosticarCliente:', error);
await this.bot.sendMessage(chatId, `❌ Erro: ${error.message}`);
}
}
async _mostrarServicosParaDiagnostico(chatId, idCliente, location) {
const servicosResult = await this.topsapp.obterServicosCliente(idCliente, location);
if (!servicosResult.success) {
await this.bot.sendMessage(chatId, `❌ Erro ao buscar serviços: ${servicosResult.error}`);
return;
}
const servicos = (servicosResult.servicos || []).filter(s => {
const st = (s.id_status || s.statusNumerico);
return st === 1 || st === '1' || String(s.status).toLowerCase() === 'liberado' || String(s.status).toLowerCase() === 'ativo';
});
if (servicos.length === 0) {
await this.bot.sendMessage(chatId, `⚠️ Cliente sem serviços ativos para diagnosticar.`);
return;
}
if (servicos.length === 1) {
await this.runDiagnosticoServico(chatId, idCliente, servicos[0].id_servico || servicos[0].id, location, servicos[0]);
return;
}
let message = `🩺 *Selecione o serviço para diagnosticar:*\n\n`;
const keyboard = [];
servicos.forEach((s, i) => {
const nome = s.descricao || s.nome || `Serviço ${i + 1}`;
const login = s.usuario || s.pppoe_login || s.login || '';
message += `*${i + 1}.* ${nome}${login ? ` — \`${login}\`` : ''}\n`;
keyboard.push([{
text: `🔍 ${nome.substring(0, 35)}`,
callback_data: `diag_servico_${idCliente}_${s.id_servico || s.id}_${location}`
}]);
});
await this.bot.sendMessage(chatId, message, {
parse_mode: 'Markdown',
reply_markup: { inline_keyboard: keyboard }
});
}
async handleDiagClienteCallback(callbackQuery, data) {
const chatId = callbackQuery.message.chat.id;
const parts = data.replace('diag_cliente_', '').split('_');
const idCliente = parts[0];
const location = parts.slice(1).join('_');
await this.bot.answerCallbackQuery(callbackQuery.id);
await this._mostrarServicosParaDiagnostico(chatId, idCliente, location);
}
async handleDiagServicoCallback(callbackQuery, data) {
const chatId = callbackQuery.message.chat.id;
const parts = data.replace('diag_servico_', '').split('_');
const idCliente = parts[0];
const idServico = parts[1];
const location = parts.slice(2).join('_');
await this.bot.answerCallbackQuery(callbackQuery.id);
await this.runDiagnosticoServico(chatId, idCliente, idServico, location, null);
}
async runDiagnosticoServico(chatId, idCliente, idServico, location, servicoPreCarregado) {
try {
await this.bot.sendMessage(chatId, '⏳ Executando diagnóstico completo...');
// Buscar serviços caso não tenhamos o objeto do serviço
let servico = servicoPreCarregado;
if (!servico) {
const servicosResult = await this.topsapp.obterServicosCliente(idCliente, location);
if (!servicosResult.success) {
await this.bot.sendMessage(chatId, `❌ Erro ao buscar serviços: ${servicosResult.error}`);
return;
}
const idNum = parseInt(idServico, 10);
servico = (servicosResult.servicos || []).find(s =>
(s.id_servico || s.id) === idNum || String(s.id_servico || s.id) === String(idServico)
);
}
if (!servico) {
await this.bot.sendMessage(chatId, `❌ Serviço #${idServico} não encontrado.`);
return;
}
const pppoeLogin = servico.usuario || servico.pppoe_login || servico.login || null;
const serial = servico.serial || servico.comodato_serial || servico.mac || null;
const statusServico = this.topsapp.getStatusServicoDetalhado
? this.topsapp.getStatusServicoDetalhado(servico.id_status)
: (servico.status || 'N/A');
const nomePlano = servico.descricao || servico.nome || 'N/A';
const endereco = servico.instalacao_endereco || servico.end_rua || null;
const cidade = servico.instalacao_cidade || null;
// Executar consultas em paralelo: Juniper + ONU
const [juniperResult, onuResult] = await Promise.all([
pppoeLogin
? this.ssh.getJuniperSubscriberInfo('juniper', pppoeLogin).catch(e => ({ success: false, error: e.message }))
: Promise.resolve({ success: false, skipped: true }),
serial
? this._diagnosticarONU(serial).catch(e => ({ success: false, error: e.message }))
: Promise.resolve({ success: false, skipped: true })
]);
// Montar relatório
let msg = `🩺 *Diagnóstico do Cliente*\n`;
msg += `━━━━━━━━━━━━━━━━━━━━━\n\n`;
// Bloco 1: TopSapp
msg += `📋 *Serviço TopSapp*\n`;
msg += ` 📦 Plano: ${nomePlano}\n`;
msg += ` 🔌 Status: ${statusServico}\n`;
if (pppoeLogin) msg += ` 👤 Login PPPoE: \`${pppoeLogin}\`\n`;
if (endereco) msg += ` 📍 Endereço: ${endereco}${cidade ? `, ${cidade}` : ''}\n`;
msg += '\n';
// Bloco 2: Concentrador Juniper
msg += `🌐 *Concentrador Juniper*\n`;
if (juniperResult.skipped) {
msg += ` ⚫ Login PPPoE não informado no cadastro\n`;
} else if (!juniperResult.success) {
msg += ` ⚠️ Erro ao consultar: ${juniperResult.error || 'falha na consulta'}\n`;
} else if (juniperResult.connected) {
msg += ` 🟢 *Conectado*\n`;
msg += ` 🌐 IP: \`${juniperResult.ip || 'N/A'}\`\n`;
msg += ` 🔌 Interface: \`${juniperResult.interface || 'N/A'}\`\n`;
} else {
msg += ` 🔴 *Desconectado* (sem sessão PPPoE ativa)\n`;
}
msg += '\n';
// Bloco 3: ONU
msg += `📡 *ONU / ONT*\n`;
if (onuResult.skipped) {
msg += ` ⚫ Serial não informado no cadastro\n`;
} else if (!onuResult.success) {
msg += ` ❌ ${onuResult.error || 'ONU não encontrada'}\n`;
if (serial) msg += ` 📋 Serial buscado: \`${serial}\`\n`;
} else {
const rxLabel = onuResult.rxPower || 'N/A';
const rxNum = parseFloat(rxLabel);
const rxEmoji = isNaN(rxNum) ? '⚫' : rxNum >= -27 ? '🟢' : rxNum >= -30 ? '🟡' : '🔴';
msg += ` 📋 Serial: \`${serial}\`\n`;
msg += ` 🏢 OLT: ${onuResult.oltName || onuResult.oltType || 'N/A'}\n`;
if (onuResult.slot || onuResult.pon) {
msg += ` 📍 Slot/PON: ${onuResult.slot || '?'}/${onuResult.pon || '?'}\n`;
}
msg += ` 🔌 Estado: ${onuResult.online ? '🟢 Online' : '🔴 Offline'}\n`;
msg += ` ${rxEmoji} Rx Power: *${rxLabel}*`;
if (onuResult.type === 'fiberhome') msg += ` _(compensado)_`;
msg += '\n';
if (onuResult.portaEthernet) {
const ethOk = /forward|up|1gbit|100mbit/i.test(onuResult.portaEthernet);
msg += ` ${ethOk ? '🟢' : '🔴'} Porta Ethernet: ${onuResult.portaEthernet}\n`;
}
}
await this.bot.sendMessage(chatId, msg, { parse_mode: 'Markdown' });
} catch (error) {
console.error('❌ Erro em runDiagnosticoServico:', error);
await this.bot.sendMessage(chatId, `❌ Erro no diagnóstico: ${error.message}`);
}
}
/**
* Diagnóstico de ONU: detecta tipo (Datacom/FiberHome) e retorna dados estruturados
*/
async _diagnosticarONU(serial) {
const serialUpper = serial.toUpperCase();
if (serialUpper.startsWith('DACM')) {
return await this._diagnosticarONUDatacom(serial);
} else {
return await this._diagnosticarONUFiberhome(serial);
}
}
async _diagnosticarONUDatacom(serial) {
const olts = this.ssh.listOLTs();
if (olts.length === 0) {
return { success: false, error: 'Nenhuma OLT Datacom configurada' };
}
// Buscar ONU em todas as OLTs em paralelo
const searches = olts.map(olt =>
this.ssh.findOnuBySerial(olt.id, serial)
.then(r => ({ ...r, oltId: olt.id, oltName: olt.name }))
.catch(() => ({ success: false }))
);
const results = await Promise.allSettled(searches);
let found = null;
for (const r of results) {
if (r.status === 'fulfilled' && r.value.success) {
found = r.value;
break;
}
}
if (!found) {
return { success: false, error: `ONU ${serial} não encontrada em nenhuma OLT Datacom` };
}
const { oltId, oltName, onuInfo } = found;
const { slot, onuId } = onuInfo;
// Buscar sinal e porta ethernet em paralelo
const [signalResult, ethResult] = await Promise.all([
this.ssh.checkOnuSignal(oltId, slot, onuId).catch(e => ({ success: false, error: e.message })),
this.ssh.checkOnuEthernetDatacom(oltId, slot, onuId).catch(e => ({ success: false }))
]);
// Parsear sinal
const rawSignal = signalResult.output || '';
const stateMatch = rawSignal.match(/Operational\s+state\s*:\s*(\S+)/i);
const rxMatch = rawSignal.match(/Rx\s+Optical\s+Power\s*\[dBm\]\s*:\s*([-\d.]+)/i);
const operationalState = stateMatch ? stateMatch[1] : null;
const rxPower = rxMatch ? `${rxMatch[1]} dBm` : null;
const online = operationalState ? /up|active|online/i.test(operationalState) : false;
// Parsear ethernet
let portaEthernet = null;
if (ethResult.success) {
const ethRaw = ethResult.rawOutput || '';
const ethMatch = ethRaw.match(/\b(Forwarding|Down|Up|Blocking)\b[^\n]*([\d]+(?:Gbit|Mbit)[^\n]*|N\/A)?/i);
if (ethMatch) {
portaEthernet = ethMatch[0].trim().replace(/\s+/g, ' ');
}
}
return {
success: true,
type: 'datacom',
oltName,
slot,
pon: slot ? slot.split('/')[2] || slot : null,
onuId,
online,
rxPower,
operationalState,
portaEthernet
};
}
async _diagnosticarONUFiberhome(serial) {
const resultado = await this.fiberhome.obterStatusONU(serial);
if (!resultado.success) {
return { success: false, error: resultado.error || 'ONU não encontrada na FiberHome' };
}
const portaPrincipal = resultado.portasEthernet && resultado.portasEthernet.length > 0
? resultado.portasEthernet[0]
: null;
return {
success: true,
type: 'fiberhome',
oltName: 'FiberHome',
slot: resultado.slot,
pon: resultado.pon,
onuId: resultado.onuId,
online: resultado.online,
rxPower: resultado.rxPower,
txPower: resultado.txPower,
portaEthernet: portaPrincipal ? `${portaPrincipal.status}` : null
};
}
/**
* Verificar sinal de ONU
*/
@@ -1539,6 +1893,12 @@ Digite /help para ver todos os comandos disponíveis!
const serialNumber = data.replace('fiberhome_details_', '');
await this.bot.answerCallbackQuery(callbackQuery.id);
await this.handleStatusONU(chatId, serialNumber);
} else if (data.startsWith('diag_cliente_')) {
console.log(`🔍 Condição diag_cliente_ atendida`);
await this.handleDiagClienteCallback(callbackQuery, data);
} else if (data.startsWith('diag_servico_')) {
console.log(`🔍 Condição diag_servico_ atendida`);
await this.handleDiagServicoCallback(callbackQuery, data);
} else if (data.startsWith('dados_cliente_')) {
console.log(`🔍 Condição dados_cliente_ atendida`);
await this.handleDadosClienteCallback(callbackQuery, data);