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 descriptions = document.DocumentNode.Descendants("meta")
.Where(p => p.GetAttributeValue("name", string.Empty).Equals("description", StringComparison.InvariantCultureIgnoreCase));
var description = descriptions.FirstOrDefault()?.GetAttributeValue("content", string.Empty);
if (description.HasValue()) {
report.Description = description;
} else {
var title = document.DocumentNode.Descendants("title").FirstOrDefault()?.InnerText;
report.Description = title;
}
} 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);
}
}