genieacs: improvements
Signed-off-by: Rodrigo Bertoldo de Sousa Martins <rodrigo.sousa.577@gmail.com>
This commit is contained in:
1 parent
31926ecf80
commit
8dd2680838
4 files changed
+456
-1
No files matched your search
@@ -259,6 +259,11 @@ class BotHandler {
|
||||
await this.handleVerRoteador(chatId, target);
|
||||
break;
|
||||
|
||||
case 'configurar_roteador':
|
||||
console.log(`⚙️ Executando handleConfigurarRoteador com target: ${target}`);
|
||||
await this.handleConfigurarRoteador(chatId, userId, target);
|
||||
break;
|
||||
|
||||
case 'abrir_suporte':
|
||||
case 'adicionar_suporte':
|
||||
case 'criar_suporte':
|
||||
@@ -1660,6 +1665,12 @@ Digite /help para ver todos os comandos disponíveis!
|
||||
|
||||
// Verificar se é sessão baseada em action (Fiberhome ONU)
|
||||
if (session.action) {
|
||||
// Sessões de configuração de roteador (ação dinâmica com prefixo)
|
||||
if (session.action.startsWith('router_cfg_wait_')) {
|
||||
await this._processarInputConfigurarRoteador(chatId, userId, session, text);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (session.action) {
|
||||
case 'adicionar_onu_fiberhome_step1':
|
||||
// Recebeu o nome do usuário, adicionar sufixo e perguntar pelo tipo da ONU
|
||||
@@ -2015,6 +2026,9 @@ 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('router_cfg_')) {
|
||||
console.log(`🔍 Condição router_cfg_ atendida`);
|
||||
await this.handleRouterCfgCallback(callbackQuery, data);
|
||||
} else if (data.startsWith('diag_cliente_')) {
|
||||
console.log(`🔍 Condição diag_cliente_ atendida`);
|
||||
await this.handleDiagClienteCallback(callbackQuery, data);
|
||||
@@ -7469,6 +7483,359 @@ Digite /help para ver todos os comandos disponíveis!
|
||||
await this.bot.sendMessage(chatId, `❌ Erro ao consultar o GenieACS: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
// CONFIGURAR ROTEADOR VIA GENIEACS
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Mapa de campos configuráveis: chave curta → detalhes do parâmetro TR-069.
|
||||
* Centralizado aqui para ser usado tanto no menu quanto nos callbacks.
|
||||
*/
|
||||
_routerParamMap() {
|
||||
return {
|
||||
ssid24: { label: 'SSID 2.4GHz', param: 'InternetGatewayDevice.LANDevice.1.WLANConfiguration.1.SSID', type: 'xsd:string', toggle: false },
|
||||
ssid5: { label: 'SSID 5GHz', param: 'InternetGatewayDevice.LANDevice.1.WLANConfiguration.2.SSID', type: 'xsd:string', toggle: false },
|
||||
ch24: { label: 'Canal 2.4GHz', param: 'InternetGatewayDevice.LANDevice.1.WLANConfiguration.1.Channel', type: 'xsd:unsignedInt', toggle: false },
|
||||
ch5: { label: 'Canal 5GHz', param: 'InternetGatewayDevice.LANDevice.1.WLANConfiguration.2.Channel', type: 'xsd:unsignedInt', toggle: false },
|
||||
auto24: { label: 'Auto-Canal 2.4', param: 'InternetGatewayDevice.LANDevice.1.WLANConfiguration.1.AutoChannelEnable', type: 'xsd:boolean', toggle: true },
|
||||
auto5: { label: 'Auto-Canal 5', param: 'InternetGatewayDevice.LANDevice.1.WLANConfiguration.2.AutoChannelEnable', type: 'xsd:boolean', toggle: true },
|
||||
dnswan: { label: 'DNS WAN', param: 'InternetGatewayDevice.WANDevice.1.WANConnectionDevice.1.WANPPPConnection.1.DNSServers', type: 'xsd:string', toggle: false },
|
||||
dnslan: { label: 'DNS LAN', param: 'InternetGatewayDevice.LANDevice.1.LANHostConfigManagement.DNSServers', type: 'xsd:string', toggle: false },
|
||||
dhcpstart: { label: 'DHCP Início', param: 'InternetGatewayDevice.LANDevice.1.LANHostConfigManagement.MinAddress', type: 'xsd:string', toggle: false },
|
||||
dhcpend: { label: 'DHCP Fim', param: 'InternetGatewayDevice.LANDevice.1.LANHostConfigManagement.MaxAddress', type: 'xsd:string', toggle: false },
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Comando "configurar roteador <serial|tag>".
|
||||
* Busca o dispositivo e exibe o menu de configurações com inline keyboard.
|
||||
*/
|
||||
async handleConfigurarRoteador(chatId, userId, termo) {
|
||||
if (!termo) {
|
||||
await this.bot.sendMessage(chatId,
|
||||
'⚙️ *Configurar Roteador*\n\n' +
|
||||
'Informe o serial ou a TAG (login TopSapp) do dispositivo.\n' +
|
||||
'Exemplos:\n' +
|
||||
'• `configurar roteador ABCD12345678`\n' +
|
||||
'• `configurar roteador joao.silva`',
|
||||
{ parse_mode: 'Markdown' }
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
await this.bot.sendMessage(chatId, `🔍 Buscando dispositivo \`${termo}\` no GenieACS...`, { parse_mode: 'Markdown' });
|
||||
|
||||
try {
|
||||
const resultado = await this.genieacs.buscarRoteador(termo);
|
||||
|
||||
if (!resultado.success) {
|
||||
await this.bot.sendMessage(chatId,
|
||||
`❌ *Dispositivo não encontrado*\n\n🔍 Busca: \`${termo}\`\n⚠️ ${resultado.error || 'Nenhum resultado'}`,
|
||||
{ parse_mode: 'Markdown' }
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Salva contexto na sessão para os callbacks seguintes
|
||||
this.userSessions.set(userId, {
|
||||
action: 'router_cfg',
|
||||
deviceId: resultado.device.deviceId,
|
||||
device: resultado.device,
|
||||
instance: resultado.instance || '',
|
||||
timestamp: Date.now()
|
||||
});
|
||||
|
||||
await this._enviarMenuConfigurarRoteador(chatId, resultado.device, resultado.instance || '');
|
||||
|
||||
} catch (error) {
|
||||
logger.error('Erro em handleConfigurarRoteador:', error);
|
||||
await this.bot.sendMessage(chatId, `❌ Erro ao consultar o GenieACS: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Envia/atualiza a mensagem de menu de configuração do roteador.
|
||||
*/
|
||||
async _enviarMenuConfigurarRoteador(chatId, device, instance) {
|
||||
const esc = (v) => (v === null || v === undefined || v === '') ? 'N/A' : String(v).replace(/[_*`\[]/g, '\\$&');
|
||||
|
||||
const auto24On = device.autoChannel24 === 'Sim';
|
||||
const auto5On = device.autoChannel5 === 'Sim';
|
||||
|
||||
const sumario =
|
||||
`⚙️ *Configurar Roteador*\n` +
|
||||
`📌 ${esc(instance)} — \`${esc(device.serial)}\`\n\n` +
|
||||
`📶 *Wi-Fi 2.4 GHz*\n` +
|
||||
`├ SSID: ${esc(device.ssid24)}\n` +
|
||||
`├ Canal: ${esc(device.channel24)} (Auto: ${esc(device.autoChannel24)})\n\n` +
|
||||
`📶 *Wi-Fi 5 GHz*\n` +
|
||||
`├ SSID: ${esc(device.ssid5)}\n` +
|
||||
`├ Canal: ${esc(device.channel5)} (Auto: ${esc(device.autoChannel5)})\n\n` +
|
||||
`🌐 *WAN/PPPoE*\n` +
|
||||
`├ DNS WAN: ${esc(device.dnsWAN)}\n\n` +
|
||||
`🏠 *LAN/DHCP*\n` +
|
||||
`├ DNS LAN: ${esc(device.dnsLAN)}\n` +
|
||||
`├ DHCP Início: ${esc(device.dhcpInicio)}\n` +
|
||||
`└ DHCP Fim: ${esc(device.dhcpFim)}\n\n` +
|
||||
`_Selecione o que deseja alterar:_`;
|
||||
|
||||
const keyboard = {
|
||||
inline_keyboard: [
|
||||
[
|
||||
{ text: '📶 SSID 2.4GHz', callback_data: 'router_cfg_ssid24' },
|
||||
{ text: '📶 SSID 5GHz', callback_data: 'router_cfg_ssid5' },
|
||||
],
|
||||
[
|
||||
{ text: `${auto24On ? '✅' : '⬜'} Auto-Canal 2.4`, callback_data: 'router_cfg_auto24' },
|
||||
{ text: `${auto5On ? '✅' : '⬜'} Auto-Canal 5`, callback_data: 'router_cfg_auto5' },
|
||||
],
|
||||
[
|
||||
{ text: '📡 Canal 2.4GHz', callback_data: 'router_cfg_ch24' },
|
||||
{ text: '📡 Canal 5GHz', callback_data: 'router_cfg_ch5' },
|
||||
],
|
||||
[
|
||||
{ text: '🌐 DNS WAN', callback_data: 'router_cfg_dnswan' },
|
||||
{ text: '🏠 DNS LAN', callback_data: 'router_cfg_dnslan' },
|
||||
],
|
||||
[
|
||||
{ text: '▶ DHCP Início', callback_data: 'router_cfg_dhcpstart' },
|
||||
{ text: '◀ DHCP Fim', callback_data: 'router_cfg_dhcpend' },
|
||||
],
|
||||
[
|
||||
{ text: '🔄 Atualizar leitura', callback_data: 'router_cfg_refresh' },
|
||||
{ text: '❌ Fechar', callback_data: 'cancel_action' },
|
||||
],
|
||||
]
|
||||
};
|
||||
|
||||
await this.bot.sendMessage(chatId, sumario, { parse_mode: 'Markdown', reply_markup: keyboard });
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatcher de todos os callbacks com prefixo "router_cfg_".
|
||||
*/
|
||||
async handleRouterCfgCallback(callbackQuery, data) {
|
||||
const chatId = callbackQuery.message.chat.id;
|
||||
const userId = callbackQuery.from.id;
|
||||
const msgId = callbackQuery.message.message_id;
|
||||
|
||||
await this.bot.answerCallbackQuery(callbackQuery.id);
|
||||
|
||||
const session = this.userSessions.get(userId);
|
||||
if (!session || session.action !== 'router_cfg') {
|
||||
await this.bot.sendMessage(chatId, '⚠️ Sessão expirada. Use `configurar roteador <serial>` novamente.', { parse_mode: 'Markdown' });
|
||||
return;
|
||||
}
|
||||
|
||||
const field = data.replace('router_cfg_', ''); // ex.: "ssid24", "auto24", "ch24_6", "refresh"
|
||||
|
||||
// ── Atualizar leitura ────────────────────────────────────────────────
|
||||
if (field === 'refresh') {
|
||||
await this.bot.sendMessage(chatId, '🔄 Relendo dados do dispositivo...');
|
||||
const fresh = await this.genieacs.buscarRoteadorPorId(session.deviceId, session.instance);
|
||||
if (!fresh.success) {
|
||||
await this.bot.sendMessage(chatId, `❌ Falha ao reler dispositivo: ${fresh.error}`);
|
||||
return;
|
||||
}
|
||||
session.device = fresh.device;
|
||||
this.userSessions.set(userId, session);
|
||||
await this._enviarMenuConfigurarRoteador(chatId, fresh.device, session.instance);
|
||||
return;
|
||||
}
|
||||
|
||||
// ── Seleção de canal vinda do picker inline (ch24_N ou ch5_N) ───────
|
||||
const chPickMatch = field.match(/^(ch24|ch5)_(\d+)$/);
|
||||
if (chPickMatch) {
|
||||
const band = chPickMatch[1]; // 'ch24' ou 'ch5'
|
||||
const canal = parseInt(chPickMatch[2], 10);
|
||||
const paramMap = this._routerParamMap();
|
||||
const meta = paramMap[band];
|
||||
|
||||
await this.bot.sendMessage(chatId, `⏳ Aplicando ${meta.label} → canal ${canal}...`);
|
||||
const res = await this.genieacs.configurarRoteador(
|
||||
session.deviceId,
|
||||
[[meta.param, canal, 'xsd:unsignedInt']],
|
||||
session.instance
|
||||
);
|
||||
if (!res.success) {
|
||||
await this.bot.sendMessage(chatId, `❌ Falha: ${res.error}`);
|
||||
} else {
|
||||
if (band === 'ch24') session.device.channel24 = String(canal);
|
||||
else session.device.channel5 = String(canal);
|
||||
this.userSessions.set(userId, session);
|
||||
await this.bot.sendMessage(chatId, `✅ *${meta.label}* definido para o canal *${canal}*.`, { parse_mode: 'Markdown' });
|
||||
}
|
||||
await this._enviarMenuConfigurarRoteador(chatId, session.device, session.instance);
|
||||
return;
|
||||
}
|
||||
|
||||
const paramMap = this._routerParamMap();
|
||||
|
||||
// ── Toggle de auto-canal ─────────────────────────────────────────────
|
||||
if (field === 'auto24' || field === 'auto5') {
|
||||
const meta = paramMap[field];
|
||||
const atualSim = field === 'auto24'
|
||||
? session.device.autoChannel24 === 'Sim'
|
||||
: session.device.autoChannel5 === 'Sim';
|
||||
const novoValor = !atualSim; // inverte
|
||||
|
||||
await this.bot.sendMessage(chatId, `⏳ ${atualSim ? 'Desativando' : 'Ativando'} ${meta.label}...`);
|
||||
const res = await this.genieacs.configurarRoteador(
|
||||
session.deviceId,
|
||||
[[meta.param, novoValor, 'xsd:boolean']],
|
||||
session.instance
|
||||
);
|
||||
|
||||
if (!res.success) {
|
||||
await this.bot.sendMessage(chatId, `❌ Falha: ${res.error}`);
|
||||
return;
|
||||
}
|
||||
// Atualiza o device local
|
||||
if (field === 'auto24') session.device.autoChannel24 = novoValor ? 'Sim' : 'Não';
|
||||
else session.device.autoChannel5 = novoValor ? 'Sim' : 'Não';
|
||||
this.userSessions.set(userId, session);
|
||||
|
||||
await this.bot.sendMessage(chatId, `✅ ${meta.label} ${novoValor ? 'ativado' : 'desativado'} com sucesso.`);
|
||||
await this._enviarMenuConfigurarRoteador(chatId, session.device, session.instance);
|
||||
return;
|
||||
}
|
||||
|
||||
// ── Picker de canal com botões inline ────────────────────────────────
|
||||
if (field === 'ch24' || field === 'ch5') {
|
||||
const meta = paramMap[field];
|
||||
const canalAtual = field === 'ch24' ? (session.device.channel24 || '') : (session.device.channel5 || '');
|
||||
const is24 = field === 'ch24';
|
||||
|
||||
const canais24 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
|
||||
const canais5 = [36, 40, 44, 48, 52, 60, 64, 149, 153, 157, 161];
|
||||
const canais = is24 ? canais24 : canais5;
|
||||
|
||||
// Monta rows de 4 botões por linha
|
||||
const rows = [];
|
||||
for (let i = 0; i < canais.length; i += 4) {
|
||||
rows.push(
|
||||
canais.slice(i, i + 4).map(ch => ({
|
||||
text: String(ch) === String(canalAtual) ? `✅ ${ch}` : String(ch),
|
||||
callback_data: `router_cfg_${field}_${ch}`
|
||||
}))
|
||||
);
|
||||
}
|
||||
rows.push([{ text: '↩️ Voltar', callback_data: 'router_cfg_refresh' }]);
|
||||
|
||||
await this.bot.sendMessage(chatId,
|
||||
`📡 *${meta.label}*\nCanal atual: \`${canalAtual || 'N/A'}\`\n\nEscolha o novo canal:`,
|
||||
{ parse_mode: 'Markdown', reply_markup: { inline_keyboard: rows } }
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// ── Campos de texto/número: solicita input ───────────────────────────
|
||||
const meta = paramMap[field];
|
||||
if (!meta) {
|
||||
await this.bot.sendMessage(chatId, `❓ Campo desconhecido: \`${field}\``, { parse_mode: 'Markdown' });
|
||||
return;
|
||||
}
|
||||
|
||||
// Valor atual para mostrar ao usuário
|
||||
const fieldToCurrent = {
|
||||
ssid24: 'ssid24', ssid5: 'ssid5',
|
||||
dnswan: 'dnsWAN', dnslan: 'dnsLAN',
|
||||
dhcpstart: 'dhcpInicio', dhcpend: 'dhcpFim',
|
||||
};
|
||||
const atualKey = fieldToCurrent[field];
|
||||
const valorAtual = atualKey ? (session.device[atualKey] || 'N/A') : 'N/A';
|
||||
|
||||
let hint = '';
|
||||
if (field.startsWith('dns')) hint = ' (ex.: 8.8.8.8,8.8.4.4)';
|
||||
else if (field.startsWith('dhcp')) hint = ' (ex.: 192.168.1.100)';
|
||||
|
||||
// Promove o estado de sessão para aguardar o valor
|
||||
session.action = `router_cfg_wait_${field}`;
|
||||
this.userSessions.set(userId, session);
|
||||
|
||||
await this.bot.sendMessage(chatId,
|
||||
`⚙️ *Alterar ${meta.label}*\n\n` +
|
||||
`Valor atual: \`${valorAtual}\`\n\n` +
|
||||
`Digite o novo valor${hint}:\n` +
|
||||
`_(ou envie /cancelar para abortar)_`,
|
||||
{ parse_mode: 'Markdown' }
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processa o valor digitado pelo usuário para alterar um parâmetro do roteador.
|
||||
* Chamado por handleUserSessionInput quando session.action começa com "router_cfg_wait_".
|
||||
*/
|
||||
async _processarInputConfigurarRoteador(chatId, userId, session, text) {
|
||||
const field = session.action.replace('router_cfg_wait_', ''); // ex.: "ssid24"
|
||||
const paramMap = this._routerParamMap();
|
||||
const meta = paramMap[field];
|
||||
|
||||
if (!meta) {
|
||||
this.userSessions.delete(userId);
|
||||
await this.bot.sendMessage(chatId, '❌ Campo desconhecido. Operação cancelada.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Cancela se o usuário enviou /cancelar
|
||||
if (text.trim().toLowerCase() === '/cancelar') {
|
||||
session.action = 'router_cfg';
|
||||
this.userSessions.set(userId, session);
|
||||
await this.bot.sendMessage(chatId, '🚫 Alteração cancelada.');
|
||||
await this._enviarMenuConfigurarRoteador(chatId, session.device, session.instance);
|
||||
return;
|
||||
}
|
||||
|
||||
// Converte para o tipo correto
|
||||
let valorFinal;
|
||||
if (meta.type === 'xsd:unsignedInt') {
|
||||
const n = parseInt(text.trim(), 10);
|
||||
if (isNaN(n) || n < 0) {
|
||||
await this.bot.sendMessage(chatId, `❌ Valor inválido. Informe um número inteiro positivo.`);
|
||||
return; // mantém sessão aguardando nova tentativa
|
||||
}
|
||||
valorFinal = n;
|
||||
} else {
|
||||
valorFinal = text.trim();
|
||||
if (!valorFinal) {
|
||||
await this.bot.sendMessage(chatId, `❌ Valor não pode ser vazio.`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
await this.bot.sendMessage(chatId, `⏳ Aplicando ${meta.label}...`);
|
||||
|
||||
const res = await this.genieacs.configurarRoteador(
|
||||
session.deviceId,
|
||||
[[meta.param, valorFinal, meta.type]],
|
||||
session.instance
|
||||
);
|
||||
|
||||
if (!res.success) {
|
||||
await this.bot.sendMessage(chatId, `❌ Falha ao aplicar: ${res.error}`);
|
||||
session.action = 'router_cfg';
|
||||
this.userSessions.set(userId, session);
|
||||
return;
|
||||
}
|
||||
|
||||
await this.bot.sendMessage(chatId, `✅ *${meta.label}* atualizado para: \`${valorFinal}\``, { parse_mode: 'Markdown' });
|
||||
|
||||
// Atualiza o device local com o novo valor para o menu refletir
|
||||
const fieldToDeviceKey = {
|
||||
ssid24: 'ssid24', ssid5: 'ssid5',
|
||||
ch24: 'channel24', ch5: 'channel5',
|
||||
dnswan: 'dnsWAN', dnslan: 'dnsLAN',
|
||||
dhcpstart: 'dhcpInicio', dhcpend: 'dhcpFim',
|
||||
};
|
||||
const devKey = fieldToDeviceKey[field];
|
||||
if (devKey) session.device[devKey] = String(valorFinal);
|
||||
session.action = 'router_cfg';
|
||||
this.userSessions.set(userId, session);
|
||||
|
||||
await this._enviarMenuConfigurarRoteador(chatId, session.device, session.instance);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = BotHandler;
|
||||
|
||||
Reference in new issue
Block a user