Separated Opportunitues from Applied using headers, Added Date Posted to jobs.
This commit is contained in:
@@ -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');
|
||||
|
||||
Reference in New Issue
Block a user