Fase 5: Implementada la configuración dinámica. Implementado el scraping web.

This commit is contained in:
2025-10-28 12:56:42 -03:00
parent 9be62937bd
commit 75d06820aa
11 changed files with 395 additions and 21 deletions

View File

@@ -82,4 +82,70 @@ public class TitularRepositorio
return false;
}
}
public async Task SincronizarDesdeScraping(List<ArticuloScrapeado> articulosScrapeados, int limiteTotal)
{
using var connection = CreateConnection();
await connection.OpenAsync();
using var transaction = connection.BeginTransaction();
try
{
// 1. Obtener las URLs que ya tenemos en la base de datos
var urlsEnDb = (await connection.QueryAsync<string>(
"SELECT UrlFuente FROM Titulares WHERE UrlFuente IS NOT NULL", transaction: transaction))
.ToHashSet();
// 2. Filtrar para quedarnos solo con los artículos que son realmente nuevos
var articulosNuevos = articulosScrapeados
.Where(a => !urlsEnDb.Contains(a.UrlFuente))
.ToList();
if (articulosNuevos.Any())
{
var cantidadNuevos = articulosNuevos.Count;
// 3. Hacer espacio para los nuevos: empujamos todos los existentes hacia abajo
await connection.ExecuteAsync(
"UPDATE Titulares SET OrdenVisual = OrdenVisual + @cantidadNuevos",
new { cantidadNuevos },
transaction: transaction);
// 4. Insertar los nuevos artículos al principio (OrdenVisual 0, 1, 2...)
for (int i = 0; i < cantidadNuevos; i++)
{
var articulo = articulosNuevos[i];
var sqlInsert = @"
INSERT INTO Titulares (Texto, UrlFuente, ModificadoPorUsuario, EsEntradaManual, OrdenVisual, Tipo, Fuente)
VALUES (@Texto, @UrlFuente, 0, 0, @OrdenVisual, 'Scraped', 'eldia.com');
";
await connection.ExecuteAsync(sqlInsert, new
{
articulo.Texto,
articulo.UrlFuente,
OrdenVisual = i
}, transaction: transaction);
}
// 5. Purgar los más antiguos si superamos el límite, ignorando los manuales
var sqlDelete = @"
DELETE FROM Titulares
WHERE Id IN (
SELECT Id FROM Titulares
WHERE EsEntradaManual = 0
ORDER BY OrdenVisual DESC
OFFSET @limiteTotal ROWS
);
";
await connection.ExecuteAsync(sqlDelete, new { limiteTotal }, transaction: transaction);
}
transaction.Commit();
}
catch
{
transaction.Rollback();
throw; // Relanzamos la excepción para que el worker sepa que algo falló
}
}
}