using HtmlAgilityPack; using IOL.BookmarkThing.Server.Api.Internal.Dtos; namespace IOL.BookmarkThing.Server.Api.Internal; public class GetSiteReportRoute : RouteBaseInternalAsync.WithRequest.WithActionResult { private readonly HttpClient _client; private readonly ILogger _logger; private readonly AppDbContext _context; public GetSiteReportRoute(HttpClient client, ILogger logger, AppDbContext context) { _client = client; _logger = logger; _context = context; } [ApiVersionNeutral] [ApiExplorerSettings(IgnoreApi = true)] [HttpPost("~/v{version:apiVersion}/site-report")] public override async Task HandleAsync(GetSiteReportRequest request, CancellationToken cancellationToken = default) { var report = new SiteReportDto(); var exists = _context.Entries.Any(c => c.Url == request.Url && c.UserId == LoggedInUser.Id); if (exists) { report.Duplicate = true; return Ok(report); } try { var http_request = await _client.GetAsync(request.Url, cancellationToken); if (http_request.IsSuccessStatusCode) { try { var document = new HtmlDocument(); document.Load(await http_request.Content.ReadAsStreamAsync(cancellationToken)); var htmlNodes = document.DocumentNode.Descendants("meta") .Where(p => p.GetAttributeValue("name", string.Empty).Equals("description", StringComparison.InvariantCultureIgnoreCase)); report.Description = htmlNodes.FirstOrDefault()?.GetAttributeValue("content", string.Empty); } catch (Exception e) { _logger.LogWarning(e, "An error occured when parsing site for site report"); } } else { report.Unreachable = true; } } catch (Exception e) { if (e is HttpRequestException) { report.Unreachable = true; } _logger.LogError(e, "An error occured when getting external site for site report"); } return Ok(report); } }