221 lines
7.3 KiB
JavaScript
221 lines
7.3 KiB
JavaScript
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';
|
|
import os from 'os';
|
|
|
|
console.log(app.getAppPath());
|
|
|
|
let url_cred = app.getAppPath().replace('app.asar', '');
|
|
url_cred = url_cred + '\\credenciales.json';
|
|
console.log(url_cred);
|
|
|
|
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'
|
|
}
|
|
}
|
|
};
|
|
|
|
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 });
|
|
|
|
async function listarArchivosEnCarpeta(folderId) {
|
|
const res = await drive.files.list({
|
|
q: `'${folderId}' in parents and mimeType='application/vnd.google-apps.spreadsheet' and name='base_pruebas'`,
|
|
fields: '*'
|
|
});
|
|
return res.data.files;
|
|
}
|
|
|
|
async function obtenerDatosHoja(spreadsheetId) {
|
|
const response = await sheets.spreadsheets.values.get({
|
|
spreadsheetId,
|
|
range: 'A:H',
|
|
});
|
|
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;
|
|
}
|
|
}
|
|
|
|
async function cerrarChromeDebugging() {
|
|
return new Promise((resolve) => {
|
|
if (process.platform === 'win32') {
|
|
exec('wmic process where "commandline like \'%--remote-debugging-port=%\'" call terminate', () => resolve());
|
|
} else {
|
|
exec("pkill -f 'chrome.*--remote-debugging-port='", () => resolve());
|
|
}
|
|
});
|
|
}
|
|
|
|
async function iniciarChromeConPuerto(url, port, userDir) {
|
|
return new Promise((resolve) => {
|
|
const chromeProcess = exec(
|
|
`start chrome ` +
|
|
`--remote-debugging-port=${port} ` +
|
|
`--no-sandbox ` +
|
|
`--disable-setuid-sandbox ` +
|
|
`--user-data-dir="${userDir}" ` +
|
|
`"${url}"`,
|
|
() => resolve()
|
|
);
|
|
});
|
|
}
|
|
|
|
async function getWebSocketUrl(port) {
|
|
const maxRetries = 15;
|
|
for (let i = 0; i < maxRetries; i++) {
|
|
try {
|
|
const response = await fetch(`http://localhost:${port}/json/version`);
|
|
const json = await response.json();
|
|
if (json.webSocketDebuggerUrl) return json.webSocketDebuggerUrl;
|
|
} catch {}
|
|
await new Promise(res => setTimeout(res, 2000));
|
|
}
|
|
throw new Error(`No se pudo conectar a Chrome en el puerto ${port}`);
|
|
}
|
|
|
|
async function initBrowserEnPuerto(url, port, userDir) {
|
|
await cerrarChromeDebugging();
|
|
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
await iniciarChromeConPuerto(url, port, userDir);
|
|
await new Promise(resolve => setTimeout(resolve, 8000));
|
|
const webSocketDebuggerUrl = await getWebSocketUrl(port);
|
|
return await puppeteer.connect({
|
|
browserWSEndpoint: webSocketDebuggerUrl,
|
|
defaultViewport: null
|
|
});
|
|
}
|
|
|
|
async function delay(ms) {
|
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
}
|
|
|
|
async function procesarCasoUSCIS(page, element, spreadsheetId, intentos = 1) {
|
|
const MAX_INTENTOS = 3;
|
|
try {
|
|
await page.goto(CONFIG.PLATFORMS.USCIS.URL, { waitUntil: 'domcontentloaded', timeout: 20000 });
|
|
await page.waitForSelector('#receipt_number', { timeout: 10000 });
|
|
await page.type('#receipt_number', element.valor);
|
|
await delay(1000);
|
|
await page.click('::-p-text(Verifique Estatus)');
|
|
await delay(2000);
|
|
const errorMessage = await page.$('.errorMessage');
|
|
if (errorMessage) {
|
|
await actualizarCelda(spreadsheetId, `G${element.fila}`, ['El número de recibo ingresado no es válido']);
|
|
} else {
|
|
const [titulo, descripcion] = await Promise.all([
|
|
page.$eval('.conditionalLanding h2', el => el.innerText),
|
|
page.$eval('.conditionalLanding p', el => el.innerText)
|
|
]);
|
|
await actualizarCelda(spreadsheetId, `G${element.fila}:H${element.fila}`, [titulo, descripcion]);
|
|
}
|
|
return true;
|
|
} catch (error) {
|
|
if (intentos < MAX_INTENTOS) {
|
|
return await procesarCasoUSCIS(page, element, spreadsheetId, intentos + 1);
|
|
} else {
|
|
await actualizarCelda(spreadsheetId, `G${element.fila}`, ['Error al procesar el caso']);
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
async function procesarArchivoEnGrupo(filas, archivo, port, userDir) {
|
|
const browser = await initBrowserEnPuerto(CONFIG.PLATFORMS.USCIS.URL, port, userDir);
|
|
const page = (await browser.pages())[0];
|
|
for (const element of filas) {
|
|
const fechaHoraActual = new Date().toLocaleString('es-ES', {
|
|
year: 'numeric', month: '2-digit', day: '2-digit',
|
|
hour: '2-digit', minute: '2-digit', second: '2-digit'
|
|
});
|
|
await Promise.all([
|
|
actualizarCelda(archivo.id, `F${element.fila}`, [fechaHoraActual]),
|
|
actualizarCelda(archivo.id, `G${element.fila}:H${element.fila}`, ['', ''])
|
|
]);
|
|
await procesarCasoUSCIS(page, element, archivo.id);
|
|
}
|
|
await browser.close();
|
|
}
|
|
|
|
async function procesarArchivo(archivo) {
|
|
const datos = await obtenerDatosHoja(archivo.id);
|
|
const filas = datos.slice(1).map((row, index) => ({
|
|
valor: row[4], fila: index + 2,
|
|
ultimaConsulta: row[5], resultado: row[6]
|
|
})).filter(row => !row.resultado || !row.ultimaConsulta || ((new Date() - new Date(row.ultimaConsulta)) / 3600000 > 1));
|
|
|
|
if (!filas.length) return;
|
|
|
|
const numProcesos = 4;
|
|
const chunkSize = Math.ceil(filas.length / numProcesos);
|
|
const grupos = Array.from({ length: numProcesos }, (_, i) => filas.slice(i * chunkSize, (i + 1) * chunkSize));
|
|
|
|
await Promise.all(grupos.map((grupo, i) => {
|
|
if (grupo.length === 0) return;
|
|
const port = 9224 + i;
|
|
const userDir = `C:/temp/chrome_debug_temp_migracion_${i}`;
|
|
return procesarArchivoEnGrupo(grupo, archivo, port, userDir);
|
|
}));
|
|
}
|
|
|
|
async function cerrarTodo() {
|
|
await cerrarChromeDebugging();
|
|
process.exit();
|
|
app.quit();
|
|
}
|
|
|
|
process.on('SIGINT', async () => {
|
|
console.log('Ctrl + C detectado');
|
|
await cerrarTodo();
|
|
});
|
|
|
|
async function procesarArchivos() {
|
|
const archivos = await listarArchivosEnCarpeta(CONFIG.DRIVE.FOLDER_ID);
|
|
for (const archivo of archivos) {
|
|
await procesarArchivo(archivo);
|
|
}
|
|
await cerrarTodo();
|
|
}
|
|
|
|
app.on('ready', () => {
|
|
procesarArchivos();
|
|
}); |