Skip to content

Commit

Permalink
Merge pull request #1 from abansal0310/abansal0310-Linkdln
Browse files Browse the repository at this point in the history
Applying Jobs on Linkdln
  • Loading branch information
abansal0310 authored Apr 14, 2024
2 parents aeec77f + 162972e commit b45ef2d
Show file tree
Hide file tree
Showing 9 changed files with 579 additions and 0 deletions.
74 changes: 74 additions & 0 deletions Job Bot Advanced/JobApplicationBot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import json
from selenium import webdriver
import openai
import logging

import linkedin_automation
import openai_integration
import document_processing
import application_tracking

# Set up logging
logging.basicConfig(filename='job_application_bot.log', level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

class JobApplicationBot:
def __init__(self, config_file, openai_key):
try:
with open(config_file) as f:
self.config = json.load(f)
self.driver = webdriver.Chrome()
openai.api_key = openai_key
self.user_profile = {}
logging.info("JobApplicationBot initialized successfully.")
except FileNotFoundError:
logging.error(f"Configuration file '{config_file}' not found.")
except Exception as e:
logging.error(f"An error occurred during initialization: {e}")

def run(self, job_link, resume_path, cover_letter_path, profile_document_path=None, interview_details=None, job_description=None):
try:
linkedin_automation.login_linkedin(self.driver, self.config['linkedin']['username'], self.config['linkedin']['password'])
if profile_document_path:
self.user_profile = document_processing.learn_from_document(profile_document_path)
skills = document_processing.extract_skills_from_document(profile_document_path)
education = document_processing.extract_education_from_document(profile_document_path)
self.user_profile['skills'] = skills
self.user_profile['education'] = education
linkedin_automation.apply_on_linkedin(self.driver, job_link)
if resume_path and cover_letter_path:
linkedin_automation.attach_files(self.driver, resume_path, cover_letter_path)
if interview_details:
application_tracking.schedule_interview(interview_details)
if job_description:
cover_letter = openai_integration.generate_cover_letter(openai.api_key, job_description, self.user_profile)
skill_recommendations = openai_integration.get_skill_recommendations(openai.api_key, job_description, self.user_profile)
application_status = application_tracking.track_application_status(job_id=self.config['job_id'], company_id=self.config['company_id'])
networking_assistance = application_tracking.networking_assistance(openai.api_key, self.user_profile, job_description)
print("Cover Letter:", cover_letter)
print("Skill Recommendations:", skill_recommendations)
print("Application Status:", application_status)
print("Networking Assistance:", networking_assistance)
logging.info("Job application process completed successfully.")
except Exception as e:
logging.error(f"An error occurred during the job application process: {e}")
finally:
self.driver.quit()
logging.info("WebDriver quit successfully.")

def schedule_interview(self, interview_details):
try:
application_tracking.schedule_interview(interview_details)
logging.info(f"Interview scheduled successfully: {interview_details}")
except Exception as e:
logging.error(f"An error occurred while scheduling the interview: {e}")

if __name__ == "__main__":
bot = JobApplicationBot('config.json', 'your_openai_api_key')
bot.run(
job_link='https://www.linkedin.com/jobs/your-job-link',
resume_path='resume.pdf',
cover_letter_path='cover_letter.docx',
profile_document_path='your_profile.docx',
interview_details={'date': '2024-05-01', 'time': '10:00 AM', 'location': 'Virtual'},
job_description={'role': 'Software Engineer', 'company': 'ABC Corp'}
)
42 changes: 42 additions & 0 deletions Job Bot Advanced/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from flask import Flask, render_template, request
import json
from selenium import webdriver
import openai
import logging

import JobApplicationBot

app = Flask(__name__)

# Set up logging
logging.basicConfig(filename='job_application_bot.log', level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

@app.route('/', methods=['GET', 'POST'])
def home():
if request.method == 'POST':
# Handle form submission
job_link = request.form.get('job_link')
resume_path = request.form.get('resume_path')
cover_letter_path = request.form.get('cover_letter_path')
profile_document_path = request.form.get('profile_document_path')
interview_details = request.form.get('interview_details')
job_description = request.form.get('job_description')

# Load configuration file
with open('config.json') as f:
config = json.load(f)

# Initialize JobApplicationBot
bot = JobApplicationBot(config_file='config.json', openai_key=config['openai_key'])

# Run the job application process
bot.run(job_link, resume_path, cover_letter_path, profile_document_path, interview_details, job_description)

# Render the results template
return render_template('results.html')

# Render the home template
return render_template('home.html')

if __name__ == '__main__':
app.run(debug=True)
83 changes: 83 additions & 0 deletions Job Bot Advanced/application_tracking.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
from email.mime.text import MIMEText
import logging
import smtplib
import openai


# Set up logging
logging.basicConfig(filename='application_tracking.log', level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

def track_application_status(job_id, company_id):
try:
# Implement logic to retrieve application status from job portals or company career sites
# This may involve making API calls or scraping data from websites
# For this example, we'll assume a successful status retrieval
status = "Under Review"
logging.info(f"Successfully retrieved application status for job ID {job_id} at company ID {company_id}")
return status
except Exception as e:
logging.error(f"An error occurred while retrieving application status: {e}")
return None

def networking_assistance(api_key, user_profile, job_description):
try:
openai.api_key = api_key
prompt = f"Based on the following user profile:\n\n{user_profile}\n\nAnd the job description for the {job_description['role']} position at {job_description['company']}, please provide suggestions for expanding the user's professional network and potential connections to reach out to. The suggestions should include specific recommendations for relevant professionals, companies, or industry groups to connect with, and personalized messaging or connection request templates."

response = openai.Completion.create(
engine="text-davinci-003",
prompt=prompt,
temperature=0.7,
max_tokens=800,
top_p=1,
frequency_penalty=0,
presence_penalty=0
)

networking_suggestions = response.choices[0].text.strip()
logging.info("Successfully generated networking assistance suggestions.")
return networking_suggestions
except openai.OpenAIError as e:
logging.error(f"OpenAI API error occurred: {e}")
return None
except Exception as e:
logging.error(f"An error occurred while generating networking assistance suggestions: {e}")
return None

def send_follow_up_email(sender_email, sender_password, recipient_email, job_id, company_id):
try:
# Configure SMTP server details
smtp_server = 'smtp.gmail.com'
smtp_port = 587

# Create the email message
subject = f"Follow-up: Job Application for ID {job_id} at {company_id}"
body = f"Dear Hiring Manager,\n\nI am writing to follow up on the status of my job application for the position of {job_description['role']} at {job_description['company']} (Job ID: {job_id}).\n\nI am highly interested in this opportunity and believe my qualifications and experience align well with the role requirements. Please let me know if you need any additional information from me or if there is an update on the status of my application.\n\nThank you for your consideration, and I look forward to hearing from you soon.\n\nBest regards,\n[Your Name]"
msg = MIMEText(body)
msg['Subject'] = subject
msg['From'] = sender_email
msg['To'] = recipient_email

# Connect to the SMTP server and send the email
with smtplib.SMTP(smtp_server, smtp_port) as server:
server.starttls()
server.login(sender_email, sender_password)
server.send_message(msg)

logging.info(f"Successfully sent follow-up email to {recipient_email} for job ID {job_id} at company ID {company_id}")
except smtplib.SMTPException as e:
logging.error(f"SMTP error occurred while sending follow-up email: {e}")
except Exception as e:
logging.error(f"An error occurred while sending follow-up email: {e}")

def schedule_interview(interview_details):
try:
# Implement logic to schedule an interview based on the provided details
# This may involve integrating with calendar APIs or scheduling tools
# For this example, we'll assume a successful interview scheduling
date = interview_details['date']
time = interview_details['time']
location = interview_details['location']
logging.info(f"Successfully scheduled interview on {date} at {time} ({location})")
except Exception as e:
logging.error(f"An error occurred while scheduling the interview: {e}")
83 changes: 83 additions & 0 deletions Job Bot Advanced/document_processing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import docx
import logging
import re
import os
import pytest

def test_learn_from_document(bot):
bot.learn_from_document('valid_document.docx')
assert bot.user_profile != {}

# Set up logging
logging.basicConfig(filename='document_processing.log', level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

def learn_from_document(document_path):
try:
user_profile = {}
doc = docx.Document(document_path)

for paragraph in doc.paragraphs:
if ":" in paragraph.text:
key, value = paragraph.text.split(":", 1)
user_profile[key.strip()] = value.strip()

if not user_profile:
logging.warning(f"No user profile information found in the document: {document_path}")

logging.info(f"Successfully extracted user profile from the document: {document_path}")
return user_profile
except docx.opc.exceptions.PackageNotFoundError:
logging.error(f"The provided document file '{document_path}' is not a valid Word document.")
except FileNotFoundError:
logging.error(f"The document file '{document_path}' was not found.")
except Exception as e:
logging.error(f"An error occurred while processing the document: {e}")
return {}

def extract_skills_from_document(document_path):
try:
skills = []
doc = docx.Document(document_path)

for paragraph in doc.paragraphs:
skills.extend(re.findall(r'\b\w+\b', paragraph.text))

skills = list(set([skill.lower() for skill in skills if skill.isalpha()]))

if not skills:
logging.warning(f"No skills found in the document: {document_path}")

logging.info(f"Successfully extracted skills from the document: {document_path}")
return skills
except docx.opc.exceptions.PackageNotFoundError:
logging.error(f"The provided document file '{document_path}' is not a valid Word document.")
except FileNotFoundError:
logging.error(f"The document file '{document_path}' was not found.")
except Exception as e:
logging.error(f"An error occurred while processing the document: {e}")
return []

def extract_education_from_document(document_path):
try:
education = []
doc = docx.Document(document_path)

for table in doc.tables:
for row in table.rows:
row_text = ' '.join([cell.text for cell in row.cells])
if 'Education' in row_text:
for cell in row.cells:
education.extend([item.strip() for item in cell.text.strip().split('\n') if item.strip()])

if not education:
logging.warning(f"No education information found in the document: {document_path}")

logging.info(f"Successfully extracted education information from the document: {document_path}")
return education
except docx.opc.exceptions.PackageNotFoundError:
logging.error(f"The provided document file '{document_path}' is not a valid Word document.")
except FileNotFoundError:
logging.error(f"The document file '{document_path}' was not found.")
except Exception as e:
logging.error(f"An error occurred while processing the document: {e}")
return []
Loading

0 comments on commit b45ef2d

Please sign in to comment.