From da6e9e9b8f0dee1e207264551a4fc5607059df88 Mon Sep 17 00:00:00 2001 From: dmolinari Date: Fri, 15 Aug 2025 18:13:10 -0300 Subject: [PATCH] Fix 1813 --- .../Services/CurlElectoralApiService.cs | 126 ++++++++++-------- 1 file changed, 69 insertions(+), 57 deletions(-) diff --git a/Elecciones-Web/src/Elecciones.Infrastructure/Services/CurlElectoralApiService.cs b/Elecciones-Web/src/Elecciones.Infrastructure/Services/CurlElectoralApiService.cs index ce33bb5..b5721c0 100644 --- a/Elecciones-Web/src/Elecciones.Infrastructure/Services/CurlElectoralApiService.cs +++ b/Elecciones-Web/src/Elecciones.Infrastructure/Services/CurlElectoralApiService.cs @@ -13,71 +13,83 @@ namespace Elecciones.Infrastructure.Services; // Implementación de emergencia que usa el comando 'curl' del sistema operativo public class CurlElectoralApiService : IElectoralApiService { - private readonly ILogger _logger; - private readonly IConfiguration _configuration; - private readonly string _baseUrl; + private readonly ILogger _logger; + private readonly IConfiguration _configuration; + private readonly string _baseUrl; - public CurlElectoralApiService(ILogger logger, IConfiguration configuration) + public CurlElectoralApiService(ILogger logger, IConfiguration configuration) + { + _logger = logger; + _configuration = configuration; + _baseUrl = _configuration["ElectoralApi__BaseUrl"] ?? ""; + } + + private async Task<(int, string)> ExecuteCurlCommand(string arguments) + { + var process = new Process { - _logger = logger; - _configuration = configuration; - _baseUrl = _configuration["ElectoralApi:BaseUrl"] ?? ""; + StartInfo = new ProcessStartInfo + { + FileName = "curl", + Arguments = arguments, + RedirectStandardOutput = true, + RedirectStandardError = true, + UseShellExecute = false, + CreateNoWindow = true, + } + }; + + process.Start(); + string output = await process.StandardOutput.ReadToEndAsync(); + string error = await process.StandardError.ReadToEndAsync(); + await process.WaitForExitAsync(); + + if (process.ExitCode != 0) + { + _logger.LogError("Error al ejecutar curl. Exit Code: {ExitCode}. Error: {Error}", process.ExitCode, error); + return (-1, error); } - private async Task<(int, string)> ExecuteCurlCommand(string arguments) + // Extraemos el código de estado HTTP del final del stderr si usamos -w + // (Simplificación: asumimos 200 si el ExitCode es 0) + return (200, output); + } + + public async Task GetAuthTokenAsync() + { + var username = _configuration["ElectoralApi__Username"]; + var password = _configuration["ElectoralApi__Password"]; // OJO: Verifica el nombre exacto de la variable en tu .env + var arguments = $"-s -H \"username: {username}\" -H \"password: {password}\" \"{_baseUrl}/api/createtoken\""; + + var (status, output) = await ExecuteCurlCommand(arguments); + if (status != 200) { - var process = new Process - { - StartInfo = new ProcessStartInfo - { - FileName = "curl", - Arguments = arguments, - RedirectStandardOutput = true, - RedirectStandardError = true, - UseShellExecute = false, - CreateNoWindow = true, - } - }; - - process.Start(); - string output = await process.StandardOutput.ReadToEndAsync(); - string error = await process.StandardError.ReadToEndAsync(); - await process.WaitForExitAsync(); - - if (process.ExitCode != 0) - { - _logger.LogError("Error al ejecutar curl. Exit Code: {ExitCode}. Error: {Error}", process.ExitCode, error); - return (-1, error); - } - - // Extraemos el código de estado HTTP del final del stderr si usamos -w - // (Simplificación: asumimos 200 si el ExitCode es 0) - return (200, output); + _logger.LogError("Curl recibió un código de estado no exitoso. Respuesta: {Output}", output); + return null; } - public async Task GetAuthTokenAsync() + try { - var username = _configuration["ElectoralApi:Username"]; - var password = _configuration["ElectoralApi:Password"]; - var arguments = $"-s -H \"username: {username}\" -H \"password: {password}\" \"{_baseUrl}/api/createtoken\""; - - var (status, output) = await ExecuteCurlCommand(arguments); - if (status != 200) return null; - - var tokenResponse = JsonSerializer.Deserialize(output); - return tokenResponse?.Data?.AccessToken; + var tokenResponse = JsonSerializer.Deserialize(output); + return tokenResponse?.Data?.AccessToken; } + catch (JsonException ex) + { + _logger.LogError(ex, "Falló la deserialización del JSON. La respuesta del servidor NO era un JSON válido. Respuesta recibida: {Output}", output); + return null; + } + } - // Implementa los demás métodos de la interfaz usando el mismo patrón - // ... - // Por ahora, solo necesitamos GetAuthTokenAsync para validar la conexión. - public Task?> GetCategoriasAsync(string authToken) => Task.FromResult?>(null); - public Task?> GetCatalogoCompletoAsync(string authToken) => Task.FromResult?>(null); - public Task?> GetAgrupacionesAsync(string authToken, string distritoId, int categoriaId) => Task.FromResult?>(null); - public Task GetResultadosAsync(string authToken, string distritoId, string seccionId, string municipioId) => Task.FromResult(null); - public Task GetBancasAsync(string authToken, string distritoId, string seccionId) => Task.FromResult(null); - public Task?> GetTelegramasTotalizadosAsync(string authToken, string distritoId, string seccionId) => Task.FromResult?>(null); - public Task GetTelegramaFileAsync(string authToken, string mesaId) => Task.FromResult(null); - public Task GetResumenAsync(string authToken, string distritoId) => Task.FromResult(null); - public Task GetEstadoRecuentoGeneralAsync(string authToken, string distritoId) => Task.FromResult(null); + // Implementa los demás métodos de la interfaz usando el mismo patrón + // ... + // Por ahora, solo necesitamos GetAuthTokenAsync para validar la conexión. + public Task?> GetCategoriasAsync(string authToken) => Task.FromResult?>(null); + public Task?> GetCatalogoCompletoAsync(string authToken) => Task.FromResult?>(null); + public Task?> GetAgrupacionesAsync(string authToken, string distritoId, int categoriaId) => Task.FromResult?>(null); + public Task GetResultadosAsync(string authToken, string distritoId, string seccionId, string municipioId) => Task.FromResult(null); + public Task GetBancasAsync(string authToken, string distritoId, string seccionId) => Task.FromResult(null); + public Task?> GetTelegramasTotalizadosAsync(string authToken, string distritoId, string seccionId) => Task.FromResult?>(null); + public Task GetTelegramaFileAsync(string authToken, string mesaId) => Task.FromResult(null); + public Task GetResumenAsync(string authToken, string distritoId) => Task.FromResult(null); + public Task GetEstadoRecuentoGeneralAsync(string authToken, string distritoId) => Task.FromResult(null); } \ No newline at end of file