949 lines
42 KiB
JavaScript
949 lines
42 KiB
JavaScript
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;
|