hh-applicant-tool 0.5.1__tar.gz → 0.5.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of hh-applicant-tool might be problematic. Click here for more details.

Files changed (29) hide show
  1. {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/PKG-INFO +37 -5
  2. {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/README.md +36 -4
  3. hh_applicant_tool-0.5.3/hh_applicant_tool/ai/blackbox.py +55 -0
  4. hh_applicant_tool-0.5.3/hh_applicant_tool/operations/__init__.py +0 -0
  5. {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/operations/apply_similar.py +51 -7
  6. {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/operations/clear_negotiations.py +18 -5
  7. hh_applicant_tool-0.5.3/hh_applicant_tool/operations/config.py +36 -0
  8. {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/operations/reply_employers.py +4 -4
  9. {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/pyproject.toml +1 -1
  10. {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/__init__.py +0 -0
  11. {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/__main__.py +0 -0
  12. {hh_applicant_tool-0.5.1/hh_applicant_tool/operations → hh_applicant_tool-0.5.3/hh_applicant_tool/ai}/__init__.py +0 -0
  13. {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/api/__init__.py +0 -0
  14. {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/api/client.py +0 -0
  15. {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/api/errors.py +0 -0
  16. {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/color_log.py +0 -0
  17. {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/constants.py +0 -0
  18. {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/main.py +0 -0
  19. {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/mixins.py +0 -0
  20. {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/operations/authorize.py +0 -0
  21. {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/operations/call_api.py +0 -0
  22. {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/operations/get_employer_contacts.py +0 -0
  23. {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/operations/list_resumes.py +0 -0
  24. {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/operations/refresh_token.py +0 -0
  25. {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/operations/update_resumes.py +0 -0
  26. {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/operations/whoami.py +0 -0
  27. {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/telemetry_client.py +0 -0
  28. {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/types.py +0 -0
  29. {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hh-applicant-tool
3
- Version: 0.5.1
3
+ Version: 0.5.3
4
4
  Summary:
5
5
  Author: Senior YAML Developer
6
6
  Author-email: yamldeveloper@proton.me
@@ -32,7 +32,9 @@ Description-Content-Type: text/markdown
32
32
 
33
33
  ### Описание
34
34
 
35
- Утилита для успешных волчат, служащая для автоматизации действий на HH.RU таких как рассылка откликов на подходящие вакансии и обновление всех резюме. Но данная утилита больше чем просто спамилка отзывами, вы так же выступаете в роли тайного агента, и если в списке подходящих вакансий встречается отказ, она возвращает ссылку на обсуждение работодателя в группе [Отзывы о работодателях с HH.RU](https://t.me/otzyvy_headhunter). Там вы можете написать отзыв о работодателе и почитать чужие. Для этого собираются данные о работодателях и их вакансиях (персональные данные пользователя не передаются ни в каком виде). Отправку данных на сервер разработчика можно отключить, но тогда вы не получите ссылку на обсуждение, а так же не сможете пожаловаться на неадекватного мудака, выкатившего отказ после "небольшого" тестового задания на недельку. Через сайты на таких жаловаться бесполезно: владелец сайта за деньги или после угроз судом удаляют отзывы. Единственное место где можно написать отзыв — это **Telegram**.
35
+ > Утилита для генерации сопроводительного письма может использовать AI
36
+
37
+ Утилита для успешных волчат и старых волков с опытом, служащая для автоматизации действий на HH.RU таких как рассылка откликов на подходящие вакансии и обновление всех резюме (бесплатный аналог услуги на HH). Но данная утилита больше чем просто спамилка откликами, вы так же выступаете в роли тайного агента, и если в списке подходящих вакансий встречается отказ, она возвращает ссылку на обсуждение работодателя в группе [Отзывы о работодателях с HH.RU](https://t.me/otzyvy_headhunter). Там вы можете написать отзыв о работодателе и почитать чужие. Для этого собираются данные о работодателях и их вакансиях (персональные данные пользователя не передаются ни в каком виде). Отправку данных на сервер разработчика можно отключить, но тогда вы не получите ссылку на обсуждение, а так же не сможете пожаловаться на неадекватного мудака, выкатившего отказ после "небольшого" тестового задания на недельку. Через сайты на таких жаловаться бесполезно: владелец сайта за деньги или после угроз судом удаляют отзывы. Единственное место где можно написать отзыв — это **Telegram**.
36
38
 
37
39
  Работает с Python >= 3.10. Нужную версию Python можно поставить через
38
40
  asdf/pyenv/conda и что-то еще.
@@ -43,11 +45,10 @@ asdf/pyenv/conda и что-то еще.
43
45
 
44
46
  ![image](https://github.com/user-attachments/assets/a0cce1aa-884b-4d84-905a-3bb207eba4a3)
45
47
 
48
+ > Если в веб-интерфейсе выставить фильтры, то они будут применяться в скрипте при отклике на подходящие
46
49
 
47
50
  ### Предыстория
48
51
 
49
- Был один знакомый знакомого, который работал хрюшей. Этот чувак не заморачивался с чтением резюме, а тупо скриптами рассылал предложения о работе... Бывают, конечно, филологини, которые не могут отличить Java от JavaScript, но я думаю, что <s>в значительном числе случаев, тут имеют место такие вот рассылки</s> они просто идиотки... И я тупо стал спамить как они. Мне уже было просто лень читать весь этот бред, что пишут долбоебы в описании вакансий. Там стандартное ООП, алгоритмы и прочая хуета... Вроде все подходят, а вроде хз — все не мое.
50
-
51
52
  Долгое время я делал массовые заявки с помощью консоли браузера:
52
53
 
53
54
  ```js
@@ -167,6 +168,11 @@ $ hh-applicant-tool refresh-token
167
168
  | **macOS** | `~/Library/Application Support/hh-applicant-tool/config.json` |
168
169
  | **Linux** | `~/.config/hh-applicant-tool/config.json` |
169
170
 
171
+ Полный путь до конфигурационного файла можно вывести с помощью команды:
172
+
173
+ ```bash
174
+ hh-applicant-tool config -p
175
+ ```
170
176
 
171
177
  Через конфиг можно задать дополнительные настройки:
172
178
 
@@ -239,11 +245,12 @@ https://hh.ru/employer/1918903
239
245
  | **whoami** | Выводит информацию об авторизованном пользователе |
240
246
  | **list-resumes** | Список резюме |
241
247
  | **update-resumes** | Обновить все резюме. Аналогично нажатию кнопки «Обновить дату». |
242
- | **apply-similar** | Откликнуться на все подходящие вакансии. Лимит = 200 в день. На HH есть спам-фильтры, так что лучше не рассылайте отклики со ссылками. |
248
+ | **apply-similar** | Откликнуться на все подходящие вакансии. Лимит = 200 в день. На HH есть спам-фильтры, так что лучше не рассылайте отклики со ссылками, иначе рискуете попасть в теневой бан. |
243
249
  | **reply-employers** | Ответить во все чаты с работодателями, где нет ответа либо не прочитали ваш предыдущий ответ |
244
250
  | **clear-negotiations** | Удаляет отказы и отменяет заявки, которые долго висят |
245
251
  | **call-api** | Вызов произвольного метода API с выводом результата. |
246
252
  | **refresh-token** | Обновляет access_token. |
253
+ | **config** | Редактировать конфигурационный файл. |
247
254
  | **get-employer-contacts** | Получить список контактов работодателя, даже если тот не высылал приглашения. Это функционал для избранных, но в группе есть бесплатный бот с тем же функционалом. |
248
255
 
249
256
  ### Формат текста сообщений
@@ -277,6 +284,31 @@ https://hh.ru/employer/1918903
277
284
  Привет, как ты?
278
285
  ```
279
286
 
287
+ ### Использование AI для генерации сопроводительного письма
288
+
289
+ * Перейдите на сайт [blackbox.ai](https://www.blackbox.ai) и создайте чат.
290
+ * В первом сообщении опишите свой опыт и тп.
291
+ * Далее откройте devtools, нажав `F12`.
292
+ * Во вкладке `Network` последним должен быть POST-запрос на `https://www.blackbox.ai/api/chat`.
293
+ * Запустите редактирование конфига:
294
+ ```sh
295
+ hh-applicant-tool config
296
+ ```
297
+ * Измените конфиг:
298
+ ```json
299
+ {
300
+ // ...
301
+ "blackbox": {
302
+ "session_id": "<В заголовках запроса найдите Cookie, скопируйте сюда значение sessionId до ;>",
303
+ "chat_payload": <Сюда вставьте тело запроса типа {"messages":[{"id":"IXqdOx9","content":"Я программист fullstack-разработчик...","role":"user"}],"id":"IXqdOx9","previewToken":null,"userId":null,...,"webSearchModePrompt":false,"deepSearchMode":false}>
304
+ }
305
+ }
306
+ ```
307
+ * Пример рассылки откликов с генерированным письмом:
308
+ ```sh
309
+ hh-applicant-tool apply-similar -f --ai
310
+ ```
311
+
280
312
  ### Написание плагинов
281
313
 
282
314
  Утилита использует систему плагинов. Все они лежат в [operations](https://github.com/s3rgeym/hh-applicant-tool/tree/main/hh_applicant_tool/operations). Модули расположенные там автоматически добавляются как доступные операции. За основу для своего плагина можно взять [whoami.py](https://github.com/s3rgeym/hh-applicant-tool/tree/main/hh_applicant_tool/operations/whoami.py).
@@ -13,7 +13,9 @@
13
13
 
14
14
  ### Описание
15
15
 
16
- Утилита для успешных волчат, служащая для автоматизации действий на HH.RU таких как рассылка откликов на подходящие вакансии и обновление всех резюме. Но данная утилита больше чем просто спамилка отзывами, вы так же выступаете в роли тайного агента, и если в списке подходящих вакансий встречается отказ, она возвращает ссылку на обсуждение работодателя в группе [Отзывы о работодателях с HH.RU](https://t.me/otzyvy_headhunter). Там вы можете написать отзыв о работодателе и почитать чужие. Для этого собираются данные о работодателях и их вакансиях (персональные данные пользователя не передаются ни в каком виде). Отправку данных на сервер разработчика можно отключить, но тогда вы не получите ссылку на обсуждение, а так же не сможете пожаловаться на неадекватного мудака, выкатившего отказ после "небольшого" тестового задания на недельку. Через сайты на таких жаловаться бесполезно: владелец сайта за деньги или после угроз судом удаляют отзывы. Единственное место где можно написать отзыв — это **Telegram**.
16
+ > Утилита для генерации сопроводительного письма может использовать AI
17
+
18
+ Утилита для успешных волчат и старых волков с опытом, служащая для автоматизации действий на HH.RU таких как рассылка откликов на подходящие вакансии и обновление всех резюме (бесплатный аналог услуги на HH). Но данная утилита больше чем просто спамилка откликами, вы так же выступаете в роли тайного агента, и если в списке подходящих вакансий встречается отказ, она возвращает ссылку на обсуждение работодателя в группе [Отзывы о работодателях с HH.RU](https://t.me/otzyvy_headhunter). Там вы можете написать отзыв о работодателе и почитать чужие. Для этого собираются данные о работодателях и их вакансиях (персональные данные пользователя не передаются ни в каком виде). Отправку данных на сервер разработчика можно отключить, но тогда вы не получите ссылку на обсуждение, а так же не сможете пожаловаться на неадекватного мудака, выкатившего отказ после "небольшого" тестового задания на недельку. Через сайты на таких жаловаться бесполезно: владелец сайта за деньги или после угроз судом удаляют отзывы. Единственное место где можно написать отзыв — это **Telegram**.
17
19
 
18
20
  Работает с Python >= 3.10. Нужную версию Python можно поставить через
19
21
  asdf/pyenv/conda и что-то еще.
@@ -24,11 +26,10 @@ asdf/pyenv/conda и что-то еще.
24
26
 
25
27
  ![image](https://github.com/user-attachments/assets/a0cce1aa-884b-4d84-905a-3bb207eba4a3)
26
28
 
29
+ > Если в веб-интерфейсе выставить фильтры, то они будут применяться в скрипте при отклике на подходящие
27
30
 
28
31
  ### Предыстория
29
32
 
30
- Был один знакомый знакомого, который работал хрюшей. Этот чувак не заморачивался с чтением резюме, а тупо скриптами рассылал предложения о работе... Бывают, конечно, филологини, которые не могут отличить Java от JavaScript, но я думаю, что <s>в значительном числе случаев, тут имеют место такие вот рассылки</s> они просто идиотки... И я тупо стал спамить как они. Мне уже было просто лень читать весь этот бред, что пишут долбоебы в описании вакансий. Там стандартное ООП, алгоритмы и прочая хуета... Вроде все подходят, а вроде хз — все не мое.
31
-
32
33
  Долгое время я делал массовые заявки с помощью консоли браузера:
33
34
 
34
35
  ```js
@@ -148,6 +149,11 @@ $ hh-applicant-tool refresh-token
148
149
  | **macOS** | `~/Library/Application Support/hh-applicant-tool/config.json` |
149
150
  | **Linux** | `~/.config/hh-applicant-tool/config.json` |
150
151
 
152
+ Полный путь до конфигурационного файла можно вывести с помощью команды:
153
+
154
+ ```bash
155
+ hh-applicant-tool config -p
156
+ ```
151
157
 
152
158
  Через конфиг можно задать дополнительные настройки:
153
159
 
@@ -220,11 +226,12 @@ https://hh.ru/employer/1918903
220
226
  | **whoami** | Выводит информацию об авторизованном пользователе |
221
227
  | **list-resumes** | Список резюме |
222
228
  | **update-resumes** | Обновить все резюме. Аналогично нажатию кнопки «Обновить дату». |
223
- | **apply-similar** | Откликнуться на все подходящие вакансии. Лимит = 200 в день. На HH есть спам-фильтры, так что лучше не рассылайте отклики со ссылками. |
229
+ | **apply-similar** | Откликнуться на все подходящие вакансии. Лимит = 200 в день. На HH есть спам-фильтры, так что лучше не рассылайте отклики со ссылками, иначе рискуете попасть в теневой бан. |
224
230
  | **reply-employers** | Ответить во все чаты с работодателями, где нет ответа либо не прочитали ваш предыдущий ответ |
225
231
  | **clear-negotiations** | Удаляет отказы и отменяет заявки, которые долго висят |
226
232
  | **call-api** | Вызов произвольного метода API с выводом результата. |
227
233
  | **refresh-token** | Обновляет access_token. |
234
+ | **config** | Редактировать конфигурационный файл. |
228
235
  | **get-employer-contacts** | Получить список контактов работодателя, даже если тот не высылал приглашения. Это функционал для избранных, но в группе есть бесплатный бот с тем же функционалом. |
229
236
 
230
237
  ### Формат текста сообщений
@@ -258,6 +265,31 @@ https://hh.ru/employer/1918903
258
265
  Привет, как ты?
259
266
  ```
260
267
 
268
+ ### Использование AI для генерации сопроводительного письма
269
+
270
+ * Перейдите на сайт [blackbox.ai](https://www.blackbox.ai) и создайте чат.
271
+ * В первом сообщении опишите свой опыт и тп.
272
+ * Далее откройте devtools, нажав `F12`.
273
+ * Во вкладке `Network` последним должен быть POST-запрос на `https://www.blackbox.ai/api/chat`.
274
+ * Запустите редактирование конфига:
275
+ ```sh
276
+ hh-applicant-tool config
277
+ ```
278
+ * Измените конфиг:
279
+ ```json
280
+ {
281
+ // ...
282
+ "blackbox": {
283
+ "session_id": "<В заголовках запроса найдите Cookie, скопируйте сюда значение sessionId до ;>",
284
+ "chat_payload": <Сюда вставьте тело запроса типа {"messages":[{"id":"IXqdOx9","content":"Я программист fullstack-разработчик...","role":"user"}],"id":"IXqdOx9","previewToken":null,"userId":null,...,"webSearchModePrompt":false,"deepSearchMode":false}>
285
+ }
286
+ }
287
+ ```
288
+ * Пример рассылки откликов с генерированным письмом:
289
+ ```sh
290
+ hh-applicant-tool apply-similar -f --ai
291
+ ```
292
+
261
293
  ### Написание плагинов
262
294
 
263
295
  Утилита использует систему плагинов. Все они лежат в [operations](https://github.com/s3rgeym/hh-applicant-tool/tree/main/hh_applicant_tool/operations). Модули расположенные там автоматически добавляются как доступные операции. За основу для своего плагина можно взять [whoami.py](https://github.com/s3rgeym/hh-applicant-tool/tree/main/hh_applicant_tool/operations/whoami.py).
@@ -0,0 +1,55 @@
1
+ import logging
2
+ from copy import deepcopy
3
+
4
+ import requests
5
+
6
+ logger = logging.getLogger(__package__)
7
+
8
+
9
+ class BlackboxError(Exception):
10
+ pass
11
+
12
+
13
+ class BlackboxChat:
14
+ chat_endpoint: str = "https://www.blackbox.ai/api/chat"
15
+
16
+ def __init__(
17
+ self,
18
+ session_id: str,
19
+ chat_payload: dict,
20
+ proxies: dict[str, str] = {},
21
+ session: requests.Session | None = None,
22
+ ):
23
+ self.session_id = session_id
24
+ self.chat_payload = chat_payload
25
+ self.proxies = proxies
26
+ self.session = session or requests.session()
27
+
28
+ def default_headers(self) -> dict[str, str]:
29
+ return {
30
+ "Accept": "*/*",
31
+ "Accept-Language": "en-US,en;q=0.9,ru;q=0.8",
32
+ "Content-Type": "application/json",
33
+ "Origin": "https://www.blackbox.ai",
34
+ "Priority": "u=0",
35
+ "Referer": "https://www.blackbox.ai/",
36
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
37
+ }
38
+
39
+ def send_message(self, message: str) -> str:
40
+ payload = deepcopy(self.chat_payload)
41
+ payload["messages"].append(
42
+ {**payload["messages"][0], "content": message}
43
+ )
44
+
45
+ try:
46
+ response = self.session.post(
47
+ self.chat_endpoint,
48
+ json=payload,
49
+ cookies={"sessionId": self.session_id},
50
+ headers=self.default_headers(),
51
+ proxies=self.proxies,
52
+ )
53
+ return response.text
54
+ except requests.exceptions.RequestException as ex:
55
+ raise BlackboxError(str(ex)) from ex
@@ -6,6 +6,7 @@ from collections import defaultdict
6
6
  from datetime import datetime, timedelta, timezone
7
7
  from typing import TextIO, Tuple
8
8
 
9
+ from ..ai.blackbox import BlackboxChat, BlackboxError
9
10
  from ..api import ApiError, BadRequest
10
11
  from ..main import BaseOperation
11
12
  from ..main import Namespace as BaseNamespace
@@ -15,6 +16,7 @@ from ..telemetry_client import TelemetryClient, TelemetryError
15
16
  from ..types import ApiListResponse, VacancyItem
16
17
  from ..utils import (fix_datetime, parse_interval, parse_invalid_datetime,
17
18
  random_text, truncate_string)
19
+ from hh_applicant_tool.ai import blackbox
18
20
 
19
21
  logger = logging.getLogger(__package__)
20
22
 
@@ -23,8 +25,10 @@ class Namespace(BaseNamespace):
23
25
  resume_id: str | None
24
26
  message_list: TextIO
25
27
  force_message: bool
26
- apply_interval: Tuple[float, float]
27
- page_interval: Tuple[float, float]
28
+ use_ai: bool
29
+ pre_prompt: str
30
+ apply_interval: tuple[float, float]
31
+ page_interval: tuple[float, float]
28
32
  order_by: str
29
33
  search: str
30
34
  dry_run: bool
@@ -36,16 +40,32 @@ class Operation(BaseOperation, GetResumeIdMixin):
36
40
  def setup_parser(self, parser: argparse.ArgumentParser) -> None:
37
41
  parser.add_argument("--resume-id", help="Идентефикатор резюме")
38
42
  parser.add_argument(
43
+ "-L",
39
44
  "--message-list",
40
45
  help="Путь до файла, где хранятся сообщения для отклика на вакансии. Каждое сообщение — с новой строки.",
41
46
  type=argparse.FileType(),
42
47
  )
43
48
  parser.add_argument(
49
+ "-f",
44
50
  "--force-message",
51
+ "--force",
45
52
  help="Всегда отправлять сообщение при отклике",
46
53
  default=False,
47
54
  action=argparse.BooleanOptionalAction,
48
55
  )
56
+ parser.add_argument(
57
+ "--use-ai",
58
+ "--ai",
59
+ help="Использовать AI для генерации сообщений",
60
+ default=False,
61
+ action=argparse.BooleanOptionalAction,
62
+ )
63
+ parser.add_argument(
64
+ "--pre-prompt",
65
+ "--prompt",
66
+ help="Добавочный промпт для генерации сопроводительного письма",
67
+ default="Сгенерируй сопроводительное письмо не более 5-7 предложений от моего имени для вакансии",
68
+ )
49
69
  parser.add_argument(
50
70
  "--apply-interval",
51
71
  help="Интервал перед отправкой откликов в секундах (X, X-Y)",
@@ -104,6 +124,16 @@ class Operation(BaseOperation, GetResumeIdMixin):
104
124
  self.application_messages = self._get_application_messages(
105
125
  args.message_list
106
126
  )
127
+ self.chat = None
128
+
129
+ if config := args.config.get("blackbox"):
130
+ self.chat = BlackboxChat(
131
+ session_id=config["session_id"],
132
+ chat_payload=config["chat_payload"],
133
+ proxies=self.api.proxies or {},
134
+ )
135
+
136
+ self.pre_prompt = args.pre_prompt
107
137
 
108
138
  self.apply_min_interval, self.apply_max_interval = args.apply_interval
109
139
  self.page_min_interval, self.page_max_interval = args.page_interval
@@ -255,7 +285,7 @@ class Operation(BaseOperation, GetResumeIdMixin):
255
285
 
256
286
  if not do_apply:
257
287
  logger.debug(
258
- "Проопускаем вакансию так как достигла лимита заявок: %s",
288
+ "Пропускаем вакансию так как достигла лимита заявок: %s",
259
289
  vacancy["alternate_url"],
260
290
  )
261
291
  continue
@@ -276,11 +306,25 @@ class Operation(BaseOperation, GetResumeIdMixin):
276
306
  if self.force_message or vacancy.get(
277
307
  "response_letter_required"
278
308
  ):
279
- msg = params["message"] = (
280
- random_text(random.choice(self.application_messages))
281
- % message_placeholders
282
- )
309
+ if self.chat:
310
+ try:
311
+ msg = self.pre_prompt + "\n\n"
312
+ msg += message_placeholders["vacancy_name"]
313
+ logger.debug(msg)
314
+ msg = self.chat.send_message(msg)
315
+ except BlackboxError as ex:
316
+ logger.error(ex)
317
+ continue
318
+ else:
319
+ msg = (
320
+ random_text(
321
+ random.choice(self.application_messages)
322
+ )
323
+ % message_placeholders
324
+ )
325
+
283
326
  logger.debug(msg)
327
+ params["message"] = msg
284
328
 
285
329
  if self.dry_run:
286
330
  logger.info(
@@ -5,8 +5,9 @@ from datetime import datetime, timedelta, timezone
5
5
 
6
6
  from ..api import ApiClient, ClientError
7
7
  from ..constants import INVALID_ISO8601_FORMAT
8
- from ..main import BaseOperation, get_api
8
+ from ..main import BaseOperation
9
9
  from ..main import Namespace as BaseNamespace
10
+ from ..main import get_api
10
11
  from ..types import ApiListResponse
11
12
  from ..utils import print_err, truncate_string
12
13
 
@@ -19,14 +20,21 @@ class Namespace(BaseNamespace):
19
20
 
20
21
 
21
22
  class Operation(BaseOperation):
22
- """Отменяет старые заявки, скрывает отказы с опциональной блокировкой работодателя."""
23
+ """Отменяет старые отклики, скрывает отказы с опциональной блокировкой работодателя."""
23
24
 
24
25
  def setup_parser(self, parser: argparse.ArgumentParser) -> None:
25
26
  parser.add_argument(
26
27
  "--older-than",
27
28
  type=int,
28
29
  default=30,
29
- help="Удалить заявки старше опр. кол-ва дней. По умолчанию: %(default)d",
30
+ help="Удалить отклики старше опр. кол-ва дней. По умолчанию: %(default)d",
31
+ )
32
+ parser.add_argument(
33
+ "--all",
34
+ type=bool,
35
+ default=False,
36
+ action=argparse.BooleanOptionalAction,
37
+ help="Удалить все отклики в тч с приглашениями",
30
38
  )
31
39
  parser.add_argument(
32
40
  "--blacklist-discard",
@@ -61,7 +69,8 @@ class Operation(BaseOperation):
61
69
  # hidden True
62
70
  is_discard = state["id"] == "discard"
63
71
  if not item["hidden"] and (
64
- is_discard
72
+ args.all
73
+ or is_discard
65
74
  or (
66
75
  state["id"] == "response"
67
76
  and (
@@ -72,7 +81,11 @@ class Operation(BaseOperation):
72
81
  )
73
82
  )
74
83
  ):
75
- r = api.delete(f"/negotiations/active/{item['id']}")
84
+ decline_allowed = item.get("decline_allowed") or False
85
+ r = api.delete(
86
+ f"/negotiations/active/{item['id']}",
87
+ with_decline_message=decline_allowed,
88
+ )
76
89
  assert {} == r
77
90
  vacancy = item["vacancy"]
78
91
  print(
@@ -0,0 +1,36 @@
1
+ import argparse
2
+ import logging
3
+ import os
4
+ import subprocess
5
+
6
+ from ..main import BaseOperation
7
+ from ..main import Namespace as BaseNamespace
8
+
9
+ logger = logging.getLogger(__package__)
10
+
11
+ EDITOR = os.getenv("EDITOR", "nano")
12
+
13
+
14
+ class Namespace(BaseNamespace):
15
+ print: bool
16
+
17
+
18
+ class Operation(BaseOperation):
19
+ """Редактировать конфигурационный файл или показать путь до него"""
20
+
21
+ def setup_parser(self, parser: argparse.ArgumentParser) -> None:
22
+ parser.add_argument(
23
+ "-p",
24
+ "--print",
25
+ type=bool,
26
+ default=False,
27
+ action=argparse.BooleanOptionalAction,
28
+ help="Напечатать путь и выйти",
29
+ )
30
+
31
+ def run(self, args: Namespace) -> None:
32
+ config_path = str(args.config._config_path)
33
+ if args.print:
34
+ print(config_path)
35
+ else:
36
+ subprocess.call([EDITOR, config_path])
@@ -160,15 +160,15 @@ class Operation(BaseOperation, GetResumeIdMixin):
160
160
  print("💼", message_placeholders["vacancy_name"])
161
161
  print("📅", vacancy["created_at"])
162
162
  if salary:
163
- salary_from = salary.get("from", "-")
164
- salary_to = salary.get("to", "-")
163
+ salary_from = salary.get("from")or "-"
164
+ salary_to = salary.get("to")or "-"
165
165
  salary_currency = salary.get("currency")
166
166
  print("💵 от", salary_from, "до", salary_to, salary_currency)
167
167
  print("")
168
168
  print("Последние сообщения:")
169
169
  for msg in (
170
- message_history[:1] + ["..."] + message_history[-2:]
171
- if len(message_history) > 3
170
+ message_history[:1] + ["..."] + message_history[-3:]
171
+ if len(message_history) > 5
172
172
  else message_history
173
173
  ):
174
174
  print(msg)
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "hh-applicant-tool"
3
- version = "0.5.1"
3
+ version = "0.5.3"
4
4
  description = ""
5
5
  authors = ["Senior YAML Developer <yamldeveloper@proton.me>"]
6
6
  readme = "README.md"