feat: show the German/French drop count in the digest
Jobs rejected for German/French content never reach jobs.csv, so daily.ts had no way to see they existed — the digest silently under-reported how much the run actually looked at. index.ts now counts them across both the LinkedIn and extra-source paths and writes results/.lang-dropped.json; daily.ts reads it back, keyed on the digest date, and appends a count-only category. Count-only because there is no Row to list — these were dropped before ever being parsed.
This commit is contained in:
@@ -8,6 +8,7 @@ import { matchesProfile } from "./profile.ts";
|
|||||||
|
|
||||||
const CSV = "./results/jobs.csv";
|
const CSV = "./results/jobs.csv";
|
||||||
const SENT = "./results/sent.txt"; // links already pushed — never resend
|
const SENT = "./results/sent.txt"; // links already pushed — never resend
|
||||||
|
const LANG_DROPPED = "./results/.lang-dropped.json"; // written by index.ts — jobs dropped for German/French content never reach the CSV
|
||||||
const dry = process.argv.includes("--dry-run");
|
const dry = process.argv.includes("--dry-run");
|
||||||
const resend = process.argv.includes("--resend");
|
const resend = process.argv.includes("--resend");
|
||||||
|
|
||||||
@@ -47,10 +48,19 @@ const sent = new Set(
|
|||||||
: []
|
: []
|
||||||
);
|
);
|
||||||
const dateArg = process.argv.find((a) => a.startsWith("--date="))?.slice(7);
|
const dateArg = process.argv.find((a) => a.startsWith("--date="))?.slice(7);
|
||||||
|
const digestDate = dateArg ?? new Date().toISOString().slice(0, 10);
|
||||||
const fresh = resend
|
const fresh = resend
|
||||||
? all.filter((r) => r.fetched === (dateArg ?? new Date().toISOString().slice(0, 10)))
|
? all.filter((r) => r.fetched === digestDate)
|
||||||
: all.filter((r) => !before.has(r.link));
|
: all.filter((r) => !before.has(r.link));
|
||||||
|
|
||||||
|
// Jobs dropped for German/French content never make it into the CSV, so this
|
||||||
|
// is the only place their count survives — shown as a count-only category,
|
||||||
|
// never listed, since there's no Row to show for them.
|
||||||
|
const langDropped = await Bun.file(LANG_DROPPED)
|
||||||
|
.json()
|
||||||
|
.then((j) => (j.date === digestDate ? j.count : 0))
|
||||||
|
.catch(() => 0);
|
||||||
|
|
||||||
// Only leads that actually match the CV (profile.ts) and haven't been sent before.
|
// Only leads that actually match the CV (profile.ts) and haven't been sent before.
|
||||||
const matched = fresh.filter((r) => !sent.has(r.link) && matchesProfile(r.title, r.company).ok);
|
const matched = fresh.filter((r) => !sent.has(r.link) && matchesProfile(r.title, r.company).ok);
|
||||||
console.log(`${fresh.length} new · ${matched.length} match profile · ${fresh.length - matched.length} filtered or already sent`);
|
console.log(`${fresh.length} new · ${matched.length} match profile · ${fresh.length - matched.length} filtered or already sent`);
|
||||||
@@ -95,6 +105,9 @@ for (const k of order) {
|
|||||||
lines.push(`• ${escapeHtml(r.title)} — ${escapeHtml(r.company)} ${label}`);
|
lines.push(`• ${escapeHtml(r.title)} — ${escapeHtml(r.company)} ${label}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (langDropped > 0) {
|
||||||
|
lines.push(`\n<b>🔴 Ignored (German/French)</b> (${langDropped})`);
|
||||||
|
}
|
||||||
|
|
||||||
const msg = lines.join("\n");
|
const msg = lines.join("\n");
|
||||||
if (dry) {
|
if (dry) {
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ try {
|
|||||||
|
|
||||||
const date = new Date().toISOString().slice(0, 10);
|
const date = new Date().toISOString().slice(0, 10);
|
||||||
const newRows: string[] = [];
|
const newRows: string[] = [];
|
||||||
|
let totalLangDropped = 0; // jobs dropped for German/French content — never reach the CSV, so daily.ts can't see them on its own
|
||||||
|
|
||||||
function csvCell(val: string): string {
|
function csvCell(val: string): string {
|
||||||
return `"${val.replace(/"/g, '""')}"`;
|
return `"${val.replace(/"/g, '""')}"`;
|
||||||
@@ -111,6 +112,7 @@ async function processLinkedInSearch(config: (typeof searches)[number]): Promise
|
|||||||
if (!viable.ok) {
|
if (!viable.ok) {
|
||||||
console.log(`dropped (${viable.reason})`);
|
console.log(`dropped (${viable.reason})`);
|
||||||
langDropped++;
|
langDropped++;
|
||||||
|
totalLangDropped++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
console.log("ok");
|
console.log("ok");
|
||||||
@@ -162,6 +164,7 @@ async function processExtraSource({ label, fetch: fetchFn }: (typeof extraSource
|
|||||||
if (!viable.ok) {
|
if (!viable.ok) {
|
||||||
console.log(`dropped (${viable.reason})`);
|
console.log(`dropped (${viable.reason})`);
|
||||||
langDropped++;
|
langDropped++;
|
||||||
|
totalLangDropped++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
console.log("ok");
|
console.log("ok");
|
||||||
@@ -184,6 +187,12 @@ await Promise.all([
|
|||||||
runWithConcurrency(extraSources, EXTRA_SOURCE_CONCURRENCY, processExtraSource),
|
runWithConcurrency(extraSources, EXTRA_SOURCE_CONCURRENCY, processExtraSource),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// Jobs dropped for German/French content never reach the CSV, so this is the
|
||||||
|
// only record of them — daily.ts reads it back to show a count in the digest
|
||||||
|
// without listing rejects that were never even parsed into a Row.
|
||||||
|
const LANG_DROPPED = "./results/.lang-dropped.json";
|
||||||
|
await Bun.write(LANG_DROPPED, JSON.stringify({ date, count: totalLangDropped }));
|
||||||
|
|
||||||
if (newRows.length === 0) {
|
if (newRows.length === 0) {
|
||||||
console.log("\nNo new jobs.");
|
console.log("\nNo new jobs.");
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
|
|||||||
Reference in New Issue
Block a user