Add XML doc to all service interfaces and implementations (#26)
- Update CLAUDE.md: replace incorrect 'no XML doc on internal code' rule with the correct convention (XML doc on all public methods and non-trivial private/protected helpers) - Restore /// <summary> on FileDownloadController private helpers (HandleRangeRequest, StreamRangeAsync) - Add full XML doc to all service contracts: ICaptchaVerifier, IEmailSender, ICvMatcherService, IJobTextExtractor, IJobTokenService, IDocumentClassifier, IRagService, ITextChunker, ITextExtractor, IEmailTemplateService, ITemplateService - Add /// <summary> and /// <inheritdoc /> to all concrete service classes and their methods: RecaptchaVerifier, EmailApiEmailSender, SmtpEmailDispatcher, CvMatcherService, JobTextExtractor, JobTokenService, RagService, DocumentClassifier, TextChunker, TextExtractor, HtmlJobSearcher, CvSearchEmailSender, CvSearchJobTask, EmailTemplateService, DbTemplateService Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -7,6 +7,10 @@ using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace CvSearchJob.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Sends job search results emails to the session user and the operator copy address,
|
||||
/// with an optional CV PDF attachment.
|
||||
/// </summary>
|
||||
public sealed class CvSearchEmailSender
|
||||
{
|
||||
private readonly IEmailApiClient _emailApi;
|
||||
@@ -23,6 +27,16 @@ public sealed class CvSearchEmailSender
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Builds and sends the job search results email.
|
||||
/// Resolves the recipient list from <paramref name="toEmail"/> and the operator copy address
|
||||
/// stored in the email template. Does nothing when no recipients can be resolved.
|
||||
/// </summary>
|
||||
/// <param name="toEmail">Primary recipient (the user who triggered the search).</param>
|
||||
/// <param name="attachmentFileName">Relative filename of the CV PDF to attach, or <c>null</c>.</param>
|
||||
/// <param name="results">Ranked list of job search results to include in the email body.</param>
|
||||
/// <param name="language">Two-letter language code for template rendering.</param>
|
||||
/// <param name="ct">Cancellation token.</param>
|
||||
public async Task SendResultsAsync(
|
||||
string toEmail,
|
||||
string? attachmentFileName,
|
||||
@@ -64,6 +78,10 @@ public sealed class CvSearchEmailSender
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders the HTML email body from the results list.
|
||||
/// Returns the empty-results template when no results are present.
|
||||
/// </summary>
|
||||
private string BuildBody(IReadOnlyList<JobSearchResultEntity> results, string language)
|
||||
{
|
||||
if (results.Count == 0)
|
||||
@@ -92,6 +110,10 @@ public sealed class CvSearchEmailSender
|
||||
("items", items.ToString()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to deserialise the stored result JSON into a <see cref="JobMatchResponse"/>.
|
||||
/// Returns <c>null</c> on parse failure so the email still renders without a summary.
|
||||
/// </summary>
|
||||
private static JobMatchResponse? TryParseResult(string json)
|
||||
{
|
||||
try
|
||||
|
||||
@@ -5,6 +5,11 @@ using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace CvSearchJob.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Config-driven HTML scraper that fetches a provider's job listing page and extracts matching job URLs.
|
||||
/// Uses a two-stage anchor filter: href must contain the provider's link pattern, and anchor text must
|
||||
/// contain at least one CV keyword.
|
||||
/// </summary>
|
||||
public sealed class HtmlJobSearcher
|
||||
{
|
||||
private readonly HttpClient _http;
|
||||
@@ -18,6 +23,15 @@ public sealed class HtmlJobSearcher
|
||||
_http.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (compatible; MyAi.ro CV-Search/1.0)");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetches the provider's search result page for the combined initial + CV keywords, parses all anchor
|
||||
/// tags, applies the two-stage filter, and returns up to <see cref="JobProviderConfig.MaxResults"/> absolute URLs.
|
||||
/// Returns an empty list when the HTTP request fails rather than throwing.
|
||||
/// </summary>
|
||||
/// <param name="provider">Provider configuration including search URL template, link filter, and result cap.</param>
|
||||
/// <param name="cvKeywords">Keywords extracted from the user's CV to inject into the search query.</param>
|
||||
/// <param name="ct">Cancellation token.</param>
|
||||
/// <returns>Deduplicated list of absolute job page URLs (query string stripped).</returns>
|
||||
public async Task<IReadOnlyList<string>> SearchJobUrlsAsync(
|
||||
JobProviderConfig provider,
|
||||
IReadOnlyList<string> cvKeywords,
|
||||
|
||||
Reference in New Issue
Block a user