Ajustes
This commit is contained in:
@@ -0,0 +1,438 @@
|
|||||||
|
import path from 'path';
|
||||||
|
import { exec } from 'child_process';
|
||||||
|
import puppeteer from 'puppeteer-core';
|
||||||
|
import fetch from 'node-fetch';
|
||||||
|
import { google } from 'googleapis';
|
||||||
|
import { createWriteStream } from 'fs';
|
||||||
|
// import ExcelJS from 'exceljs';
|
||||||
|
import fs from 'fs';
|
||||||
|
import { app } from 'electron';
|
||||||
|
|
||||||
|
console.log(app.getAppPath());
|
||||||
|
|
||||||
|
let url_cred = app.getAppPath().replace('app.asar', '');
|
||||||
|
url_cred = url_cred + '\\credenciales.json';
|
||||||
|
console.log(url_cred);
|
||||||
|
|
||||||
|
// Configuración
|
||||||
|
const CONFIG = {
|
||||||
|
PATHS: {
|
||||||
|
BASE_DIR: 'C:\\Users\\Drackxus\\Documents\\NODE\\migracion',
|
||||||
|
ARCHIVOS: 'C:\\Users\\Drackxus\\Documents\\NODE\\migracion\\archivos',
|
||||||
|
CREDENTIALS: url_cred
|
||||||
|
},
|
||||||
|
DRIVE: {
|
||||||
|
FOLDER_ID: '1bjEaxLFkv4toUt0SeUz_HqrvIWAI2Xv5',
|
||||||
|
SCOPES: [
|
||||||
|
'https://www.googleapis.com/auth/drive',
|
||||||
|
'https://www.googleapis.com/auth/spreadsheets'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
PLATFORMS: {
|
||||||
|
CORTE: {
|
||||||
|
URL: 'https://acis.eoir.justice.gov/en/',
|
||||||
|
TYPE: 'corte'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Inicialización de Google APIs
|
||||||
|
const auth = new google.auth.GoogleAuth({
|
||||||
|
keyFile: CONFIG.PATHS.CREDENTIALS,
|
||||||
|
scopes: CONFIG.DRIVE.SCOPES
|
||||||
|
});
|
||||||
|
|
||||||
|
const sheets = google.sheets({ version: 'v4', auth });
|
||||||
|
const drive = google.drive({ version: 'v3', auth });
|
||||||
|
|
||||||
|
let browser; // Variable global para el navegador
|
||||||
|
|
||||||
|
// Funciones de Google Sheets
|
||||||
|
async function listarArchivosEnCarpeta(folderId) {
|
||||||
|
const res = await drive.files.list({
|
||||||
|
q: `'${folderId}' in parents and mimeType='application/vnd.google-apps.spreadsheet' and name='base_corte'`,
|
||||||
|
fields: '*'
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`${res.data.files.length} archivo(s) encontrados con el nombre "base_corte"`);
|
||||||
|
return res.data.files;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function obtenerDatosHoja(spreadsheetId) {
|
||||||
|
const response = await sheets.spreadsheets.values.get({
|
||||||
|
spreadsheetId,
|
||||||
|
range: 'A:F', // Ajusta el rango según tus necesidades
|
||||||
|
});
|
||||||
|
return response.data.values;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function actualizarCelda(spreadsheetId, range, values) {
|
||||||
|
try {
|
||||||
|
await sheets.spreadsheets.values.update({
|
||||||
|
spreadsheetId,
|
||||||
|
range,
|
||||||
|
valueInputOption: 'USER_ENTERED',
|
||||||
|
requestBody: {
|
||||||
|
values: [values]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error al actualizar celda:', error.message);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Funciones de manejo del navegador
|
||||||
|
async function cerrarChromeDebugging() {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
if (process.platform === 'win32') {
|
||||||
|
exec('wmic process where "commandline like \'%--remote-debugging-port=9224%\'" call terminate', (error) => {
|
||||||
|
if (error) {
|
||||||
|
console.log('⚠️ No se encontraron instancias de Chrome debugging');
|
||||||
|
} else {
|
||||||
|
console.log('🔒 Chrome debugging cerrado correctamente');
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
exec("pkill -f 'chrome.*--remote-debugging-port=9224'", () => {
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function iniciarChrome(url) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
const chromeProcess = exec(
|
||||||
|
`start chrome `
|
||||||
|
+ `--remote-debugging-port=9224 `
|
||||||
|
+ `--no-sandbox `
|
||||||
|
+ `--disable-setuid-sandbox `
|
||||||
|
+ `--disable-background-timer-throttling `
|
||||||
|
+ `--disable-renderer-backgrounding `
|
||||||
|
+ `--disable-backgrounding-occluded-windows `
|
||||||
|
+ `--user-data-dir="C:\\temp\\chrome_debug_temp_corte" `
|
||||||
|
+ `"${url}"`,
|
||||||
|
(error) => {
|
||||||
|
if (error) {
|
||||||
|
console.log('⚠️ Error al iniciar Chrome:', error);
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
async function initBrowser(url) {
|
||||||
|
try {
|
||||||
|
await cerrarChromeDebugging();
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||||
|
|
||||||
|
console.log('🌐 Iniciando Chrome con debugging...');
|
||||||
|
await iniciarChrome(url);
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 8000)); // Aumentado a 8 segundos
|
||||||
|
|
||||||
|
console.log('🔍 Intentando conectar con Chrome...');
|
||||||
|
const webSocketDebuggerUrl = await getWebSocketUrl();
|
||||||
|
|
||||||
|
console.log('✅ Conexión establecida con Chrome');
|
||||||
|
return await puppeteer.connect({
|
||||||
|
browserWSEndpoint: webSocketDebuggerUrl,
|
||||||
|
defaultViewport: null
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Error al inicializar el navegador:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getWebSocketUrl() {
|
||||||
|
let retries = 10; // Aumentado a 15 intentos
|
||||||
|
while (retries > 0) {
|
||||||
|
try {
|
||||||
|
const response = await fetch('http://localhost:9224/json/version');
|
||||||
|
if (!response.ok) throw new Error('No se pudo obtener la versión del navegador');
|
||||||
|
const json = await response.json();
|
||||||
|
if (json.webSocketDebuggerUrl) {
|
||||||
|
return json.webSocketDebuggerUrl;
|
||||||
|
}
|
||||||
|
throw new Error('URL de WebSocket no encontrada');
|
||||||
|
} catch (err) {
|
||||||
|
console.log(`🔄 Reintentando conexión a Chrome... (intentos restantes: ${retries})`);
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 2000)); // Aumentado a 4 segundos
|
||||||
|
retries--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Error('No se pudo conectar a Chrome después de varios intentos');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Funciones de utilidad
|
||||||
|
async function delay(ms) {
|
||||||
|
return new Promise(resolve => setTimeout(resolve, ms));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Funciones de procesamiento CORTE
|
||||||
|
async function procesarCasoCorte(page, element, spreadsheetId, intentos = 1) {
|
||||||
|
const MAX_INTENTOS = 3;
|
||||||
|
|
||||||
|
try {
|
||||||
|
console.log(` ⌛ Consultando caso Corte... (Intento ${intentos}/${MAX_INTENTOS})`);
|
||||||
|
try {
|
||||||
|
await page.goto(CONFIG.PLATFORMS.CORTE.URL, {
|
||||||
|
waitUntil: 'domcontentloaded',
|
||||||
|
timeout: 20000
|
||||||
|
});
|
||||||
|
} catch (navigationError) {
|
||||||
|
console.log(' ⚠️ Error de navegación o campo no encontrado, reintentando...');
|
||||||
|
if (intentos < MAX_INTENTOS) {
|
||||||
|
return await procesarCasoCorte(page, element, spreadsheetId, intentos + 1);
|
||||||
|
} else {
|
||||||
|
throw new Error('No se pudo acceder a la página después de varios intentos');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await page.waitForSelector('button.btn', { visible: true, timeout: 2000 });
|
||||||
|
await delay(2000);
|
||||||
|
await page.click('button.btn');
|
||||||
|
} catch (error) {
|
||||||
|
console.log('❌ No se pudo encontrar el botón de caso Corte.');
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await page.waitForSelector('.codeInput > input:nth-child(1)', { visible: true, timeout: 10000 });
|
||||||
|
await delay(2000);
|
||||||
|
await page.type('.codeInput > input:nth-child(1)', element.valor);
|
||||||
|
} catch (error) {
|
||||||
|
console.log('❌ No se pudo encontrar el campo de entrada de caso Corte.');
|
||||||
|
}
|
||||||
|
|
||||||
|
await delay(2000);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await page.waitForSelector('#btn_submit', { visible: true, timeout: 10000 });
|
||||||
|
await page.click('#btn_submit');
|
||||||
|
} catch (error) {
|
||||||
|
console.log('❌ No se pudo encontrar el botón de consulta Corte.');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
await delay(1000);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await delay(2000);
|
||||||
|
const noResultsElement = await page.$x("//div[contains(text(), 'No case found for this A-Number.')]");
|
||||||
|
if (noResultsElement.length > 0) {
|
||||||
|
console.log("⚠️ No case found for this A-Number");
|
||||||
|
await actualizarCelda(
|
||||||
|
spreadsheetId,
|
||||||
|
`C${element.fila}`,
|
||||||
|
['No case found for this A-Number']
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log('ℹ️ Case found, continuing with data extraction...');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Esperar a que aparezca la tarjeta de información
|
||||||
|
await page.waitForSelector('.caseInfoCard', { timeout: 8000 });
|
||||||
|
console.log(" ✅ Información encontrada");
|
||||||
|
|
||||||
|
// Obtener todos los elementos de información
|
||||||
|
const elements = await page.$$eval('div.caseInfoCard', nodes =>
|
||||||
|
nodes.map(el => el.innerText.replace(/\n/g, ''))
|
||||||
|
);
|
||||||
|
|
||||||
|
// Extraer la información relevante
|
||||||
|
const [box1, box2, box3, box4] = elements;
|
||||||
|
console.log(' 📋 Información obtenida:');
|
||||||
|
console.log(' Box 1:', box1);
|
||||||
|
console.log(' Box 2:', box2);
|
||||||
|
console.log(' Box 3:', box3);
|
||||||
|
console.log(' Box 4:', box4);
|
||||||
|
|
||||||
|
await actualizarCelda(
|
||||||
|
spreadsheetId,
|
||||||
|
`C${element.fila}:F${element.fila}`,
|
||||||
|
[box1, box2, box3, box4]
|
||||||
|
);
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.log('❌ No se pudo encontrar la información de la tarjeta.');
|
||||||
|
}
|
||||||
|
return true; // Indica que el proceso fue exitoso
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error(' ❌ Error procesando caso CORTE:', error);
|
||||||
|
|
||||||
|
if (intentos < MAX_INTENTOS) {
|
||||||
|
console.log(` 🔄 Reintentando... (${intentos}/${MAX_INTENTOS})`);
|
||||||
|
return await procesarCasoCorte(page, element, spreadsheetId, intentos + 1);
|
||||||
|
} else {
|
||||||
|
console.log(' ⚠️ Se agotaron los intentos o error no recuperable');
|
||||||
|
await actualizarCelda(
|
||||||
|
spreadsheetId,
|
||||||
|
`C${element.fila}`,
|
||||||
|
['Error al procesar el caso. Por favor, intente más tarde.']
|
||||||
|
);
|
||||||
|
return false; // Indica que el proceso falló
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Modificar la función procesarArchivo para manejar mejor la reconexión de Chrome
|
||||||
|
async function procesarArchivo(archivo) {
|
||||||
|
console.log('\n🔍 Analizando archivo:', archivo.name);
|
||||||
|
const platform_type = 'corte';
|
||||||
|
const platform = CONFIG.PLATFORMS[platform_type.toUpperCase()].URL;
|
||||||
|
|
||||||
|
|
||||||
|
const datos = await obtenerDatosHoja(archivo.id);
|
||||||
|
|
||||||
|
const filasAProcesar = datos.slice(1)
|
||||||
|
.map((row, index) => ({
|
||||||
|
valor: row[0], // Columna A
|
||||||
|
fila: index + 2, // Número de fila real
|
||||||
|
ultimaConsulta: row[1], // Columna B
|
||||||
|
columnaC: row[2] // Columna C
|
||||||
|
}))
|
||||||
|
.filter(row => {
|
||||||
|
if (!row.columnaC) return true; // Si la columna C está vacía, procesar
|
||||||
|
|
||||||
|
// Si la columna C no está vacía, verificar la fecha de última consulta en la columna B
|
||||||
|
if (!row.ultimaConsulta) return true; // Si no hay fecha en B, procesar (aunque C no esté vacía)
|
||||||
|
|
||||||
|
// Parsear la fecha en formato español DD/MM/YYYY
|
||||||
|
const [date, time] = row.ultimaConsulta.split(', ');
|
||||||
|
const [day, month, year] = date.split('/');
|
||||||
|
const [hours, minutes, seconds] = time.split(':');
|
||||||
|
|
||||||
|
const fechaUltimaConsulta = new Date(year, month - 1, day, hours, minutes, seconds);
|
||||||
|
const ahora = new Date();
|
||||||
|
|
||||||
|
// Calcular la diferencia en horas
|
||||||
|
const diferenciaHoras = (ahora - fechaUltimaConsulta) / (1000 * 60 * 60);
|
||||||
|
|
||||||
|
// Para fechas futuras, no procesar
|
||||||
|
if (fechaUltimaConsulta > ahora) return false;
|
||||||
|
|
||||||
|
return diferenciaHoras > 1; // Procesar solo si ha pasado más de 1 hora
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(filasAProcesar);
|
||||||
|
|
||||||
|
console.log(`📊 Total de filas a procesar: ${filasAProcesar.length}`);
|
||||||
|
|
||||||
|
if (filasAProcesar.length > 0) {
|
||||||
|
console.log('🌐 Iniciando navegador...');
|
||||||
|
let browser = await initBrowser(platform);
|
||||||
|
let page = (await browser.pages())[0];
|
||||||
|
let fallosConsecutivos = 0;
|
||||||
|
const MAX_FALLOS_CONSECUTIVOS = 3;
|
||||||
|
|
||||||
|
let procesadas = 0;
|
||||||
|
for (const element of filasAProcesar) {
|
||||||
|
procesadas++;
|
||||||
|
console.log(`\n⏳ Procesando fila ${element.fila} (${procesadas}/${filasAProcesar.length})`);
|
||||||
|
console.log(`📝 Valor a consultar: ${element.valor}`);
|
||||||
|
|
||||||
|
// Guardar la fecha y hora actual
|
||||||
|
const fechaHoraActual = new Date().toLocaleString('es-ES', {
|
||||||
|
year: 'numeric',
|
||||||
|
month: '2-digit',
|
||||||
|
day: '2-digit',
|
||||||
|
hour: '2-digit',
|
||||||
|
minute: '2-digit',
|
||||||
|
second: '2-digit'
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update timestamp and clear status columns
|
||||||
|
await Promise.all([
|
||||||
|
actualizarCelda(
|
||||||
|
archivo.id,
|
||||||
|
`B${element.fila}`,
|
||||||
|
[fechaHoraActual]
|
||||||
|
),
|
||||||
|
actualizarCelda(
|
||||||
|
archivo.id,
|
||||||
|
`C${element.fila}:F${element.fila}`,
|
||||||
|
['', '', '', '']
|
||||||
|
)
|
||||||
|
]);
|
||||||
|
|
||||||
|
const resultado = await procesarCasoCorte(page, element, archivo.id);
|
||||||
|
|
||||||
|
if (!resultado) {
|
||||||
|
fallosConsecutivos++;
|
||||||
|
if (fallosConsecutivos >= MAX_FALLOS_CONSECUTIVOS) {
|
||||||
|
console.log('🔄 Reiniciando navegador debido a fallos consecutivos...');
|
||||||
|
await browser.close();
|
||||||
|
await cerrarChromeDebugging();
|
||||||
|
await delay(2000);
|
||||||
|
|
||||||
|
browser = await initBrowser(platform);
|
||||||
|
page = (await browser.pages())[0];
|
||||||
|
fallosConsecutivos = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fallosConsecutivos = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('\n✅ Proceso completado para el archivo:', archivo.name);
|
||||||
|
await browser.close();
|
||||||
|
} else {
|
||||||
|
console.log('ℹ️ No hay filas para procesar en este archivo');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Función para cerrar el navegador y la aplicación
|
||||||
|
async function cerrarTodo() {
|
||||||
|
if (browser) {
|
||||||
|
await browser.close(); // Cerrar el navegador si está abierto
|
||||||
|
}
|
||||||
|
console.log('🔄 Cerrando Chrome debugging y finalizando...');
|
||||||
|
await cerrarChromeDebugging();
|
||||||
|
process.exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Manejar la señal SIGINT (Ctrl + C)
|
||||||
|
process.on('SIGINT', async () => {
|
||||||
|
console.log('Recibida señal de interrupción (Ctrl + C)');
|
||||||
|
await cerrarTodo();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Función principal
|
||||||
|
async function procesarArchivos() {
|
||||||
|
try {
|
||||||
|
console.log('🚀 Iniciando proceso...');
|
||||||
|
const archivos = await listarArchivosEnCarpeta(CONFIG.DRIVE.FOLDER_ID);
|
||||||
|
console.log(`📁 Total de archivos encontrados: ${archivos.length}`);
|
||||||
|
|
||||||
|
let procesados = 0;
|
||||||
|
for (const archivo of archivos) {
|
||||||
|
procesados++;
|
||||||
|
console.log(`\n📌 Procesando archivo ${procesados}/${archivos.length}: ${archivo.name}`);
|
||||||
|
await procesarArchivo(archivo);
|
||||||
|
}
|
||||||
|
console.log('\n🎉 Proceso completado exitosamente!');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Error en el proceso:', error);
|
||||||
|
} finally {
|
||||||
|
await cerrarTodo(); // Asegúrate de cerrar todo al final
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ejecutar el proceso
|
||||||
|
app.on('ready', () => {
|
||||||
|
console.log('Aplicación Electron está lista y en ejecución sin ventana.');
|
||||||
|
procesarArchivos();
|
||||||
|
});
|
||||||
@@ -1,506 +0,0 @@
|
|||||||
import path from 'path';
|
|
||||||
import { exec } from 'child_process';
|
|
||||||
import puppeteer from 'puppeteer-core';
|
|
||||||
import fetch from 'node-fetch';
|
|
||||||
import { google } from 'googleapis';
|
|
||||||
import { createWriteStream } from 'fs';
|
|
||||||
import fs from 'fs';
|
|
||||||
import { app } from 'electron';
|
|
||||||
|
|
||||||
console.log(app.getAppPath());
|
|
||||||
|
|
||||||
let url_cred = app.getAppPath().replace('app.asar', '');
|
|
||||||
url_cred = url_cred + '\\credenciales.json';
|
|
||||||
console.log(url_cred);
|
|
||||||
|
|
||||||
// Configuración
|
|
||||||
const CONFIG = {
|
|
||||||
PATHS: {
|
|
||||||
BASE_DIR: 'C:\\Users\\Drackxus\\Documents\\NODE\\migracion',
|
|
||||||
ARCHIVOS: 'C:\\Users\\Drackxus\\Documents\\NODE\\migracion\\archivos',
|
|
||||||
CREDENTIALS: url_cred
|
|
||||||
},
|
|
||||||
DRIVE: {
|
|
||||||
FOLDER_ID: '1bjEaxLFkv4toUt0SeUz_HqrvIWAI2Xv5',
|
|
||||||
SCOPES: [
|
|
||||||
'https://www.googleapis.com/auth/drive',
|
|
||||||
'https://www.googleapis.com/auth/spreadsheets'
|
|
||||||
]
|
|
||||||
},
|
|
||||||
PLATFORMS: {
|
|
||||||
CORTE: {
|
|
||||||
URL: 'https://acis.eoir.justice.gov/en/',
|
|
||||||
TYPE: 'corte'
|
|
||||||
},
|
|
||||||
USCIS: {
|
|
||||||
URL: 'https://egov.uscis.gov/es',
|
|
||||||
TYPE: 'uscis'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Inicialización de Google APIs
|
|
||||||
const auth = new google.auth.GoogleAuth({
|
|
||||||
keyFile: CONFIG.PATHS.CREDENTIALS,
|
|
||||||
scopes: CONFIG.DRIVE.SCOPES
|
|
||||||
});
|
|
||||||
|
|
||||||
const sheets = google.sheets({ version: 'v4', auth });
|
|
||||||
const drive = google.drive({ version: 'v3', auth });
|
|
||||||
|
|
||||||
let browser; // Variable global para el navegador
|
|
||||||
|
|
||||||
// Funciones de Google Sheets
|
|
||||||
async function listarArchivosEnCarpeta(folderId) {
|
|
||||||
const res = await drive.files.list({
|
|
||||||
q: `'${folderId}' in parents and mimeType='application/vnd.google-apps.spreadsheet'`,
|
|
||||||
fields: '*'
|
|
||||||
});
|
|
||||||
console.log(`${res.data.files.length} archivos encontrados`);
|
|
||||||
return res.data.files;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function obtenerDatosHoja(spreadsheetId) {
|
|
||||||
const response = await sheets.spreadsheets.values.get({
|
|
||||||
spreadsheetId,
|
|
||||||
range: 'A:G', // Ajusta el rango según tus necesidades
|
|
||||||
});
|
|
||||||
return response.data.values;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function actualizarCelda(spreadsheetId, range, values) {
|
|
||||||
try {
|
|
||||||
await sheets.spreadsheets.values.update({
|
|
||||||
spreadsheetId,
|
|
||||||
range,
|
|
||||||
valueInputOption: 'USER_ENTERED',
|
|
||||||
requestBody: {
|
|
||||||
values: [values]
|
|
||||||
}
|
|
||||||
});
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error al actualizar celda:', error.message);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Funciones de manejo de archivos
|
|
||||||
async function descargarArchivo(fileId, fileName) {
|
|
||||||
const filePath = path.join(CONFIG.PATHS.ARCHIVOS, fileName);
|
|
||||||
const res = await drive.files.get(
|
|
||||||
{ fileId, alt: 'media' },
|
|
||||||
{ responseType: 'stream' }
|
|
||||||
);
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const dest = createWriteStream(filePath);
|
|
||||||
res.data.pipe(dest);
|
|
||||||
dest.on('finish', () => resolve(filePath));
|
|
||||||
dest.on('error', reject);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function subirArchivo(filePath, fileId) {
|
|
||||||
const media = {
|
|
||||||
mimeType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
|
||||||
body: fs.createReadStream(filePath)
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
|
||||||
const res = await drive.files.update({
|
|
||||||
fileId: fileId,
|
|
||||||
media: media,
|
|
||||||
fields: 'id, name'
|
|
||||||
});
|
|
||||||
console.log(`✅ Archivo actualizado: ${res.data.name}`);
|
|
||||||
return res.data.id;
|
|
||||||
} catch (error) {
|
|
||||||
console.error('❌ Error al actualizar archivo:', error.message);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Funciones de manejo del navegador
|
|
||||||
async function cerrarChromeDebugging() {
|
|
||||||
return new Promise((resolve) => {
|
|
||||||
if (process.platform === 'win32') {
|
|
||||||
exec('wmic process where "commandline like \'%--remote-debugging-port=9223%\'" call terminate', (error) => {
|
|
||||||
if (error) {
|
|
||||||
console.log('⚠️ No se encontraron instancias de Chrome debugging');
|
|
||||||
} else {
|
|
||||||
console.log('🔒 Chrome debugging cerrado correctamente');
|
|
||||||
}
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
exec("pkill -f 'chrome.*--remote-debugging-port=9223'", () => {
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function iniciarChrome(url) {
|
|
||||||
return new Promise((resolve) => {
|
|
||||||
const chromeProcess = exec(
|
|
||||||
`start chrome --remote-debugging-port=9223 --user-data-dir="C:\\temp\\chrome_debug_temp" "${url}"`,
|
|
||||||
(error) => {
|
|
||||||
if (error) {
|
|
||||||
console.log('⚠️ Error al iniciar Chrome:', error);
|
|
||||||
}
|
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function initBrowser(url) {
|
|
||||||
try {
|
|
||||||
await cerrarChromeDebugging();
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
||||||
|
|
||||||
console.log('🌐 Iniciando Chrome con debugging...');
|
|
||||||
await iniciarChrome(url);
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 8000)); // Aumentado a 8 segundos
|
|
||||||
|
|
||||||
console.log('🔍 Intentando conectar con Chrome...');
|
|
||||||
const webSocketDebuggerUrl = await getWebSocketUrl();
|
|
||||||
|
|
||||||
console.log('✅ Conexión establecida con Chrome');
|
|
||||||
return await puppeteer.connect({
|
|
||||||
browserWSEndpoint: webSocketDebuggerUrl,
|
|
||||||
defaultViewport: null
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
console.error('❌ Error al inicializar el navegador:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getWebSocketUrl() {
|
|
||||||
let retries = 15; // Aumentado a 15 intentos
|
|
||||||
while (retries > 0) {
|
|
||||||
try {
|
|
||||||
const response = await fetch('http://localhost:9223/json/version');
|
|
||||||
if (!response.ok) throw new Error('No se pudo obtener la versión del navegador');
|
|
||||||
const json = await response.json();
|
|
||||||
if (json.webSocketDebuggerUrl) {
|
|
||||||
return json.webSocketDebuggerUrl;
|
|
||||||
}
|
|
||||||
throw new Error('URL de WebSocket no encontrada');
|
|
||||||
} catch (err) {
|
|
||||||
console.log(`🔄 Reintentando conexión a Chrome... (intentos restantes: ${retries})`);
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 4000)); // Aumentado a 4 segundos
|
|
||||||
retries--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new Error('No se pudo conectar a Chrome después de varios intentos');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Funciones de procesamiento de Excel
|
|
||||||
async function procesarExcel(filePath, cell, platformType) {
|
|
||||||
const workbook = new ExcelJS.Workbook();
|
|
||||||
await workbook.xlsx.readFile(filePath);
|
|
||||||
const worksheet = workbook.getWorksheet(1);
|
|
||||||
|
|
||||||
let dataRows = [];
|
|
||||||
worksheet.eachRow((row, rowNumber) => {
|
|
||||||
if (rowNumber > 1) {
|
|
||||||
const cellF = row.getCell(cell).value;
|
|
||||||
dataRows.push({ valor, coordenada: row.number });
|
|
||||||
// if (!cellF && cellF !== '') {
|
|
||||||
// const valor = row.getCell(platformType === 'uscis' ? 5 : 1).value;
|
|
||||||
// dataRows.push({ valor, coordenada: row.number });
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return { dataRows, workbook };
|
|
||||||
}
|
|
||||||
|
|
||||||
// Funciones de utilidad
|
|
||||||
async function delay(ms) {
|
|
||||||
return new Promise(resolve => setTimeout(resolve, ms));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Funciones de procesamiento USCIS
|
|
||||||
async function procesarCasoUSCIS(page, element, spreadsheetId, intentos = 1) {
|
|
||||||
const MAX_INTENTOS = 3;
|
|
||||||
|
|
||||||
try {
|
|
||||||
console.log(` ⌛ Consultando caso USCIS... (Intento ${intentos}/${MAX_INTENTOS})`);
|
|
||||||
|
|
||||||
// Esperar a que el elemento esté disponible
|
|
||||||
try {
|
|
||||||
await page.waitForSelector('#receipt_number', { timeout: 5000 });
|
|
||||||
} catch (selectorError) {
|
|
||||||
console.log(' ⚠️ No se encontró el campo de recibo, reiniciando navegador...');
|
|
||||||
if (intentos < MAX_INTENTOS) {
|
|
||||||
// Cerrar el navegador actual
|
|
||||||
const browser = page.browser();
|
|
||||||
await browser.close();
|
|
||||||
await cerrarChromeDebugging();
|
|
||||||
await delay(1000);
|
|
||||||
|
|
||||||
// Iniciar nuevo navegador
|
|
||||||
const newBrowser = await initBrowser(CONFIG.PLATFORMS.USCIS.URL);
|
|
||||||
const [newPage] = await newBrowser.pages();
|
|
||||||
|
|
||||||
// Reintentar con la nueva página
|
|
||||||
return await procesarCasoUSCIS(newPage, element, spreadsheetId, intentos + 1);
|
|
||||||
} else {
|
|
||||||
throw new Error('No se pudo encontrar el campo de recibo después de varios intentos');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Intentar llenar el campo y hacer clic
|
|
||||||
await page.type('#receipt_number', element.valor);
|
|
||||||
await page.click('::-p-text(Verifique Estatus)');
|
|
||||||
|
|
||||||
await page.waitForFunction(() => {
|
|
||||||
const input = document.querySelector('#receipt_number');
|
|
||||||
return input && input.value === '';
|
|
||||||
}, { timeout: 2000 });
|
|
||||||
|
|
||||||
try {
|
|
||||||
await page.waitForSelector('.errorMessage', { timeout: 2000 });
|
|
||||||
console.log(' ⚠️ Caso no válido');
|
|
||||||
await actualizarCelda(
|
|
||||||
spreadsheetId,
|
|
||||||
`F${element.fila}`,
|
|
||||||
['El número de recibo ingresado no es válido, intente nuevamente.']
|
|
||||||
);
|
|
||||||
} catch {
|
|
||||||
const titulo = await page.$eval('.conditionalLanding h2', el => el.innerText);
|
|
||||||
const descripcion = await page.$eval('.conditionalLanding p', el => el.innerText);
|
|
||||||
|
|
||||||
console.log(' ✅ Información obtenida');
|
|
||||||
console.log(` 📌 Estado: ${titulo}`);
|
|
||||||
|
|
||||||
await actualizarCelda(
|
|
||||||
spreadsheetId,
|
|
||||||
`F${element.fila}:G${element.fila}`,
|
|
||||||
[titulo, descripcion]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error(' ❌ Error procesando caso USCIS:', error);
|
|
||||||
|
|
||||||
if (intentos < MAX_INTENTOS) {
|
|
||||||
console.log(` 🔄 Reiniciando navegador y reintentando... (${intentos}/${MAX_INTENTOS})`);
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Cerrar el navegador actual
|
|
||||||
const browser = page.browser();
|
|
||||||
await browser.close();
|
|
||||||
await cerrarChromeDebugging();
|
|
||||||
await delay(2000);
|
|
||||||
|
|
||||||
// Iniciar nuevo navegador
|
|
||||||
const newBrowser = await initBrowser(CONFIG.PLATFORMS.USCIS.URL);
|
|
||||||
const [newPage] = await newBrowser.pages();
|
|
||||||
|
|
||||||
// Reintentar con la nueva página
|
|
||||||
return await procesarCasoUSCIS(newPage, element, spreadsheetId, intentos + 1);
|
|
||||||
} catch (retryError) {
|
|
||||||
console.error(' ❌ Error al reiniciar navegador:', retryError);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.log(' ⚠️ Se agotaron los intentos o error no recuperable');
|
|
||||||
await actualizarCelda(
|
|
||||||
spreadsheetId,
|
|
||||||
`F${element.fila}`,
|
|
||||||
['Error al procesar el caso. Por favor, intente más tarde.']
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Modificar la función procesarArchivo para manejar el nuevo browser
|
|
||||||
async function procesarArchivo(archivo) {
|
|
||||||
console.log('\n🔍 Analizando archivo:', archivo.name);
|
|
||||||
const datos = await obtenerDatosHoja(archivo.id);
|
|
||||||
const platform_type = archivo.name.includes('corte') ? 'corte' : 'uscis';
|
|
||||||
const platform = CONFIG.PLATFORMS[platform_type.toUpperCase()].URL;
|
|
||||||
|
|
||||||
// const filasAProcesar = datos.slice(1).map((row, index) => ({
|
|
||||||
// valor: platform_type === 'uscis' ? row[4] : row[0],
|
|
||||||
// fila: index + 2,
|
|
||||||
// tieneValor: platform_type === 'uscis' ? !row[5] : !row[1]
|
|
||||||
// })).filter(row => row.tieneValor);
|
|
||||||
|
|
||||||
const filasAProcesar = datos.slice(1).map((row, index) => ({
|
|
||||||
valor: platform_type === 'uscis' ? row[4] : row[0],
|
|
||||||
fila: index + 2,
|
|
||||||
tieneValor: platform_type === 'uscis' ? !row[5] : !row[1]
|
|
||||||
}));
|
|
||||||
|
|
||||||
console.log(`📊 Total de filas a procesar: ${filasAProcesar.length}`);
|
|
||||||
|
|
||||||
if (filasAProcesar.length > 0) {
|
|
||||||
console.log('🌐 Iniciando navegador...');
|
|
||||||
let browser = await initBrowser(platform);
|
|
||||||
const [page] = await browser.pages();
|
|
||||||
|
|
||||||
let procesadas = 0;
|
|
||||||
for (const element of filasAProcesar) {
|
|
||||||
procesadas++;
|
|
||||||
console.log(`\n⏳ Procesando fila ${element.fila} (${procesadas}/${filasAProcesar.length})`);
|
|
||||||
console.log(`📝 Valor a consultar: ${element.valor}`);
|
|
||||||
|
|
||||||
if (platform_type === 'uscis') {
|
|
||||||
await procesarCasoUSCIS(page, element, archivo.id);
|
|
||||||
} else {
|
|
||||||
await procesarCasoCorte(page, element, archivo.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('\n✅ Proceso completado para el archivo:', archivo.name);
|
|
||||||
await browser.close();
|
|
||||||
} else {
|
|
||||||
console.log('ℹ️ No hay filas para procesar en este archivo');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Función para esperar y obtener resultados de la Corte
|
|
||||||
async function esperarYObtenerResultadoCorte(page, element, spreadsheetId, intentos = 1) {
|
|
||||||
const MAX_INTENTOS = 3; // Número máximo de intentos
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Esperar a que aparezca la tarjeta de información
|
|
||||||
await page.waitForSelector('.caseInfoCard', { timeout: 8000 });
|
|
||||||
console.log(" ✅ Información encontrada");
|
|
||||||
|
|
||||||
// Obtener todos los elementos de información
|
|
||||||
const elements = await page.$$eval('div.caseInfoCard', nodes =>
|
|
||||||
nodes.map(el => el.innerText.replace(/\n/g, ''))
|
|
||||||
);
|
|
||||||
|
|
||||||
// Extraer la información relevante
|
|
||||||
const [box1, box2, box3, box4] = elements;
|
|
||||||
console.log(' 📋 Información obtenida:');
|
|
||||||
console.log(' Box 1:', box1);
|
|
||||||
console.log(' Box 2:', box2);
|
|
||||||
console.log(' Box 3:', box3);
|
|
||||||
console.log(' Box 4:', box4);
|
|
||||||
|
|
||||||
return [box1, box2, box3, box4];
|
|
||||||
} catch (error) {
|
|
||||||
if (error.name === 'TimeoutError') {
|
|
||||||
console.log(` ⚠️ No se encontró información después de 8 segundos (Intento ${intentos}/${MAX_INTENTOS})`);
|
|
||||||
|
|
||||||
if (intentos < MAX_INTENTOS) {
|
|
||||||
console.log(' 🔄 Reintentando proceso...');
|
|
||||||
await page.goto(CONFIG.PLATFORMS.CORTE.URL);
|
|
||||||
await delay(2000);
|
|
||||||
|
|
||||||
// Reiniciar el proceso completo
|
|
||||||
try {
|
|
||||||
await page.waitForSelector('button.btn', { visible: true, timeout: 2000 });
|
|
||||||
await delay(2000);
|
|
||||||
await page.click('button.btn');
|
|
||||||
|
|
||||||
await page.waitForSelector('.codeInput > input:nth-child(1)', { visible: true, timeout: 10000 });
|
|
||||||
await delay(2000);
|
|
||||||
await page.type('.codeInput > input:nth-child(1)', element.valor);
|
|
||||||
|
|
||||||
await page.waitForSelector('#btn_submit', { visible: true, timeout: 10000 });
|
|
||||||
await page.click('#btn_submit');
|
|
||||||
|
|
||||||
// Llamada recursiva con incremento de intentos
|
|
||||||
return await esperarYObtenerResultadoCorte(page, element, spreadsheetId, intentos + 1);
|
|
||||||
} catch (retryError) {
|
|
||||||
console.error(' ❌ Error en el reintento:', retryError);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ["", "", "", ""];
|
|
||||||
}
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Modificar la función procesarCasoCorte para pasar los parámetros necesarios
|
|
||||||
async function procesarCasoCorte(page, element, spreadsheetId) {
|
|
||||||
try {
|
|
||||||
console.log(' ⌛ Consultando caso Corte...');
|
|
||||||
|
|
||||||
try {
|
|
||||||
await page.waitForSelector('button.btn', { visible: true, timeout: 2000 });
|
|
||||||
await delay(2000);
|
|
||||||
await page.click('button.btn');
|
|
||||||
} catch (error) {
|
|
||||||
console.log(' ❌ No se pudo encontrar el botón de caso Corte.');
|
|
||||||
}
|
|
||||||
|
|
||||||
await page.waitForSelector('.codeInput > input:nth-child(1)', { visible: true, timeout: 10000 });
|
|
||||||
await delay(2000);
|
|
||||||
await page.type('.codeInput > input:nth-child(1)', element.valor);
|
|
||||||
|
|
||||||
await page.waitForSelector('#btn_submit', { visible: true, timeout: 10000 });
|
|
||||||
await page.click('#btn_submit');
|
|
||||||
|
|
||||||
// Pasar los parámetros necesarios para el reintento
|
|
||||||
const resultado = await esperarYObtenerResultadoCorte(page, element, spreadsheetId);
|
|
||||||
await actualizarCelda(spreadsheetId, `B${element.fila}:E${element.fila}`, resultado);
|
|
||||||
|
|
||||||
console.log(' ✅ Información actualizada en la hoja');
|
|
||||||
await page.goto(CONFIG.PLATFORMS.CORTE.URL);
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error(' ❌ Error procesando caso Corte:', error);
|
|
||||||
try {
|
|
||||||
console.log(' 🔄 Intentando recargar la página...');
|
|
||||||
await delay(3000);
|
|
||||||
await page.goto(CONFIG.PLATFORMS.CORTE.URL);
|
|
||||||
await delay(3000);
|
|
||||||
} catch (navError) {
|
|
||||||
console.error(' ❌ Error al recargar la página:', navError);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Función para cerrar el navegador y la aplicación
|
|
||||||
async function cerrarTodo() {
|
|
||||||
if (browser) {
|
|
||||||
await browser.close(); // Cerrar el navegador si está abierto
|
|
||||||
}
|
|
||||||
console.log('🔄 Cerrando Chrome debugging y finalizando...');
|
|
||||||
await cerrarChromeDebugging();
|
|
||||||
process.exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Manejar la señal SIGINT (Ctrl + C)
|
|
||||||
process.on('SIGINT', async () => {
|
|
||||||
console.log('Recibida señal de interrupción (Ctrl + C)');
|
|
||||||
await cerrarTodo();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Función principal
|
|
||||||
async function procesarArchivos() {
|
|
||||||
try {
|
|
||||||
console.log('🚀 Iniciando proceso...');
|
|
||||||
const archivos = await listarArchivosEnCarpeta(CONFIG.DRIVE.FOLDER_ID);
|
|
||||||
console.log(`📁 Total de archivos encontrados: ${archivos.length}`);
|
|
||||||
|
|
||||||
let procesados = 0;
|
|
||||||
for (const archivo of archivos) {
|
|
||||||
procesados++;
|
|
||||||
console.log(`\n📌 Procesando archivo ${procesados}/${archivos.length}: ${archivo.name}`);
|
|
||||||
await procesarArchivo(archivo);
|
|
||||||
}
|
|
||||||
console.log('\n🎉 Proceso completado exitosamente!');
|
|
||||||
} catch (error) {
|
|
||||||
console.error('❌ Error en el proceso:', error);
|
|
||||||
} finally {
|
|
||||||
await cerrarTodo(); // Asegúrate de cerrar todo al final
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ejecutar el proceso
|
|
||||||
app.on('ready', () => {
|
|
||||||
console.log('Aplicación Electron está lista y en ejecución sin ventana.');
|
|
||||||
procesarArchivos();
|
|
||||||
});
|
|
||||||
Generated
+46
-113
@@ -1,17 +1,17 @@
|
|||||||
{
|
{
|
||||||
"name": "migracion",
|
"name": "migracion-corte",
|
||||||
"version": "0.0.10",
|
"version": "0.0.13",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "migracion",
|
"name": "migracion-corte",
|
||||||
"version": "0.0.10",
|
"version": "0.0.13",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"googleapis": "^144.0.0",
|
"googleapis": "^144.0.0",
|
||||||
"node-fetch": "^3.3.2",
|
"node-fetch": "^3.3.2",
|
||||||
"puppeteer": "^24.1.1",
|
"puppeteer": "^24.9.0",
|
||||||
"puppeteer-core": "^24.2.0"
|
"puppeteer-core": "^24.2.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -590,18 +590,17 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@puppeteer/browsers": {
|
"node_modules/@puppeteer/browsers": {
|
||||||
"version": "2.7.0",
|
"version": "2.10.5",
|
||||||
"resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.10.5.tgz",
|
||||||
"integrity": "sha512-bO61XnTuopsz9kvtfqhVbH6LTM1koxK0IlBR+yuVrM2LB7mk8+5o1w18l5zqd5cs8xlf+ntgambqRqGifMDjog==",
|
"integrity": "sha512-eifa0o+i8dERnngJwKrfp3dEq7ia5XFyoqB17S4gK8GhsQE4/P8nxOfQSE0zQHxzzLo/cmF+7+ywEQ7wK7Fb+w==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"debug": "^4.4.0",
|
"debug": "^4.4.1",
|
||||||
"extract-zip": "^2.0.1",
|
"extract-zip": "^2.0.1",
|
||||||
"progress": "^2.0.3",
|
"progress": "^2.0.3",
|
||||||
"proxy-agent": "^6.5.0",
|
"proxy-agent": "^6.5.0",
|
||||||
"semver": "^7.6.3",
|
"semver": "^7.7.2",
|
||||||
"tar-fs": "^3.0.6",
|
"tar-fs": "^3.0.8",
|
||||||
"unbzip2-stream": "^1.4.3",
|
|
||||||
"yargs": "^17.7.2"
|
"yargs": "^17.7.2"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
@@ -1280,6 +1279,7 @@
|
|||||||
"version": "5.7.1",
|
"version": "5.7.1",
|
||||||
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
|
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
|
||||||
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
|
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
|
||||||
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "github",
|
"type": "github",
|
||||||
@@ -1545,13 +1545,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/chromium-bidi": {
|
"node_modules/chromium-bidi": {
|
||||||
"version": "1.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-5.1.0.tgz",
|
||||||
"integrity": "sha512-HislCEczCuamWm3+55Lig9XKmMF13K+BGKum9rwtDAzgUAHT4h5jNwhDmD4U20VoVUG8ujnv9UZ89qiIf5uF8w==",
|
"integrity": "sha512-9MSRhWRVoRPDG0TgzkHrshFSJJNZzfY5UFqUMuksg7zL1yoZIZ3jLB0YAgHclbiAxPI86pBnwDX1tbzoiV8aFw==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"mitt": "3.0.1",
|
"mitt": "^3.0.1",
|
||||||
"zod": "3.24.1"
|
"zod": "^3.24.1"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"devtools-protocol": "*"
|
"devtools-protocol": "*"
|
||||||
@@ -1895,9 +1895,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/debug": {
|
"node_modules/debug": {
|
||||||
"version": "4.4.0",
|
"version": "4.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
|
||||||
"integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
|
"integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ms": "^2.1.3"
|
"ms": "^2.1.3"
|
||||||
@@ -2041,9 +2041,9 @@
|
|||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"node_modules/devtools-protocol": {
|
"node_modules/devtools-protocol": {
|
||||||
"version": "0.0.1380148",
|
"version": "0.0.1439962",
|
||||||
"resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1380148.tgz",
|
"resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1439962.tgz",
|
||||||
"integrity": "sha512-1CJABgqLxbYxVI+uJY/UDUHJtJ0KZTSjNYJYKqd9FRoXT33WDakDHNxRapMEgzeJ/C3rcs01+avshMnPmKQbvA==",
|
"integrity": "sha512-jJF48UdryzKiWhJ1bLKr7BFWUQCEIT5uCNbDLqkQJBtkFxYzILJH44WN0PDKMIlGDN7Utb8vyUY85C3w4R/t2g==",
|
||||||
"license": "BSD-3-Clause"
|
"license": "BSD-3-Clause"
|
||||||
},
|
},
|
||||||
"node_modules/dir-compare": {
|
"node_modules/dir-compare": {
|
||||||
@@ -3295,6 +3295,7 @@
|
|||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
||||||
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
|
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
|
||||||
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "github",
|
"type": "github",
|
||||||
@@ -4575,17 +4576,17 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/puppeteer": {
|
"node_modules/puppeteer": {
|
||||||
"version": "24.1.1",
|
"version": "24.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-24.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-24.9.0.tgz",
|
||||||
"integrity": "sha512-fuhceZ5HZuDXVuaMIRxUuDHfCJLmK0pXh8FlzVQ0/+OApStevxZhU5kAVeYFOEqeCF5OoAyZjcWbdQK27xW/9A==",
|
"integrity": "sha512-L0pOtALIx8rgDt24Y+COm8X52v78gNtBOW6EmUcEPci0TYD72SAuaXKqasRIx4JXxmg2Tkw5ySKcpPOwN8xXnQ==",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@puppeteer/browsers": "2.7.0",
|
"@puppeteer/browsers": "2.10.5",
|
||||||
"chromium-bidi": "1.1.0",
|
"chromium-bidi": "5.1.0",
|
||||||
"cosmiconfig": "^9.0.0",
|
"cosmiconfig": "^9.0.0",
|
||||||
"devtools-protocol": "0.0.1380148",
|
"devtools-protocol": "0.0.1439962",
|
||||||
"puppeteer-core": "24.1.1",
|
"puppeteer-core": "24.9.0",
|
||||||
"typed-query-selector": "^2.12.0"
|
"typed-query-selector": "^2.12.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
@@ -4596,69 +4597,17 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/puppeteer-core": {
|
"node_modules/puppeteer-core": {
|
||||||
"version": "24.2.0",
|
"version": "24.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.9.0.tgz",
|
||||||
"integrity": "sha512-e4A4/xqWdd4kcE6QVHYhJ+Qlx/+XpgjP4d8OwBx0DJoY/nkIRhSgYmKQnv7+XSs1ofBstalt+XPGrkaz4FoXOQ==",
|
"integrity": "sha512-HFdCeH/wx6QPz8EncafbCqJBqaCG1ENW75xg3cLFMRUoqZDgByT6HSueiumetT2uClZxwqj0qS4qMVZwLHRHHw==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@puppeteer/browsers": "2.7.1",
|
"@puppeteer/browsers": "2.10.5",
|
||||||
"chromium-bidi": "1.2.0",
|
"chromium-bidi": "5.1.0",
|
||||||
"debug": "^4.4.0",
|
"debug": "^4.4.1",
|
||||||
"devtools-protocol": "0.0.1402036",
|
"devtools-protocol": "0.0.1439962",
|
||||||
"typed-query-selector": "^2.12.0",
|
"typed-query-selector": "^2.12.0",
|
||||||
"ws": "^8.18.0"
|
"ws": "^8.18.2"
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/puppeteer-core/node_modules/@puppeteer/browsers": {
|
|
||||||
"version": "2.7.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.7.1.tgz",
|
|
||||||
"integrity": "sha512-MK7rtm8JjaxPN7Mf1JdZIZKPD2Z+W7osvrC1vjpvfOX1K0awDIHYbNi89f7eotp7eMUn2shWnt03HwVbriXtKQ==",
|
|
||||||
"dependencies": {
|
|
||||||
"debug": "^4.4.0",
|
|
||||||
"extract-zip": "^2.0.1",
|
|
||||||
"progress": "^2.0.3",
|
|
||||||
"proxy-agent": "^6.5.0",
|
|
||||||
"semver": "^7.7.0",
|
|
||||||
"tar-fs": "^3.0.8",
|
|
||||||
"yargs": "^17.7.2"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"browsers": "lib/cjs/main-cli.js"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/puppeteer-core/node_modules/chromium-bidi": {
|
|
||||||
"version": "1.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-1.2.0.tgz",
|
|
||||||
"integrity": "sha512-XtdJ1GSN6S3l7tO7F77GhNsw0K367p0IsLYf2yZawCVAKKC3lUvDhPdMVrB2FNhmhfW43QGYbEX3Wg6q0maGwQ==",
|
|
||||||
"dependencies": {
|
|
||||||
"mitt": "^3.0.1",
|
|
||||||
"zod": "^3.24.1"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"devtools-protocol": "*"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/puppeteer-core/node_modules/devtools-protocol": {
|
|
||||||
"version": "0.0.1402036",
|
|
||||||
"resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1402036.tgz",
|
|
||||||
"integrity": "sha512-JwAYQgEvm3yD45CHB+RmF5kMbWtXBaOGwuxa87sZogHcLCv8c/IqnThaoQ1y60d7pXWjSKWQphPEc+1rAScVdg=="
|
|
||||||
},
|
|
||||||
"node_modules/puppeteer/node_modules/puppeteer-core": {
|
|
||||||
"version": "24.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.1.1.tgz",
|
|
||||||
"integrity": "sha512-7FF3gq6bpIsbq3I8mfbodXh3DCzXagoz3l2eGv1cXooYU4g0P4mcHQVHuBD4iSZPXNg8WjzlP5kmRwK9UvwF0A==",
|
|
||||||
"dependencies": {
|
|
||||||
"@puppeteer/browsers": "2.7.0",
|
|
||||||
"chromium-bidi": "1.1.0",
|
|
||||||
"debug": "^4.4.0",
|
|
||||||
"devtools-protocol": "0.0.1380148",
|
|
||||||
"typed-query-selector": "^2.12.0",
|
|
||||||
"ws": "^8.18.0"
|
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
@@ -4892,9 +4841,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/semver": {
|
"node_modules/semver": {
|
||||||
"version": "7.7.1",
|
"version": "7.7.2",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
|
||||||
"integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
|
"integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"bin": {
|
"bin": {
|
||||||
"semver": "bin/semver.js"
|
"semver": "bin/semver.js"
|
||||||
@@ -5348,12 +5297,6 @@
|
|||||||
"b4a": "^1.6.4"
|
"b4a": "^1.6.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/through": {
|
|
||||||
"version": "2.3.8",
|
|
||||||
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
|
||||||
"integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/tmp": {
|
"node_modules/tmp": {
|
||||||
"version": "0.2.3",
|
"version": "0.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz",
|
||||||
@@ -5426,16 +5369,6 @@
|
|||||||
"node": ">=14.17"
|
"node": ">=14.17"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/unbzip2-stream": {
|
|
||||||
"version": "1.4.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz",
|
|
||||||
"integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"buffer": "^5.2.1",
|
|
||||||
"through": "^2.3.8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/undici-types": {
|
"node_modules/undici-types": {
|
||||||
"version": "6.20.0",
|
"version": "6.20.0",
|
||||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
|
||||||
@@ -5631,9 +5564,9 @@
|
|||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/ws": {
|
"node_modules/ws": {
|
||||||
"version": "8.18.0",
|
"version": "8.18.2",
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
|
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.2.tgz",
|
||||||
"integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==",
|
"integrity": "sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10.0.0"
|
"node": ">=10.0.0"
|
||||||
|
|||||||
+9
-8
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "migracion",
|
"name": "migracion-uscis",
|
||||||
"version": "0.0.12",
|
"version": "1.0.0",
|
||||||
"main": "main.mjs",
|
"main": "uscis.mjs",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
"start": "electron .",
|
"start": "electron .",
|
||||||
@@ -10,11 +10,11 @@
|
|||||||
"keywords": [],
|
"keywords": [],
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"description": "Migracion",
|
"description": "Migracion Uscis",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"googleapis": "^144.0.0",
|
"googleapis": "^144.0.0",
|
||||||
"node-fetch": "^3.3.2",
|
"node-fetch": "^3.3.2",
|
||||||
"puppeteer": "^24.1.1",
|
"puppeteer": "^24.9.0",
|
||||||
"puppeteer-core": "^24.2.0"
|
"puppeteer-core": "^24.2.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -23,8 +23,8 @@
|
|||||||
},
|
},
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"build": {
|
"build": {
|
||||||
"appId": "com.migracion.id",
|
"appId": "com.migracion.uscis.id",
|
||||||
"productName": "Migracion",
|
"productName": "Migracion Uscis",
|
||||||
"win": {
|
"win": {
|
||||||
"target": "nsis",
|
"target": "nsis",
|
||||||
"icon": "path/to/icon.ico"
|
"icon": "path/to/icon.ico"
|
||||||
@@ -33,4 +33,5 @@
|
|||||||
"credenciales.json"
|
"credenciales.json"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"name": "migracion-uscis",
|
||||||
|
"version": "0.0.14",
|
||||||
|
"main": "uscis.mjs",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
|
"start": "electron .",
|
||||||
|
"build": "electron-builder"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"description": "Migracion Uscis",
|
||||||
|
"dependencies": {
|
||||||
|
"googleapis": "^144.0.0",
|
||||||
|
"node-fetch": "^3.3.2",
|
||||||
|
"puppeteer": "^24.9.0",
|
||||||
|
"puppeteer-core": "^24.2.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"electron": "^34.1.1",
|
||||||
|
"electron-builder": "^25.1.8"
|
||||||
|
},
|
||||||
|
"type": "module",
|
||||||
|
"build": {
|
||||||
|
"appId": "com.migracion.uscis.id",
|
||||||
|
"productName": "Migracion Uscis",
|
||||||
|
"win": {
|
||||||
|
"target": "nsis",
|
||||||
|
"icon": "path/to/icon.ico"
|
||||||
|
},
|
||||||
|
"extraResources": [
|
||||||
|
"credenciales.json"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
import puppeteer from 'puppeteer';
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
try {
|
||||||
|
|
||||||
|
const browser = await puppeteer.launch({
|
||||||
|
headless: false,
|
||||||
|
defaultViewport: null,
|
||||||
|
args: [
|
||||||
|
// `--app=https://egov.uscis.gov/es`,
|
||||||
|
'--start-maximized',
|
||||||
|
'--no-sandbox',
|
||||||
|
'--disable-setuid-sandbox'
|
||||||
|
],
|
||||||
|
executablePath: process.platform === 'win32'
|
||||||
|
? 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe'
|
||||||
|
: undefined
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create new page
|
||||||
|
const page = await browser.newPage();
|
||||||
|
|
||||||
|
// Go to website
|
||||||
|
await page.goto('https://egov.uscis.gov/es');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// // Get page title
|
||||||
|
// const title = await page.title();
|
||||||
|
// console.log('Page title:', title);
|
||||||
|
|
||||||
|
// // Type in search box (example)
|
||||||
|
// await page.type('textarea', 'puppeteer automation');
|
||||||
|
|
||||||
|
// // Press Enter key
|
||||||
|
// await page.keyboard.press('Enter');
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('An error occurred:', error);
|
||||||
|
}
|
||||||
|
})();
|
||||||
@@ -0,0 +1,422 @@
|
|||||||
|
import path from 'path';
|
||||||
|
import { exec } from 'child_process';
|
||||||
|
import puppeteer from 'puppeteer-core';
|
||||||
|
import fetch from 'node-fetch';
|
||||||
|
import { google } from 'googleapis';
|
||||||
|
import { createWriteStream } from 'fs';
|
||||||
|
import fs from 'fs';
|
||||||
|
import { app } from 'electron';
|
||||||
|
|
||||||
|
console.log(app.getAppPath());
|
||||||
|
|
||||||
|
let url_cred = app.getAppPath().replace('app.asar', '');
|
||||||
|
url_cred = url_cred + '\\credenciales.json';
|
||||||
|
console.log(url_cred);
|
||||||
|
|
||||||
|
// Configuración
|
||||||
|
const CONFIG = {
|
||||||
|
PATHS: {
|
||||||
|
BASE_DIR: 'C:\\Users\\Drackxus\\Documents\\NODE\\migracion',
|
||||||
|
ARCHIVOS: 'C:\\Users\\Drackxus\\Documents\\NODE\\migracion\\archivos',
|
||||||
|
CREDENTIALS: url_cred
|
||||||
|
},
|
||||||
|
DRIVE: {
|
||||||
|
FOLDER_ID: '1bjEaxLFkv4toUt0SeUz_HqrvIWAI2Xv5',
|
||||||
|
SCOPES: [
|
||||||
|
'https://www.googleapis.com/auth/drive',
|
||||||
|
'https://www.googleapis.com/auth/spreadsheets'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
PLATFORMS: {
|
||||||
|
USCIS: {
|
||||||
|
URL: 'https://egov.uscis.gov/es',
|
||||||
|
TYPE: 'uscis'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Inicialización de Google APIs
|
||||||
|
const auth = new google.auth.GoogleAuth({
|
||||||
|
keyFile: CONFIG.PATHS.CREDENTIALS,
|
||||||
|
scopes: CONFIG.DRIVE.SCOPES
|
||||||
|
});
|
||||||
|
|
||||||
|
const sheets = google.sheets({ version: 'v4', auth });
|
||||||
|
const drive = google.drive({ version: 'v3', auth });
|
||||||
|
|
||||||
|
let browser; // Variable global para el navegador
|
||||||
|
|
||||||
|
// Funciones de Google Sheets
|
||||||
|
async function listarArchivosEnCarpeta(folderId) {
|
||||||
|
const res = await drive.files.list({
|
||||||
|
q: `'${folderId}' in parents and mimeType='application/vnd.google-apps.spreadsheet' and name='base_uscis'`,
|
||||||
|
fields: '*'
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`${res.data.files.length} archivo(s) encontrados con el nombre "base_uscis"`);
|
||||||
|
|
||||||
|
return res.data.files;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function obtenerDatosHoja(spreadsheetId) {
|
||||||
|
const response = await sheets.spreadsheets.values.get({
|
||||||
|
spreadsheetId,
|
||||||
|
range: 'A:H', // Ajusta el rango según tus necesidades
|
||||||
|
});
|
||||||
|
return response.data.values;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function actualizarCelda(spreadsheetId, range, values) {
|
||||||
|
try {
|
||||||
|
await sheets.spreadsheets.values.update({
|
||||||
|
spreadsheetId,
|
||||||
|
range,
|
||||||
|
valueInputOption: 'USER_ENTERED',
|
||||||
|
requestBody: {
|
||||||
|
values: [values]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error al actualizar celda:', error.message);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Funciones de manejo del navegador
|
||||||
|
async function cerrarChromeDebugging() {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
if (process.platform === 'win32') {
|
||||||
|
exec('wmic process where "commandline like \'%--remote-debugging-port=9223%\'" call terminate', (error) => {
|
||||||
|
if (error) {
|
||||||
|
console.log('⚠️ No se encontraron instancias de Chrome debugging');
|
||||||
|
} else {
|
||||||
|
console.log('🔒 Chrome debugging cerrado correctamente');
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
exec("pkill -f 'chrome.*--remote-debugging-port=9223'", () => {
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function iniciarChrome(url) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
const chromeProcess = exec(
|
||||||
|
`start chrome `
|
||||||
|
+ `--remote-debugging-port=9223 `
|
||||||
|
+ `--no-sandbox `
|
||||||
|
+ `--disable-setuid-sandbox `
|
||||||
|
+ `--disable-background-timer-throttling `
|
||||||
|
+ `--disable-renderer-backgrounding `
|
||||||
|
+ `--disable-backgrounding-occluded-windows `
|
||||||
|
+ `--user-data-dir="C:\\temp\\chrome_debug_temp_uscis" `
|
||||||
|
+ `"${url}"`,
|
||||||
|
(error) => {
|
||||||
|
if (error) {
|
||||||
|
console.log('⚠️ Error al iniciar Chrome:', error);
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function initBrowser(url) {
|
||||||
|
try {
|
||||||
|
await cerrarChromeDebugging();
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||||
|
|
||||||
|
console.log('🌐 Iniciando Chrome con debugging...');
|
||||||
|
await iniciarChrome(url);
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 8000)); // Aumentado a 8 segundos
|
||||||
|
|
||||||
|
console.log('🔍 Intentando conectar con Chrome...');
|
||||||
|
const webSocketDebuggerUrl = await getWebSocketUrl();
|
||||||
|
|
||||||
|
console.log('✅ Conexión establecida con Chrome');
|
||||||
|
return await puppeteer.connect({
|
||||||
|
browserWSEndpoint: webSocketDebuggerUrl,
|
||||||
|
defaultViewport: null
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Error al inicializar el navegador:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getWebSocketUrl() {
|
||||||
|
let retries = 10; // Aumentado a 15 intentos
|
||||||
|
while (retries > 0) {
|
||||||
|
try {
|
||||||
|
const response = await fetch('http://localhost:9223/json/version');
|
||||||
|
if (!response.ok) throw new Error('No se pudo obtener la versión del navegador');
|
||||||
|
const json = await response.json();
|
||||||
|
if (json.webSocketDebuggerUrl) {
|
||||||
|
return json.webSocketDebuggerUrl;
|
||||||
|
}
|
||||||
|
throw new Error('URL de WebSocket no encontrada');
|
||||||
|
} catch (err) {
|
||||||
|
console.log(`🔄 Reintentando conexión a Chrome... (intentos restantes: ${retries})`);
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 2000)); // Aumentado a 4 segundos
|
||||||
|
retries--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Error('No se pudo conectar a Chrome después de varios intentos');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Funciones de utilidad
|
||||||
|
async function delay(ms) {
|
||||||
|
return new Promise(resolve => setTimeout(resolve, ms));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Funciones de procesamiento USCIS
|
||||||
|
async function procesarCasoUSCIS(page, element, spreadsheetId, intentos = 1) {
|
||||||
|
const MAX_INTENTOS = 3;
|
||||||
|
|
||||||
|
try {
|
||||||
|
console.log(`⌛ Consultando caso USCIS... (Intento ${intentos}/${MAX_INTENTOS})`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await page.goto(CONFIG.PLATFORMS.USCIS.URL, {
|
||||||
|
waitUntil: 'domcontentloaded',
|
||||||
|
timeout: 20000
|
||||||
|
});
|
||||||
|
await page.waitForSelector('#receipt_number', { timeout: 10000 });
|
||||||
|
} catch (navigationError) {
|
||||||
|
console.log(' ⚠️ Error de navegación o campo no encontrado, reintentando...');
|
||||||
|
if (intentos < MAX_INTENTOS) {
|
||||||
|
return await procesarCasoUSCIS(page, element, spreadsheetId, intentos + 1);
|
||||||
|
} else {
|
||||||
|
throw new Error('No se pudo acceder a la página después de varios intentos');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Intentar llenar el campo y hacer clic
|
||||||
|
await page.type('#receipt_number', element.valor);
|
||||||
|
await delay(1000);
|
||||||
|
await page.click('::-p-text(Verifique Estatus)');
|
||||||
|
await delay(2000);
|
||||||
|
// Esperar a que se complete la acción
|
||||||
|
|
||||||
|
// page.waitForSelector('.errorMessage', { timeout: 5000 }),
|
||||||
|
// page.waitForSelector('.conditionalLanding', { timeout: 5000 })
|
||||||
|
|
||||||
|
|
||||||
|
// Verificar el resultado
|
||||||
|
const errorMessage = await page.$('.errorMessage', { timeout: 5000 });
|
||||||
|
if (errorMessage) {
|
||||||
|
console.log(' ⚠️ Caso no válido');
|
||||||
|
await actualizarCelda(
|
||||||
|
spreadsheetId,
|
||||||
|
`G${element.fila}`,
|
||||||
|
['El número de recibo ingresado no es válido, intente nuevamente.']
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
const [titulo, descripcion] = await Promise.all([
|
||||||
|
page.$eval('.conditionalLanding h2', el => el.innerText),
|
||||||
|
page.$eval('.conditionalLanding p', el => el.innerText)
|
||||||
|
]);
|
||||||
|
|
||||||
|
console.log(' ✅ Información obtenida');
|
||||||
|
console.log(` 📌 Estado: ${titulo}`);
|
||||||
|
|
||||||
|
await actualizarCelda(
|
||||||
|
spreadsheetId,
|
||||||
|
`G${element.fila}:H${element.fila}`,
|
||||||
|
[titulo, descripcion]
|
||||||
|
);
|
||||||
|
} catch (dataError) {
|
||||||
|
console.error(' ❌ Error al obtener datos de la página:', dataError);
|
||||||
|
throw dataError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await delay(1000);
|
||||||
|
return true; // Indica que el proceso fue exitoso
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error(' ❌ Error procesando caso USCIS:', error);
|
||||||
|
|
||||||
|
if (intentos < MAX_INTENTOS) {
|
||||||
|
console.log(` 🔄 Reintentando... (${intentos}/${MAX_INTENTOS})`);
|
||||||
|
return await procesarCasoUSCIS(page, element, spreadsheetId, intentos + 1);
|
||||||
|
} else {
|
||||||
|
console.log(' ⚠️ Se agotaron los intentos o error no recuperable');
|
||||||
|
await actualizarCelda(
|
||||||
|
spreadsheetId,
|
||||||
|
`G${element.fila}`,
|
||||||
|
['Error al procesar el caso. Por favor, intente más tarde.']
|
||||||
|
);
|
||||||
|
return false; // Indica que el proceso falló
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Modificar la función procesarArchivo para manejar mejor la reconexión de Chrome
|
||||||
|
async function procesarArchivo(archivo) {
|
||||||
|
console.log('\n🔍 Analizando archivo:', archivo.name);
|
||||||
|
const datos = await obtenerDatosHoja(archivo.id);
|
||||||
|
const platform_type = 'uscis';
|
||||||
|
const platform = CONFIG.PLATFORMS[platform_type.toUpperCase()].URL;
|
||||||
|
|
||||||
|
// const filasAProcesar = datos.slice(1).map((row, index) => ({
|
||||||
|
// valor: row[4],
|
||||||
|
// fila: index + 2,
|
||||||
|
// tieneValor: !row[5],
|
||||||
|
// ultimaConsulta: row[5] || ''
|
||||||
|
// })).filter(row => {
|
||||||
|
// if (!row.ultimaConsulta) return true;
|
||||||
|
// const fechaUltimaConsulta = new Date(row.ultimaConsulta);
|
||||||
|
// const ahora = new Date();
|
||||||
|
// const diferenciaHoras = (ahora - fechaUltimaConsulta) / (1000 * 60 * 60);
|
||||||
|
// return diferenciaHoras > 1;
|
||||||
|
// });
|
||||||
|
|
||||||
|
const filasAProcesar = datos.slice(1)
|
||||||
|
.map((row, index) => ({
|
||||||
|
valor: row[4], // Columna 5 (Valor a consultar)
|
||||||
|
fila: index + 2, // Número de fila real
|
||||||
|
ultimaConsulta: row[5], // Columna 6 (Fecha de última consulta)
|
||||||
|
resultado: row[6] // Columna 7 (Resultado)
|
||||||
|
}))
|
||||||
|
.filter(row => {
|
||||||
|
// Priorizar si la columna G (resultado) está vacía
|
||||||
|
if (!row.resultado) return true;
|
||||||
|
|
||||||
|
// Si la columna G no está vacía, verificar la fecha en la columna F
|
||||||
|
if (!row.ultimaConsulta) return true; // Si no hay fecha en F, también se procesa (aunque G no esté vacía)
|
||||||
|
|
||||||
|
// Parse date in Spanish format DD/MM/YYYY
|
||||||
|
const [date, time] = row.ultimaConsulta.split(', ');
|
||||||
|
const [day, month, year] = date.split('/');
|
||||||
|
const [hours, minutes, seconds] = time.split(':');
|
||||||
|
|
||||||
|
const fechaUltimaConsulta = new Date(year, month - 1, day, hours, minutes, seconds);
|
||||||
|
const ahora = new Date();
|
||||||
|
|
||||||
|
// Calculate hours difference
|
||||||
|
const diferenciaHoras = (ahora - fechaUltimaConsulta) / (1000 * 60 * 60);
|
||||||
|
|
||||||
|
// For future dates, return false to skip processing
|
||||||
|
if (fechaUltimaConsulta > ahora) return false;
|
||||||
|
|
||||||
|
return diferenciaHoras > 1; // Process only if more than 1 hour has passed
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(filasAProcesar);
|
||||||
|
|
||||||
|
|
||||||
|
console.log(`📊 Total de filas a procesar: ${filasAProcesar.length}`);
|
||||||
|
|
||||||
|
if (filasAProcesar.length > 0) {
|
||||||
|
console.log('🌐 Iniciando navegador...');
|
||||||
|
let browser = await initBrowser(platform);
|
||||||
|
let page = (await browser.pages())[0];
|
||||||
|
let fallosConsecutivos = 0;
|
||||||
|
const MAX_FALLOS_CONSECUTIVOS = 3;
|
||||||
|
|
||||||
|
let procesadas = 0;
|
||||||
|
for (const element of filasAProcesar) {
|
||||||
|
procesadas++;
|
||||||
|
console.log(`\n⏳ Procesando fila ${element.fila} (${procesadas}/${filasAProcesar.length})`);
|
||||||
|
console.log(`📝 Valor a consultar: ${element.valor}`);
|
||||||
|
|
||||||
|
// Guardar la fecha y hora actual
|
||||||
|
const fechaHoraActual = new Date().toLocaleString('es-ES', {
|
||||||
|
year: 'numeric',
|
||||||
|
month: '2-digit',
|
||||||
|
day: '2-digit',
|
||||||
|
hour: '2-digit',
|
||||||
|
minute: '2-digit',
|
||||||
|
second: '2-digit'
|
||||||
|
});
|
||||||
|
|
||||||
|
// Actualizar la marca de tiempo en la columna F y limpiar las columnas G y H
|
||||||
|
await Promise.all([
|
||||||
|
actualizarCelda(
|
||||||
|
archivo.id,
|
||||||
|
`F${element.fila}`,
|
||||||
|
[fechaHoraActual]
|
||||||
|
),
|
||||||
|
actualizarCelda(
|
||||||
|
archivo.id,
|
||||||
|
`G${element.fila}:H${element.fila}`,
|
||||||
|
['', '']
|
||||||
|
)
|
||||||
|
]);
|
||||||
|
|
||||||
|
const resultado = await procesarCasoUSCIS(page, element, archivo.id);
|
||||||
|
|
||||||
|
if (!resultado) {
|
||||||
|
fallosConsecutivos++;
|
||||||
|
if (fallosConsecutivos >= MAX_FALLOS_CONSECUTIVOS) {
|
||||||
|
console.log('🔄 Reiniciando navegador debido a fallos consecutivos...');
|
||||||
|
await browser.close();
|
||||||
|
await cerrarChromeDebugging();
|
||||||
|
await delay(2000);
|
||||||
|
|
||||||
|
browser = await initBrowser(platform);
|
||||||
|
page = (await browser.pages())[0];
|
||||||
|
fallosConsecutivos = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fallosConsecutivos = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('\n✅ Proceso completado para el archivo:', archivo.name);
|
||||||
|
await browser.close();
|
||||||
|
} else {
|
||||||
|
console.log('ℹ️ No hay filas para procesar en este archivo');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Función para cerrar el navegador y la aplicación
|
||||||
|
async function cerrarTodo() {
|
||||||
|
if (browser) {
|
||||||
|
await browser.close(); // Cerrar el navegador si está abierto
|
||||||
|
}
|
||||||
|
console.log('🔄 Cerrando Chrome debugging y finalizando...');
|
||||||
|
await cerrarChromeDebugging();
|
||||||
|
process.exit();
|
||||||
|
app.quit(); // Cerrar la aplicación Electron
|
||||||
|
}
|
||||||
|
|
||||||
|
// Manejar la señal SIGINT (Ctrl + C)
|
||||||
|
process.on('SIGINT', async () => {
|
||||||
|
console.log('Recibida señal de interrupción (Ctrl + C)');
|
||||||
|
await cerrarTodo();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Función principal
|
||||||
|
async function procesarArchivos() {
|
||||||
|
try {
|
||||||
|
console.log('🚀 Iniciando proceso...');
|
||||||
|
const archivos = await listarArchivosEnCarpeta(CONFIG.DRIVE.FOLDER_ID);
|
||||||
|
console.log(`📁 Total de archivos encontrados: ${archivos.length}`);
|
||||||
|
|
||||||
|
let procesados = 0;
|
||||||
|
for (const archivo of archivos) {
|
||||||
|
procesados++;
|
||||||
|
console.log(`\n📌 Procesando archivo ${procesados}/${archivos.length}: ${archivo.name}`);
|
||||||
|
await procesarArchivo(archivo);
|
||||||
|
}
|
||||||
|
console.log('\n🎉 Proceso completado exitosamente!');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Error en el proceso:', error);
|
||||||
|
} finally {
|
||||||
|
await cerrarTodo(); // Asegúrate de cerrar todo al final
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ejecutar el proceso
|
||||||
|
app.on('ready', () => {
|
||||||
|
console.log('Aplicación Electron está lista y en ejecución sin ventana.');
|
||||||
|
procesarArchivos();
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user