Files
rodrigonet/src/nlp/processor.js
T
rodrigo 6e2473719d genieacs: implantação (TESTING)
Signed-off-by: Rodrigo Bertoldo de Sousa Martins <rodrigo.sousa.577@gmail.com>
2026-04-01 08:40:57 -03:00

949 lines
42 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
class NLPProcessor {
constructor() {
// Dicionário de sinônimos para ações
this.actionSynonyms = {
'desconectar': ['desconectar', 'desligar', 'parar', 'stop', 'disconnect', 'kick', 'expulsar', 'encerrar', 'fechar conexão', 'fechar conexao'],
'desconectar_usuario': ['desconectar cliente', 'desconectar usuário', 'desconectar usuario', 'desconectar user', 'kick cliente', 'kick usuário', 'kick usuario', 'expulsar cliente', 'remover cliente', 'tirar cliente', 'cortar usuário', 'cortar usuario'],
'conectar': ['conectar', 'ligar', 'iniciar', 'start', 'connect', 'abrir conexão', 'abrir conexao', 'entrar em', 'acessar'],
'reiniciar': ['reiniciar', 'restart', 'reboot', 'reset', 'reinicializar', 'rebotar', 'rebootar', 'dar reboot', 'resetar'],
'status': ['status', 'estado', 'verificar', 'check', 'info', 'situação', 'situacao', 'checar'],
'help': ['ajuda', 'help', 'socorro', 'comandos', 'menu', 'opções', 'opcoes', 'o que posso fazer'],
'ssh': ['ssh', 'acessar', 'entrar', 'login', 'terminal', 'acesso remoto', 'shell'],
'lista': ['lista', 'listar', 'equipamentos', 'devices', 'list', 'dispositivos', 'mostrar equipamentos'],
'listar_usuarios': ['listar usuários', 'listar usuarios', 'listar clientes', 'usuarios conectados', 'usuarios ativos', 'clientes conectados', 'show users', 'ver usuarios', 'mostrar usuários', 'mostrar usuarios', 'quem está conectado', 'quem ta conectado', 'quem esta conectado', 'ppp active', 'ativos no concentrador'],
'ver_sinal': ['ver sinal', 'verificar sinal', 'sinal', 'check signal', 'signal', 'potência onu', 'potencia onu', 'nivel de sinal', 'nível de sinal', 'rx onu', 'ver onu sinal'],
'remover_onu': ['remover onu', 'deletar onu', 'apagar onu', 'remove onu', 'delete onu', 'tirar onu', 'excluir onu', 'retirar onu', 'desconfigurar onu', 'del onu'],
'adicionar_onu': ['adicionar onu', 'add onu', 'criar onu', 'cadastrar onu', 'registrar onu', 'configurar onu', 'provisionar onu', 'instalar onu', 'nova onu', 'provisionar'],
'adicionar_onu_vlan': ['adicionar onu vlan', 'add onu vlan', 'criar onu vlan', 'cadastrar onu vlan', 'adicionar com vlan', 'add com vlan'],
'adicionar_onu_fiberhome': ['adicionar onu fiberhome', 'add onu fiberhome', 'criar onu fiberhome', 'cadastrar onu fiberhome', 'registrar onu fiberhome', 'fiberhome onu', 'onu fiberhome'],
'remover_onu_fiberhome': ['remover onu fiberhome', 'deletar onu fiberhome', 'apagar onu fiberhome', 'remove onu fiberhome', 'delete onu fiberhome', 'tirar onu fiberhome'],
'ping': ['ping', 'testar', 'test', 'conectividade', 'alcançável', 'alcancavel', 'latência', 'latencia'],
'admin': ['admin', 'administração', 'administracao', 'painel', 'configurações', 'configuracoes', 'gerenciar'],
'usuarios_autorizados': ['usuarios autorizados', 'users autorizados', 'lista usuarios', 'listar usuarios autorizados'],
'meu_id': ['meu id', 'meu user id', 'my id', 'user id', 'minha id', 'qual meu id', 'meu telegram id'],
'buscar_cliente': ['buscar cliente', 'procurar cliente', 'encontrar cliente', 'search cliente', 'cliente', 'ver cliente', 'consultar cliente', 'pesquisar cliente', 'localizar cliente', 'achar cliente'],
'ver_faturas': ['ver faturas', 'ver fatura', 'faturas', 'fatura', 'boletos', 'boleto', 'contas', 'débitos', 'debitos', 'pendências', 'pendencias', 'financeiro cliente', 'em aberto', 'inadimplência', 'inadimplencia', 'mensalidade', 'vencimento', 'segunda via'],
'gerar_boleto': ['gerar boleto', 'boleto', 'criar boleto', 'pdf boleto', 'imprimir boleto', 'emitir boleto', 'segunda via boleto', 'segunda via fatura'],
'bloquear_cliente': ['bloquear cliente', 'bloquear', 'suspender cliente', 'cortar cliente', 'cortar internet', 'suspender acesso', 'desativar cliente', 'suspender internet'],
'liberar_cliente': ['liberar cliente', 'liberar', 'desbloquear cliente', 'reconectar cliente', 'reativar cliente', 'religar cliente', 'reativar', 'religar internet', 'tirar bloqueio', 'desbloquear'],
'status_topsapp': ['status topsapp', 'verificar topsapp', 'topsapp status', 'topsapp'],
'status_onu': ['status onu', 'verificar onu', 'onu status', 'check onu', 'status ont', 'ont status', 'checar onu', 'info onu', 'informações onu', 'informacoes onu', 'dados onu'],
'fiberhome_status': ['fiberhome status', 'status fiberhome', 'conexões fiberhome', 'fiberhome conexoes', 'fiberhome conectado'],
'dados_cliente': ['dados cliente', 'dados cadastrais', 'cadastro cliente', 'informações cliente', 'info cliente', 'perfil cliente', 'ficha cliente', 'registro cliente', 'ver dados'],
'listar_servicos': ['listar serviços', 'servicos cliente', 'planos cliente', 'contratos cliente', 'ver servicos', 'plano cliente', 'assinaturas', 'planos', 'serviços ativos', 'ver plano'],
'abrir_suporte': ['abrir suporte', 'criar suporte', 'adicionar suporte', 'novo suporte', 'suporte', 'chamado', 'ticket', 'atendimento', 'suporte tecnico', 'atendimento tecnico', 'abrir chamado', 'registrar chamado', 'criar chamado', 'visita tecnica', 'agendar visita', 'reclamação', 'reclamacao'],
'consultar_usuario': ['consultar usuario', 'consultar user', 'ver usuario', 'status usuario', 'status user', 'info usuario', 'info user', 'checar usuario', 'verificar usuario', 'pesquisar usuario', 'localizar usuario', 'buscar usuario', 'usuario conectado', 'user conectado', 'usuario online', 'user online', 'usuario ativo', 'user ativo'],
'diagnosticar': ['diagnosticar', 'diagnostico', 'diagnose', 'diagnosticar cliente', 'diagnostico cliente', 'checar cliente completo', 'verificar cliente completo', 'relatorio cliente', 'relatorio completo', 'status completo cliente', 'analisar cliente', 'inspecionar cliente', 'situacao do cliente', 'situação do cliente'],
'ver_roteador': ['ver roteador', 'info roteador', 'status roteador', 'roteador', 'cpe', 'ver cpe', 'info cpe', 'dados roteador', 'informações roteador', 'informacoes roteador', 'genieacs', 'ver device', 'info device', 'dispositivo cpe']
};
// Padrões de comandos
this.commandPatterns = [
// Padrões específicos para GenieACS – ver roteador
/^(ver|info|status|dados|informações|informacoes)\s+(roteador|cpe|device)\s+([A-Z0-9_-]+)$/i,
/^(roteador|cpe)\s+([A-Z0-9_-]+)$/i,
// Padrões específicos para TopSapp
/^(buscar|procurar|encontrar)\s+(cliente|user)\s+(.+)$/i,
/^(ver|mostrar)\s+(faturas?|boletos?|contas?)\s+(.+)$/i,
/^(gerar|criar|imprimir)\s+(boleto|pdf)\s+(.+)$/i,
/^(bloquear|suspender|cortar)\s+(cliente|user)\s+(.+)$/i,
/^(liberar|desbloquear|reconectar)\s+(cliente|user)\s+(.+)$/i,
/^(status|verificar)\s+(topsapp)$/i,
/^(dados|cadastro|informações|info)\s+(cliente|cadastrais?)\s+(.+)$/i,
/^(listar|ver)\s+(serviços?|servicos|planos|contratos)\s+(.+)$/i,
// Padrões específicos para suporte
/^(abrir|criar|adicionar|novo)\s+(suporte|chamado|ticket|atendimento)(?:\s+(.+))?$/i,
/^(suporte|chamado|ticket|atendimento)(?:\s+(.+))?$/i,
// Padrões específicos para Fiberhome
/^(status|verificar|check)\s+(onu|ont)\s+([A-Z0-9]+)$/i,
/^(onu|ont)\s+(status|verificar|check)\s+([A-Z0-9]+)$/i,
/^(status|verificar|check)\s+(fiberhome)$/i,
/^(fiberhome)\s+(status|conexões|conexoes)$/i,
// Padrões específicos para ver sinal
/^(ver|verificar|check)\s+(sinal|signal)\s+([A-Z0-9]+)$/i,
/^(sinal|signal)\s+([A-Z0-9]+)$/i,
// Padrões específicos para adicionar ONU com VLAN customizada
/^(adicionar|add|criar|cadastrar|registrar)\s+(onu|ont)\s+vlan\s+(\d+)\s+([A-Z0-9]+)$/i,
/^(adicionar|add|criar)\s+vlan\s+(\d+)\s+([A-Z0-9]+)$/i,
// Padrões específicos para adicionar ONU Fiberhome via TL1
/^(adicionar|add|criar|cadastrar|registrar)\s+(onu|ont)\s+fiberhome\s+([A-Z0-9]+)$/i,
/^(fiberhome)\s+(onu|ont)\s+([A-Z0-9]+)$/i,
// Padrões específicos para remover ONU Fiberhome via TL1
/^(remover|deletar|apagar|remove|delete)\s+(onu|ont)\s+fiberhome\s+([A-Z0-9]+)$/i,
/^(fiberhome)\s+(remover|deletar|apagar|remove|delete)\s+(onu|ont)\s+([A-Z0-9]+)$/i,
// Padrões específicos para adicionar ONU
/^(adicionar|add|criar|cadastrar|registrar)\s+(onu|ont)\s+([A-Z0-9]+)$/i,
/^(adicionar|add|criar|cadastrar|registrar)\s+([A-Z0-9]+)$/i,
// Padrões específicos para remover ONU
/^(remover|deletar|apagar|remove|delete)\s+(onu|ont)\s+([A-Z0-9]+)$/i,
/^(remover|deletar|apagar|remove|delete)\s+([A-Z0-9]+)$/i,
// Padrões específicos para desconectar usuário (devem vir primeiro)
/^(desconectar|kick|expulsar|remover)\s+(cliente|usuário|usuario|user)\s+(.+)$/i,
/^(desconectar|kick|expulsar|remover)\s+(usuario|user)\s+(.+)$/i,
/^(desconectar|kick|expulsar|remover)\s+(.+)\s+(do|no)?\s*(concentrador|juniper)?$/i,
// Padrão genérico para desconectar (detectar se é nome de usuário)
/^(desconectar|kick|expulsar|remover)\s+([a-zA-Z0-9_.-]+)$/i,
// Padrões para consultar usuário específico
/^(consultar|ver|status|info|checar|verificar|pesquisar|localizar|buscar)\s+(usuario|user)\s+(.+)$/i,
/^(usuario|user)\s+(.+)$/i,
// Padrões para diagnosticar cliente
/^(diagnosticar|diagnostico|diagnose|analisar|inspecionar)\s+(cliente\s+)?(.+)$/i,
// Padrões para listar usuários
/^(listar|mostrar)\s+(usuários|usuarios|clientes|users)(\s+conectados)?$/i,
// Padrões gerais (devem vir por último)
/^(conectar|ligar|iniciar)\s+(.+)$/i,
/^(reiniciar|restart)\s+(.+)$/i,
/^(verificar|check)\s+(status\s+)?(.+)$/i,
/^ssh\s+(.+)$/i,
/^ping\s+(.+)$/i,
// Segunda via / emitir boleto com identificador
/^(segunda\s+via|emitir\s+boleto|2[aª]?\s*via)\s+(.+)$/i,
// Reativar / religar / desbloquear → liberar_cliente
/^(reativar|religar|ativar|desbloquear)\s+(.+)$/i,
// Cortar / suspender com alvo (exceto "usuario/user/cliente")
/^(cortar|suspender)\s+(?!usu|cli|sess)(.+)$/i,
// Plano / serviço / contrato de cliente → listar_servicos
/^(planos?|servi[çc]os?|contratos?)\s+(?:de\s+|do\s+|da\s+)?(.+)$/i,
// Ficha / perfil de cliente → dados_cliente
/^(ficha|perfil)\s+(?:de\s+|do\s+|da\s+)?(.+)$/i,
// Consultar / pesquisar / localizar / achar cliente
/^(consultar|pesquisar|localizar|achar)\s+(?:cliente|user)\s+(.+)$/i,
// Quem está conectado → listar_usuarios
/^(quem)\s+(?:está|esta|tá|ta)\s+conectado.*$/i
];
}
/**
* Processa uma mensagem de texto e extrai a intenção
* @param {string} text - Texto da mensagem
* @returns {Object} - Objeto com ação, equipamento e confiança
*/
processMessage(text) {
if (!text || typeof text !== 'string') {
return { action: null, target: null, confidence: 0 };
}
const normalizedText = text.toLowerCase().trim();
// Verificar se é um comando direto (/comando)
if (normalizedText.startsWith('/')) {
return this.processSlashCommand(normalizedText);
}
// Verificar padrões de comandos
for (const pattern of this.commandPatterns) {
const match = normalizedText.match(pattern);
if (match) {
return this.extractFromPattern(match);
}
}
// Verificar palavras-chave individuais
return this.extractFromKeywords(normalizedText);
}
/**
* Processa comandos que começam com /
*/
processSlashCommand(text) {
const parts = text.split(' ');
const command = parts[0].substring(1); // Remove o /
const target = parts.slice(1).join(' ');
return {
action: command,
target: target || null,
confidence: 1.0,
type: 'slash_command'
};
}
/**
* Extrai ação e alvo de padrões regex
*/
extractFromPattern(match) {
const fullMatch = match[0];
const action = match[1];
// Detectar comando de ver roteador / CPE via GenieACS
if (/roteador|cpe|device/i.test(fullMatch) && !/sinal|signal|onu|ont/i.test(fullMatch)) {
// Padrão "ver roteador SERIAL" ou "roteador SERIAL"
const serial = match[match.length - 1] || match[2];
return {
action: 'ver_roteador',
target: serial ? serial.trim().toUpperCase() : null,
confidence: 0.95,
type: 'genieacs_pattern'
};
}
// Detectar comando de ver sinal
if (/ver|verificar|check|sinal|signal/i.test(action) && /sinal|signal/i.test(fullMatch)) {
let serialNumber = match[match.length - 1]; // Último grupo capturado
// Se não encontrou serial, tentar extrair de forma diferente
if (!serialNumber || serialNumber.trim() === '') {
const serialMatch = fullMatch.match(/([A-Z0-9]+)$/i);
if (serialMatch) {
serialNumber = serialMatch[1];
}
}
return {
action: 'ver_sinal',
target: serialNumber ? serialNumber.trim().toUpperCase() : null,
confidence: 0.95,
type: 'signal_check_pattern'
};
}
// Detectar comandos TopSapp - buscar cliente
if (/buscar|procurar|encontrar/i.test(action) && /cliente|user/i.test(fullMatch)) {
let query = match[3] || match[2]; // Nome/CPF do cliente
return {
action: 'buscar_cliente',
target: query ? query.trim() : null,
confidence: 0.95,
type: 'topsapp_search_pattern'
};
}
// Detectar comandos TopSapp - dados cadastrais
if (/dados|cadastro|informações|info/i.test(action) && /cliente|cadastrais?/i.test(fullMatch)) {
let query = match[3] || match[2]; // Nome/CPF/ID do cliente
return {
action: 'dados_cliente',
target: query ? query.trim() : null,
confidence: 0.95,
type: 'topsapp_dados_pattern'
};
}
// Detectar comandos TopSapp - ver faturas
if (/ver|mostrar/i.test(action) && /faturas?|boletos?|contas?/i.test(fullMatch)) {
let query = match[3] || match[2]; // ID/CPF do cliente
if (query) {
query = query.trim();
// Converter CPF sem formatação (11 dígitos) para formato XXX.XXX.XXX-XX
if (/^\d{11}$/.test(query)) {
query = `${query.slice(0,3)}.${query.slice(3,6)}.${query.slice(6,9)}-${query.slice(9,11)}`;
}
}
return {
action: 'ver_faturas',
target: query || null,
confidence: 0.95,
type: 'topsapp_faturas_pattern'
};
}
// Detectar comandos TopSapp - gerar boleto
if (/gerar|criar|imprimir/i.test(action) && /boleto|pdf/i.test(fullMatch)) {
let faturaId = match[3] || match[2]; // ID da fatura
return {
action: 'gerar_boleto',
target: faturaId ? faturaId.trim() : null,
confidence: 0.95,
type: 'topsapp_boleto_pattern'
};
}
// Detectar consulta de usuário específico no Juniper
if (/consultar|ver|status|info|checar|verificar|pesquisar|localizar|buscar/i.test(action) && /usuario|user/i.test(fullMatch)) {
let username = match[3] || match[2];
return {
action: 'consultar_usuario',
target: username ? username.trim() : null,
confidence: 0.95,
type: 'consultar_usuario_pattern'
};
}
// Detectar "usuario NOME" / "user NOME"
if (/^usuario$|^user$/i.test(action)) {
let username = match[2];
return {
action: 'consultar_usuario',
target: username ? username.trim() : null,
confidence: 0.9,
type: 'consultar_usuario_simple'
};
}
// Detectar diagnóstico de cliente
if (/^diagnosticar$|^diagnostico$|^diagnose$|^analisar$|^inspecionar$/i.test(action)) {
// match[2] pode ser "cliente " ou já o nome, match[3] é o nome quando match[2]="cliente "
let query = match[3] || match[2];
// remover prefixo "cliente" se vier junto
if (query) query = query.replace(/^cliente\s+/i, '').trim();
return {
action: 'diagnosticar',
target: query || null,
confidence: 0.95,
type: 'diagnosticar_pattern'
};
}
// Detectar comandos de suporte
if (/abrir|criar|adicionar|novo|suporte|chamado|ticket|atendimento/i.test(action) &&
/suporte|chamado|ticket|atendimento/i.test(fullMatch)) {
let query = match[3] || match[2] || ''; // Nome/CPF do cliente (opcional)
return {
action: 'abrir_suporte',
target: query ? query.trim() : null,
confidence: 0.95,
type: 'suporte_pattern'
};
}
// Detectar comandos TopSapp - bloquear cliente/serviço
if (/bloquear|suspender|cortar/i.test(action)) {
let clienteId = match[3] || match[2]; // ID/CPF/Nome do cliente
return {
action: 'bloquear_cliente',
target: clienteId ? clienteId.trim() : null,
confidence: 0.95,
type: 'topsapp_block_pattern'
};
}
// Detectar comandos TopSapp - liberar cliente/serviço
if (/liberar|desbloquear|reconectar|ativar|religar/i.test(action)) {
let clienteId = match[3] || match[2]; // ID/CPF/Nome do cliente
return {
action: 'liberar_cliente',
target: clienteId ? clienteId.trim() : null,
confidence: 0.95,
type: 'topsapp_unblock_pattern'
};
}
// Detectar comandos TopSapp - status
if (/status|verificar/i.test(action) && /topsapp/i.test(fullMatch)) {
return {
action: 'status_topsapp',
target: null,
confidence: 0.95,
type: 'topsapp_status_pattern'
};
}
// Detectar comandos Fiberhome - status ONU
if (/status|verificar|check/i.test(action) && /onu|ont/i.test(fullMatch)) {
let serialNumber = match[3] || match[2]; // Capturar serial do terceiro ou segundo grupo
return {
action: 'status_onu',
target: serialNumber ? serialNumber.trim().toUpperCase() : null,
confidence: 0.95,
type: 'fiberhome_onu_status_pattern'
};
}
// Detectar comandos Fiberhome - status geral
if (/status|verificar|conexões|conexoes/i.test(action) && /fiberhome/i.test(fullMatch)) {
return {
action: 'fiberhome_status',
target: null,
confidence: 0.95,
type: 'fiberhome_status_pattern'
};
}
// Padrão específico para "sinal SERIAL"
if (/sinal|signal/i.test(action)) {
let serialNumber = match[2]; // Segundo grupo capturado
return {
action: 'ver_sinal',
target: serialNumber ? serialNumber.trim().toUpperCase() : null,
confidence: 0.9,
type: 'signal_simple_pattern'
};
}
// Padrões específicos para adicionar ONU
if (/adicionar|add|criar|cadastrar|registrar/i.test(action)) {
// Padrão especial: "adicionar onu fiberhome SERIAL"
if (/fiberhome/i.test(fullMatch)) {
let serialNumber;
// Formato: "adicionar onu fiberhome SERIAL"
if (match.length === 4 && /onu|ont/i.test(fullMatch)) {
serialNumber = match[3]; // Serial
}
// Formato: "fiberhome onu SERIAL"
else if (match.length === 4 && match[1] === 'fiberhome') {
serialNumber = match[3]; // Serial
}
if (serialNumber) {
return {
action: 'adicionar_onu_fiberhome',
target: serialNumber.trim().toUpperCase(),
confidence: 0.95,
type: 'add_onu_fiberhome_pattern'
};
}
}
// Padrão especial: "adicionar onu vlan XXX SERIAL" ou "add onu vlan XXX SERIAL"
if (/vlan/i.test(fullMatch)) {
let vlanId, serialNumber;
// Formato: "adicionar onu vlan XXX SERIAL"
if (match.length === 5 && /onu|ont/i.test(fullMatch)) {
vlanId = match[3]; // VLAN ID
serialNumber = match[4]; // Serial
}
// Formato: "adicionar vlan XXX SERIAL"
else if (match.length === 4) {
vlanId = match[2]; // VLAN ID
serialNumber = match[3]; // Serial
}
if (vlanId && serialNumber) {
return {
action: 'adicionar_onu_vlan',
target: serialNumber.trim().toUpperCase(),
vlanId: parseInt(vlanId),
confidence: 0.95,
type: 'add_onu_vlan_pattern'
};
}
}
// Padrão 1: "adicionar onu SERIAL" ou "add ont SERIAL"
if (/onu|ont/i.test(fullMatch)) {
let serialNumber = match[3]; // Terceiro grupo capturado (serial após "onu/ont")
return {
action: 'adicionar_onu',
target: serialNumber ? serialNumber.trim().toUpperCase() : null,
confidence: 0.95,
type: 'add_onu_pattern'
};
}
// Padrão 2: "adicionar SERIAL" - assumir que é ONU se parece com serial
let potentialSerial = match[2];
if (potentialSerial && this.looksLikeOnuSerial(potentialSerial)) {
return {
action: 'adicionar_onu',
target: potentialSerial.trim().toUpperCase(),
confidence: 0.85,
type: 'add_onu_inferred'
};
}
}
// Padrões específicos para remover ONU
if (/remover|deletar|apagar|remove|delete/i.test(action)) {
// Padrão especial: "remover onu fiberhome SERIAL"
if (/fiberhome/i.test(fullMatch)) {
let serialNumber;
// Formato: "remover onu fiberhome SERIAL"
if (match.length === 4 && /onu|ont/i.test(fullMatch)) {
serialNumber = match[3]; // Serial
}
// Formato: "fiberhome remover onu SERIAL"
else if (match.length === 5 && match[1] === 'fiberhome') {
serialNumber = match[4]; // Serial
}
if (serialNumber) {
return {
action: 'remover_onu_fiberhome',
target: serialNumber.trim().toUpperCase(),
confidence: 0.95,
type: 'remove_onu_fiberhome_pattern'
};
}
}
// Padrão 1: "remover onu SERIAL" ou "remover ont SERIAL"
if (/onu|ont/i.test(fullMatch)) {
let serialNumber = match[3]; // Terceiro grupo capturado (serial após "onu/ont")
return {
action: 'remover_onu',
target: serialNumber ? serialNumber.trim().toUpperCase() : null,
confidence: 0.95,
type: 'remove_onu_pattern'
};
}
// Padrão 2: "remover SERIAL" - assumir que é ONU se parece com serial
let potentialSerial = match[2];
if (potentialSerial && this.looksLikeOnuSerial(potentialSerial)) {
return {
action: 'remover_onu',
target: potentialSerial.trim().toUpperCase(),
confidence: 0.85,
type: 'remove_onu_inferred'
};
}
}
// Detectar se é comando de desconectar usuário - verificar padrões específicos
if (/desconectar|kick|expulsar|remover/i.test(action)) {
// Padrão 1: "desconectar cliente/usuario/user NOME"
if (/cliente|usuário|usuario|user/i.test(fullMatch)) {
let username = match[3] || match[2]; // Pegar o grupo com o nome do usuário
// Se não encontrou o nome, tentar extrair de forma mais robusta
if (!username || username.trim() === '') {
const parts = fullMatch.toLowerCase().split(/cliente|usuário|usuario|user/);
if (parts.length > 1) {
username = parts[1].trim().split(/\s+/)[0]; // Primeira palavra após cliente/usuário
}
}
return {
action: 'desconectar_usuario',
target: username ? username.trim() : null,
confidence: 0.95,
type: 'user_disconnect_pattern'
};
}
// Padrão 2: "desconectar NOME do concentrador" ou similar
if (/concentrador|juniper/i.test(fullMatch)) {
let username = match[2]; // Nome do usuário deve estar no segundo grupo
return {
action: 'desconectar_usuario',
target: username ? username.trim() : null,
confidence: 0.9,
type: 'user_disconnect_pattern'
};
}
// Padrão 3: "desconectar NOME" - detectar se NOME parece ser um usuário
if (match[2] && this.looksLikeUsername(match[2])) {
return {
action: 'desconectar_usuario',
target: match[2].trim(),
confidence: 0.85,
type: 'user_disconnect_inferred'
};
}
}
// Detectar comando de listar usuários
if (/listar|mostrar/i.test(action) && /usuários|usuarios|clientes|users/i.test(fullMatch)) {
return {
action: 'listar_usuarios',
target: 'concentrador', // Target padrão
confidence: 0.9,
type: 'list_users_pattern'
};
}
// Detectar comandos de suporte
if (/abrir|criar|adicionar|novo/i.test(action) && /suporte|chamado|ticket|atendimento/i.test(fullMatch)) {
let clienteQuery = match[3] || null; // Cliente opcional
return {
action: 'abrir_suporte',
target: clienteQuery ? clienteQuery.trim() : null,
confidence: 0.95,
type: 'suporte_pattern'
};
}
// Detectar comando simples de suporte
if (/suporte|chamado|ticket|atendimento/i.test(action)) {
let clienteQuery = match[2] || null; // Cliente opcional
return {
action: 'abrir_suporte',
target: clienteQuery ? clienteQuery.trim() : null,
confidence: 0.9,
type: 'suporte_simple_pattern'
};
}
// Detectar segunda via / emitir boleto
if (/segunda\s*via|emitir\s*boleto|2[aª]?\s*via/i.test(action) || /segunda\s*via|2[aª]?\s*via/i.test(fullMatch)) {
const query = match[2] || match[1];
return {
action: 'gerar_boleto',
target: query ? query.trim() : null,
confidence: 0.9,
type: 'segunda_via_pattern'
};
}
// Detectar reativar / religar / desbloquear → liberar_cliente
if (/^(reativar|religar|ativar|desbloquear)$/i.test(action)) {
const query = match[2] || match[1];
return {
action: 'liberar_cliente',
target: query ? query.trim() : null,
confidence: 0.9,
type: 'liberar_pattern'
};
}
// Detectar cortar / suspender → bloquear_cliente
if (/^(cortar|suspender)$/i.test(action)) {
const query = match[2] || match[1];
return {
action: 'bloquear_cliente',
target: query ? query.trim() : null,
confidence: 0.9,
type: 'bloquear_pattern'
};
}
// Detectar plano / serviço / contrato → listar_servicos
if (/^(planos?|servi[çc]os?|contratos?)$/i.test(action)) {
const query = match[2] || match[1];
return {
action: 'listar_servicos',
target: query ? query.trim() : null,
confidence: 0.9,
type: 'servicos_pattern'
};
}
// Detectar ficha / perfil → dados_cliente
if (/^(ficha|perfil)$/i.test(action)) {
const query = match[2] || match[1];
return {
action: 'dados_cliente',
target: query ? query.trim() : null,
confidence: 0.9,
type: 'dados_perfil_pattern'
};
}
// Detectar quem está conectado → listar_usuarios
if (/^quem$/i.test(action) && /conectado/i.test(fullMatch)) {
return {
action: 'listar_usuarios',
target: 'concentrador',
confidence: 0.95,
type: 'list_users_quem_pattern'
};
}
// Detectar consultar / pesquisar / localizar / achar → buscar_cliente
if (/^(consultar|pesquisar|localizar|achar)$/i.test(action) && /cliente|user/i.test(fullMatch)) {
const query = match[2] || match[1];
return {
action: 'buscar_cliente',
target: query ? query.trim() : null,
confidence: 0.9,
type: 'buscar_cliente_extra_pattern'
};
}
// Padrões gerais
const normalizedAction = this.normalizeAction(action);
const target = match[match.length - 1]; // Último grupo capturado
return {
action: normalizedAction,
target: target ? target.trim() : null,
confidence: 0.9,
type: 'pattern_match'
};
}
/**
* Extrai informações baseado em palavras-chave
*/
extractFromKeywords(text) {
let bestMatch = { action: null, target: null, confidence: 0 };
// Verificar primeiro se é um comando de desconectar usuário
if (/desconectar|kick|expulsar|remover/i.test(text)) {
// Padrão explícito: "desconectar usuario/cliente NOME"
if (/usuario|user|cliente/i.test(text)) {
const match = text.match(/(?:desconectar|kick|expulsar|remover)\s+(?:usuario|user|cliente)\s+(\w+)/i);
if (match) {
return {
action: 'desconectar_usuario',
target: match[1],
confidence: 0.9,
type: 'keyword_user_disconnect'
};
}
// Tentar padrão mais simples: "desconectar NOME" onde o texto contém "usuario"
const simpleMatch = text.match(/(?:desconectar|kick|expulsar|remover)\s+(\w+)/i);
if (simpleMatch) {
return {
action: 'desconectar_usuario',
target: simpleMatch[1],
confidence: 0.8,
type: 'keyword_user_disconnect_simple'
};
}
}
// Padrão implícito: "desconectar NOME" onde NOME parece ser username
const implicitMatch = text.match(/(?:desconectar|kick|expulsar|remover)\s+([a-zA-Z0-9._-]+)/i);
if (implicitMatch && this.looksLikeUsername(implicitMatch[1])) {
return {
action: 'desconectar_usuario',
target: implicitMatch[1],
confidence: 0.75,
type: 'keyword_user_disconnect_inferred'
};
}
}
// Detectar reativar / religar / desbloquear → liberar_cliente
if (/reativar|religar|desbloquear|tirar\s+bloqueio/i.test(text)) {
const rlMatch = text.match(/(?:reativar|religar|desbloquear)\s+(.+)/i);
if (rlMatch) {
return {
action: 'liberar_cliente',
target: rlMatch[1].trim(),
confidence: 0.85,
type: 'keyword_liberar'
};
}
}
// Detectar "quem está/ta conectado" → listar_usuarios
if (/quem\s+(?:está|esta|tá|ta)\s+conectado/i.test(text)) {
return {
action: 'listar_usuarios',
target: 'concentrador',
confidence: 0.95,
type: 'keyword_quem_conectado'
};
}
// Detectar segunda via → gerar_boleto
if (/segunda\s*via|2[aª]\s*via/i.test(text)) {
const svMatch = text.match(/(?:segunda\s*via|2[aª]\s*via)\s*(.*)/i);
return {
action: 'gerar_boleto',
target: svMatch && svMatch[1] ? svMatch[1].trim() : null,
confidence: 0.9,
type: 'keyword_segunda_via'
};
}
// Detectar cortar internet / suspender acesso → bloquear_cliente
if (/cortar\s+internet|suspender\s+(?:cliente|acesso|internet)/i.test(text)) {
const blMatch = text.match(/(?:cortar|suspender)\s+(?:internet|acesso|cliente)?\s*(.+)?/i);
if (blMatch && blMatch[1]) {
return {
action: 'bloquear_cliente',
target: blMatch[1].trim(),
confidence: 0.85,
type: 'keyword_bloquear'
};
}
}
// Detectar "ver roteador SERIAL" / "roteador SERIAL" via GenieACS
if (/roteador|cpe/i.test(text) && !/onu|ont|sinal|signal/i.test(text)) {
const rrMatch = text.match(/(?:ver|info|status|dados)?\s*(?:roteador|cpe)\s+([A-Z0-9_-]+)/i);
if (rrMatch && rrMatch[1]) {
return {
action: 'ver_roteador',
target: rrMatch[1].trim().toUpperCase(),
confidence: 0.9,
type: 'keyword_roteador'
};
}
}
// Procurar por ações conhecidas
for (const [action, synonyms] of Object.entries(this.actionSynonyms)) {
for (const synonym of synonyms) {
if (text.includes(synonym)) {
const confidence = synonym.length / text.length;
if (confidence > bestMatch.confidence) {
bestMatch = {
action: action,
target: this.extractTarget(text, synonym),
confidence: Math.min(confidence * 2, 0.8), // Max 0.8 para keywords
type: 'keyword_match'
};
}
}
}
}
return bestMatch;
}
/**
* Extrai o alvo removendo a palavra de ação
*/
extractTarget(text, actionWord) {
const parts = text.split(actionWord);
if (parts.length > 1) {
return parts[1].trim();
}
return parts[0].trim();
}
/**
* Normaliza a ação para um formato padrão
*/
normalizeAction(action) {
const normalized = action.toLowerCase();
for (const [standardAction, synonyms] of Object.entries(this.actionSynonyms)) {
if (synonyms.includes(normalized)) {
return standardAction;
}
}
return normalized;
}
/**
* Verifica se o texto parece ser um endereço IP
*/
isIPAddress(text) {
const ipPattern = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/;
return ipPattern.test(text);
}
/**
* Verifica se o texto parece ser um hostname
*/
isHostname(text) {
const hostnamePattern = /^[a-zA-Z0-9.-]+$/;
return hostnamePattern.test(text) && text.includes('.');
}
/**
* Verifica se o texto parece ser um nome de usuário
*/
looksLikeUsername(text) {
if (!text || typeof text !== 'string') return false;
const trimmedText = text.trim();
// Lista de palavras que indicam equipamentos/sistemas, não usuários
const equipmentWords = [
'router', 'switch', 'juniper', 'concentrador', 'equipamento',
'servidor', 'firewall', 'modem', 'access', 'point', 'ap',
'gateway', 'bridge', 'hub', 'repeater', 'todas', 'all',
'conexões', 'conexoes', 'sistema'
];
// Se contém palavras de equipamento, provavelmente não é username
if (equipmentWords.some(word => trimmedText.toLowerCase().includes(word))) {
return false;
}
// Padrões típicos de username:
// - Apenas letras, números, pontos, hífens, underscores
// - Não muito longo (geralmente < 50 caracteres)
// - Não contém espaços (exceto se for nome completo como "ana lucia")
const usernamePattern = /^[a-zA-Z0-9._-]+$/;
const namePattern = /^[a-zA-Z][a-zA-Z0-9._\s-]*[a-zA-Z0-9]$/;
return (
trimmedText.length > 2 &&
trimmedText.length < 50 &&
(usernamePattern.test(trimmedText) || namePattern.test(trimmedText))
);
}
/**
* Verifica se o texto parece ser um serial de ONU
*/
looksLikeOnuSerial(text) {
if (!text || typeof text !== 'string') return false;
const trimmedText = text.trim().toUpperCase();
// Padrões típicos de serial de ONU:
// - Combinação de letras e números
// - Geralmente entre 8-16 caracteres
// - Pode conter caracteres alfanuméricos
// - Não contém espaços ou caracteres especiais (exceto _ ou -)
// Verificar se tem tamanho apropriado
if (trimmedText.length < 6 || trimmedText.length > 20) {
return false;
}
// Verificar se contém apenas caracteres válidos para serial
const serialPattern = /^[A-Z0-9_-]+$/;
if (!serialPattern.test(trimmedText)) {
return false;
}
// Verificar se tem pelo menos algumas letras e números (serial típico)
const hasLetters = /[A-Z]/.test(trimmedText);
const hasNumbers = /[0-9]/.test(trimmedText);
return hasLetters && hasNumbers;
}
/**
* Sugere correções para comandos não reconhecidos
*/
suggestCorrection(text) {
const suggestions = [];
const normalized = text.toLowerCase();
// Verificar similaridade com ações conhecidas
for (const [action, synonyms] of Object.entries(this.actionSynonyms)) {
for (const synonym of synonyms) {
if (this.levenshteinDistance(normalized, synonym) <= 2) {
suggestions.push(synonym);
}
}
}
return suggestions;
}
/**
* Calcula distância de Levenshtein para sugestões
*/
levenshteinDistance(str1, str2) {
const matrix = [];
for (let i = 0; i <= str2.length; i++) {
matrix[i] = [i];
}
for (let j = 0; j <= str1.length; j++) {
matrix[0][j] = j;
}
for (let i = 1; i <= str2.length; i++) {
for (let j = 1; j <= str1.length; j++) {
if (str2.charAt(i - 1) === str1.charAt(j - 1)) {
matrix[i][j] = matrix[i - 1][j - 1];
} else {
matrix[i][j] = Math.min(
matrix[i - 1][j - 1] + 1,
matrix[i][j - 1] + 1,
matrix[i - 1][j] + 1
);
}
}
}
return matrix[str2.length][str1.length];
}
}
module.exports = NLPProcessor;