diff --git a/.gitignore b/.gitignore index 89bc5c66..9b53de8b 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ __pycache__/ # C extensions *.so + # Distribution / packaging .Python build/ @@ -34,6 +35,9 @@ answers.json # before PyInstaller builds the exe, so as to inject date/other infos into it. *.manifest *.spec +.venv +.pytest_cache +virtual # Installer logs pip-log.txt diff --git a/README.md b/README.md index dc287913..2c357a7c 100644 --- a/README.md +++ b/README.md @@ -3,22 +3,18 @@ - - - [![Gmail](https://img.shields.io/badge/Gmail-D14836?style=for-the-badge&logo=gmail&logoColor=white)](mailto:federico.elia.majo@gmail.com) - - # Auto_Jobs_Applier_AIHawk - ![CI](https://github.com/feder-cr/Auto_Jobs_Applier_AIHawk/actions/workflows/ci.yml/badge.svg) - #### 🤖🔍 Your AI-powered job search assistant. Automate applications, get personalized recommendations, and land your dream job faster. + [![Gmail](https://img.shields.io/badge/Gmail-D14836?style=for-the-badge&logo=gmail&logoColor=white)](mailto:federico.elia.majo@gmail.com) +# Auto_Jobs_Applier_AIHawk + ![CI](https://github.com/feder-cr/Auto_Jobs_Applier_AIHawk/actions/workflows/ci.yml/badge.svg) -
+**🤖🔍 Your AI-powered job search assistant. Automate applications, get personalized recommendations, and land your dream job faster.** -## 🚀 Join the AIHawk Community 🚀 +## 🚀 Join the AIHawk Community 🚀 Connect with like-minded individuals and get the most out of AIHawk. @@ -32,6 +28,7 @@ Connect with like-minded individuals and get the most out of AIHawk. ### Join Now 👇 + [![Telegram](https://img.shields.io/badge/Telegram-2CA5E0?style=for-the-badge&logo=telegram&logoColor=white )](https://t.me/AIhawkCommunity) @@ -108,6 +105,7 @@ Auto_Jobs_Applier_AIHawk steps in as a game-changing solution to these challenge ## Installation **Confirmed successful runs on the following:** + - Operating Systems: - Windows 10 - Ubuntu 22 @@ -128,6 +126,7 @@ Auto_Jobs_Applier_AIHawk steps in as a game-changing solution to these challenge - Download and install the latest version of Google Chrome in its default location from the [official website](https://www.google.com/chrome). 3. **Clone the repository:** + ```bash git clone https://github.com/feder-cr/Auto_Jobs_Applier_AIHawk.git @@ -135,6 +134,7 @@ Auto_Jobs_Applier_AIHawk steps in as a game-changing solution to these challenge ``` 4. **Activate virtual environment:** + ```bash python3 -m venv virtual ``` @@ -144,11 +144,13 @@ Auto_Jobs_Applier_AIHawk steps in as a game-changing solution to these challenge ``` or for Windows-based machines - + ```bash .\virtual\Scripts\activate ``` 5. **Install the required packages:** + ```bash pip install -r requirements.txt ``` @@ -161,7 +163,7 @@ This file contains sensitive information. Never share or commit this file to ver - `llm_api_key: [Your OpenAI or Ollama API key or Gemini API key]` - Replace with your OpenAI API key for GPT integration - - To obtain an API key, follow the tutorial at: https://medium.com/@lorenzozar/how-to-get-your-own-openai-api-key-f4d44e60c327 + - To obtain an API key, follow the tutorial at: - Note: You need to add credit to your OpenAI account to use the API. You can add credit by visiting the [OpenAI billing dashboard](https://platform.openai.com/account/billing). - According to the [OpenAI community](https://community.openai.com/t/usage-tier-free-to-tier-1/919150) and our users' reports, right after setting up the OpenAI account and purchasing the required credits, users still have a `Free` account type. This prevents them from having unlimited access to OpenAI models and allows only 200 requests per day. This might cause runtime errors such as: `Error code: 429 - {'error': {'message': 'You exceeded your current quota, please check your plan and billing details. ...}}` @@ -170,7 +172,6 @@ This file contains sensitive information. Never share or commit this file to ver You can find more about your organization limits on the [official page](https://platform.openai.com/settings/organization/limits). - For obtaining Gemini API key visit [Google AI for Devs](https://ai.google.dev/gemini-api/docs/api-key) - ### 2. config.yaml This file defines your job search parameters and bot behavior. Each section contains options that you can customize: @@ -187,10 +188,10 @@ This file defines your job search parameters and bot behavior. Each section cont - `date:` - Choose one time range for job postings by setting it to `true`, others to `false` - - `positions:` - List job titles you're interested in, one per line - Example: + ```yaml positions: - Software Developer @@ -200,11 +201,13 @@ This file defines your job search parameters and bot behavior. Each section cont - `locations:` - List locations you want to search in, one per line - Example: + ```yaml locations: - Italy - London ``` + - `apply_once_at_company: [True/False]` - Set to `True` to apply only once per company, `False` to allow multiple applications per company @@ -215,6 +218,7 @@ This file defines your job search parameters and bot behavior. Each section cont - `companyBlacklist:` - List companies you want to exclude from your search, one per line - Example: + ```yaml companyBlacklist: - Company X @@ -224,28 +228,30 @@ This file defines your job search parameters and bot behavior. Each section cont - `titleBlacklist:` - List keywords in job titles you want to avoid, one per line - Example: + ```yaml titleBlacklist: - Sales - Marketing ``` + #### 2.1 config.yaml - Customize LLM model endpoint - `llm_model_type`: - Choose the model type, supported: openai / ollama / claude / gemini -- `llm_model`: - - Choose the LLM model, currently supported: +- `llm_model`: + - Choose the LLM model, currently supported: - openai: gpt-4o - ollama: llama2, mistral:v0.3 - - claude: any model + - claude: any model - gemini: any model -- `llm_api_url`: +- `llm_api_url`: - Link of the API endpoint for the LLM model - - openai: https://api.pawan.krd/cosmosrp/v1 - - ollama: http://127.0.0.1:11434/ - - claude: https://api.anthropic.com/v1 + - openai: + - ollama: + - claude: - gemini: no api_url - - Note: To run local Ollama, follow the guidelines here: [Guide to Ollama deployment](https://github.com/ollama/ollama) +- Note: To run local Ollama, follow the guidelines here: [Guide to Ollama deployment](https://github.com/ollama/ollama) ### 3. plain_text_resume.yaml @@ -268,6 +274,7 @@ Each section has specific fields to fill out: - **github**: URL to your GitHub profile, if applicable. - **linkedin**: URL to your LinkedIn profile, if applicable. - Example + ```yaml personal_information: name: "Jane" @@ -295,6 +302,7 @@ Each section has specific fields to fill out: - **exam**: A list of courses or subjects taken along with their respective grades. - Example: + ```yaml education_details: - education_level: "Bachelor's Degree" @@ -322,6 +330,7 @@ Each section has specific fields to fill out: - **skills_acquired**: Skills or expertise gained through this role, e.g. "React". - Example: + ```yaml experience_details: - position: "Software Developer" @@ -345,7 +354,8 @@ Each section has specific fields to fill out: - **description**: A brief summary of what the project involves or its purpose. - **link**: URL to the project, if available (e.g., GitHub repository, website). - - Example: + - Example: + ```yaml projects: - name: "Weather App" @@ -362,6 +372,7 @@ Each section has specific fields to fill out: - **description**: A brief explanation of the achievement and its significance. - Example: + ```yaml achievements: - name: "Employee of the Month" @@ -372,10 +383,11 @@ Each section has specific fields to fill out: - `certifications:` - Include any professional certifications you have earned. - - name: "PMP" + - name: "PMP" description: "Certification for project management professionals, issued by the Project Management Institute (PMI)" - Example: + ```yaml certifications: - "Certified Scrum Master" @@ -388,6 +400,7 @@ Each section has specific fields to fill out: - **proficiency**: Your level of proficiency (e.g., Native, Fluent, Intermediate). - Example: + ```yaml languages: - language: "English" @@ -402,6 +415,7 @@ Each section has specific fields to fill out: - **interest**: A list of interests or hobbies. - Example: + ```yaml interests: - "Machine Learning" @@ -416,6 +430,7 @@ Each section has specific fields to fill out: - **notice_period**: The amount of time required before you can start a new role (e.g., "2 weeks", "1 month"). - Example: + ```yaml availability: notice_period: "2 weeks" @@ -426,6 +441,7 @@ Each section has specific fields to fill out: - **salary_range_usd**: The salary range you are expecting, expressed in USD. - Example: + ```yaml salary_expectations: salary_range_usd: "80000 - 100000" @@ -440,6 +456,7 @@ Each section has specific fields to fill out: - **ethnicity**: Your ethnicity. - Example: + ```yaml self_identification: gender: "Female" @@ -468,8 +485,8 @@ Each section has specific fields to fill out: - **legally_allowed_to_work_in_uk**: Whether you are legally allowed to work in the United Kingdom (Yes/No). - **requires_uk_sponsorship**: Whether you require sponsorship to work in the United Kingdom (Yes/No). - - Example: + ```yaml legal_authorization: eu_work_authorization: "Yes" @@ -500,6 +517,7 @@ Each section has specific fields to fill out: - **willing_to_undergo_background_checks**: Whether you are willing to undergo background checks (Yes/No). - Example: + ```yaml work_preferences: remote_work: "Yes" @@ -524,7 +542,7 @@ Inside this folder, you'll find example versions of the key files: These files are already populated with fictitious but realistic data. They show you the correct format and type of information to enter in each file. -#### Usage +#### Using the data_folder_example Using this folder as a guide can be particularly helpful for: @@ -532,7 +550,6 @@ Using this folder as a guide can be particularly helpful for: 2. Seeing examples of valid data for each field 3. Having a reference point while filling out your personal files - ## Usage 0. **Account language** @@ -579,17 +596,17 @@ Using this folder as a guide can be particularly helpful for: python main.py --collect ``` - -### Troubleshooting Common Issues +### Troubleshooting #### 1. OpenAI API Rate Limit Errors **Error Message:** -openai.RateLimitError: Error code: 429 - {'error': {'message': 'You exceeded your current quota, please check your plan and billing details. For more information on this error, read the docs: https://platform.openai.com/docs/guides/error-codes/api-errors.', 'type': 'insufficient_quota', 'param': None, 'code': 'insufficient_quota'}} +openai.RateLimitError: Error code: 429 - {'error': {'message': 'You exceeded your current quota, please check your plan and billing details. For more information on this error, read the docs: .', 'type': 'insufficient_quota', 'param': None, 'code': 'insufficient_quota'}} **Solution:** -- Check your OpenAI API billing settings at https://platform.openai.com/account/billing + +- Check your OpenAI API billing settings at - Ensure you have added a valid payment method to your OpenAI account - Note that ChatGPT Plus subscription is different from API access - If you've recently added funds or upgraded, wait 12-24 hours for changes to take effect @@ -602,6 +619,7 @@ openai.RateLimitError: Error code: 429 - {'error': {'message': 'You exceeded you Exception: No clickable 'Easy Apply' button found **Solution:** + - Ensure that you're logged properly - Check if the job listings you're targeting actually have the "Easy Apply" option - Verify that your search parameters in the `config.yaml` file are correct and returning jobs with the "Easy Apply" button @@ -612,6 +630,7 @@ Exception: No clickable 'Easy Apply' button found **Issue:** Bot provides inaccurate data for experience, CTC, and notice period **Solution:** + - Update prompts for professional experience specificity - Add fields in `config.yaml` for current CTC, expected CTC, and notice period - Modify bot logic to use these new config fields @@ -623,6 +642,7 @@ Exception: No clickable 'Easy Apply' button found yaml.scanner.ScannerError: while scanning a simple key **Solution:** + - Copy example `config.yaml` and modify gradually - Ensure proper YAML indentation and spacing - Use a YAML validator tool @@ -633,6 +653,7 @@ yaml.scanner.ScannerError: while scanning a simple key **Issue:** Bot searches for jobs but continues scrolling without applying **Solution:** + - Check for security checks or CAPTCHAs - Verify `config.yaml` job search parameters - Ensure your account profile meets job requirements @@ -647,7 +668,7 @@ yaml.scanner.ScannerError: while scanning a simple key For further assistance, please create an issue on the [GitHub repository](https://github.com/feder-cr/Auto_Jobs_Applier_AIHawk/issues) with detailed information about your problem, including error messages and your configuration (with sensitive information removed). -## Setup Documents +## Documentation ### Ollama & Gemini Setup @@ -657,13 +678,14 @@ To install and configure **Ollama** and **Gemini**, please refer to the followin Follow the instructions in these guides to ensure proper configuration of **AIHawk** with **Ollama** and **Gemini**. - ### Editing YAML Files + For detailed instructions on editing YAML configuration sections for **AIHawk**, refer to this document: - [Download YAML Editing Guide (PDF)](https://github.com/feder-cr/Auto_Jobs_Applier_AIHawk/blob/main/docs/guide_yaml_sections.pdf) ### Auto-start AIHawk + To make **AIHawk** automatically start when your system boots, follow the steps in this guide: - [Download Auto-start AIHawk Guide (PDF)](https://github.com/feder-cr/Auto_Jobs_Applier_AIHawk/blob/main/docs/guide_to_autostart_aihawk.pdf) @@ -678,7 +700,6 @@ Written by Rushi, [Linkedin](https://www.linkedin.com/in/rushichaganti/), suppor - [OpenAI API Documentation](https://platform.openai.com/docs/) - [Lang Chain Developer Documentation](https://python.langchain.com/v0.2/docs/integrations/components/) - If you encounter any issues, you can open an issue on [GitHub](https://github.com/feder-cr/Auto_Jobs_Applier_AIHawk/issues). Please add valuable details to the subject and to the description. If you need new feature then please reflect this. I'll be more than happy to assist you! @@ -693,10 +714,10 @@ Auto_Jobs_Applier_AIHawk provides a significant advantage in the modern job mark Auto_Jobs_Applier_AIHawk is still in beta, and your feedback, suggestions, and contributions are highly valued. Feel free to open issues, suggest enhancements, or submit pull requests to help improve the project. Let's work together to make Auto_Jobs_Applier_AIHawk an even more powerful tool for job seekers worldwide. - ## License This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. ## Disclaimer + This tool, Auto_Jobs_Applier_AIHawk, is intended for educational purposes only. The creator assumes no responsibility for any consequences arising from its use. Users are advised to comply with the terms of service of relevant platforms and adhere to all applicable laws, regulations, and ethical guidelines. The use of automated tools for job applications may carry risks, including potential impacts on user accounts. Proceed with caution and at your own discretion. diff --git a/src/aihawk_easy_applier.py b/src/aihawk_easy_applier.py index ca30b4e7..a404b2e8 100644 --- a/src/aihawk_easy_applier.py +++ b/src/aihawk_easy_applier.py @@ -35,6 +35,7 @@ def __init__(self, driver: Any, resume_dir: Optional[str], set_old_answers: List self.gpt_answerer = gpt_answerer self.resume_generator_manager = resume_generator_manager self.all_data = self._load_questions_from_json() + self.current_job = None logger.debug("AIHawkEasyApplier initialized successfully") @@ -126,6 +127,8 @@ def job_apply(self, job: Any): job.set_recruiter_link(recruiter_link) logger.debug(f"Recruiter link set: {recruiter_link}") + self.current_job = job + logger.debug("Attempting to click 'Easy Apply' button") actions = ActionChains(self.driver) actions.move_to_element(easy_apply_button).click().perform() @@ -841,6 +844,9 @@ def _save_questions_to_json(self, question_data: dict) -> None: if self._sanitize_text(item['question']) == question_data['question'] and item['type'] == question_data['type']: logger.debug(f"Question already exists in answers.json. Aborting save of: {item['question']}") return + if self.current_job.company in item['answer']: + logger.debug(f"Answer contains the Company name. Aborting save of: {item['question']}") + return logger.debug(f"Saving question data to JSON: {question_data}") try: