const { app, BrowserWindow, Menu, dialog, ipcMain, desktopCapturer, Notification, ipcRenderer, protocol, session } = require('electron'); const { autoUpdater } = require('electron-updater'); const os = require('os'); const pie = require("puppeteer-in-electron"); const puppeteer = require("puppeteer-core"); const path = require('path'); const https = require('https'); process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; const axios = require('axios'); const $ = require('jquery'); const fs = require('fs'); const argv = require('yargs').argv; const { exec } = require('child_process'); const { rr } = require('./rr'); const { HttpsProxyAgent } = require('https-proxy-agent'); const { spawn } = require('child_process'); app.disableHardwareAcceleration(); const logsDir = 'C:/RpaClaro'; const app_version = app.getVersion(); let url_platform = ''; let username = ''; let password = ''; let xpath_username = ''; let xpath_password = ''; let xpath_button = ''; let data_apps; let okanToken; let splashWindow; let mainWindow; let windowNew; let browser; let page; let data_apps_user = []; let appsOkan; let appHtml; let userDataApps; let from_okan = false; const CONFIG = { ENDPOINT_URL_APPS: 'https://rpa.okan.tools/users/apps/byUserAdOrDocument', ENDPOINT_URL_APP: 'https://rpa.okan.tools/app', ENDPOINT_OKAN_TOKEN: 'https://io.okan.tools/api/auth/electron', TOKEN_OKAN_USER: 'HrZTvmBNyQaM6jPI7sHo5ywN35ht/cplIBFeE+4Ufx8=', PROXY: 'http://proxyop.bop.local:8080', ENDPOINT_GET_PROFILE: 'https://io.okan.tools/api/auth/users/electron', ENDPOINT_GET_APPS: 'https://adm.okan.tools/wp-json/okanapiwp/v1/aplicativos/' }; app.disableHardwareAcceleration(); pie.initialize(app); const setupLogging = async () => { console.log(">> Iniciando configuracion de logs.."); if (!fs.existsSync(logsDir)) { fs.mkdirSync(logsDir, { recursive: true }); } const logFilePath = path.join(logsDir, 'console-log.txt'); // Limpia el archivo de logs al inicio await fs.promises.writeFile(logFilePath, '', 'utf-8'); // Helper para escribir logs en el archivo const writeLogToFile = (message) => { const now = new Date(); const timestamp = now.toLocaleString('en-US', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: true }).replace(/(\d+)\/(\d+)\/(\d+)/, '$3-$1-$2'); fs.appendFileSync(logFilePath, `[${timestamp}] ${message}\n`); }; // Sobrescribe métodos de console ['log', 'info', 'warn', 'error'].forEach((method) => { const originalMethod = console[method]; console[method] = (...args) => { const message = args .map((arg) => (typeof arg === 'object' ? JSON.stringify(arg, null, 2) : arg)) .join(' '); writeLogToFile(message); originalMethod.apply(console, args); // Mantén la salida en la consola }; }); }; // Función para manejar cookies en ASC069 async function handleCookiesASC069(page, data_code) { if (data_code === 'ASC069') { console.log('>> Verificando popup de cookies para ASC069...'); try { // Lista de selectores comunes para popups de cookies const cookieSelectors = [ // Selectores comunes para botones de aceptar cookies 'button[id*="accept"]', 'button[class*="accept"]', 'button[id*="cookie"]', 'button[class*="cookie"]', '[data-cy*="accept"]', '[data-testid*="accept"]', // Selectores por texto '//button[contains(text(), "Aceptar")]', '//button[contains(text(), "Accept")]', '//button[contains(text(), "Acepto")]', '//button[contains(text(), "OK")]', '//button[contains(text(), "Continuar")]', '//a[contains(text(), "Aceptar")]', '//a[contains(text(), "Accept")]', // Selectores específicos de ASCard si los conoces '#cookie-accept', '.cookie-accept', '[data-cookie="accept"]' ]; let cookieHandled = false; // Intentar con selectores CSS primero for (const selector of cookieSelectors.filter(s => !s.startsWith('//'))) { try { await page.waitForSelector(selector, { timeout: 2000 }); const element = await page.$(selector); if (element) { await element.click(); console.log(`>> Cookies aceptadas automáticamente usando selector: ${selector}`); cookieHandled = true; break; } } catch (e) { // Continuar con el siguiente selector } } // Si no funcionó con CSS, intentar con XPath if (!cookieHandled) { for (const xpath of cookieSelectors.filter(s => s.startsWith('//'))) { try { await page.waitForXPath(xpath, { timeout: 2000 }); const elements = await page.$x(xpath); if (elements && elements.length > 0) { await elements[0].click(); console.log(`>> Cookies aceptadas automáticamente usando XPath: ${xpath}`); cookieHandled = true; break; } } catch (e) { // Continuar con el siguiente XPath } } } if (cookieHandled) { // Esperar un momento para que se procese la aceptación await page.waitForTimeout(2000); console.log('>> Popup de cookies manejado correctamente'); return true; } else { console.log('>> No se detectó popup de cookies o no se pudo manejar automáticamente'); return false; } } catch (error) { console.log('>> Error al manejar cookies:', error.message); return false; } } return true; // Para otros códigos, continuar normalmente } async function getOkanToken() { try { const agent = new HttpsProxyAgent(CONFIG.PROXY); const responseOkan = await axios.post(CONFIG.ENDPOINT_OKAN_TOKEN, { user: process.env.USUARIO }, { headers: { 'Authorization': CONFIG.TOKEN_OKAN_USER }, httpsAgent: agent }); if (responseOkan.data.cod == '0') { console.log('>> Token de Okan obtenido.'); return responseOkan.data.data; } else { console.log('>> Error al obtener el token de Okan.'); return null; } } catch (error) { console.log('>> Error en la petición del token de Okan:', error); await dialog.showMessageBox({ type: 'error', defaultId: 0, title: 'Error de acceso', message: 'Error al comunicarse con Okan', }); app.quit(); return null; } } const processArguments = async () => { console.log(argv); process.env.MODE = 'prod'; let url_okan = argv['_']; let code_okan_str = url_okan.toString(); console.log(code_okan_str); // Handle OKAN code from URL or direct argument if (code_okan_str != '' && !argv.dev) { console.log('sika desde okan'); let code_okan = code_okan_str.split('&')[0].replace('rpaclaro:///?code=', ''); let user_okan = code_okan_str.split('&')[1].replace('user=', ''); process.env.OKAN = code_okan; process.env.USUARIO = user_okan; from_okan = true; } else if (code_okan_str == '' && argv['$0'] && argv['$0'].includes('RpaClaro.exe')) { console.log('sika desde exe'); await dialog.showMessageBox({ type: 'error', defaultId: 0, title: 'Error de acceso', message: 'Debes abrir RpaClaro desde Okan', }); app.quit(); return null; } else { console.log('sika desde cli'); process.env.OKAN = argv.code; process.env.USUARIO = argv.user; } // Set environment mode if (argv.dev) { process.env.MODE = 'dev'; } else { process.env.MODE = 'prod'; } console.log('>> Iniciando RpaClaro..'); console.log('_____________________________'); console.log('RPA CLARO'); console.log('Usuario: ' + process.env.USUARIO); console.log('Version: ' + app_version); console.log('Modo: ' + process.env.MODE); console.log('_____________________________'); }; const setupProtocolClient = async () => { // Get the path to the packaged executable const exePath = process.env.PORTABLE_EXECUTABLE_FILE || app.getPath('exe'); try { // For development environment if (process.defaultApp) { if (process.argv.length >= 2) { app.setAsDefaultProtocolClient('RpaClaro', process.execPath, [path.resolve(process.argv[1])]); } } else { // For packaged executable // Remove any existing protocol registration first app.removeAsDefaultProtocolClient('RpaClaro'); // Register the protocol with the packaged exe path const success = app.setAsDefaultProtocolClient('RpaClaro', exePath); if (!success) { throw new Error('Failed to register protocol handler'); } } console.log('>> Protocol configuration established successfully'); console.log('>> Executable path:', exePath); } catch (error) { console.error('>> Error setting up protocol client:', error); // Attempt to register without arguments as fallback app.setAsDefaultProtocolClient('RpaClaro'); } } const copyFilesFromRR = () => { const origen = path.join(__dirname, 'rr'); fs.readdir(origen, (err, archivos) => { if (err) { console.error('Error al leer el directorio de origen:', err); return; } archivos.forEach((archivo) => { const archivoOrigen = path.join(origen, archivo); const archivoDestino = path.join(logsDir, archivo); // Copia el archivo al directorio de destino fs.copyFile(archivoOrigen, archivoDestino, (err) => { if (err) { console.error(`Error al copiar ${archivo}:`, err); } else { // console.log(`${archivo} copiado correctamente.`); } }); }); console.log('>> Archivos copiados correctamente.'); }); }; async function getOkanToken() { try { const agent = new HttpsProxyAgent(CONFIG.PROXY); const responseOkan = await axios.post(CONFIG.ENDPOINT_OKAN_TOKEN, { user: '45957768' }, { headers: { 'Authorization': CONFIG.TOKEN_OKAN_USER }, httpsAgent: agent }); if (responseOkan.data.cod == '0') { console.log('>> Token de Okan obtenido.'); return responseOkan.data.data; } else { console.log('>> Error al obtener el token de Okan.'); return null; } } catch (error) { console.log('>> Error en la petición del token de Okan:', error); await dialog.showMessageBox({ type: 'error', defaultId: 0, title: 'Error de acceso', message: 'Error al comunicarse con Okan', }); app.quit(); return null; } } async function getProfile(token) { const token_okan = 'Bearer ' + token; try { const agent_two = new HttpsProxyAgent(CONFIG.PROXY); const responseGetProfile = await axios.get(CONFIG.ENDPOINT_GET_PROFILE, { headers: { 'Authorization': token_okan }, httpsAgent: agent_two }); if (responseGetProfile.data.cod == '0') { documento = responseGetProfile.data.data.document_number; profile = responseGetProfile.data.data.profile.id; console.log('>> Perfil: ' + profile); return profile; } } catch (e) { console.log('>> No se pudo obtener el perfil: ' + e); } } async function getApps(data_apps_user) { try { const agent_three = new HttpsProxyAgent(CONFIG.PROXY); // First attempt with proxy try { const urlAplicativos = CONFIG.ENDPOINT_GET_APPS + `${documento}/${profile}`; const responseAplicativos = await axios.get(urlAplicativos, { headers: { "Accept": "*/*", "Content-Type": "application/json" }, httpsAgent: agent_three, timeout: 30000 }); if (responseAplicativos.data['cod'] == '0') { return processAppsResponse(responseAplicativos.data, data_apps_user); } } catch (proxyError) { console.log('>> Attempting without proxy after proxy error:', proxyError.message); // Second attempt without proxy const urlAplicativos = CONFIG.ENDPOINT_GET_APPS + `${documento}/${profile}`; const responseAplicativos = await axios.get(urlAplicativos, { headers: { "Accept": "*/*", "Content-Type": "application/json" }, timeout: 30000 }); if (responseAplicativos.data['cod'] == '0') { return processAppsResponse(responseAplicativos.data, data_apps_user); } } } catch (e) { console.log('>> Error al obtener aplicaciones: ' + e); } } // Helper function to process the apps response function processAppsResponse(responseData, data_apps_user) { var apps_okan = []; const new_apps = responseData['data'] .filter(element => element['nombre_app'].startsWith('RPA')) .sort((a, b) => a.nombre_app.localeCompare(b.nombre_app)); console.log('>> Aplicativos Okan: ' + new_apps.length); // Process each app from new_apps for (const app of new_apps) { let code = app.url.replace('rpaclaro://?code=', ''); code = code.replace('RpaClaro://?code=', ''); code = code.replace('&user={user}', ''); let appExists = data_apps_user.desk?.some(deskApp => deskApp.code === code) || data_apps_user.web?.some(webApp => webApp.code === code); apps_okan.push({ nombre_app: app.nombre_app, code_app: code, logo: app.logo, status: appExists, status_integrado: appExists ? 'integrado' : 'no_integrado', }); } // Generate HTML for all apps return apps_okan.map(app => `
${app.nombre_app}
`).join(''); } async function getNetworkInfo() { const interfaces = os.networkInterfaces(); let ipAddress = ''; let macAddress = ''; // Buscar en todas las interfaces de red for (const name of Object.keys(interfaces)) { for (const net of interfaces[name]) { // Buscar IPv4 y no localhost if (net.family === 'IPv4' && !net.internal) { ipAddress = net.address; macAddress = net.mac; break; } } if (ipAddress && macAddress) break; } return { ip: ipAddress, mac: macAddress }; } async function getUserData(token) { try { const agent_four = new HttpsProxyAgent(CONFIG.PROXY); const networkInfo = await getNetworkInfo(); console.log('>> Usuario: ' + process.env.USUARIO); console.log('>> IP: ' + networkInfo.ip); console.log('>> MAC: ' + networkInfo.mac); console.log('>> Hostname: ' + os.hostname()); const headersList = { "Accept": "*/*", "Content-Type": "application/json", "X-Client-Mac": networkInfo.mac, "X-Client-Host": os.hostname(), "X-Client-Ip": networkInfo.ip, "Authorization": "Bearer " + token }; const bodyContent = JSON.stringify({ "filtrar_por": "user_ad", "valor": process.env.USUARIO, }); const response = await axios.post(CONFIG.ENDPOINT_URL_APPS, bodyContent, { headers: headersList, httpsAgent: agent_four }); return response.data.apps; } catch (error) { console.error('Error en la solicitud:', error); } }; async function createMainWindow(appsOkan) { mainWindow = new BrowserWindow({ width: 1200, height: 650, show: true, // frame: false, // Remove window frame/menu webPreferences: { nodeIntegration: true, contextIsolation: false }, }); await mainWindow.loadFile('./views/main/index.html'); const menuTemplate = [ { label: 'Archivo', submenu: [ { label: 'Recargar', accelerator: 'Ctrl+Shift+R', icon: __dirname + '/views/assets/icons/reload.png', // Ruta al icono click: () => { mainWindow.webContents.reloadIgnoringCache(); } }, { type: 'separator' }, // Separador en el menú { label: 'Salir', accelerator: 'Ctrl+Q', icon: __dirname + '/views/assets/icons/exit.png', // Ruta al icono click: () => { app.quit(); } } ] }, { label: 'Ayuda', submenu: [ // { // label: 'Mostrar DevTools', // accelerator: 'Ctrl+Shift+L', // icon: __dirname + '/views/assets/icons/screenshot.png', // Ruta al icono // click: () => { // mainWindow.openDevTools(); // } // }, // { type: 'separator' }, { label: 'Acerca de', accelerator: 'Ctrl+Shift+A', icon: __dirname + '/views/assets/icons/reload.png', // Ruta al icono click: () => { const { version } = require('./package.json'); // Obtener la versión desde package.json dialog.showMessageBox({ type: 'info', title: 'Acerca de Mi Aplicación', message: `Versión ${version}`, }); } } ] } ]; const menu = Menu.buildFromTemplate(menuTemplate); mainWindow.setMenu(menu); mainWindow.maximize(); if (process.env.MODE == 'dev') { mainWindow.show(); mainWindow.openDevTools(); // mainWindow.setKiosk(true); } // const webContents = mainWindow.webContents; // webContents.setMaxListeners(50); mainWindow.webContents.send('set-version', app_version); mainWindow.webContents.send('set-userpc', process.env.USUARIO); try { mainWindow.webContents.send('data-apps', appsOkan); } catch (e) { console.log('>> Error al enviar datos:' + e); } // webContents.on('did-stop-loading', () => { // console.log('>> Vista main cargada'); // }); mainWindow.on('ready-to-show', () => { // mainWindow.show(); // mainWindow.setMenu(menu); // mainWindow.maximize(); }); mainWindow.on('closed', function () { mainWindow = null; app.quit(); }); mainWindow.show(); return mainWindow; } async function createNewWindow() { browser = await pie.connect(app, puppeteer, { defaultViewport: null, ignoreHTTPSErrors: true, }); // const page = await browser.newPage(); windowNew = new BrowserWindow({ args: ['--no-sandbox', '--disable-setuid-sandbox', '--ignore-certificate-errors'], ignoreHTTPSErrors: true, width: 1200, height: 650, show: false, webPreferences: { nodeIntegration: true, // contextIsolation: false, partition: 'nopersist' }, }); windowNew.setMenu(null); windowNew.loadURL('https://apps.okan.tools'); return 'test'; } const mainIni = async () => { await setupProtocolClient(); await setupLogging(); await processArguments(); copyFilesFromRR(); let getOkanTokenVal = await getOkanToken(); console.log('Okan token: ' + getOkanTokenVal); await getProfile(getOkanTokenVal); userDataApps = await getUserData(getOkanTokenVal); console.log('>> Aplicaciones:' + userDataApps); appsOkan = await getApps(userDataApps); console.log('>> Html generado'); let mainWindowInstance = await createMainWindow(appsOkan); console.log(mainWindowInstance); await createNewWindow(); // mainWindow.webContents.on('did-finish-load', async () => { console.log('termino de cargar'); // try { await rpa(process.env.OKAN); // } catch(e) { // console.log('oka error: '+e); // } // }); }; async function openExternalBrowserForTYD075(webApp) { console.log('>> Iniciando TYD075 en navegador externo'); try { const puppeteer = require('puppeteer'); const browser = await puppeteer.launch({ headless: false, defaultViewport: null, args: [ `--app=${webApp.url}`, '--start-maximized', '--no-sandbox', '--disable-setuid-sandbox' ], executablePath: process.platform === 'win32' ? 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe' : undefined }); const pages = await browser.pages(); const page = pages[0]; await new Promise(resolve => setTimeout(resolve, 5000)); console.log('>> Rellenando credenciales para TYD075'); await page.waitForSelector('#username', { timeout: 10000 }); const usernameField = await page.$('#username'); if (usernameField) { await usernameField.click({ clickCount: 3 }); await usernameField.type(webApp.username, { delay: 5 }); console.log('>> Campo usuario rellenado'); } await page.waitForSelector('#password', { timeout: 5000 }); const passwordField = await page.$('#password'); if (passwordField) { await passwordField.click({ clickCount: 3 }); await passwordField.type(webApp.password, { delay: 5 }); console.log('>> Campo contraseña rellenado'); } await page.waitForSelector('#loginform fieldset button', { timeout: 5000 }); const loginButton = await page.$('#loginform fieldset button'); if (loginButton) { await loginButton.click(); console.log('>> Click en botón de login realizado'); try { await page.waitForNavigation({ waitUntil: 'networkidle0', timeout: 1500 }); console.log('>> Navegación después del login completada'); await page.evaluate(() => { document.addEventListener('contextmenu', event => event.preventDefault()); document.addEventListener('keydown', (e) => { if ( e.key === 'F12' || (e.ctrlKey && e.shiftKey && e.key === 'I') || (e.ctrlKey && e.shiftKey && e.key === 'J') || (e.ctrlKey && e.key === 'U') ) { e.preventDefault(); e.stopPropagation(); return false; } }); }); console.log('>> Medidas de seguridad aplicadas correctamente'); } catch (navError) { console.log('>> No hubo navegación o ya estamos en la página correcta'); try { await page.evaluate(() => { document.addEventListener('contextmenu', event => event.preventDefault()); document.addEventListener('keydown', (e) => { if ( e.key === 'F12' || (e.ctrlKey && e.shiftKey && e.key === 'I') || (e.ctrlKey && e.shiftKey && e.key === 'J') || (e.ctrlKey && e.key === 'U') ) { e.preventDefault(); e.stopPropagation(); return false; } }); const userField = document.querySelector('#username'); const passField = document.querySelector('#password'); const loginBtn = document.querySelector('#loginform fieldset button'); if (userField) { userField.setAttribute('readonly', 'true'); userField.style.pointerEvents = 'none'; } if (passField) { passField.setAttribute('readonly', 'true'); passField.style.pointerEvents = 'none'; } if (loginBtn) { loginBtn.style.pointerEvents = 'none'; } }); } catch (evalError) { console.log('>> Error al aplicar medidas de seguridad:', evalError.message); } } } await new Promise(resolve => setTimeout(resolve, 5000)); try { const errorElements = await page.$x('//*[contains(text(), "incorrect") or contains(text(), "error") or contains(text(), "invalid")]'); if (errorElements.length > 0) { console.log('>> Error de credenciales detectado'); dialog.showErrorBox('Error', 'Credenciales incorrectas para TYD075. Por favor, repórtalo al Coordinador'); await browser.close(); return false; } } catch (e) { console.log('>> No se detectaron errores de login'); } console.log('>> TYD075 iniciado exitosamente en navegador externo'); return true; } catch (error) { console.error('>> Error al abrir TYD075 en navegador externo:', error); dialog.showErrorBox('Error', `No se pudo abrir TYD075: ${error.message}`); return false; } } async function openExternalBrowserForDIM072(webApp) { console.log('>> Iniciando DIM072 en navegador externo'); try { const puppeteer = require('puppeteer'); const browser = await puppeteer.launch({ headless: false, defaultViewport: null, args: [ `--app=${webApp.url}`, '--start-maximized', '--no-sandbox', '--disable-setuid-sandbox' ], executablePath: process.platform === 'win32' ? 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe' : undefined }); const pages = await browser.pages(); const page = pages[0]; await new Promise(resolve => setTimeout(resolve, 1000)); console.log('>> Rellenando credenciales para DIM072'); await page.waitForSelector('#Usuario', { timeout: 5000 }); const usernameField = await page.$('#Usuario'); if (usernameField) { await usernameField.click({ clickCount: 3 }); await usernameField.type(webApp.username, { delay: 5 }); console.log('>> Campo usuario rellenado'); } await page.waitForSelector('#Contrase_a', { timeout: 5000 }); const passwordField = await page.$('#Contrase_a'); if (passwordField) { await passwordField.click({ clickCount: 3 }); await passwordField.type(webApp.password, { delay: 5 }); console.log('>> Campo contraseña rellenado'); } await new Promise(resolve => setTimeout(resolve, 250)); await page.waitForSelector('button[class="btn btn-lg red"]', { timeout: 5000 }); const loginButton = await page.$('button[class="btn btn-lg red"]'); if (loginButton) { await loginButton.click(); console.log('>> Click en botón de login realizado'); try { await page.waitForNavigation({ waitUntil: 'networkidle0', timeout: 1500 }); console.log('>> Navegación después del login completada'); await page.evaluate(() => { document.addEventListener('contextmenu', event => event.preventDefault()); document.addEventListener('keydown', (e) => { if ( e.key === 'F12' || (e.ctrlKey && e.shiftKey && e.key === 'I') || (e.ctrlKey && e.shiftKey && e.key === 'J') || (e.ctrlKey && e.key === 'U') ) { e.preventDefault(); e.stopPropagation(); return false; } }); }); console.log('>> Medidas de seguridad aplicadas correctamente'); } catch (navError) { console.log('>> No hubo navegación o ya estamos en la página correcta'); try { await page.evaluate(() => { document.addEventListener('contextmenu', event => event.preventDefault()); document.addEventListener('keydown', (e) => { if ( e.key === 'F12' || (e.ctrlKey && e.shiftKey && e.key === 'I') || (e.ctrlKey && e.shiftKey && e.key === 'J') || (e.ctrlKey && e.key === 'U') ) { e.preventDefault(); e.stopPropagation(); return false; } }); const userField = document.querySelector('#Usuario'); const passField = document.querySelector('#Contrase_a'); const loginBtn = document.querySelector('button[class="btn btn-lg red"]'); if (userField) { userField.setAttribute('readonly', 'true'); userField.style.pointerEvents = 'none'; } if (passField) { passField.setAttribute('readonly', 'true'); passField.style.pointerEvents = 'none'; } if (loginBtn) { loginBtn.style.pointerEvents = 'none'; } }); } catch (evalError) { console.log('>> Error al aplicar medidas de seguridad:', evalError.message); } } } await new Promise(resolve => setTimeout(resolve, 5000)); try { const errorElements = await page.$x('//*[contains(text(), "incorrect") or contains(text(), "error") or contains(text(), "invalid")]'); if (errorElements.length > 0) { console.log('>> Error de credenciales detectado'); dialog.showErrorBox('Error', 'Credenciales incorrectas para DIM072. Por favor, repórtalo al Coordinador'); await browser.close(); return false; } } catch (e) { console.log('>> No se detectaron errores de login'); } console.log('>> DIM072 iniciado exitosamente en navegador externo'); return true; } catch (error) { console.error('>> Error al abrir DIM072 en navegador externo:', error); dialog.showErrorBox('Error', `No se pudo abrir DIM072: ${error.message}`); return false; } } async function openExternalBrowserForTUN065(webApp) { console.log('>> Iniciando TUN065 en navegador externo'); try { const puppeteer = require('puppeteer'); const browser = await puppeteer.launch({ headless: false, defaultViewport: null, args: [ `--app=${webApp.url}`, '--start-maximized', '--no-sandbox', '--disable-setuid-sandbox' ], executablePath: process.platform === 'win32' ? 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe' : undefined }); const pages = await browser.pages(); const page = pages[0]; await new Promise(resolve => setTimeout(resolve, 1000)); console.log('>> Rellenando credenciales para TUN065'); await page.waitForSelector('input[name="ctl00$cpC$dcLogin$txtUserId"]', { timeout: 5000 }); const usernameField = await page.$('input[name="ctl00$cpC$dcLogin$txtUserId"]'); if (usernameField) { await usernameField.click({ clickCount: 3 }); await usernameField.type(webApp.username, { delay: 5 }); console.log('>> Campo usuario rellenado'); } await page.waitForSelector('input[name="ctl00$cpC$dcLogin$txtPassword"]', { timeout: 5000 }); const passwordField = await page.$('input[name="ctl00$cpC$dcLogin$txtPassword"]'); if (passwordField) { await passwordField.click({ clickCount: 3 }); await passwordField.type(webApp.password, { delay: 5 }); console.log('>> Campo contraseña rellenado'); } await new Promise(resolve => setTimeout(resolve, 50)); await page.waitForSelector('div[class="button fs-bold text-center"]', { timeout: 5000 }); const loginButton = await page.$('div[class="button fs-bold text-center"]'); if (loginButton) { await loginButton.click(); console.log('>> Click en botón de login realizado'); try { await page.waitForNavigation({ waitUntil: 'networkidle0', timeout: 1000 }); console.log('>> Navegación después del login completada'); await page.evaluate(() => { document.addEventListener('contextmenu', event => event.preventDefault()); document.addEventListener('keydown', (e) => { if ( e.key === 'F12' || (e.ctrlKey && e.shiftKey && e.key === 'I') || (e.ctrlKey && e.shiftKey && e.key === 'J') || (e.ctrlKey && e.key === 'U') ) { e.preventDefault(); e.stopPropagation(); return false; } }); }); console.log('>> Medidas de seguridad aplicadas correctamente'); } catch (navError) { console.log('>> No hubo navegación o ya estamos en la página correcta'); try { await page.evaluate(() => { document.addEventListener('contextmenu', event => event.preventDefault()); document.addEventListener('keydown', (e) => { if ( e.key === 'F12' || (e.ctrlKey && e.shiftKey && e.key === 'I') || (e.ctrlKey && e.shiftKey && e.key === 'J') || (e.ctrlKey && e.key === 'U') ) { e.preventDefault(); e.stopPropagation(); return false; } }); const userField = document.querySelector('input[name="ctl00$cpC$dcLogin$txtUserId"]'); const passField = document.querySelector('input[name="ctl00$cpC$dcLogin$txtPassword"]'); const loginBtn = document.querySelector('div[class="button fs-bold text-center"]'); if (userField) { userField.setAttribute('readonly', 'true'); userField.style.pointerEvents = 'none'; } if (passField) { passField.setAttribute('readonly', 'true'); passField.style.pointerEvents = 'none'; } if (loginBtn) { loginBtn.style.pointerEvents = 'none'; } }); } catch (evalError) { console.log('>> Error al aplicar medidas de seguridad:', evalError.message); } } } await new Promise(resolve => setTimeout(resolve, 5000)); try { const errorElements = await page.$x('//*[contains(text(), "incorrect") or contains(text(), "error") or contains(text(), "invalid")]'); if (errorElements.length > 0) { console.log('>> Error de credenciales detectado'); dialog.showErrorBox('Error', 'Credenciales incorrectas para TUN065. Por favor, repórtalo al Coordinador'); await browser.close(); return false; } } catch (e) { console.log('>> No se detectaron errores de login'); } console.log('>> TUN065 iniciado exitosamente en navegador externo'); return true; } catch (error) { console.error('>> Error al abrir TUN065 en navegador externo:', error); dialog.showErrorBox('Error', `No se pudo abrir IDV03: ${error.message}`); return false; } } async function openExternalBrowserForPOL(webApp) { console.log('>> Iniciando POLIEDRO en navegador externo'); try { const puppeteer = require('puppeteer'); const browser = await puppeteer.launch({ headless: false, defaultViewport: null, args: [ `--app=${webApp.url}`, '--start-maximized', '--no-sandbox', '--disable-setuid-sandbox', '--disable-web-security', '--disable-features=VizDisplayCompositor' ], executablePath: process.platform === 'win32' ? 'C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe' : undefined }); const pages = await browser.pages(); const page = pages[0]; await page.waitForLoadState?.('networkidle') || await new Promise(resolve => setTimeout(resolve, 2000)); console.log('>> Rellenando credenciales para POLIEDRO'); async function fillFieldRobustly(selector, value, fieldName, maxRetries = 3) { for (let attempt = 1; attempt <= maxRetries; attempt++) { try { console.log(`>> Intento ${attempt} para llenar ${fieldName}`); await page.waitForSelector(selector, { timeout: 10000 }); const field = await page.$(selector); if (!field) { throw new Error(`Campo ${fieldName} no encontrado`); } // Limpiar el campo completamente await field.click({ clickCount: 3 }); await page.keyboard.press('Delete'); await page.keyboard.press('Backspace'); await new Promise(resolve => setTimeout(resolve, 100)); // Escribir el valor caracter por caracter para mayor confiabilidad for (const char of value) { await page.keyboard.type(char, { delay: 20 }); await new Promise(resolve => setTimeout(resolve, 10)); } // Verificar que el valor se escribió correctamente await new Promise(resolve => setTimeout(resolve, 500)); const currentValue = await page.$eval(selector, el => el.value); if (currentValue === value) { console.log(`>> ${fieldName} rellenado correctamente: `); return true; } else { console.warn(`>> ${fieldName} no coincide. Esperado: , Actual:`); if (attempt === maxRetries) { throw new Error(`No se pudo llenar ${fieldName} después de ${maxRetries} intentos`); } } } catch (error) { console.error(`>> Error en intento ${attempt} para ${fieldName}:`, error.message); if (attempt === maxRetries) { throw error; } await new Promise(resolve => setTimeout(resolve, 1000)); } } return false; } await fillFieldRobustly('#ctl00_ContentPlaceHolder1_txtUsuario', webApp.username, 'usuario'); await new Promise(resolve => setTimeout(resolve, 500)); await fillFieldRobustly('#ctl00_ContentPlaceHolder1_txtContraseña', webApp.password, 'contraseña'); console.log('>> Realizando validación final de credenciales...'); await new Promise(resolve => setTimeout(resolve, 250)); const finalUsernameCheck = await page.$eval('#ctl00_ContentPlaceHolder1_txtUsuario', el => el.value); const finalPasswordCheck = await page.$eval('#ctl00_ContentPlaceHolder1_txtContraseña', el => el.value); if (finalUsernameCheck !== webApp.username) { throw new Error(`Usuario final no coincide. Esperado: "${webApp.username}", Actual: "${finalUsernameCheck}"`); } if (finalPasswordCheck !== webApp.password) { throw new Error(`Contraseña final no coincide. Esperado: , Actual: "${finalPasswordCheck}"`); } console.log('>> Validación final exitosa. Procediendo con el login...'); await page.waitForSelector('input[name="ctl00$ContentPlaceHolder1$btnIngresarUsuarioContraseña"]', { timeout: 5000 }); const loginButton = await page.$('input[name="ctl00$ContentPlaceHolder1$btnIngresarUsuarioContraseña"]'); if (loginButton) { const isDisabled = await page.$eval('input[name="ctl00$ContentPlaceHolder1$btnIngresarUsuarioContraseña"]', el => el.disabled); if (isDisabled) { console.warn('>> El botón de login está deshabilitado, esperando...'); await new Promise(resolve => setTimeout(resolve, 300)); } await loginButton.click(); console.log('>> Click en botón de login realizado'); try { await new Promise(resolve => setTimeout(resolve, 3000)); try { const hasTokenField = await page.$('td[colspan="2"].auto-style1'); if (!hasTokenField) { const errorElements = await page.evaluate(() => { const elements = document.querySelectorAll('*'); for (let element of elements) { const text = element.textContent.toLowerCase(); if (text.includes('incorrect') || text.includes('error') || text.includes('invalid') || text.includes('incorrecto') || text.includes('inválido') || (text.includes('usuario') && text.includes('contraseña'))) { return true; } } return false; }); if (errorElements) { console.log('>> Error de credenciales detectado'); dialog.showErrorBox('Error', 'Credenciales incorrectas para POLIEDRO. Por favor, repórtalo al Coordinador'); await browser.close(); return false; } } else { console.log('>> Campo de token detectado. No se verifica error de login aún.'); } } catch (e) { console.log('>> Error al verificar errores de credenciales:', e.message); } try { await page.waitForSelector('td[colspan="2"].auto-style1', { visible: true, timeout: 2000 }); const element = await page.$('td[colspan="2"].auto-style1'); const textContent = await page.evaluate(el => el.textContent, element); console.log(`>> Contenido encontrado: ${textContent.trim()}`); if (textContent.includes('token') && textContent.includes('SMS')) { console.log('>> Campo de token detectado - Habilitando interacción completa'); dialog.showMessageBox({ type: 'info', title: 'Token SMS Requerido', message: 'Se ha detectado que se requiere un token SMS. Por favor, ingrese el código que recibió por SMS en la página web y complete el proceso de autenticación.', buttons: ['Entendido'] }); let authCompleted = false; let attempts = 0; const maxAttempts = 15; while (!authCompleted && attempts < maxAttempts) { await new Promise(resolve => setTimeout(resolve, 5000)); attempts++; try { const tokenFieldStillExists = await page.$('td[colspan="2"].auto-style1'); if (!tokenFieldStillExists) { authCompleted = true; console.log('>> Autenticación completada - Campo de token ya no presente'); break; } const currentUrl = page.url(); const pageTitle = await page.title(); if (!currentUrl.includes('/login') && !pageTitle.toLowerCase().includes('login')) { authCompleted = true; console.log('>> Autenticación completada - Navegación detectada'); break; } console.log(`>> Esperando autenticación... Intento ${attempts}/${maxAttempts}`); } catch (e) { console.log('>> Error al verificar estado de autenticación:', e.message); } } if (!authCompleted && attempts >= maxAttempts) { console.log('>> Tiempo de espera agotado para autenticación OTP'); dialog.showWarningBox('Tiempo Agotado', 'El tiempo de espera para la autenticación OTP ha expirado. La sesión seguirá activa, pero puede que necesite completar manualmente el proceso.'); } } } catch (otpError) { console.log('>> No se detectó campo de token OTP, continuando...'); } try { await page.evaluate(() => { document.addEventListener('contextmenu', event => event.preventDefault()); document.addEventListener('keydown', (e) => { if ( e.key === 'F12' || (e.ctrlKey && e.shiftKey && e.key === 'I') || (e.ctrlKey && e.shiftKey && e.key === 'J') || (e.ctrlKey && e.key === 'U') ) { e.preventDefault(); e.stopPropagation(); return false; } }); }); console.log('>> Medidas de seguridad aplicadas correctamente'); } catch (securityError) { console.log('>> Error al aplicar medidas de seguridad:', securityError.message); } } catch (loginError) { console.log('>> Error durante el proceso de login:', loginError.message); dialog.showErrorBox('Error', `Error durante el proceso de login: ${loginError.message}`); await browser.close(); return false; } } await new Promise(resolve => setTimeout(resolve, 2000)); console.log('>> POLIEDRO iniciado exitosamente en navegador externo'); return true; } catch (error) { console.error('>> Error al abrir POLIEDRO en navegador externo:', error); dialog.showErrorBox('Error', `No se pudo abrir POLIEDRO: ${error.message}`); return false; } } async function rpa(data_code) { console.log('>> Iniciando RPA'); if (userDataApps) { const codeExists = userDataApps.desk.some(app => app.code === data_code) || userDataApps.web.some(app => app.code === data_code); if (codeExists) { console.log(`>> Aplicativo ${data_code} esta asociado`); const deskApp = userDataApps.desk.find(app => app.code === data_code); const webApp = userDataApps.web.find(app => app.code === data_code); if (deskApp) { type = 'desktop'; username = deskApp.username; password = deskApp.password; xpath_username = deskApp.xpath_username; xpath_password = deskApp.xpath_password; xpath_button = deskApp.btn_login; if (type == 'desktop') { switch (data_code) { case 'IRR123': console.log('=== INICIANDO PROCESO IRR123 ==='); console.log(`Timestamp: ${new Date().toISOString()}`); console.log(`Usuario: ${username}`); console.log('Ejecutando función rr() para automatización AS400...'); rrtest = rr(username, password); console.log(`Resultado de rr(): ${rrtest}`); console.log('=== PROCESO IRR123 COMPLETADO ==='); break; case 'ACC098': console.log('ACC098'); programa = '"C:\\Program Files (x86)\\AC Administración de Clientes\\AC Administrador de Clientes.exe"'; exec(programa, (error, stdout, stderr) => { if (error) { console.error(`Error al abrir el programa: ${error.message}`); return; } if (stderr) { console.error(`Error en la salida estándar: ${stderr}`); return; } console.log(`Salida del programa: ${stdout}`); }); break; case 'AVY003': console.log('AVY003'); programa = '"C:\\Program Files (x86)\\Avaya\\Avaya one-X Agent\\OneXAgentUI.exe"'; exec(programa, (error, stdout, stderr) => { // if (error) { // console.error(`Error al abrir el programa: ${error.message}`); // return; // } if (stderr) { console.error(`Error en la salida estándar: ${stderr}`); return; } console.log(`Salida del programa: ${stdout}`); }); break; case 'XLT001': console.log('XLT001'); programa = '"C:\\Program Files (x86)\\CounterPath\\X-Lite\\x-lite.exe"'; exec(programa, (error, stdout, stderr) => { if (error) { console.error(`Error al abrir el programa: ${error.message}`); return; } if (stderr) { console.error(`Error en la salida estándar: ${stderr}`); return; } console.log(`Salida del programa: ${stdout}`); }); break; case 'CTB002': console.log('CTB002'); programa = '"C:\\avaya\\CTIbar\\ctibar.exe"'; exec(programa, (error, stdout, stderr) => { if (error) { console.error(`Error al abrir el programa: ${error.message}`); return; } if (stderr) { console.error(`Error en la salida estándar: ${stderr}`); return; } console.log(`Salida del programa: ${stdout}`); }); break; } } } else if (webApp) { type = 'web'; url_platform = webApp.url; username = webApp.username; password = webApp.password; xpath_username = webApp.xpath_user; xpath_password = webApp.xpath_pass; xpath_button = webApp.btn_login; // if (data_code === 'TYD075') { // console.log('>> Detectado TYD075 - Usando navegador externo'); // const success = await openExternalBrowserForTYD075(webApp); // if (!success) { // console.log('>> Error al procesar TYD075'); // } // return; // } // if (data_code === 'DIM072') { // console.log('>> Detectado DIM072 - Usando navegador externo'); // const success = await openExternalBrowserForDIM072(webApp); // if (!success) { // console.log('>> Error al procesar DIM072'); // } // return; // } // if (data_code === 'TUN065') { // console.log('>> Detectado TUN065 - Usando navegador externo'); // const success = await openExternalBrowserForTUN065(webApp); // if (!success) { // console.log('>> Error al procesar TUN065'); // } // return; // } // if (data_code === 'POL911' || data_code === 'POL912' || data_code === 'POL913' || data_code === 'POL914' || data_code === 'POL915' || data_code === 'POD911') { // console.log('>> Detectado POLIEDRO - Usando navegador externo'); // const success = await openExternalBrowserForPOL(webApp); // if (!success) { // console.log('>> Error al procesar POLIEDRO'); // } // return; // } // if (!windowNew || windowNew.isDestroyed()) { windowNew = new BrowserWindow({ args: ['--no-sandbox', '--disable-setuid-sandbox', '--ignore-certificate-errors'], ignoreHTTPSErrors: true, width: 1200, height: 650, show: false, webPreferences: { nodeIntegration: true, // contextIsolation: false, partition: 'nopersist' }, }); // } windowNew.on('closed', function () { windowNew = null; console.log('>> Ventana cerrada'); }); console.log('Esta es la url act: ' + webApp.url); if (data_code == 'POL911' || data_code == 'POL912' || data_code == 'POL913' || data_code == 'POL914' || data_code == 'POL915' || data_code == 'POD911') { webApp.url = 'https://poliedro.comcel.com.co/LoginPoliedro/Login.aspx'; } windowNew.loadURL(webApp.url); windowNew.show(); windowNew.maximize(); windowNew.setIgnoreMouseEvents(false); if (process.env.MODE != 'prod') { windowNew.openDevTools(); windowNew.setIgnoreMouseEvents(false); } try { await Promise.race([ new Promise(resolve => { windowNew.webContents.on('did-finish-load', resolve); }), new Promise((_, reject) => setTimeout(() => reject(new Error('Timeout loading page')), 30000) ) ]); page = await pie.getPage(browser, windowNew); if (!page) { throw new Error('Failed to get page'); } console.log('>> URL cargada: ' + page.url()); } catch (error) { console.log('>> Error al cargar la página:', error.message); if (windowNew && !windowNew.isDestroyed()) { windowNew.close(); } throw error; } } console.log(`>> Tipo: ${type}`); if (type != 'desktop') { console.log(`>> URL: ${url_platform}`); console.log(`>> Username: ${username}`); console.log(`>> Password: **********`); console.log('>> Xpath username: ' + xpath_username); console.log('>> Xpath password: ' + xpath_password); console.log('>> Xpath button: ' + xpath_button); console.log('--------------------------'); console.log('Abriendo aplicativo'); console.log('--------------------------'); try { app.on('login', (event, webContents, request, authInfo, callback) => { console.log('______________________login___________________'); event.preventDefault(); callback(username, password); }); windowNew.setOpacity(1); windowNew.maximize(); windowNew.setMenu(null); windowNew.setIgnoreMouseEvents(true); if (process.env.MODE != 'prod') { windowNew.openDevTools(); windowNew.setIgnoreMouseEvents(false); } console.log('>> Url aplicativo: ' + url_platform); let data_response_service = { App: webApp.url || url_platform }; const allowedCodes = ['SMO098', 'CTD094', 'SGC095', 'MAX096', 'CUP045']; const specialCodes = ['MAP039']; const loginCodes = ['ATB089', 'VTT046', 'DSC047', 'SMO098', 'CTD094', 'SGC095', 'MAX096', 'CUP045', 'BDC087']; let url_mod; if (allowedCodes.includes(data_code)) { url_mod = `http://${username}:${password}@${data_response_service.App.replace('http://', '')}`; url_mod = url_platform; } else { url_mod = url_platform; } try { if (data_code == 'BDC087') { url_mod = 'http://100.123.251.118:8082/componentes/ASP/consultabroadcast.aspx' } if (data_code == 'SRA074') { url_mod = 'http://100.126.20.149:8080/sara/index.html' } await windowNew.loadURL(url_mod); // Manejar casos especiales de tiempo de espera if (data_code == 'POL911' || data_code == 'POL912' || data_code == 'POL913' || data_code == 'POL914' || data_code == 'POL915' || data_code == 'POD911') { await new Promise(resolve => setTimeout(resolve, 5000)); } // **NUEVO: Manejar cookies para ASC069** if (data_code === 'ASC069') { console.log('>> Procesando aplicativo ASC069 - Verificando cookies...'); await new Promise(resolve => setTimeout(resolve, 3000)); // Esperar a que cargue completamente const cookiesHandled = await handleCookiesASC069(page, data_code); if (!cookiesHandled) { console.log('>> No se pudieron manejar las cookies automáticamente'); console.log('>> Permitiendo interacción manual del usuario'); // Habilitar interacción del usuario temporalmente windowNew.setIgnoreMouseEvents(false); // Mostrar notificación al usuario const notification = new Notification({ title: 'Acción requerida - ASC069', body: 'Por favor, acepta las cookies manualmente y el proceso continuará automáticamente', icon: 'logo-claro.ico' }); notification.show(); // Esperar un tiempo razonable para que el usuario acepte las cookies await new Promise(resolve => setTimeout(resolve, 10000)); // Verificar si la página cambió (indicando que se aceptaron las cookies) try { // Intentar detectar si el popup de cookies ya no está presente const cookiePopupGone = await page.$eval('body', () => { // Buscar indicadores comunes de que el popup se cerró const commonCookieIndicators = [ '[class*="cookie"]', '[id*="cookie"]', '[data-cookie]', '.modal[style*="display: block"]' ]; for (const selector of commonCookieIndicators) { if (document.querySelector(selector)) { return false; // Aún hay popup } } return true; // Popup desapareció }); if (cookiePopupGone) { console.log('>> Cookies aparentemente aceptadas por el usuario'); } else { console.log('>> Continuando proceso - el usuario debe haber manejado las cookies'); } } catch (e) { console.log('>> Continuando con el proceso normal'); } // Continuar con el proceso automático windowNew.setIgnoreMouseEvents(true); } } console.log('>> Cargo la pagina'); } catch (error) { console.log('>> No se pudo cargar la pagina: ' + error); dialog.showErrorBox('Error', 'No se pudo cargar la pagina. Por favor reporta al Helpdesk'); windowNew.setOpacity(1); windowNew.close(); } // const page = await pie.getPage(browser, windowNew); try { // const pages = await browser.pages().then(pages => pages).catch(err => console.error(err)); // console.log(pages); // var page; var pageUrl; // for (const pages_sel of pages) { // const pageUrl = await pages_sel.url(); // // console.log('la obtenida: ' + pageUrl + '_____' + 'la real: ' + url_mod); // if (pageUrl == 'http://100.126.20.149:8080/sara/login') { // url_mod = 'http://100.126.20.149:8080/sara/login'; // } // if (pageUrl == 'http://dime.claro.com.co/Portal/Produccion/Sesion/Inicio/Ingresar?ReturnUrl=%2FPortal%2FProduccion%2FFidelizacion%2FRetencion%2FRegistrarSolicitud%3Fdato%3D1007227477%26Cuenta%3D89715445%26Ticket%3D1%26Internet%3D1%26TV%3D1%26Telefonia%3D0') { // url_mod = 'http://dime.claro.com.co/Portal/Produccion/Sesion/Inicio/Ingresar?ReturnUrl=%2FPortal%2FProduccion%2FFidelizacion%2FRetencion%2FRegistrarSolicitud%3Fdato%3D1007227477%26Cuenta%3D89715445%26Ticket%3D1%26Internet%3D1%26TV%3D1%26Telefonia%3D0'; // } // if (pageUrl === url_mod) { // console.log(`Ok pagina`); // page = pages_sel; // break; // Detén el bucle cuando encuentras la coincidencia // } // } if (page) { console.log(`Nombre de la pagina: ${await page.title()}`); if (data_code == 'ASW049') { console.log('avaya web'); await new Promise(resolve => setTimeout(resolve, 5000)); console.log('okan avaya'); } // await page.waitForLoad(); if (xpath_username != 'na') { // if (data_code == 'POL911' || data_code == 'POL912' || data_code == 'POL913' || data_code == 'POL914' || data_code == 'POL915' || data_code == 'POD911') { // await page.waitForXPath('//input[@id="ctl00_ContentPlaceHolder1_BtnRegresarMensaje"]'); // const backBtn = await page.$x('//input[@id="ctl00_ContentPlaceHolder1_BtnRegresarMensaje"]'); // await backBtn[0].click(); // } if (!loginCodes.includes(data_code)) { if (data_code == 'CLU100') { const elementHandleClu = await page.$('.sign-in-uclaro'); if (elementHandleClu) { await elementHandleClu.click(); } } //empieza a llenar el campo de usuario await page.waitForXPath(xpath_username); const elementHandleUser = await page.$x(xpath_username); await elementHandleUser[0].type('', { delay: 100 }); await elementHandleUser[0].type(username); console.log('>> Diligencio campo usuario'); if (data_code == 'ABS099') { await page.keyboard.press("Enter"); } else { await page.keyboard.press("Tab"); } if (data_code == 'AGE036') { await page.waitForTimeout(4000); } else { await page.waitForTimeout(1000); } await page.waitForXPath(xpath_password); const elementHandlePass = await page.$x(xpath_password); await elementHandlePass[0].type('', { delay: 100 }); await elementHandlePass[0].type(password); console.log('>> Diligencio campo password'); await page.waitForTimeout(1000); // Manejo específico para MAP039 if (data_code === 'MAP039') { console.log('>> Procesando botón de login para MAP039...'); try { console.log('>> Intentando submit directo del formulario...'); const formSubmitted = await page.evaluate(() => { const form = document.querySelector('form.vc_menu-search'); if (form) { form.submit(); return true; } return false; }); if (formSubmitted) { console.log('>> Formulario enviado con submit()'); } else { console.log('>> Intentando disparar evento submit...'); await page.evaluate(() => { const form = document.querySelector('form.vc_menu-search'); if (form) { const submitEvent = new Event('submit', { bubbles: true, cancelable: true }); form.dispatchEvent(submitEvent); } }); console.log('>> Evento submit disparado'); } } catch (error) { console.log('>> Error con submit:', error.message); try { console.log('>> Intentando click forzado en div Entrar...'); await page.evaluate(() => { const enterDiv = document.querySelector('.vc_menu-send'); if (enterDiv) { const clickEvent = new MouseEvent('click', { bubbles: true, cancelable: true, view: window }); enterDiv.dispatchEvent(clickEvent); } }); console.log('>> Click forzado realizado'); } catch (clickError) { console.log('>> Click forzado falló:', clickError.message); console.log('>> Intentando Enter en campo contraseña...'); await page.focus('#contra'); await page.keyboard.press('Enter'); } } await page.waitForTimeout(2000); } else { const xpathMap = { 'DIM072': '//button[contains(@id, "btiniciar")]', 'CLU100': '//button[contains(@class, "ingresarBoton")]', 'CMC093': xpath_button, 'MCA030': '//input[contains(@id, "login-button")]' }; const xpath = xpathMap[data_code] || null; if (xpath) { try { await page.waitForXPath(xpath, { timeout: 5000 }); const elementHandle = await page.$x(xpath); if (elementHandle && elementHandle.length > 0) { await elementHandle[0].click(); console.log('>> Se dio click en boton'); } else { console.log('>> No encontro boton'); await page.keyboard.press('Enter'); } } catch (error) { console.log('>> Error esperando botón, usando Enter'); await page.keyboard.press('Enter'); } } else { await page.keyboard.press('Enter'); } } } // await page.waitForTimeout(70000); console.log('>> Envio formulario'); await page.waitForTimeout(7000); if (data_code == 'POL911' || data_code == 'POL912' || data_code == 'POL913' || data_code == 'POL914' || data_code == 'POL915' || data_code == 'POD911') { console.log('>> Procesando aplicativo Poliedro'); try { console.log('>> Esperando campo de token...'); try { await page.waitForSelector('td[colspan="2"][class="auto-style1"]', { visible: true, timeout: 10000 }); const element = await page.$('td[colspan="2"][class="auto-style1"]'); const textContent = await page.evaluate(el => el.textContent, element); console.log(`>> Contenido encontrado: ${textContent.trim()}`); if (textContent.includes('token') && textContent.includes('SMS')) { console.log('>> Campo de token detectado - Habilitando interacción completa'); windowNew.setIgnoreMouseEvents(false); windowNew.show(); windowNew.focus(); windowNew.setAlwaysOnTop(true); setTimeout(() => { windowNew.setAlwaysOnTop(false); }, 1000); const notification = new Notification({ title: 'Acción requerida - Poliedro', body: 'Ingresa el código de verificación. La ventana ya está habilitada para uso.', icon: 'logo-claro.ico' }); notification.show(); console.log('>> Interacción habilitada permanentemente para Poliedro'); return; } else { throw new Error('Contenido no coincide con mensaje de token'); } } catch (tokenError) { console.log('>> No se encontró mensaje de token, verificando login exitoso...'); await page.waitForTimeout(3000); windowNew.setIgnoreMouseEvents(false); windowNew.show(); windowNew.focus(); console.log('>> Interacción habilitada para uso normal de Poliedro'); } } catch (e) { console.log('>> Error en Poliedro, habilitando interacción manual: ' + e); windowNew.setIgnoreMouseEvents(false); windowNew.show(); windowNew.focus(); windowNew.setAlwaysOnTop(true); setTimeout(() => { windowNew.setAlwaysOnTop(false); }, 1000); const notification = new Notification({ title: 'Atención - Poliedro', body: 'Complete el proceso manualmente. La ventana está habilitada.', icon: 'logo-claro.ico' }); notification.show(); } return; } else { const checkAndClose = async (message, text, xpath) => { var elementHandles; if (xpath) { elementHandles = await page.$x(text, { timeout: 1000 }); } else { if (data_code != 'SRA074' && text != 'valid') { elementHandles = await page.$x(`//*[contains(text(), "${text}")]`, { timeout: 1000 }); } } if (elementHandles && elementHandles.length > 0) { if (data_code == 'VIM059' && elementHandles.length <= 2) { // No hace nada para VIM059 con 2 elementos o menos } else if (data_code == 'DIM072' && elementHandles.length <= 1) { // No hace nada para DIM072 con 1 elemento o menos } else if (data_code == '') { // No hacer nada para TUN065 - permitir que continúe normalmente console.log(`>> IDV033: Se encontró texto "${text}" pero se permite continuar`); } else if (data_code == 'ASC069') { // No hace nada para ASC069 console.log(`>> ASC069: Se encontró texto "${text}" pero se permite continuar`); } else { console.log(`Se encontró mensaje de error de credenciales: ${message}`); dialog.showErrorBox('Error', 'Parece que hubo un problema con el ingreso. Por favor, repórtalo al Coordinador'); windowNew.close(); } } else { console.log(`>> No se encontró mensaje de error de credenciales: ${message}`); } }; await checkAndClose('Incorrect', 'incorrect', false) || await checkAndClose('Incorrectos', 'INCORRECTOS', false) || await checkAndClose('Error', 'error', false) || await checkAndClose('Error', 'Error', false) || await checkAndClose('Errada', 'errad', false) || await checkAndClose('Valid', 'valid', false) || await checkAndClose('no se encuentra habilitado para', 'no se encuentra habilitado para', false) || await checkAndClose('Could not log', 'could not log', false) || await checkAndClose('Form', xpath_username, true); } } windowNew.setIgnoreMouseEvents(false); // windowNew.setOpacity(1); // windowNew.maximize(); // windowNew.focus(); } else { console.log('>> No se encontro ninguna pagina con la URL proporcionada.'); } } catch (error) { console.log(error); } } catch (error) { windowNew.setOpacity(1); windowNew.close(); console.error('Ha ocurrido un error ', data_code, error); dialog.showErrorBox('Error', 'Ha ocurrido un error ' + error); } } } else { console.log(`>> Aplicativo ${data_code} no esta asociado`); await dialog.showMessageBox({ type: 'error', defaultId: 0, title: 'Error de acceso', message: 'Lo siento, no tienes acceso a este aplicativo', }); } } }; // Ensure mainIni is called after app is ready app.on('ready', mainIni); const gotTheLock = app.requestSingleInstanceLock(); if (!gotTheLock) { app.quit(); } else { app.on('second-instance', async (event, argv, workingDirectory) => { console.log('>> Segunda instancia'); console.log(argv); // Focus the main window if a second instance is detected if (mainWindow) { if (mainWindow.isMinimized()) mainWindow.restore(); mainWindow.focus(); } process.env.MODE = 'prod'; let url_okan = argv[3]; let code_okan_str = url_okan.toString(); // Handle OKAN code from URL or direct argument if (argv[3] && !argv.dev) { let code_okan = code_okan_str.split('&')[0].replace('rpaclaro:///?code=', ''); let user_okan = code_okan_str.split('&')[1].replace('user=', ''); process.env.OKAN = code_okan; process.env.USUARIO = user_okan; console.log('>> Sgundos instancia code: ' + process.env.OKAN); await rpa(process.env.OKAN); } else { process.env.OKAN = argv.code; process.env.USUARIO = argv.user; } // Set environment mode if (argv.dev) { process.env.MODE = 'dev'; } else { process.env.MODE = 'prod'; } console.log('>> Iniciando RpaClaro..'); console.log('_____________________________'); console.log('RPA CLARO'); console.log('Usuario: ' + process.env.USUARIO); console.log('Version: ' + app_version); console.log('Modo: ' + process.env.MODE); console.log('_____________________________'); }); // app.on('ready', mainIni); } // ... existing code ... app.on('window-all-closed', () => { if (process.platform !== 'darwin') { app.quit(); } }); app.commandLine.appendSwitch('ignore-certificate-errors'); app.on('certificate-error', (event, webContents, url, error, certificate, callback) => { event.preventDefault(); callback(true); }); ipcMain.on('openNewWindow', (event, data_code) => { rpa(data_code); }); ipcMain.on('newNotification', (event, message) => { const notification = new Notification({ title: message.title, body: message.body, icon: 'logo-claro.ico' }); notification.show(); }); ipcMain.on('show-help', () => { dialog.showMessageBox({ type: 'info', title: 'Acerca de Mi Aplicación', message: `Versión ` + app.getVersion(), }); }); ipcMain.on('reload-app', () => { mainWindow.webContents.reloadIgnoringCache(); // Reload main window ignoring cache }); ipcMain.on('close-app', () => { app.quit(); // Cierra la aplicación });