Files
rodado fb67c38edd chore: reorganize repo structure and update docs
- move temp scripts to scripts/, cv files to cv/, jobs.csv to results/
- update index.ts and recheck.ts CSV path to results/jobs.csv
- fix imports in scripts/ to use ../config.ts and ../fetch.ts
- update CLAUDE.md and README.md to reflect new structure
- add plans/ with LinkedIn post drafts
- update .gitignore: ignore results/, jobs/, cv binaries, .DS_Store
2026-06-03 16:01:32 +02:00

66 lines
2.0 KiB
TypeScript

#!/usr/bin/env bun
import { searches } from "./config.ts";
import { fetchJobs, SOFTWARE_TITLE_RE } from "./fetch.ts";
const CSV = "./results/jobs.csv";
const existingIds = new Set<string>();
try {
const text = await Bun.file(CSV).text();
for (const line of text.split("\n").slice(1)) {
const id = line.match(/\/jobs\/view\/(\d+)\//)?.[1];
if (id) existingIds.add(id);
}
} catch { /* first run */ }
const missed: { title: string; company: string; link: string }[] = [];
const seenIds = new Set<string>();
for (const config of searches) {
console.log(`\n[${config.label}]`);
const all = await fetchJobs(config, { raw: true });
for (const job of all) {
if (!seenIds.has(job.id) && !existingIds.has(job.id) && !SOFTWARE_TITLE_RE.test(job.title)) {
seenIds.add(job.id);
missed.push({ title: job.title, company: job.company, link: job.link });
}
}
}
if (missed.length === 0) {
console.log("\nNo missed jobs — all new titles pass the filter.");
process.exit(0);
}
console.log(`\n── ${missed.length} new jobs currently filtered out ──\n`);
for (const j of missed) {
console.log(` ${j.title}`);
console.log(` ${j.company} ${j.link}`);
}
// Word frequency analysis to suggest keywords
const STOP = new Set([
"and", "or", "of", "the", "a", "an", "in", "for", "to", "at", "by",
"with", "on", "as", "is", "its", "be", "are", "was", "were", "our",
"your", "this", "that", "we", "you", "all", "new", "use",
]);
const wordCounts = new Map<string, number>();
for (const { title } of missed) {
const words = title.match(/\b[a-zA-Z]{3,}\b/g) ?? [];
for (const w of words) {
const key = w.toLowerCase();
if (!STOP.has(key)) wordCounts.set(key, (wordCounts.get(key) ?? 0) + 1);
}
}
const suggestions = [...wordCounts.entries()]
.sort((a, b) => b[1] - a[1])
.filter(([, n]) => n >= 1)
.slice(0, 20);
console.log("\n── Suggested keywords to consider ──\n");
for (const [word, count] of suggestions) {
console.log(` "${word}" — ${count} title${count > 1 ? "s" : ""}`);
}