base: implementa guarai e pedro afonso
Signed-off-by: Rodrigo Bertoldo de Sousa Martins <rodrigo@MacBook-Air-de-Rodrigo.local>
This commit is contained in:
1 parent
44775d671f
commit
bb32aebfc9
6 files changed
+384
-101
No files matched your search
@@ -8,8 +8,32 @@ DEFAULT_SSH_PASSWORD=password
|
||||
|
||||
# Configurações do bot
|
||||
BOT_DEBUG=true
|
||||
|
||||
# IDs do Telegram com acesso a TODAS as cidades/provedores (admin)
|
||||
ALLOWED_USERS=123456789,987654321
|
||||
|
||||
# ==========================================================
|
||||
# Acesso por cidade/provedor (IDs do Telegram, separados por vírgula)
|
||||
# Um usuário pode estar em mais de uma lista; se estiver em mais de
|
||||
# uma cidade, o bot exibirá um menu para escolher qual atender.
|
||||
# ==========================================================
|
||||
GUARAI_ALLOWED_USERS=
|
||||
PEDRO_AFONSO_ALLOWED_USERS=
|
||||
|
||||
# ==========================================================
|
||||
# Concentrador Juniper - Guaraí
|
||||
# ==========================================================
|
||||
JUNIPER_GUARAI_HOST=131.0.192.254
|
||||
JUNIPER_GUARAI_USER=rodrigo
|
||||
JUNIPER_GUARAI_PASS=
|
||||
|
||||
# ==========================================================
|
||||
# Concentrador Juniper - Pedro Afonso
|
||||
# ==========================================================
|
||||
JUNIPER_PEDRO_AFONSO_HOST=45.189.140.2
|
||||
JUNIPER_PEDRO_AFONSO_USER=rodrigo
|
||||
JUNIPER_PEDRO_AFONSO_PASS=
|
||||
|
||||
# Configurações TopSapp - Instância Guarai/Colmeia
|
||||
TOPSAPP_GUARAI_USER=seu_usuario_guarai
|
||||
TOPSAPP_GUARAI_PASS=sua_senha_guarai
|
||||
|
||||
+31
-1
@@ -15,10 +15,40 @@ DEFAULT_SSH_PASSWORD=YOUR_SSH_PASSWORD_HERE
|
||||
BOT_DEBUG=false
|
||||
NODE_ENV=production
|
||||
|
||||
# IDs dos usuários autorizados (separados por vírgula)
|
||||
# IDs dos usuários autorizados em TODAS as cidades/provedores (admin)
|
||||
# Para descobrir seu ID, envie /start para @userinfobot
|
||||
ALLOWED_USERS=593272271
|
||||
|
||||
# IDs autorizados por cidade/provedor (deixe vazio se só ALLOWED_USERS for usado)
|
||||
GUARAI_ALLOWED_USERS=
|
||||
PEDRO_AFONSO_ALLOWED_USERS=
|
||||
|
||||
# ==========================================================
|
||||
# Concentrador Juniper - Guaraí
|
||||
# ==========================================================
|
||||
JUNIPER_GUARAI_HOST=131.0.192.254
|
||||
JUNIPER_GUARAI_USER=rodrigo
|
||||
JUNIPER_GUARAI_PASS=@102030Rod
|
||||
|
||||
# ==========================================================
|
||||
# Concentrador Juniper - Pedro Afonso
|
||||
# ==========================================================
|
||||
JUNIPER_PEDRO_AFONSO_HOST=45.189.140.2
|
||||
JUNIPER_PEDRO_AFONSO_USER=rodrigo
|
||||
JUNIPER_PEDRO_AFONSO_PASS=2311@Goiania#2017
|
||||
|
||||
# ==========================================================
|
||||
# Configurações TopSapp - Instância Guaraí/Colmeia
|
||||
# ==========================================================
|
||||
TOPSAPP_GUARAI_USER=
|
||||
TOPSAPP_GUARAI_PASS=
|
||||
|
||||
# ==========================================================
|
||||
# Configurações TopSapp - Instância Pedro Afonso
|
||||
# ==========================================================
|
||||
TOPSAPP_PEDRO_AFONSO_USER=rodrigo
|
||||
TOPSAPP_PEDRO_AFONSO_PASS=34641747
|
||||
|
||||
# ==========================================================
|
||||
# Configurações GenieACS (TR-069 ACS)
|
||||
# ==========================================================
|
||||
|
||||
+195
-51
@@ -5,6 +5,7 @@ const FiberhomeManager = require('../fiberhome/manager');
|
||||
const FiberhomeTL1Manager = require('../fiberhome/manager_tl1');
|
||||
const { GenieACSManager } = require('../genieacs');
|
||||
const config = require('../config/config');
|
||||
const sites = require('../config/sites');
|
||||
const logger = require('../utils/logger');
|
||||
const DateProcessor = require('../utils/dateProcessor');
|
||||
const cgnatParser = require('../cgn_list/parser');
|
||||
@@ -23,19 +24,89 @@ class BotHandler {
|
||||
this.suporteSessions = new Map(); // Armazena sessões de suporte em andamento
|
||||
this.pendingRestarts = new Map(); // Armazena dados de reinicialização pendentes
|
||||
this._restartIdCounter = 0;
|
||||
this.activeSite = new Map(); // chatId -> siteId (cidade/provedor ativo)
|
||||
|
||||
logger.info('BotHandler inicializado');
|
||||
console.log('🎯 BotHandler inicializado');
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifica se o usuário tem permissão
|
||||
* Verifica se o usuário tem permissão (em pelo menos uma cidade/provedor)
|
||||
*/
|
||||
isAuthorized(userId) {
|
||||
if (config.bot.allowedUsers.length === 0) {
|
||||
return true; // Se não há lista de usuários, permite todos
|
||||
return sites.getUserSiteIds(userId).length > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cidade/provedor ativo para este chat. Pode ser null se ainda não
|
||||
* foi resolvido (usuário com acesso a mais de um site e que ainda não
|
||||
* escolheu via menu).
|
||||
*/
|
||||
getActiveSiteId(chatId) {
|
||||
return this.activeSite.get(chatId) || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Site (objeto completo) ativo para este chat, com fallback seguro
|
||||
* para Guaraí caso ainda não haja site resolvido (mantém o
|
||||
* comportamento histórico do bot, que sempre assumiu Guaraí).
|
||||
*/
|
||||
getActiveSite(chatId) {
|
||||
return sites.getSite(this.getActiveSiteId(chatId)) || sites.getSite('guarai');
|
||||
}
|
||||
|
||||
/**
|
||||
* Label de localização usado pelas heurísticas existentes do TopSapp
|
||||
* (substitui a antiga detecção por regex no texto da mensagem).
|
||||
*/
|
||||
getActiveLocation(chatId) {
|
||||
return this.getActiveSite(chatId).topsappLocationLabel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Garante que o usuário tenha uma cidade/provedor ativa antes de
|
||||
* processar qualquer ação. Se o usuário tiver acesso a mais de um
|
||||
* site e ainda não tiver escolhido, exibe o menu de seleção e
|
||||
* retorna null (o chamador deve interromper o processamento).
|
||||
*/
|
||||
async resolveActiveSite(chatId, userId) {
|
||||
const siteIds = sites.getUserSiteIds(userId);
|
||||
|
||||
if (siteIds.length === 0) {
|
||||
return null;
|
||||
}
|
||||
return config.bot.allowedUsers.includes(userId);
|
||||
|
||||
if (siteIds.length === 1) {
|
||||
this.activeSite.set(chatId, siteIds[0]);
|
||||
return siteIds[0];
|
||||
}
|
||||
|
||||
const current = this.activeSite.get(chatId);
|
||||
if (current && siteIds.includes(current)) {
|
||||
return current;
|
||||
}
|
||||
|
||||
await this.sendSiteSelectionMenu(chatId, siteIds);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exibe o menu de seleção de cidade/provedor
|
||||
*/
|
||||
async sendSiteSelectionMenu(chatId, siteIds) {
|
||||
const keyboard = siteIds.map(id => {
|
||||
const site = sites.getSite(id);
|
||||
return [{ text: `📍 ${site.name}`, callback_data: `select_site_${site.id}` }];
|
||||
});
|
||||
|
||||
await this.bot.sendMessage(chatId,
|
||||
`🏙️ *Selecione a cidade/provedor*\n\n` +
|
||||
`Você tem acesso a mais de uma cidade. Escolha qual deseja atender agora:`,
|
||||
{
|
||||
parse_mode: 'Markdown',
|
||||
reply_markup: { inline_keyboard: keyboard }
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -64,6 +135,12 @@ class BotHandler {
|
||||
return;
|
||||
}
|
||||
|
||||
// Resolver cidade/provedor ativo (exibe menu se houver mais de um e ainda não escolhido)
|
||||
const siteId = await this.resolveActiveSite(chatId, userId);
|
||||
if (!siteId) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Verificar se há uma sessão de suporte ativa
|
||||
const processouSuporte = await this.processarMensagemSuporte(msg);
|
||||
@@ -124,7 +201,11 @@ class BotHandler {
|
||||
break;
|
||||
|
||||
case 'help':
|
||||
await this.handleHelp(chatId);
|
||||
await this.handleHelp(chatId, userId);
|
||||
break;
|
||||
|
||||
case 'cidade':
|
||||
await this.handleCidade(chatId, userId);
|
||||
break;
|
||||
|
||||
case 'ssh':
|
||||
@@ -352,12 +433,30 @@ Digite /help para ver todos os comandos disponíveis!
|
||||
await this.bot.sendMessage(chatId, welcomeMessage, { parse_mode: 'Markdown' });
|
||||
}
|
||||
|
||||
/**
|
||||
* Comando /cidade - permite trocar a cidade/provedor ativo
|
||||
*/
|
||||
async handleCidade(chatId, userId) {
|
||||
const siteIds = sites.getUserSiteIds(userId);
|
||||
|
||||
if (siteIds.length <= 1) {
|
||||
const site = sites.getSite(siteIds[0]) || this.getActiveSite(chatId);
|
||||
await this.bot.sendMessage(chatId, `📍 Você só tem acesso a *${site.name}*.`, { parse_mode: 'Markdown' });
|
||||
return;
|
||||
}
|
||||
|
||||
await this.sendSiteSelectionMenu(chatId, siteIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Comando /help
|
||||
*/
|
||||
async handleHelp(chatId) {
|
||||
async handleHelp(chatId, userId = null) {
|
||||
const siteName = this.getActiveSite(chatId).name;
|
||||
const helpMessage = `🤖 **BOT DE AJUDA TÉCNICA**
|
||||
|
||||
📍 Cidade/provedor ativo: *${siteName}*
|
||||
|
||||
🔧 **COMANDOS PRINCIPAIS:**
|
||||
• /start - Inicia o bot
|
||||
• /help - Esta ajuda
|
||||
@@ -409,6 +508,11 @@ Digite /help para ver todos os comandos disponíveis!
|
||||
]
|
||||
];
|
||||
|
||||
if (userId && sites.getUserSiteIds(userId).length > 1) {
|
||||
keyboard.push([{ text: '🏙️ Trocar cidade', callback_data: 'open_site_menu' }]);
|
||||
}
|
||||
|
||||
|
||||
await this.bot.sendMessage(chatId, helpMessage, {
|
||||
parse_mode: 'Markdown',
|
||||
reply_markup: {
|
||||
@@ -431,7 +535,7 @@ Digite /help para ver todos os comandos disponíveis!
|
||||
|
||||
switch (helpType) {
|
||||
case 'main':
|
||||
await this.handleHelp(chatId);
|
||||
await this.handleHelp(chatId, callbackQuery.from.id);
|
||||
return;
|
||||
|
||||
case 'topsapp':
|
||||
@@ -657,7 +761,7 @@ Digite /help para ver todos os comandos disponíveis!
|
||||
* Listar equipamentos
|
||||
*/
|
||||
async handleListEquipments(chatId) {
|
||||
const equipments = this.ssh.listEquipments();
|
||||
const equipments = this.ssh.listEquipments(this.getActiveSite(chatId).id);
|
||||
|
||||
if (equipments.length === 0) {
|
||||
await this.bot.sendMessage(chatId, '📋 Nenhum equipamento configurado.');
|
||||
@@ -830,8 +934,8 @@ Digite /help para ver todos os comandos disponíveis!
|
||||
await this.bot.sendMessage(chatId, `🔄 Desconectando usuário ${username} do concentrador...`);
|
||||
|
||||
try {
|
||||
// Usar concentrador Juniper como padrão
|
||||
const result = await this.ssh.disconnectJuniperUser('juniper', username);
|
||||
const juniperId = this.getActiveSite(chatId).juniperEquipmentId;
|
||||
const result = await this.ssh.disconnectJuniperUser(juniperId, username);
|
||||
|
||||
if (result.success) {
|
||||
await this.bot.sendMessage(chatId, `✅ ${result.message}`);
|
||||
@@ -857,11 +961,12 @@ Digite /help para ver todos os comandos disponíveis!
|
||||
/**
|
||||
* Listar usuários conectados no concentrador
|
||||
*/
|
||||
async handleListUsers(chatId, target = 'juniper') {
|
||||
async handleListUsers(chatId) {
|
||||
await this.bot.sendMessage(chatId, '🔍 Listando usuários conectados no concentrador...');
|
||||
|
||||
try {
|
||||
const result = await this.ssh.listJuniperUsers(target);
|
||||
const juniperId = this.getActiveSite(chatId).juniperEquipmentId;
|
||||
const result = await this.ssh.listJuniperUsers(juniperId);
|
||||
|
||||
if (result.success) {
|
||||
let message = '📋 *Usuários Conectados:*\n\n';
|
||||
@@ -926,7 +1031,8 @@ Digite /help para ver todos os comandos disponíveis!
|
||||
await this.bot.sendMessage(chatId, `🔍 Consultando usuário *${username}* no concentrador...`, { parse_mode: 'Markdown' });
|
||||
|
||||
try {
|
||||
const result = await this.ssh.getJuniperSubscriberInfo('juniper', username);
|
||||
const juniperId = this.getActiveSite(chatId).juniperEquipmentId;
|
||||
const result = await this.ssh.getJuniperSubscriberInfo(juniperId, username);
|
||||
|
||||
if (!result.success) {
|
||||
await this.bot.sendMessage(chatId, `❌ ${result.message}`);
|
||||
@@ -972,7 +1078,7 @@ Digite /help para ver todos os comandos disponíveis!
|
||||
try {
|
||||
await this.bot.sendMessage(chatId, '🔍 Buscando cliente...');
|
||||
|
||||
let location = '';
|
||||
let location = this.getActiveLocation(chatId);
|
||||
let searchQuery = query;
|
||||
|
||||
if (/guarai|colmeia/i.test(query)) {
|
||||
@@ -1128,13 +1234,15 @@ Digite /help para ver todos os comandos disponíveis!
|
||||
|
||||
// Executar consultas em paralelo: Juniper + ONU + GenieACS (por TAG/login)
|
||||
// No concentrador Juniper usa-se só o usuário (antes do @)
|
||||
const activeSite = this.getActiveSite(chatId);
|
||||
const juniperId = activeSite.juniperEquipmentId;
|
||||
const pppoeUser = pppoeLogin ? pppoeLogin.split('@')[0] : null;
|
||||
let [juniperResult, onuResult, genieResult] = await Promise.all([
|
||||
pppoeUser
|
||||
? this.ssh.getJuniperSubscriberInfo('juniper', pppoeUser).catch(e => ({ success: false, error: e.message }))
|
||||
? this.ssh.getJuniperSubscriberInfo(juniperId, pppoeUser).catch(e => ({ success: false, error: e.message }))
|
||||
: Promise.resolve({ success: false, skipped: true }),
|
||||
serial
|
||||
? this._diagnosticarONU(serial, baseInfo).catch(e => ({ success: false, error: e.message }))
|
||||
? this._diagnosticarONU(serial, baseInfo, activeSite.id).catch(e => ({ success: false, error: e.message }))
|
||||
: Promise.resolve({ success: false, skipped: true }),
|
||||
pppoeLogin && this.genieacs.isReady()
|
||||
? this.genieacs.buscarRoteador(pppoeLogin).catch(() => ({ success: false }))
|
||||
@@ -1144,7 +1252,7 @@ Digite /help para ver todos os comandos disponíveis!
|
||||
// Fallback: se PPPoE não encontrou sessão ativa e há circuit-id (IPoE), buscar pelo circuit-id
|
||||
if (circuitId && (!juniperResult.connected)) {
|
||||
try {
|
||||
const circuitResult = await this.ssh.getJuniperSubscriberInfo('juniper', circuitId);
|
||||
const circuitResult = await this.ssh.getJuniperSubscriberInfo(juniperId, circuitId);
|
||||
if (circuitResult.success && circuitResult.connected) {
|
||||
juniperResult = { ...circuitResult, viaCircuitId: true };
|
||||
}
|
||||
@@ -1286,11 +1394,13 @@ Digite /help para ver todos os comandos disponíveis!
|
||||
|
||||
/**
|
||||
* Mapeia o campo base/AP do TopSapp para o ID da OLT Datacom (ou 'fiberhome')
|
||||
* As bases DITO/COLMEIA/CANAA só existem em Guaraí; em outro site, ignora a dica.
|
||||
*/
|
||||
_resolverOLTporBase(baseInfo) {
|
||||
_resolverOLTporBase(baseInfo, siteId = 'guarai') {
|
||||
if (!baseInfo) return null;
|
||||
const b = String(baseInfo).toUpperCase();
|
||||
if (/INTERNET\s+FIBRA\s+OPTICA/i.test(b)) return 'fiberhome';
|
||||
if (siteId !== 'guarai') return null;
|
||||
if (/COLMEIA/i.test(b)) return 'olt_colmeia';
|
||||
if (/DITO/i.test(b)) return 'olt_dito';
|
||||
if (/CANAA\s*2/i.test(b)) return 'olt_canaa2';
|
||||
@@ -1302,10 +1412,11 @@ Digite /help para ver todos os comandos disponíveis!
|
||||
* Diagnóstico de ONU: detecta tipo (Datacom/FiberHome) e retorna dados estruturados
|
||||
* @param {string} serial - Serial da ONU
|
||||
* @param {string|null} baseInfo - Campo base/AP do TopSapp para rotear para OLT correta
|
||||
* @param {string} siteId - Cidade/provedor ativo, usado para restringir a busca
|
||||
*/
|
||||
async _diagnosticarONU(serial, baseInfo) {
|
||||
async _diagnosticarONU(serial, baseInfo, siteId = 'guarai') {
|
||||
const serialUpper = serial.toUpperCase();
|
||||
const oltHint = this._resolverOLTporBase(baseInfo);
|
||||
const oltHint = this._resolverOLTporBase(baseInfo, siteId);
|
||||
|
||||
// Usar base description para decidir se é FiberHome
|
||||
if (oltHint === 'fiberhome' ||
|
||||
@@ -1313,10 +1424,10 @@ Digite /help para ver todos os comandos disponíveis!
|
||||
return await this._diagnosticarONUFiberhome(serial);
|
||||
}
|
||||
|
||||
return await this._diagnosticarONUDatacom(serial, oltHint);
|
||||
return await this._diagnosticarONUDatacom(serial, oltHint, siteId);
|
||||
}
|
||||
|
||||
async _diagnosticarONUDatacom(serial, oltIdHint) {
|
||||
async _diagnosticarONUDatacom(serial, oltIdHint, siteId = 'guarai') {
|
||||
let found = null;
|
||||
|
||||
// 1. Tentar na OLT indicada pelo campo base/AP do cadastro
|
||||
@@ -1328,9 +1439,9 @@ Digite /help para ver todos os comandos disponíveis!
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Fallback: buscar em todas as OLTs Datacom
|
||||
// 2. Fallback: buscar em todas as OLTs Datacom do site ativo
|
||||
if (!found) {
|
||||
const olts = this.ssh.listOLTs();
|
||||
const olts = this.ssh.listOLTs(siteId);
|
||||
if (olts.length === 0) {
|
||||
return { success: false, error: 'Nenhuma OLT Datacom configurada' };
|
||||
}
|
||||
@@ -1445,8 +1556,9 @@ Digite /help para ver todos os comandos disponíveis!
|
||||
return;
|
||||
}
|
||||
|
||||
// Obter lista de OLTs disponíveis
|
||||
const olts = this.ssh.listOLTs();
|
||||
// Obter lista de OLTs disponíveis no site ativo
|
||||
const activeSiteId = this.getActiveSite(chatId).id;
|
||||
const olts = this.ssh.listOLTs(activeSiteId);
|
||||
console.log(`📋 OLTs Datacom encontradas: ${olts.length}`);
|
||||
|
||||
// Criar menu de seleção de OLT
|
||||
@@ -1454,10 +1566,12 @@ Digite /help para ver todos os comandos disponíveis!
|
||||
inline_keyboard: []
|
||||
};
|
||||
|
||||
// Adicionar OLT Fiberhome como primeira opção
|
||||
keyboard.inline_keyboard.push([
|
||||
{ text: '🔶 OLT FIBERHOME', callback_data: `check_signal_fiberhome_${serialNumber}` }
|
||||
]);
|
||||
// Adicionar OLT Fiberhome como primeira opção (existe apenas em Guaraí)
|
||||
if (activeSiteId === 'guarai') {
|
||||
keyboard.inline_keyboard.push([
|
||||
{ text: '🔶 OLT FIBERHOME', callback_data: `check_signal_fiberhome_${serialNumber}` }
|
||||
]);
|
||||
}
|
||||
|
||||
// Adicionar separador visual
|
||||
if (olts.length > 0) {
|
||||
@@ -1579,8 +1693,8 @@ Digite /help para ver todos os comandos disponíveis!
|
||||
return;
|
||||
}
|
||||
|
||||
// Perguntar em qual OLT buscar
|
||||
const oltOptions = this.ssh.listOLTs();
|
||||
// Perguntar em qual OLT buscar (apenas OLTs do site ativo)
|
||||
const oltOptions = this.ssh.listOLTs(this.getActiveSite(chatId).id);
|
||||
|
||||
if (oltOptions.length === 0) {
|
||||
await this.bot.sendMessage(chatId, '❌ Nenhuma OLT disponível configurada.');
|
||||
@@ -1620,8 +1734,8 @@ Digite /help para ver todos os comandos disponíveis!
|
||||
return;
|
||||
}
|
||||
|
||||
// Perguntar em qual OLT adicionar
|
||||
const oltOptions = this.ssh.listOLTs();
|
||||
// Perguntar em qual OLT adicionar (apenas OLTs do site ativo)
|
||||
const oltOptions = this.ssh.listOLTs(this.getActiveSite(chatId).id);
|
||||
|
||||
if (oltOptions.length === 0) {
|
||||
await this.bot.sendMessage(chatId, '❌ Nenhuma OLT disponível configurada.');
|
||||
@@ -1666,8 +1780,8 @@ Digite /help para ver todos os comandos disponíveis!
|
||||
return;
|
||||
}
|
||||
|
||||
// Perguntar em qual OLT adicionar
|
||||
const oltOptions = this.ssh.listOLTs();
|
||||
// Perguntar em qual OLT adicionar (apenas OLTs do site ativo)
|
||||
const oltOptions = this.ssh.listOLTs(this.getActiveSite(chatId).id);
|
||||
|
||||
if (oltOptions.length === 0) {
|
||||
await this.bot.sendMessage(chatId, '❌ Nenhuma OLT disponível configurada.');
|
||||
@@ -2004,6 +2118,35 @@ Digite /help para ver todos os comandos disponíveis!
|
||||
return;
|
||||
}
|
||||
|
||||
// Seleção/troca de cidade — tratado antes de resolver o site ativo,
|
||||
// pois é a própria ação que define o site ativo.
|
||||
if (data.startsWith('select_site_')) {
|
||||
const siteId = data.replace('select_site_', '');
|
||||
const site = sites.getSite(siteId);
|
||||
if (!site || !sites.getUserSiteIds(userId).includes(siteId)) {
|
||||
await this.bot.answerCallbackQuery(callbackQuery.id, '🚫 Cidade inválida');
|
||||
return;
|
||||
}
|
||||
this.activeSite.set(chatId, siteId);
|
||||
await this.bot.answerCallbackQuery(callbackQuery.id, `📍 ${site.name}`);
|
||||
await this.bot.sendMessage(chatId, `📍 Cidade/provedor definido: *${site.name}*`, { parse_mode: 'Markdown' });
|
||||
await this.handleHelp(chatId, userId);
|
||||
return;
|
||||
}
|
||||
|
||||
if (data === 'open_site_menu') {
|
||||
await this.bot.answerCallbackQuery(callbackQuery.id);
|
||||
await this.sendSiteSelectionMenu(chatId, sites.getUserSiteIds(userId));
|
||||
return;
|
||||
}
|
||||
|
||||
// Garante que haja uma cidade/provedor ativa antes de qualquer outra ação
|
||||
const activeSiteId = await this.resolveActiveSite(chatId, userId);
|
||||
if (!activeSiteId) {
|
||||
await this.bot.answerCallbackQuery(callbackQuery.id);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
console.log(`🔍 Callback recebido: ${data}`);
|
||||
console.log(`🔍 Verifica confirm_remove_: ${data.startsWith('confirm_remove_')}`);
|
||||
@@ -4250,7 +4393,7 @@ Digite /help para ver todos os comandos disponíveis!
|
||||
await this.bot.sendMessage(chatId, '🔍 Buscando cliente...');
|
||||
|
||||
// Detectar se especificou uma localização
|
||||
let location = '';
|
||||
let location = this.getActiveLocation(chatId);
|
||||
let query = target;
|
||||
|
||||
if (target.toLowerCase().includes('guarai') || target.toLowerCase().includes('colmeia')) {
|
||||
@@ -4386,7 +4529,7 @@ Digite /help para ver todos os comandos disponíveis!
|
||||
await this.bot.sendMessage(chatId, '🔍 Buscando cliente...');
|
||||
|
||||
// Detectar se especificou uma localização
|
||||
let location = '';
|
||||
let location = this.getActiveLocation(chatId);
|
||||
let query = target;
|
||||
|
||||
if (target.toLowerCase().includes('guarai') || target.toLowerCase().includes('colmeia')) {
|
||||
@@ -4496,7 +4639,7 @@ Digite /help para ver todos os comandos disponíveis!
|
||||
await this.bot.sendMessage(chatId, '🔍 Buscando cliente...');
|
||||
|
||||
// Detectar se especificou uma localização
|
||||
let location = '';
|
||||
let location = this.getActiveLocation(chatId);
|
||||
let query = target;
|
||||
|
||||
if (target.toLowerCase().includes('guarai') || target.toLowerCase().includes('colmeia')) {
|
||||
@@ -4617,7 +4760,7 @@ Digite /help para ver todos os comandos disponíveis!
|
||||
await this.bot.sendMessage(chatId, '🔍 Buscando serviços...');
|
||||
|
||||
// Detectar se especificou uma localização
|
||||
let location = '';
|
||||
let location = this.getActiveLocation(chatId);
|
||||
let query = target;
|
||||
|
||||
if (target.toLowerCase().includes('guarai') || target.toLowerCase().includes('colmeia')) {
|
||||
@@ -4994,7 +5137,7 @@ Digite /help para ver todos os comandos disponíveis!
|
||||
try {
|
||||
await this.bot.sendMessage(chatId, '🔍 Buscando cliente...');
|
||||
|
||||
let location = '';
|
||||
let location = this.getActiveLocation(chatId);
|
||||
let query = target;
|
||||
|
||||
if (target.toLowerCase().includes('guarai') || target.toLowerCase().includes('colmeia')) {
|
||||
@@ -5723,7 +5866,7 @@ Digite /help para ver todos os comandos disponíveis!
|
||||
|
||||
try {
|
||||
// Primeiro, buscar o cliente
|
||||
let location = '';
|
||||
let location = this.getActiveLocation(chatId);
|
||||
let query = target;
|
||||
|
||||
if (target.toLowerCase().includes('guarai') || target.toLowerCase().includes('colmeia')) {
|
||||
@@ -6859,7 +7002,7 @@ Digite /help para ver todos os comandos disponíveis!
|
||||
}
|
||||
|
||||
session.dados.clienteSelecionado = session.dados.clientesEncontrados[numero - 1];
|
||||
session.dados.location = '';
|
||||
session.dados.location = this.getActiveLocation(session.chatId);
|
||||
await this.processarEtapaFecharBuscarSuportes(sessionId);
|
||||
}
|
||||
|
||||
@@ -7519,7 +7662,7 @@ Digite /help para ver todos os comandos disponíveis!
|
||||
}
|
||||
|
||||
session.dados.clienteSelecionado = clientes[index];
|
||||
session.dados.location = '';
|
||||
session.dados.location = this.getActiveLocation(chatId);
|
||||
await this.processarEtapaFecharBuscarSuportes(sessionId);
|
||||
}
|
||||
|
||||
@@ -8232,7 +8375,7 @@ Digite /help para ver todos os comandos disponíveis!
|
||||
try {
|
||||
await this.bot.sendMessage(chatId, '🔍 Buscando cliente...');
|
||||
|
||||
let location = '';
|
||||
let location = this.getActiveLocation(chatId);
|
||||
let query = target;
|
||||
|
||||
if (/guarai|colmeia/i.test(target)) {
|
||||
@@ -8601,7 +8744,7 @@ Digite /help para ver todos os comandos disponíveis!
|
||||
try {
|
||||
await this.bot.sendMessage(chatId, '🔍 Buscando cliente...');
|
||||
|
||||
let location = '';
|
||||
let location = this.getActiveLocation(chatId);
|
||||
let searchQuery = query;
|
||||
|
||||
if (/guarai|colmeia/i.test(query)) {
|
||||
@@ -8721,7 +8864,7 @@ Digite /help para ver todos os comandos disponíveis!
|
||||
return;
|
||||
}
|
||||
|
||||
const oltHint = this._resolverOLTporBase(base);
|
||||
const oltHint = this._resolverOLTporBase(base, this.getActiveSite(chatId).id);
|
||||
const tipoOLT = oltHint === 'fiberhome' ? '🔶 Fiberhome (TL1)' : '🔷 Datacom (SSH)';
|
||||
|
||||
const serialEscaped = serial.replace(/_/g, '\\_');
|
||||
@@ -8812,7 +8955,8 @@ Digite /help para ver todos os comandos disponíveis!
|
||||
this.pendingRestarts.delete(restartId);
|
||||
|
||||
const { serial, base } = pending;
|
||||
const oltHint = this._resolverOLTporBase(base);
|
||||
const siteId = this.getActiveSite(chatId).id;
|
||||
const oltHint = this._resolverOLTporBase(base, siteId);
|
||||
const serialEscaped = serial.replace(/_/g, '\\_');
|
||||
|
||||
await this.bot.editMessageText(
|
||||
@@ -8839,7 +8983,7 @@ Digite /help para ver todos os comandos disponíveis!
|
||||
// Sem base definida — tentar Fiberhome primeiro, depois Datacom
|
||||
result = await this.fiberhomeTL1.reiniciarOnu(serial);
|
||||
if (!result.success) {
|
||||
result = await this._reiniciarOnuDatacomAutoDetect(serial);
|
||||
result = await this._reiniciarOnuDatacomAutoDetect(serial, siteId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9176,8 +9320,8 @@ Digite /help para ver todos os comandos disponíveis!
|
||||
/**
|
||||
* Reiniciar ONU Datacom — busca em todas as OLTs
|
||||
*/
|
||||
async _reiniciarOnuDatacomAutoDetect(serial) {
|
||||
const olts = this.ssh.listOLTs();
|
||||
async _reiniciarOnuDatacomAutoDetect(serial, siteId = 'guarai') {
|
||||
const olts = this.ssh.listOLTs(siteId);
|
||||
for (const olt of olts) {
|
||||
try {
|
||||
const findResult = await this.ssh.findOnuBySerial(olt.id, serial);
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* Registro central de sites (cidades/provedores) atendidos pelo bot.
|
||||
* Para adicionar uma nova cidade: acrescente um objeto aqui e configure a
|
||||
* variável de ambiente correspondente (allowedUsersEnv) — nenhum outro
|
||||
* módulo precisa saber quantos sites existem.
|
||||
*/
|
||||
const SITES = [
|
||||
{
|
||||
id: 'guarai',
|
||||
name: 'Guaraí',
|
||||
allowedUsersEnv: 'GUARAI_ALLOWED_USERS',
|
||||
topsappKey: 'guarai_colmeia',
|
||||
topsappLocationLabel: 'Guarai/Colmeia',
|
||||
juniperEquipmentId: 'juniper',
|
||||
oltEquipmentIds: ['olt_dito', 'olt_colmeia', 'olt_canaa', 'olt_canaa2']
|
||||
},
|
||||
{
|
||||
id: 'pedro_afonso',
|
||||
name: 'Pedro Afonso',
|
||||
allowedUsersEnv: 'PEDRO_AFONSO_ALLOWED_USERS',
|
||||
topsappKey: 'pedro_afonso',
|
||||
topsappLocationLabel: 'Pedro Afonso',
|
||||
juniperEquipmentId: 'juniper_pedro_afonso',
|
||||
oltEquipmentIds: ['olt_pedro_afonso', 'olt_canavieiras']
|
||||
}
|
||||
];
|
||||
|
||||
function parseUserIds(envValue) {
|
||||
if (!envValue) return [];
|
||||
return envValue.split(',').map(id => parseInt(id.trim(), 10)).filter(id => !isNaN(id));
|
||||
}
|
||||
|
||||
function getAllSites() {
|
||||
return SITES;
|
||||
}
|
||||
|
||||
function getSite(id) {
|
||||
return SITES.find(site => site.id === id) || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retorna os ids dos sites aos quais o usuário do Telegram tem acesso.
|
||||
* - Quem está em ALLOWED_USERS (config global) tem acesso a todos os sites.
|
||||
* - Caso contrário, cada site é liberado se o userId estiver na env var
|
||||
* `site.allowedUsersEnv` correspondente.
|
||||
* - Se nenhuma das variáveis (global ou por site) estiver configurada,
|
||||
* mantém o comportamento histórico de "sem lista = libera todo mundo",
|
||||
* liberando acesso a todos os sites.
|
||||
*/
|
||||
function getUserSiteIds(userId) {
|
||||
const config = require('./config');
|
||||
const globalUsers = config.bot.allowedUsers;
|
||||
|
||||
if (globalUsers.length > 0 && globalUsers.includes(userId)) {
|
||||
return SITES.map(site => site.id);
|
||||
}
|
||||
|
||||
const siteAllowLists = SITES.map(site => parseUserIds(process.env[site.allowedUsersEnv]));
|
||||
const anyPerSiteListConfigured = siteAllowLists.some(list => list.length > 0);
|
||||
|
||||
if (globalUsers.length === 0 && !anyPerSiteListConfigured) {
|
||||
return SITES.map(site => site.id);
|
||||
}
|
||||
|
||||
const result = [];
|
||||
SITES.forEach((site, index) => {
|
||||
if (siteAllowLists[index].includes(userId)) {
|
||||
result.push(site.id);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getAllSites,
|
||||
getSite,
|
||||
getUserSiteIds
|
||||
};
|
||||
+46
-49
@@ -22,51 +22,41 @@ class SSHManager {
|
||||
});
|
||||
}
|
||||
|
||||
// Concentrador Juniper principal
|
||||
this.equipamentos.set('juniper', {
|
||||
// Concentrador Juniper - Guaraí
|
||||
const juniperGuarai = {
|
||||
name: 'Concentrador Juniper',
|
||||
host: '131.0.192.254',
|
||||
username: 'rodrigo',
|
||||
password: '@102030Rod',
|
||||
host: process.env.JUNIPER_GUARAI_HOST || '131.0.192.254',
|
||||
username: process.env.JUNIPER_GUARAI_USER || 'rodrigo',
|
||||
password: process.env.JUNIPER_GUARAI_PASS || '',
|
||||
port: 22,
|
||||
type: 'juniper'
|
||||
});
|
||||
type: 'juniper',
|
||||
site: 'guarai'
|
||||
};
|
||||
this.equipamentos.set('juniper', juniperGuarai);
|
||||
this.equipamentos.set('concentrador', juniperGuarai); // alias
|
||||
|
||||
// Aliases para o concentrador
|
||||
this.equipamentos.set('concentrador', {
|
||||
name: 'Concentrador Juniper',
|
||||
host: '131.0.192.254',
|
||||
username: 'rodrigo',
|
||||
password: '@102030Rod',
|
||||
// Concentrador Juniper - Pedro Afonso
|
||||
const juniperPedroAfonso = {
|
||||
name: 'Concentrador Juniper Pedro Afonso',
|
||||
host: process.env.JUNIPER_PEDRO_AFONSO_HOST || '45.189.140.2',
|
||||
username: process.env.JUNIPER_PEDRO_AFONSO_USER || 'rodrigo',
|
||||
password: process.env.JUNIPER_PEDRO_AFONSO_PASS || '',
|
||||
port: 22,
|
||||
type: 'juniper'
|
||||
});
|
||||
type: 'juniper',
|
||||
site: 'pedro_afonso'
|
||||
};
|
||||
this.equipamentos.set('juniper_pedro_afonso', juniperPedroAfonso);
|
||||
this.equipamentos.set('concentrador_pedro_afonso', juniperPedroAfonso); // alias
|
||||
|
||||
// Exemplos de equipamentos (você pode configurar mais)
|
||||
this.equipamentos.set('router1', {
|
||||
name: 'Router Principal',
|
||||
host: '192.168.1.1',
|
||||
username: 'admin',
|
||||
password: 'admin',
|
||||
port: 22
|
||||
});
|
||||
|
||||
this.equipamentos.set('switch1', {
|
||||
name: 'Switch Core',
|
||||
host: '192.168.1.10',
|
||||
username: 'admin',
|
||||
password: 'admin',
|
||||
port: 22
|
||||
});
|
||||
|
||||
// OLTs para verificação de sinal
|
||||
// OLTs Guaraí
|
||||
this.equipamentos.set('olt_dito', {
|
||||
name: 'OLT DITO',
|
||||
host: '192.168.190.7',
|
||||
username: 'admin',
|
||||
password: 'admin',
|
||||
port: 22,
|
||||
type: 'olt'
|
||||
type: 'olt',
|
||||
site: 'guarai'
|
||||
});
|
||||
|
||||
this.equipamentos.set('olt_colmeia', {
|
||||
@@ -75,7 +65,8 @@ class SSHManager {
|
||||
username: 'admin',
|
||||
password: 'admin',
|
||||
port: 22,
|
||||
type: 'olt'
|
||||
type: 'olt',
|
||||
site: 'guarai'
|
||||
});
|
||||
|
||||
this.equipamentos.set('olt_canaa', {
|
||||
@@ -84,7 +75,8 @@ class SSHManager {
|
||||
username: 'admin',
|
||||
password: 'admin',
|
||||
port: 22,
|
||||
type: 'olt'
|
||||
type: 'olt',
|
||||
site: 'guarai'
|
||||
});
|
||||
|
||||
this.equipamentos.set('olt_canaa2', {
|
||||
@@ -93,16 +85,19 @@ class SSHManager {
|
||||
username: 'admin',
|
||||
password: 'admin',
|
||||
port: 22,
|
||||
type: 'olt'
|
||||
type: 'olt',
|
||||
site: 'guarai'
|
||||
});
|
||||
|
||||
// OLTs Pedro Afonso
|
||||
this.equipamentos.set('olt_pedro_afonso', {
|
||||
name: 'OLT PEDRO AFONSO 1',
|
||||
host: '192.168.100.2',
|
||||
username: 'admin',
|
||||
password: 'admin',
|
||||
port: 22,
|
||||
type: 'olt'
|
||||
type: 'olt',
|
||||
site: 'pedro_afonso'
|
||||
});
|
||||
|
||||
this.equipamentos.set('olt_canavieiras', {
|
||||
@@ -111,7 +106,8 @@ class SSHManager {
|
||||
username: 'admin',
|
||||
password: 'admin',
|
||||
port: 22,
|
||||
type: 'olt'
|
||||
type: 'olt',
|
||||
site: 'pedro_afonso'
|
||||
});
|
||||
}
|
||||
|
||||
@@ -259,10 +255,11 @@ class SSHManager {
|
||||
/**
|
||||
* Lista equipamentos disponíveis
|
||||
*/
|
||||
listEquipments() {
|
||||
listEquipments(siteId = null) {
|
||||
const equipments = [];
|
||||
|
||||
for (const [id, equipment] of this.equipamentos) {
|
||||
if (siteId && equipment.site !== siteId) continue;
|
||||
equipments.push({
|
||||
id: id,
|
||||
name: equipment.name,
|
||||
@@ -696,18 +693,18 @@ class SSHManager {
|
||||
* Lista todos os equipamentos OLT disponíveis
|
||||
* @returns {Array} - Array com OLTs disponíveis
|
||||
*/
|
||||
listOLTs() {
|
||||
listOLTs(siteId = null) {
|
||||
const olts = [];
|
||||
|
||||
for (const [id, equipment] of this.equipamentos) {
|
||||
if (equipment.type === 'olt') {
|
||||
olts.push({
|
||||
id: id,
|
||||
name: equipment.name,
|
||||
host: equipment.host,
|
||||
port: equipment.port || 22
|
||||
});
|
||||
}
|
||||
if (equipment.type !== 'olt') continue;
|
||||
if (siteId && equipment.site !== siteId) continue;
|
||||
olts.push({
|
||||
id: id,
|
||||
name: equipment.name,
|
||||
host: equipment.host,
|
||||
port: equipment.port || 22
|
||||
});
|
||||
}
|
||||
|
||||
return olts;
|
||||
|
||||
@@ -48,6 +48,16 @@ class TopSappConfig {
|
||||
return this.credentials[instanceKey] || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obter credenciais a partir do site ativo (cidade/provedor)
|
||||
*/
|
||||
getCredentialsBySite(siteId) {
|
||||
const sites = require('../config/sites');
|
||||
const site = sites.getSite(siteId);
|
||||
if (!site) return this.credentials.guarai_colmeia;
|
||||
return this.credentials[site.topsappKey] || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obter credenciais por localização
|
||||
*/
|
||||
|
||||
Reference in new issue
Block a user