fix: group telegram digest by posting's real location, not search label
fetch.ts already parses each job card's own location, but index.ts discarded it and stored only the search-area label in the CSV, so daily.ts's telegram grouping used the query that found a job instead of where it actually is (e.g. a Bern search surfacing a Lausanne job). Now the location is written to a new CSV column and used for grouping, with a one-time migration for existing rows.
This commit is contained in:
@@ -5,16 +5,19 @@ import { fetchDataCareer, fetchStellenBasel, fetchItJobsCh, fetchJobRoom, fetchB
|
||||
|
||||
const CSV = "./results/jobs.csv";
|
||||
const OLD_HEADER = "date_found,posted_at,search,title,company,link";
|
||||
const HEADER = "date_found,posted_at,search,title,company,link,source";
|
||||
const HEADER_NO_LOCATION = "date_found,posted_at,search,title,company,link,source";
|
||||
const HEADER = "date_found,posted_at,search,title,company,link,source,location";
|
||||
|
||||
// Migrate CSV: add source column if the old header is present
|
||||
// Migrate CSV: add source column if the old header is present, then location
|
||||
// (the posting's real location, as parsed off its own card — distinct from
|
||||
// `search`, which is just the query that found it. See CLAUDE.md.)
|
||||
const csvExists = await Bun.file(CSV).exists();
|
||||
if (csvExists) {
|
||||
const raw = await Bun.file(CSV).text();
|
||||
if (raw.startsWith(OLD_HEADER + "\n") || raw === OLD_HEADER) {
|
||||
const lines = raw.split("\n");
|
||||
const migrated = [
|
||||
HEADER,
|
||||
HEADER_NO_LOCATION,
|
||||
...lines.slice(1).map((l) => (l.trim() ? l + ',"linkedin.com"' : "")),
|
||||
]
|
||||
.join("\n")
|
||||
@@ -22,6 +25,20 @@ if (csvExists) {
|
||||
await Bun.write(CSV, migrated);
|
||||
}
|
||||
}
|
||||
{
|
||||
const raw = await Bun.file(CSV).text().catch(() => "");
|
||||
if (raw.startsWith(HEADER_NO_LOCATION + "\n") || raw === HEADER_NO_LOCATION) {
|
||||
const lines = raw.split("\n");
|
||||
const migrated = [
|
||||
HEADER,
|
||||
// Unknown for pre-existing rows — daily.ts falls back to `search` when empty.
|
||||
...lines.slice(1).map((l) => (l.trim() ? l + ',""' : "")),
|
||||
]
|
||||
.join("\n")
|
||||
.replace(/\n+$/, "") + "\n";
|
||||
await Bun.write(CSV, migrated);
|
||||
}
|
||||
}
|
||||
|
||||
// Load existing links for deduplication
|
||||
const existingLinks = new Set<string>();
|
||||
@@ -68,7 +85,7 @@ for (const config of searches) {
|
||||
console.log("ok");
|
||||
existingLinks.add(job.link);
|
||||
newRows.push(
|
||||
[date, job.postedAt, config.label, job.title, job.company, job.link, "linkedin.com"]
|
||||
[date, job.postedAt, config.label, job.title, job.company, job.link, "linkedin.com", job.location]
|
||||
.map(csvCell)
|
||||
.join(",")
|
||||
);
|
||||
@@ -117,7 +134,7 @@ for (const { label, fetch: fetchFn } of extraSources) {
|
||||
}
|
||||
existingLinks.add(job.link);
|
||||
newRows.push(
|
||||
[date, job.postedAt, job.search, job.title, job.company, job.link, job.source]
|
||||
[date, job.postedAt, job.search, job.title, job.company, job.link, job.source, job.location]
|
||||
.map(csvCell)
|
||||
.join(",")
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user