После закрытия соискательского API стало ясно, на чём вообще держится проект.
Если бы его логика была пришита к одному способу доступа к HH, систему пришлось бы выбросить.
Но к этому моменту у проекта уже был собственный внутренний каркас. Поэтому менять пришлось не смысл, а только транспорт.
Это хорошо видно по моделям, через которые проект описывает свою работу:
class VacancyCard:
vacancy_id: str
title: str
company: str
url: str
class VacancyDetails:
vacancy_id: str
title: str
company: str
description_text: str
apply_available: bool
class ApplyDraft:
vacancy_id: str
resume_id: str
cover_letter: str
class ApplyResult:
vacancy_id: str
success: bool
status: str
class PrepareApplyOutcome(str, Enum):
PREPARED_DRAFT = "PREPARED_DRAFT"
NEEDS_HUMAN = "NEEDS_HUMAN"
SKIP = "SKIP"
RETRYABLE_TRANSIENT = "RETRYABLE_TRANSIENT"
RATE_LIMITED_EXTERNAL = "RATE_LIMITED_EXTERNAL"
VacancyCard - это краткая модель вакансии на уровне поисковой выдачи.
vacancy_id - внутренний опорный идентификатор, через который система связывает поиск, отклик, логи и антидубли.
title - название вакансии, с которым дальше работает классификация и логика релевантности.
company - работодатель, чтобы проект понимал контекст и фиксировал, куда именно идет отклик.
url - ссылка на вакансию, через которую транспорт открывает карточку уже в браузере.
VacancyDetails - это та же вакансия, но уже после полного открытия и извлечения содержимого.
description_text - полный текст вакансии, на котором строятся анализ, письмо и ответы на вопросы.
apply_available - флаг, который сразу отделяет живую вакансию от уже недоступной для отклика.
ApplyDraft - это уже не вакансия, а подготовленный черновик конкретного отклика.
resume_id - указание, каким именно резюме система должна отвечать на эту вакансию.
cover_letter - готовый текст сопроводительного, собранный под конкретную позицию, а не взятый из шаблона.
ApplyResult - это финальная фиксация того, чем закончилась попытка отклика.
success - бинарный итог, который позволяет быстро отделить удачный проход от неудачного.
status - более точный слой результата, чтобы система различала не просто успех и провал, а конкретный исход.
PrepareApplyOutcome - это самая важная часть, потому что здесь система различает типы состояний до финального submit.
PREPARED_DRAFT - черновик отклика собран и система может двигаться дальше.
NEEDS_HUMAN - страница или форма требуют ручного решения и не должны ломать весь pipeline.
SKIP - вакансия осознанно отбрасывается как нерелевантная или неподходящая.
RETRYABLE_TRANSIENT - произошёл временный технический сбой, после которого можно пробовать снова.
RATE_LIMITED_EXTERNAL - внешний контур HH начал ограничивать процесс, и системе нужен cooldown, а не агрессия.
Вся ценность этого кода в том, что он описывает не интеграцию, а внутренний мир проекта: сущности, этапы и исходы.
Поэтому после закрытия API проект не пришлось пересобирать с нуля — старый транспорт исчез, но логика, модели и state остались.
Оглавление темы 📌
Навигация по проектам канала 📍
Все проекты 🎶
#HHApply@annsFlow
💻 annFlow