hh-bot/hh_bot/config/settings.py

204 lines
5.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import os
from dataclasses import dataclass
from pathlib import Path
class AppConstants:
HH_BASE_URL = "https://api.hh.ru"
HH_SITE_URL = "https://hh.ru"
GEMINI_BASE_URL = "https://generativelanguage.googleapis.com/v1beta"
GEMINI_MODEL = "gemini-2.0-flash"
DEFAULT_TIMEOUT = 20
API_PAUSE_SECONDS = 0.5
AI_REQUEST_PAUSE = 1
MAX_VACANCIES_PER_PAGE = 50
MAX_SEARCH_PAGES = 5
DEFAULT_MAX_APPLICATIONS = 40
DEFAULT_EXPERIENCE_FILE = "data/experience.txt"
DEFAULT_ABOUT_FILE = "data/about_me.txt"
DEFAULT_SKILLS_FILE = "data/skills.txt"
DEFAULT_AI_THRESHOLD = 0.7
MIN_AI_SCORE = 0.0
MAX_AI_SCORE = 1.0
SHORT_SEPARATOR_LENGTH = 50
LONG_SEPARATOR_LENGTH = 60
SHORT_TEXT_LIMIT = 50
MEDIUM_TEXT_LIMIT = 60
GEMINI_TEMPERATURE = 0.3
GEMINI_MAX_OUTPUT_TOKENS = 1000
LOG_FILE_MAX_SIZE_MB = 10
PERCENT_MULTIPLIER = 100
@dataclass
class HHSearchConfig:
keywords: str = "python"
area: str = "1"
experience: str = "noExperience"
per_page: int = AppConstants.MAX_VACANCIES_PER_PAGE
max_pages: int = 3
order_by: str = "publication_time"
@dataclass
class BrowserConfig:
headless: bool = False
wait_timeout: int = 15
page_load_timeout: int = 30
implicit_wait: int = 10
@dataclass
class ApplicationConfig:
max_applications: int = AppConstants.DEFAULT_MAX_APPLICATIONS
pause_min: float = 3.0
pause_max: float = 6.0
manual_login: bool = True
@dataclass
class GeminiConfig:
api_key: str = ""
model: str = AppConstants.GEMINI_MODEL
base_url: str = AppConstants.GEMINI_BASE_URL
match_threshold: float = AppConstants.DEFAULT_AI_THRESHOLD
@dataclass
class ResumeConfig:
experience_file: str = AppConstants.DEFAULT_EXPERIENCE_FILE
about_me_file: str = AppConstants.DEFAULT_ABOUT_FILE
skills_file: str = AppConstants.DEFAULT_SKILLS_FILE
class ResumeFileManager:
@staticmethod
def create_sample_files() -> None:
data_dir = Path("data")
data_dir.mkdir(exist_ok=True)
experience_file = data_dir / "experience.txt"
if not experience_file.exists():
experience_file.write_text(
"""
Опыт работы:
- ноль
""".strip(),
encoding="utf-8",
)
print(f"✅ Создан файл: {experience_file}")
about_file = data_dir / "about_me.txt"
if not about_file.exists():
about_file.write_text(
"""
О себе:
Котенок.
""".strip(),
encoding="utf-8",
)
print(f"✅ Создан файл: {about_file}")
skills_file = data_dir / "skills.txt"
if not skills_file.exists():
skills_file.write_text(
"""
Технические навыки:
- Мяу
""".strip(),
encoding="utf-8",
)
print(f"✅ Создан файл: {skills_file}")
class UIFormatter:
@staticmethod
def create_separator(long: bool = False) -> str:
length = (
AppConstants.LONG_SEPARATOR_LENGTH
if long
else AppConstants.SHORT_SEPARATOR_LENGTH
)
return "=" * length
@staticmethod
def truncate_text(text: str, medium: bool = False) -> str:
limit = (
AppConstants.MEDIUM_TEXT_LIMIT if medium else AppConstants.SHORT_TEXT_LIMIT
)
return text[:limit]
@staticmethod
def format_percentage(value: float, total: float) -> str:
if total <= 0:
return "0.0%"
percentage = (value / total) * AppConstants.PERCENT_MULTIPLIER
return f"{percentage:.1f}%"
@staticmethod
def print_section_header(title: str, long: bool = False) -> None:
separator = UIFormatter.create_separator(long)
print(f"\n{separator}")
print(title)
print(separator)
class Settings:
def __init__(self):
self._load_env()
self.hh_search = HHSearchConfig()
self.browser = BrowserConfig()
self.application = ApplicationConfig()
self.gemini = GeminiConfig(api_key=os.getenv("GEMINI_API_KEY", ""))
self.resume = ResumeConfig()
self._validate_config()
def _load_env(self) -> None:
try:
from dotenv import load_dotenv
load_dotenv()
except ImportError:
print("💡 Установите python-dotenv для работы с .env файлами")
def _validate_config(self) -> None:
if not self.gemini.api_key:
print("⚠️ GEMINI_API_KEY не установлен в переменных окружения")
data_dir = Path("data")
data_dir.mkdir(exist_ok=True)
logs_dir = Path("logs")
logs_dir.mkdir(exist_ok=True)
def update_search_keywords(self, keywords: str) -> None:
self.hh_search.keywords = keywords
print(f"🔄 Обновлены ключевые слова: {keywords}")
def enable_ai_matching(self) -> bool:
return bool(self.gemini.api_key)
def get_exclude_keywords(self) -> list:
return ["стажер", "cv"]
settings = Settings()