Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
25bc4cc
делает аутентификацию через oauth2 и сохранение токена
fovendor Oct 8, 2025
86d3867
добавляет флаг переаутентификации, чтобы залогиниться в другой аккаунт
fovendor Oct 8, 2025
8064aec
добавляет sqlalchemy и меняет логику приложения на работу с БД
fovendor Oct 8, 2025
cecdd4e
добавляет профили пользователей в БД + таблицу app_state с активным п…
fovendor Oct 8, 2025
238ba6a
добавляет переключение между профилями, добавляет TUI
fovendor Oct 8, 2025
fcf359e
исправляет поведение TUI, биндит q и й
fovendor Oct 8, 2025
6f633f6
исправляет отображение таблицы и загрузку данных + стили
fovendor Oct 9, 2025
ef383b2
меняет схему БД для новой архитектуры
fovendor Oct 9, 2025
1c26a7d
добавляет логирование, синхронизацию откликов
fovendor Oct 9, 2025
89f21a8
починяет биндинги
fovendor Oct 9, 2025
d845e1e
чинит эндпоинт откликов и логи
fovendor Oct 10, 2025
2117a74
Ignore Python caches
fovendor Oct 10, 2025
4cf993f
рефакторит схему бд, добавляет кэш описания вакансий, меняет shedule …
fovendor Oct 10, 2025
be2c7bd
делает markdown-форматирование в выводе описания вакансий, красивое
fovendor Oct 10, 2025
59409f5
рефакторит tui чтобы работал мультиселект + мелкие улучшения
fovendor Oct 10, 2025
139bb25
чинит экран выбора профиля, улучшает тайминги UX, чинит даблтап для в…
fovendor Oct 10, 2025
ed6b5a6
добавляет возможность менять конфигурацию для каждого профиля прямо и…
fovendor Oct 14, 2025
020bb9a
Убирает ридми, ибо не актуально для этой ветки
fovendor Oct 14, 2025
2aad6db
Мощно рефакторит внешний вид, добавляет стили, делает UX/UI консистен…
fovendor Oct 15, 2025
2079cd4
рефакторит стили
fovendor Oct 16, 2025
81897c2
исправляет стили у экрана конфигурации
fovendor Oct 16, 2025
85bb6ba
расширяет схему БД для справочников areas и professional_roles, созда…
fovendor Oct 16, 2025
60b1c3c
добавляет мегафичу по интерактивному выбору регионов/городов и профес…
fovendor Oct 16, 2025
96f076f
исправляет багу и кривой UX, когда нельзя было очистить выбранный город
fovendor Oct 16, 2025
dc54f60
чинит выбор null в work-format
fovendor Oct 16, 2025
c049c75
Update README.md
fovendor Oct 16, 2025
c0d7f40
Исправляет исключения в gitignore
fovendor Oct 17, 2025
8d6281e
Починяет отправку откликов и правильное их логирование
fovendor Oct 17, 2025
6d6da40
Добавляет пагинацию (без стилей)
fovendor Oct 17, 2025
14a4c82
убирает поле с id резюме на экране выбора резюме внутри профиля
fovendor Oct 18, 2025
5009637
Исправляет недочёты в стилях и выводит уровень ЗП всегда
fovendor Oct 18, 2025
38a9fe4
Дорабатывает злоеб***ю пагинацию, теперь работает
fovendor Oct 18, 2025
825b8fd
Улучшает стили пагинации, добавляет обновление списков резюме после и…
fovendor Oct 19, 2025
9668a7d
выносит нужные переменные в константы, рефакторит код и убирает много…
fovendor Oct 20, 2025
519e49e
Рефакторит стили
fovendor Oct 20, 2025
6d552b3
Изменяет компоновку на экране конфигурации, рефакторит кодстайл стиле…
fovendor Oct 20, 2025
4cd6d10
улучшает стиль в списке вакансий
fovendor Oct 21, 2025
e209a75
Использует grid-gutter-horizontal для вывода колонок в настройках
fovendor Oct 21, 2025
c29e785
Чинит давний баг с ошибками в определении событий мыши
fovendor Oct 21, 2025
26de9aa
Чинит баг, при котором нельзя покинуть экран подтверждения отклика
fovendor Oct 21, 2025
61d1c99
Добавляет модалку в окно конфига
fovendor Oct 21, 2025
eee1ee2
Поправляет стили модалки
fovendor Oct 21, 2025
74e697e
Поправляет стили, добавляет компонент decline
fovendor Oct 22, 2025
e81478f
Заменяет экран отправки откликов на красивую модалку
fovendor Oct 22, 2025
34c1e2c
Добавляет экран просмотра истории откликов
fovendor Oct 22, 2025
a7e41b2
Добавляет настройки отображения воркспейсов на экран конфига
fovendor Oct 23, 2025
38582d6
Исправляет стили нового блока настроек
fovendor Oct 23, 2025
9809310
Меняет единицы измерения настроек ширины колонок
fovendor Oct 23, 2025
c5d28e6
Фиксит мелкую неточность стилей
fovendor Oct 23, 2025
0eae4cc
Рефакторит базу и переписывает маппинги статусов откликов, добавляет …
fovendor Oct 23, 2025
d8487b7
Исправляет поведение прелоадера в воркспейсе деталей вакансии на экра…
fovendor Oct 24, 2025
0919a3a
Подготовка к тестированию и загрузке в PyPL
fovendor Oct 26, 2025
b254dff
Удаляет локальную конфигурацию ключей и добавляет редирект на сервер
fovendor Oct 26, 2025
9d9040d
Merge branch 'master' into refactor
fovendor Oct 26, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/publish-to-pypi.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# заглушка
13 changes: 13 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Python cache
**/__pycache__/
*.py[cod]
*.pyo

# Частые кэши инструментов
.pytest_cache/
.mypy_cache/
.ruff_cache/
*.cache/

# Кэш приложения
/cache-dir/
Empty file added LICENSE
Empty file.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# hhcli

description = "Неофициальный CLI-клиент для поиска работы и откликов на hh.ru"
17 changes: 17 additions & 0 deletions hhcli/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from hhcli.ui import ( # noqa: F401
AVAILABLE_THEMES,
ConfigScreen,
CssManager,
HHCliApp,
HHCliThemeBase,
list_themes,
)

__all__ = [
"CssManager",
"HHCliThemeBase",
"AVAILABLE_THEMES",
"list_themes",
"ConfigScreen",
"HHCliApp",
]
361 changes: 361 additions & 0 deletions hhcli/client.py

Large diffs are not rendered by default.

136 changes: 136 additions & 0 deletions hhcli/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
from enum import Enum


class SearchMode(Enum):
"""Режимы поиска вакансий."""
AUTO = "auto"
MANUAL = "manual"


class AppStateKeys:
"""Ключи для таблицы состояния приложения app_state."""
ACTIVE_PROFILE = "active_profile"
AREAS_HASH = "areas_hash"
AREAS_UPDATED_AT = "areas_updated_at"
PROFESSIONAL_ROLES_HASH = "professional_roles_hash"
PROFESSIONAL_ROLES_UPDATED_AT = "professional_roles_updated_at"
LAST_NEGOTIATION_SYNC_PREFIX = "last_negotiation_sync_"


class ConfigKeys:
"""Ключи для конфигурации профиля."""
TEXT_INCLUDE = "text_include"
NEGATIVE = "negative"
WORK_FORMAT = "work_format"
AREA_ID = "area_id"
SEARCH_FIELD = "search_field"
PERIOD = "period"
ROLE_IDS_CONFIG = "role_ids_config"
COVER_LETTER = "cover_letter"
SKIP_APPLIED_IN_SAME_COMPANY = "skip_applied_in_same_company"
DEDUPLICATE_BY_NAME_AND_COMPANY = "deduplicate_by_name_and_company"
STRIKETHROUGH_APPLIED_VAC = "strikethrough_applied_vac"
STRIKETHROUGH_APPLIED_VAC_NAME = "strikethrough_applied_vac_name"
THEME = "theme"
VACANCY_LEFT_PANE_PERCENT = "vacancy_left_pane_percent"
VACANCY_COL_INDEX_WIDTH = "vacancy_col_index_width"
VACANCY_COL_TITLE_WIDTH = "vacancy_col_title_width"
VACANCY_COL_COMPANY_WIDTH = "vacancy_col_company_width"
VACANCY_COL_PREVIOUS_WIDTH = "vacancy_col_previous_width"
HISTORY_LEFT_PANE_PERCENT = "history_left_pane_percent"
HISTORY_COL_INDEX_WIDTH = "history_col_index_width"
HISTORY_COL_TITLE_WIDTH = "history_col_title_width"
HISTORY_COL_COMPANY_WIDTH = "history_col_company_width"
HISTORY_COL_STATUS_WIDTH = "history_col_status_width"
HISTORY_COL_SENT_WIDTH = "history_col_sent_width"
HISTORY_COL_DATE_WIDTH = "history_col_date_width"

LAYOUT_WIDTH_KEYS: tuple[str, ...] = (
ConfigKeys.VACANCY_LEFT_PANE_PERCENT,
ConfigKeys.VACANCY_COL_INDEX_WIDTH,
ConfigKeys.VACANCY_COL_TITLE_WIDTH,
ConfigKeys.VACANCY_COL_COMPANY_WIDTH,
ConfigKeys.VACANCY_COL_PREVIOUS_WIDTH,
ConfigKeys.HISTORY_LEFT_PANE_PERCENT,
ConfigKeys.HISTORY_COL_INDEX_WIDTH,
ConfigKeys.HISTORY_COL_TITLE_WIDTH,
ConfigKeys.HISTORY_COL_COMPANY_WIDTH,
ConfigKeys.HISTORY_COL_STATUS_WIDTH,
ConfigKeys.HISTORY_COL_SENT_WIDTH,
ConfigKeys.HISTORY_COL_DATE_WIDTH,
)

class ApiErrorReason:
"""
Строковые идентификаторы причин ответа API при отклике на вакансию.
"""
APPLIED = "applied"
ALREADY_APPLIED = "already_applied"
TEST_REQUIRED = "test_required"
QUESTIONS_REQUIRED = "questions_required"
NEGOTIATIONS_FORBIDDEN = "negotiations_forbidden"
RESUME_NOT_PUBLISHED = "resume_not_published"
CONDITIONS_NOT_MET = "conditions_not_met"
NOT_FOUND = "not_found"
BAD_ARGUMENT = "bad_argument"
UNKNOWN_API_ERROR = "unknown_api_error"
NETWORK_ERROR = "network_error"


ERROR_REASON_LABELS: dict[str, str] = {
ApiErrorReason.APPLIED: "Отклик отправлен",
ApiErrorReason.ALREADY_APPLIED: "Вы уже откликались",
ApiErrorReason.TEST_REQUIRED: "Требуется пройти тест",
ApiErrorReason.QUESTIONS_REQUIRED: "Требуются ответы на вопросы",
ApiErrorReason.NEGOTIATIONS_FORBIDDEN: "Работодатель запретил отклики",
ApiErrorReason.RESUME_NOT_PUBLISHED: "Резюме не опубликовано",
ApiErrorReason.CONDITIONS_NOT_MET: "Не выполнены условия",
ApiErrorReason.NOT_FOUND: "Вакансия в архиве",
ApiErrorReason.BAD_ARGUMENT: "Некорректные параметры",
ApiErrorReason.UNKNOWN_API_ERROR: "Неизвестная ошибка API",
ApiErrorReason.NETWORK_ERROR: "Ошибка сети",
}

DELIVERED_STATUS_CODES: frozenset[str] = frozenset({
"applied",
"responded",
"response",
"invited",
"interview",
"interview_assigned",
"interview_scheduled",
"offer",
"offer_made",
"rejected",
"declined",
"canceled",
"cancelled",
"discard",
"employer_viewed",
"viewed",
"seen",
"in_progress",
"considering",
"processing",
"accepted",
"hired",
})

FAILED_STATUS_CODES: frozenset[str] = frozenset({"failed"})


class LogSource:
"""Источники для логирования в базу данных."""
API_CLIENT = "APIClient"
OAUTH = "OAuth"
SYNC_ENGINE = "SyncEngine"
CONFIG_SCREEN = "ConfigScreen"
MAIN = "Main"
REFERENCE_DATA = "ReferenceData"
VACANCY_LIST_FETCH = "VacancyListFetch"
VACANCY_LIST_SCREEN = "VacancyListScreen"
CACHE = "Cache"
RESUME_SCREEN = "ResumeScreen"
SEARCH_MODE_SCREEN = "SearchModeScreen"
PROFILE_SCREEN = "ProfileScreen"
TUI = "TUI"
Loading