import { clean, fetchHtml, slugify } from "./http";
import type { ScrapedJob, Scraper } from "./types";
// Optius publishes an official RSS feed with region/field filters, so no HTML scraping is needed.
// Build a feed URL at https://www.optius.com/rss/ (its IDs differ from the search page's IDs).
const tag = (xml: string, name: string) => new RegExp(`<${name}[^>]*>([\\s\\S]*?)${name}>`).exec(xml)?.[1];
const text = (s: string | undefined) => clean((s ?? "").replace(/^$/, "$1"));
export function parseOptiusFeed(xml: string): ScrapedJob[] {
return [...xml.matchAll(/- ([\s\S]*?)<\/item>/g)]
.map((m): ScrapedJob | null => {
const item = m[1]!;
const url = text(tag(item, "link") ?? tag(item, "guid"));
const id = /-(\d+)-\1\/?$/.exec(url)?.[1] ?? /-(\d+)\/?$/.exec(url)?.[1];
const title = text(tag(item, "title"));
if (!id || !title) return null;
const pubDate = tag(item, "pubDate");
return {
externalId: id,
title,
url,
company: text(tag(item, "employer")) || undefined,
tags: [...item.matchAll(/]*)?>([\s\S]*?)<\/field>/g)].map((f) => text(f[1])).filter(Boolean),
postedAt: pubDate ? new Date(pubDate).toISOString() : undefined,
};
})
.filter((j): j is ScrapedJob => j !== null);
}
/** Scraper for an optius.com RSS feed, e.g. "https://www.optius.com/rss/?regija=7&podrocje=7". */
export function optius(label: string, feedUrl: string): Scraper {
return {
id: `optius-${label.normalize("NFD").replace(/[̀-ͯ]/g, "").replace(/[^A-Za-z0-9]+/g, "-").replace(/^-|-$/g, "").toLowerCase()}`,
name: `Optius (${label})`,
async scrape() {
const xml = await fetchHtml(feedUrl);
if (!xml.includes("