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.
- {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/PKG-INFO +37 -5
- {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/README.md +36 -4
- hh_applicant_tool-0.5.3/hh_applicant_tool/ai/blackbox.py +55 -0
- hh_applicant_tool-0.5.3/hh_applicant_tool/operations/__init__.py +0 -0
- {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/operations/apply_similar.py +51 -7
- {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/operations/clear_negotiations.py +18 -5
- hh_applicant_tool-0.5.3/hh_applicant_tool/operations/config.py +36 -0
- {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/operations/reply_employers.py +4 -4
- {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/pyproject.toml +1 -1
- {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/__init__.py +0 -0
- {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/__main__.py +0 -0
- {hh_applicant_tool-0.5.1/hh_applicant_tool/operations → hh_applicant_tool-0.5.3/hh_applicant_tool/ai}/__init__.py +0 -0
- {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/api/__init__.py +0 -0
- {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/api/client.py +0 -0
- {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/api/errors.py +0 -0
- {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/color_log.py +0 -0
- {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/constants.py +0 -0
- {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/main.py +0 -0
- {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/mixins.py +0 -0
- {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/operations/authorize.py +0 -0
- {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/operations/call_api.py +0 -0
- {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/operations/get_employer_contacts.py +0 -0
- {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/operations/list_resumes.py +0 -0
- {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/operations/refresh_token.py +0 -0
- {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/operations/update_resumes.py +0 -0
- {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/operations/whoami.py +0 -0
- {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/telemetry_client.py +0 -0
- {hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/types.py +0 -0
- {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.
|
|
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
|
-
Утилита для
|
|
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
|

|
|
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
|
-
Утилита для
|
|
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
|

|
|
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
|
|
File without changes
|
{hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/operations/apply_similar.py
RENAMED
|
@@ -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
|
-
|
|
27
|
-
|
|
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
|
-
"
|
|
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
|
-
|
|
280
|
-
|
|
281
|
-
|
|
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
|
|
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="Удалить
|
|
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
|
-
|
|
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
|
-
|
|
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])
|
{hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/operations/reply_employers.py
RENAMED
|
@@ -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[-
|
|
171
|
-
if len(message_history) >
|
|
170
|
+
message_history[:1] + ["..."] + message_history[-3:]
|
|
171
|
+
if len(message_history) > 5
|
|
172
172
|
else message_history
|
|
173
173
|
):
|
|
174
174
|
print(msg)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/operations/authorize.py
RENAMED
|
File without changes
|
{hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/operations/call_api.py
RENAMED
|
File without changes
|
|
File without changes
|
{hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/operations/list_resumes.py
RENAMED
|
File without changes
|
{hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/operations/refresh_token.py
RENAMED
|
File without changes
|
{hh_applicant_tool-0.5.1 → hh_applicant_tool-0.5.3}/hh_applicant_tool/operations/update_resumes.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|