const fs = require('fs'); const { Pool } = require('pg'); const pool = new Pool({ connectionString: "postgres://dtic_user:dtic_pass_2026@localhost:5433/dtic_bitacoras" }); async function syncFile(filePath) { const content = fs.readFileSync(filePath, 'utf8'); const lines = content.split('\n'); const dateStr = filePath.match(/(\d{4}-\d{2}-\d{2})\.md/)[1]; console.log(`Sincronizando bitácora: ${dateStr}`); // Asegurar bitácora const bResult = await pool.query( 'INSERT INTO bitacoras.bitacoras (fecha) VALUES ($1) ON CONFLICT (fecha) DO UPDATE SET fecha = EXCLUDED.fecha RETURNING id', [dateStr] ); const bitacoraId = bResult.rows[0].id; // Obtener mapeo de nodos const { rows: nodos } = await pool.query('SELECT id, nombre FROM bitacoras.nodos'); const nodoMap = {}; nodos.forEach(n => { nodoMap[n.nombre] = n.id; }); // Limpiar entradas previas await pool.query('DELETE FROM bitacoras.entradas WHERE bitacora_id = $1', [bitacoraId]); let currentNodoId = null; let inDetailedActivities = false; let entriesFound = 0; for (let line of lines) { // Detectar inicio de sección de actividades detalladas if (line.includes('Actividades Detalladas')) { inDetailedActivities = true; continue; } if (!inDetailedActivities) continue; // Detectar cambio de nodo if (line.startsWith('### ')) { const nodoName = line.replace('### ', '').trim().split(' ')[0]; currentNodoId = nodoMap[nodoName] || null; if (currentNodoId) console.log(`Cambiando a nodo: ${nodoName} (ID: ${currentNodoId})`); continue; } if (!currentNodoId) continue; // Detectar entrada de tabla const regex = /\|\s*(\d{2}:\d{2})\s*\|\s*(\d{2}:\d{2})\s*\|\s*(.*?)\s*\|\s*(.*?)\s*\|/; const match = line.match(regex); if (match) { let inicio = match[1]; let fin = match[2]; let descRaw = match[3]; let estadoRaw = match[4]; const esIA = descRaw.includes('(IA)'); let descripcion = descRaw.replace('(IA)', '').replace(/\*\*/g, '').replace(/__/g, '').trim(); // A veces el MD tiene ** al principio if (descripcion.startsWith('**')) descripcion = descripcion.substring(2); const statusMatch = estadoRaw.match(/\[([A-Z])\] (.*)/); const modo = statusMatch ? statusMatch[1] : 'P'; const estado = statusMatch ? statusMatch[2] : estadoRaw; await pool.query( `INSERT INTO bitacoras.entradas (inicio, fin, descripcion, estado, modo, es_ia, bitacora_id, nodo_id) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)`, [inicio, fin, descripcion, estado, modo, esIA, bitacoraId, currentNodoId] ); entriesFound++; } } console.log(`Sincronización finalizada. Entradas cargadas: ${entriesFound}`); await pool.end(); } const file = process.argv[2]; if (!file) { console.error('Uso: node sync_bitacora.js '); process.exit(1); } syncFile(file).catch(err => { console.error(err); process.exit(1); });