using System; namespace JobTrackerApi.Services.JobImport.Plugins; public sealed class FinnPlugin : IJobSitePlugin { public bool CanHandle(string url) => url.Contains("finn.no", StringComparison.OrdinalIgnoreCase); public JobImportResult Parse(string html, string url) { var meta = HtmlExtract.ReadMeta(html); var title = meta.TryGetValue("og:title", out var t) ? t : HtmlExtract.ReadTitle(html); var desc = meta.TryGetValue("og:description", out var d) ? d : null; var company = ExtractCompanyFromTitle(title); return new JobImportResult { SourceUrl = url, Title = CleanTitle(title), Company = company, Location = meta.TryGetValue("job:location", out var loc) ? loc : null, Description = HtmlExtract.ToPlainText(desc), Parser = "finn", Success = !string.IsNullOrWhiteSpace(title) && !string.IsNullOrWhiteSpace(desc), }; } private static string? CleanTitle(string? title) { if (string.IsNullOrWhiteSpace(title)) return null; // FINN often appends " - FINN.no" etc. var s = title.Replace(" - FINN.no", "", StringComparison.OrdinalIgnoreCase).Trim(); return s.Length == 0 ? title : s; } private static string? ExtractCompanyFromTitle(string? title) { if (string.IsNullOrWhiteSpace(title)) return null; // Common pattern: "Role hos Company" / "Role - Company" var s = title; var idx = s.LastIndexOf(" - ", StringComparison.Ordinal); if (idx > 0 && idx < s.Length - 3) return s[(idx + 3)..].Trim(); idx = s.LastIndexOf(" hos ", StringComparison.OrdinalIgnoreCase); if (idx > 0 && idx < s.Length - 5) return s[(idx + 5)..].Trim(); return null; } }