feat: add AI cover letter CLI option and update README
- Add CLI toggle for AI-generated cover letters - Update README with cover letter documentation and examples - Display cover letter status in launch summary - Independent control from AI vacancy filtering
This commit is contained in:
		
							parent
							
								
									5973d0f70e
								
							
						
					
					
						commit
						c2971645ad
					
				
							
								
								
									
										39
									
								
								README.md
								
								
								
								
							
							
						
						
									
										39
									
								
								README.md
								
								
								
								
							| 
						 | 
					@ -11,6 +11,7 @@
 | 
				
			||||||
- **🔍 Умный поиск** - Находит релевантные вакансии по ключевым словам
 | 
					- **🔍 Умный поиск** - Находит релевантные вакансии по ключевым словам
 | 
				
			||||||
- **🤖 ИИ-анализ** - Gemini AI оценивает соответствие резюме требованиям
 | 
					- **🤖 ИИ-анализ** - Gemini AI оценивает соответствие резюме требованиям
 | 
				
			||||||
- **📝 Автоматические отклики** - Отправляет заявки на подходящие вакансии
 | 
					- **📝 Автоматические отклики** - Отправляет заявки на подходящие вакансии
 | 
				
			||||||
 | 
					- **✉️ ИИ-сопроводительные письма** - Автоматически генерирует персональные письма для каждой вакансии
 | 
				
			||||||
- **⚙️ Гибкая настройка** - Настраиваемые критерии поиска и фильтрации
 | 
					- **⚙️ Гибкая настройка** - Настраиваемые критерии поиска и фильтрации
 | 
				
			||||||
- **📊 Детальная статистика** - Отчёты о проделанной работе
 | 
					- **📊 Детальная статистика** - Отчёты о проделанной работе
 | 
				
			||||||
- **🛡️ Безопасность** - Имитация человеческого поведения, паузы между действиями
 | 
					- **🛡️ Безопасность** - Имитация человеческого поведения, паузы между действиями
 | 
				
			||||||
| 
						 | 
					@ -81,6 +82,7 @@ python main.py
 | 
				
			||||||
🎯 НАСТРОЙКА ПОИСКА:
 | 
					🎯 НАСТРОЙКА ПОИСКА:
 | 
				
			||||||
Ключевые слова [python junior]: python разработчик
 | 
					Ключевые слова [python junior]: python разработчик
 | 
				
			||||||
Использовать AI фильтрацию? [y/n]: y
 | 
					Использовать AI фильтрацию? [y/n]: y
 | 
				
			||||||
 | 
					Использовать ИИ-сопроводительные письма? [y/n]: y
 | 
				
			||||||
Максимум заявок [40]: 25
 | 
					Максимум заявок [40]: 25
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Начать автоматизацию? [y/n]: y
 | 
					Начать автоматизацию? [y/n]: y
 | 
				
			||||||
| 
						 | 
					@ -132,6 +134,9 @@ class AppConstants:
 | 
				
			||||||
    # ИИ анализ
 | 
					    # ИИ анализ
 | 
				
			||||||
    DEFAULT_AI_THRESHOLD = 0.7
 | 
					    DEFAULT_AI_THRESHOLD = 0.7
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    # Сопроводительные письма
 | 
				
			||||||
 | 
					    USE_AI_COVER_LETTERS = True
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    # Таймауты
 | 
					    # Таймауты
 | 
				
			||||||
    DEFAULT_TIMEOUT = 30
 | 
					    DEFAULT_TIMEOUT = 30
 | 
				
			||||||
    API_PAUSE_SECONDS = 0.5
 | 
					    API_PAUSE_SECONDS = 0.5
 | 
				
			||||||
| 
						 | 
					@ -159,6 +164,40 @@ class AppConstants:
 | 
				
			||||||
   📈 % одобрения: 53.3%
 | 
					   📈 % одобрения: 53.3%
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## ✉️ ИИ-сопроводительные письма
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Как работает автоматическая генерация писем
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1. **Обнаружение возможности** - Ищет кнопку "Добавить сопроводительное письмо"
 | 
				
			||||||
 | 
					2. **Анализ вакансии** - Извлекает требования, обязанности, название и компанию
 | 
				
			||||||
 | 
					3. **Персонализация** - Использует ваши реальные данные из файлов резюме
 | 
				
			||||||
 | 
					4. **Генерация письма** - Gemini AI создает уникальное письмо для каждой вакансии
 | 
				
			||||||
 | 
					5. **Автозаполнение** - Вставляет письмо в поле и отправляет заявку
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Особенности ИИ-писем
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- **Персональные** - Каждое письмо уникально для конкретной вакансии
 | 
				
			||||||
 | 
					- **Честные** - Не придумывает несуществующий опыт
 | 
				
			||||||
 | 
					- **Человечные** - Дружелюбный тон без официоза
 | 
				
			||||||
 | 
					- **Контактные** - Всегда включает контакт "Telegram — @itqen"
 | 
				
			||||||
 | 
					- **Адаптивные** - Работает с любыми типами вакансий
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Пример сгенерированного письма
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					Добрый день!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Заинтересовался вашей вакансией Python-разработчика. 
 | 
				
			||||||
 | 
					У меня есть опыт работы с Python, Django и базами данных, 
 | 
				
			||||||
 | 
					что соответствует вашим требованиям.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Готов обсудить возможности сотрудничества и рассказать 
 | 
				
			||||||
 | 
					подробнее о своем опыте.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					С уважением,
 | 
				
			||||||
 | 
					Telegram — @itqen
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## 📊 Статистика работы
 | 
					## 📊 Статистика работы
 | 
				
			||||||
 | 
					
 | 
				
			||||||
После завершения работы бот предоставляет подробную статистику:
 | 
					После завершения работы бот предоставляет подробную статистику:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -39,6 +39,14 @@ class CLIInterface:
 | 
				
			||||||
            print("⚠️ AI фильтрация недоступна (нет GEMINI_API_KEY)")
 | 
					            print("⚠️ AI фильтрация недоступна (нет GEMINI_API_KEY)")
 | 
				
			||||||
            use_ai = False
 | 
					            use_ai = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        use_ai_cover_letters = True
 | 
				
			||||||
 | 
					        if settings.enable_ai_matching():
 | 
				
			||||||
 | 
					            cover_letter_choice = input("Использовать ИИ-сопроводительные письма? [y/n]: ").lower()
 | 
				
			||||||
 | 
					            use_ai_cover_letters = cover_letter_choice != "n"
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            print("⚠️ ИИ-сопроводительные письма недоступны (нет GEMINI_API_KEY)")
 | 
				
			||||||
 | 
					            use_ai_cover_letters = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        excludes = ", ".join(settings.get_exclude_keywords()[:5])
 | 
					        excludes = ", ".join(settings.get_exclude_keywords()[:5])
 | 
				
			||||||
        print(f"\n🚫 Текущие исключения: {excludes}...")
 | 
					        print(f"\n🚫 Текущие исключения: {excludes}...")
 | 
				
			||||||
        exclude_choice = input("Изменить список исключений? [y/n]: ").lower()
 | 
					        exclude_choice = input("Изменить список исключений? [y/n]: ").lower()
 | 
				
			||||||
| 
						 | 
					@ -56,7 +64,7 @@ class CLIInterface:
 | 
				
			||||||
        except ValueError:
 | 
					        except ValueError:
 | 
				
			||||||
            max_apps = settings.application.max_applications
 | 
					            max_apps = settings.application.max_applications
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return keywords, use_ai, max_apps
 | 
					        return keywords, use_ai, use_ai_cover_letters, max_apps
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @staticmethod
 | 
					    @staticmethod
 | 
				
			||||||
    def _configure_exclude_keywords():
 | 
					    def _configure_exclude_keywords():
 | 
				
			||||||
| 
						 | 
					@ -104,14 +112,16 @@ class CLIInterface:
 | 
				
			||||||
            cli.print_welcome()
 | 
					            cli.print_welcome()
 | 
				
			||||||
            ResumeFileManager.create_sample_files()
 | 
					            ResumeFileManager.create_sample_files()
 | 
				
			||||||
            cli.print_settings_info()
 | 
					            cli.print_settings_info()
 | 
				
			||||||
            keywords, use_ai, max_apps = cli.get_user_preferences()
 | 
					            keywords, use_ai, use_ai_cover_letters, max_apps = cli.get_user_preferences()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            settings.update_search_keywords(keywords)
 | 
					            settings.update_search_keywords(keywords)
 | 
				
			||||||
            settings.application.max_applications = max_apps
 | 
					            settings.application.max_applications = max_apps
 | 
				
			||||||
 | 
					            settings.application.use_ai_cover_letters = use_ai_cover_letters
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            print("\n🎯 ЗАПУСК С ПАРАМЕТРАМИ:")
 | 
					            print("\n🎯 ЗАПУСК С ПАРАМЕТРАМИ:")
 | 
				
			||||||
            print(f"🔍 Поиск: {keywords}")
 | 
					            print(f"🔍 Поиск: {keywords}")
 | 
				
			||||||
            print(f"🤖 AI: {'Включен' if use_ai else 'Отключен'}")
 | 
					            print(f"🤖 AI: {'Включен' if use_ai else 'Отключен'}")
 | 
				
			||||||
 | 
					            print(f"📝 ИИ-письма: {'Включены' if use_ai_cover_letters else 'Отключены'}")
 | 
				
			||||||
            print(f"📊 Максимум заявок: {max_apps}")
 | 
					            print(f"📊 Максимум заявок: {max_apps}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            confirm = input("\nНачать автоматизацию? [y/n]: ").lower()
 | 
					            confirm = input("\nНачать автоматизацию? [y/n]: ").lower()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -65,6 +65,7 @@ class ApplicationConfig:
 | 
				
			||||||
    pause_min: float = 3.0
 | 
					    pause_min: float = 3.0
 | 
				
			||||||
    pause_max: float = 6.0
 | 
					    pause_max: float = 6.0
 | 
				
			||||||
    manual_login: bool = True
 | 
					    manual_login: bool = True
 | 
				
			||||||
 | 
					    use_ai_cover_letters: bool = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@dataclass
 | 
					@dataclass
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -435,6 +435,9 @@ class VacancyApplicator:
 | 
				
			||||||
    def _add_cover_letter_if_possible(self, vacancy: Vacancy) -> None:
 | 
					    def _add_cover_letter_if_possible(self, vacancy: Vacancy) -> None:
 | 
				
			||||||
        """Добавление сопроводительного письма если возможно"""
 | 
					        """Добавление сопроводительного письма если возможно"""
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
 | 
					            if not settings.application.use_ai_cover_letters:
 | 
				
			||||||
 | 
					                logger.info("ИИ-сопроводительные письма отключены в настройках")
 | 
				
			||||||
 | 
					                return
 | 
				
			||||||
            cover_letter_button_selectors = [
 | 
					            cover_letter_button_selectors = [
 | 
				
			||||||
                '[data-qa="add-cover-letter"]',
 | 
					                '[data-qa="add-cover-letter"]',
 | 
				
			||||||
                'button[data-qa*="cover-letter"]',
 | 
					                'button[data-qa*="cover-letter"]',
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue