Rich apply summary with per-job details (title, company, link)
Each job now shows title @ company with a clickable link, grouped by status category. Only non-empty categories are shown. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -53,7 +53,8 @@ async function main() {
|
||||
const results = {
|
||||
submitted: 0, failed: 0, needs_answer: 0, total: 0,
|
||||
skipped_recruiter: 0, skipped_external: 0, skipped_no_apply: 0, skipped_other: 0,
|
||||
already_applied: 0, atsCounts: {}
|
||||
already_applied: 0, closed: 0, atsCounts: {},
|
||||
jobDetails: [], // { title, company, url, status } per job for summary
|
||||
};
|
||||
|
||||
lock.onShutdown(() => {
|
||||
@@ -245,6 +246,9 @@ async function handleResult(job, result, results, settings, profile, apiKey) {
|
||||
const title = meta?.title || job.title || '?';
|
||||
const company = meta?.company || job.company || '?';
|
||||
|
||||
// Track per-job detail for summary
|
||||
results.jobDetails.push({ title, company, url: job.url, status });
|
||||
|
||||
switch (status) {
|
||||
case 'submitted':
|
||||
console.log(` ✅ Applied!`);
|
||||
|
||||
@@ -93,34 +93,39 @@ export function formatSearchSummary(added, skipped, platforms) {
|
||||
}
|
||||
|
||||
export function formatApplySummary(results) {
|
||||
const { submitted, failed, needs_answer, total,
|
||||
skipped_recruiter, skipped_external, skipped_no_apply,
|
||||
skipped_other, already_applied, closed, atsCounts } = results;
|
||||
const { total, jobDetails = [] } = results;
|
||||
|
||||
const lines = [
|
||||
`✅ *Apply Run Complete* — ${total} jobs processed`,
|
||||
``,
|
||||
`📬 Applied: ${submitted}`,
|
||||
const lines = [`✅ *Apply Run Complete* — ${total} job${total !== 1 ? 's' : ''} processed`];
|
||||
|
||||
// Group jobs by display category
|
||||
const categories = [
|
||||
{ key: 'submitted', emoji: '📬', label: 'Applied' },
|
||||
{ key: 'needs_answer', emoji: '💬', label: 'Needs Answer' },
|
||||
{ key: 'closed', emoji: '🚫', label: 'Closed' },
|
||||
{ key: 'incomplete', emoji: '⚠️', label: 'Incomplete' },
|
||||
{ key: 'stuck', emoji: '⚠️', label: 'Stuck' },
|
||||
{ key: 'skipped_honeypot', emoji: '⚠️', label: 'Honeypot' },
|
||||
{ key: 'skipped_no_apply', emoji: '⏭️', label: 'No Apply Button' },
|
||||
{ key: 'no_modal', emoji: '⏭️', label: 'No Modal' },
|
||||
{ key: 'skipped_recruiter_only', emoji: '🚫', label: 'Recruiter Only' },
|
||||
{ key: 'skipped_external_unsupported', emoji: '🌐', label: 'External ATS' },
|
||||
];
|
||||
|
||||
// Only show non-zero categories to keep the summary clean
|
||||
if (needs_answer) lines.push(`💬 Needs your answer: ${needs_answer}`);
|
||||
if (failed) lines.push(`❌ Failed: ${failed}`);
|
||||
if (closed) lines.push(`🚫 Closed: ${closed}`);
|
||||
if (skipped_no_apply) lines.push(`⏭️ No apply button: ${skipped_no_apply}`);
|
||||
if (skipped_recruiter) lines.push(`🚫 Recruiter-only: ${skipped_recruiter}`);
|
||||
if (already_applied) lines.push(`🔁 Already applied: ${already_applied}`);
|
||||
if (skipped_other) lines.push(`⚠️ Other skips (honeypot/stuck/incomplete): ${skipped_other}`);
|
||||
|
||||
if (skipped_external > 0 && atsCounts) {
|
||||
const sorted = Object.entries(atsCounts).sort((a, b) => b[1] - a[1]);
|
||||
lines.push(``, `🌐 *External ATS — ${skipped_external} jobs* (saved for later):`);
|
||||
for (const [platform, count] of sorted) {
|
||||
lines.push(` • ${platform}: ${count}`);
|
||||
for (const { key, emoji, label } of categories) {
|
||||
const jobs = jobDetails.filter(j => j.status === key);
|
||||
if (jobs.length === 0) continue;
|
||||
lines.push('');
|
||||
lines.push(`${emoji} *${label}:*`);
|
||||
for (const j of jobs) {
|
||||
const shortUrl = (j.url || '').replace(/^https?:\/\/(?:www\.)?/, '').replace(/\/$/, '');
|
||||
lines.push(` • ${j.title} @ ${j.company}`);
|
||||
if (shortUrl) lines.push(` ${shortUrl}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (needs_answer > 0) lines.push(``, `💬 Check Telegram — questions waiting for your answers`);
|
||||
if (jobDetails.some(j => j.status === 'needs_answer')) {
|
||||
lines.push('', '💬 Check Telegram — questions waiting for your answers');
|
||||
}
|
||||
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user