Separated Opportunitues from Applied using headers, Added Date Posted to jobs.

This commit is contained in:
2026-07-07 20:58:42 +00:00
parent dcd00af6bb
commit 8155b121da
5 changed files with 410 additions and 173 deletions

View File

@@ -324,6 +324,41 @@ async function notifyNewJob(job) {
await sendNtfyNotification(job, companyName);
}
// Opens a job's detail page briefly just to read its "Posted X ago" text,
// then closes the tab. Only called for genuinely new jobs, not on every
// 5-minute check, to avoid needlessly opening tabs for jobs we already know about.
async function fetchPostedDate(url) {
if (!url) return null;
let tab;
try {
tab = await chrome.tabs.create({ url: url, active: false });
await new Promise((resolve) => setTimeout(resolve, 3500));
const postedDate = await new Promise((resolve) => {
chrome.tabs.sendMessage(
tab.id,
{ action: 'extractPostedDate' },
(response) => {
if (chrome.runtime.lastError) {
log(
'Error extracting posted date:',
chrome.runtime.lastError.message,
);
resolve(null);
} else {
resolve((response && response.postedDate) || null);
}
},
);
});
return postedDate;
} catch (err) {
log('Error in fetchPostedDate:', err.message);
return null;
} finally {
if (tab) chrome.tabs.remove(tab.id).catch(() => {});
}
}
let keepAliveInterval = null;
function startKeepAlive() {
@@ -354,24 +389,61 @@ async function checkForNewJobs() {
const allJobs = await fetchJobsViaContentScript();
const sortedJobs = sortJobsByRecency(allJobs);
const result = await getStoredData(['notifiedJobIds']);
const result = await getStoredData([
'notifiedJobIds',
'postedDates',
'backfillDone',
]);
const notifiedJobIds = new Set(result.notifiedJobIds || []);
const postedDates = result.postedDates || {};
const backfillDone = result.backfillDone || false;
log('Previously notified jobs: ' + notifiedJobIds.size);
sortedJobs.forEach((job) => {
if (postedDates[job.id]) job.posted_ago = postedDates[job.id];
});
const newJobs = sortedJobs.filter((job) => !notifiedJobIds.has(job.id));
if (!backfillDone) {
const toBackfill = sortedJobs.filter(
(job) => job.kind === 'opportunity' && !postedDates[job.id],
);
log(
'Backfilling posted dates for ' +
toBackfill.length +
' existing jobs...',
);
for (const job of toBackfill) {
const postedDate = await fetchPostedDate(job.url);
if (postedDate) {
job.posted_ago = postedDate;
postedDates[job.id] = postedDate;
}
}
}
const newJobs = sortedJobs.filter(
(job) => job.kind === 'opportunity' && !notifiedJobIds.has(job.id),
);
log('Found ' + newJobs.length + ' new jobs');
for (const job of newJobs) {
const postedDate = await fetchPostedDate(job.url);
if (postedDate) {
job.posted_ago = postedDate;
postedDates[job.id] = postedDate;
}
await notifyNewJob(job);
notifiedJobIds.add(job.id);
}
await setStoredData({
notifiedJobIds: Array.from(notifiedJobIds),
postedDates: postedDates,
backfillDone: true,
lastAndelaJobs: sortedJobs,
lastAndelaUpdated: new Date().toISOString(),
totalAndelaMatching: sortedJobs.length,
totalAndelaMatching: sortedJobs.filter((j) => j.kind === 'opportunity')
.length,
});
log('Notifications stored successfully');