UNPKG

naukri-automation-tool

Version:

Naukri automation tool to fetch, filter, and apply for jobs automatically using gen ai.

344 lines (327 loc) 10.4 kB
// Get the emails from json file and create a custom email body, replace the placeholders with the actual values const { getDataFromFile, writeToFile } = require("./ioUtils"); const nodemailer = require("nodemailer"); const dotenv = require("dotenv"); const prompts = require("@inquirer/prompts"); const { openUrl, localStorage, openFile } = require("./helper"); const path = require("path"); const { getResume } = require("./jobUtils"); dotenv.config(); const user = { id: "Pranesh Nangare", userDetails: { email: "praneshnangare10@gmail.com", mobile: "9145266274", name: "Pranesh Nangare", }, skills: [ { skillName: "Java", experienceYears: 3, experienceMonths: 4, }, { skillName: "React Js,Redux Toolkit", experienceYears: 3, experienceMonths: 0, }, { skillName: "Material UI", experienceYears: 3, experienceMonths: 0, }, { skillName: "Spring boot, spring data JPA", experienceYears: 3, experienceMonths: 0, }, { skillName: "Figma, Postman, Git", experienceYears: 3, experienceMonths: 4, }, { skillName: "JavaScript, HTML, CSS", experienceYears: 3, experienceMonths: 4, }, { skillName: "Node.js", experienceYears: 3, experienceMonths: 0, }, { skillName: "Dialogflow CX", experienceYears: 3, experienceMonths: 0, }, ], profile: { keySkills: "Full Stack Engineering Senior Analyst,spring boot,javascript,angular,spring,react.js,full stack,jquery,node.js,ui development,project management,web development,jsp servlets,software development,api integration,web designing,generative ai", desiredRole: [ "Java Full Stack Developer", "Frontend Web Developer", "Springboot Developer", ], totalExperience: { year: "3", month: "6", }, currentLocation: " Pune, INDIA", }, onlineProfile: [ { type: "LinkedIn", url: "https://www.linkedin.com/in/pranesh-nangare/", }, { type: "https://www.linkedin.com/in/pranesh-nangare/", url: "https://github.com/pnangare10", }, ], }; const getEmails = async () => { const emails = await getDataFromFile("hrEmails", "Pranesh Nangare"); if (!emails) return null; const newEmails = emails?.filter((email) => !email.mailSent); // the emails field is an array of emails in each object, i want to add a new object for that array if (newEmails.length > 0) { return newEmails; } return emails; }; // Load recruiter data const recipients = [ { name: "Ankita Yadav", email: "ankitauy@gmail.com", company: "Altimetrik", title: "Java developer-Immd-Chennai/Pune/Bangalore-Client-CitiBank", mailSent: false, }, ]; // Email template with placeholders const emailTemplate = ( name, contact, linkedInProfile, totalExperience, skills, workSamples ) => `<p>Dear Recruiter,</p> <p>I hope you're doing well!</p> <p>I came across the {{position}} opening at {{company}} and wanted to express my interest. <br>I have <b>${totalExperience.year} years and ${totalExperience.month} months of experience in ${skills.slice(0, 2).map((skill) => skill.skillName).join(", ")}</b> and I believe I can contribute effectively to your team.</p> <p>Attached is my resume for your reference. I would love the opportunity to discuss how my skills align with your needs.</p> ${ workSamples && workSamples.length > 0 ? `<p>Here are some of my worksamples:</p> ${workSamples ?.slice(0, 2) .map((worksample) => `<b>${worksample.title}</b><br>${worksample.url}`).join("<br>")}</p>` : "" } Looking forward to your response.</p> <p>Best regards,<br> ${name}<br> Contact: ${contact}<br> ${linkedInProfile ? `LinkedIn Profile: ${linkedInProfile}` : ""} `; const getMailPassword = async () => { const preferences = await localStorage.getItem("preferences"); if (preferences.mailPassword) { return preferences.mailPassword; } console.log( "Sending email requires an app password. Please follow these steps:" ); console.log("1. Go to https://myaccount.google.com/apppasswords"); console.log("2. Enter app name as 'gmail'"); console.log("3. Click on 'Create' button"); console.log("4. Copy the generated password"); console.log("5. Paste the password in the prompt"); await prompts.confirm({ message: "Hit enter to open the browser", default: true, }); await openUrl("https://myaccount.google.com/apppasswords"); const password = await prompts.password({ message: "Enter your password" }); preferences.mailPassword = password; await localStorage.setItem("preferences", preferences); writeToFile(preferences, "preferences"); return password; }; // Resume file path const getResumePath = async () => { const profile = await localStorage.getItem("profile"); const filename = await getResume(); if (!filename) { return null; } return path.join(__dirname, `data/${profile.id}/${filename}`); }; const resetEmailTemplate = async () => { const user = await localStorage.getItem("profile"); const linkedInProfile = user.onlineProfile.find( (profile) => profile.type === "LinkedIn" )?.url; existingTemplate = emailTemplate( user.userDetails.name, user.userDetails.mobile, linkedInProfile, user.profile.totalExperience, user.skills, user.workSamples ); writeToFile(existingTemplate, "emailTemplate.html", null, true); return existingTemplate; } const editEmailTemplate = async () => { const profile = await localStorage.getItem("profile"); let existingTemplateBuffer = await getDataFromFile("emailTemplate.html", null, true); let existingTemplate = existingTemplateBuffer ? existingTemplateBuffer.toString() : null; const res = await prompts.select({ message: "Please select an option", default: "skip", choices: [ { title: "Skip", value: "skip" }, { title: "Edit email template", value: "edit" }, { title: "View email template", value: "view" }, { title: "Reset email template", value: "reset" }, ], }); debugger; if (!existingTemplate || res === "reset") { existingTemplate = await resetEmailTemplate(); if(res === "reset") return existingTemplate; } if (res === "view") { console.log(existingTemplate); return existingTemplate; } if (res === "skip") return existingTemplate; if (res === "edit") { console.log(`Here are some instructions to edit the email template: 1. Do not replace fields mentioned with {{...}} 2. You can add html tags to format the email. For example, <b>bold text</b>, <i>italic text</i> 3. Save the file after editing 4. Use CTRL + X to exit the editor 5. Press Y to save the changes 6. Press Enter to confirm the file name Important Note: Do not change the file name`); const templatePath = path.join(__dirname, `data/${profile.id}/emailTemplate.html`); openFile(templatePath); const newTemplate = (await getDataFromFile("emailTemplate.html", null, true))?.toString(); if(newTemplate) return newTemplate; const defaultTemplate = await resetEmailTemplate(); return defaultTemplate; } }; const sendEmails = async (recipients, mailPassword, emailTemplate, resumePath) => { const profile = await localStorage.getItem("profile"); // Create Nodemailer transporter const transporter = nodemailer.createTransport({ service: "gmail", auth: { user: profile.userDetails.email, pass: mailPassword, }, }); for (const recipient of recipients) { if (recipient.mailSent) continue; emailTemplate = emailTemplate.replace("{{position}}", recipient.title) .replace("{{company}}", recipient.company); const mailOptions = { from: profile.userDetails.email, subject: `Application for ${recipient.title} at ${recipient.company}`, html: emailTemplate, attachments: [ { filename: `${profile.id}.pdf`, path: resumePath, }, ], }; for (let i = 0; i< recipient.email.length; i++) { const email = recipient.email[i]; try { if (!email) { console.log(`❌ Email not found for ${recipient.name}`); continue; } mailOptions.to = email; const info = await transporter.sendMail(mailOptions); process.stdout.write( `Sent ${i} emails out of ${recipients.length} \r` ); recipient.mailSent = true; writeToFile(recipients, "hrEmails"); } catch (error) { console.error(`❌ Error sending to ${recipient.email}:`, error.message); } } } }; // Function to send emails const setupEmails = async () => { debugger; let recipients = await getEmails(); if (!recipients) { console.log( "No emails to send. Please search for new jobs to collect emails." ); const res = await prompts.select({ message: "Do you want to search for new emails?", choices: [ { name: "Yes", value: "yes" }, { name: "No", value: "no" }, ], }); if (res) { await findNewJobs(); recipients = await getEmails(); } else return; } let mailPassword = await getMailPassword(); let resumePath = await getResumePath(); if (!mailPassword) { console.log("Email password not found"); return; } if (!resumePath) { console.log("Resume not found in your Naukri profile"); console.log("Please upload your resume to proceed"); const res = await prompts.confirm({ message: "Do you want to upload now?", default: true, }); if (res) { await openUrl("https://www.naukri.com/mnjuser/profile"); const response = await prompts.confirm({ message: "Press enter after uploading the resume", default: true, }); if (!response) { console.log("Please upload your resume and try again"); return; } else { resumePath = await getResumePath(); } } else { console.log("Please upload your resume and try again"); return; } } let emailTemplate = await editEmailTemplate(); console.log("Sending emails..."); await sendEmails(recipients, mailPassword, emailTemplate, resumePath); }; module.exports = { sendEmails, setupEmails, };