hh-applicant-tool 0.2.3__py3-none-any.whl → 0.2.5__py3-none-any.whl

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.

@@ -1,4 +1,4 @@
1
- DEFAULT_USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36"
1
+ DEFAULT_USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36"
2
2
  ANDROID_CLIENT_ID = (
3
3
  "HIOMIAS39CA9DICTA7JIO64LQKQJF5AGIK74G9ITJKLNEDAOH5FHS5G1JI7FOEGD"
4
4
  )
hh_applicant_tool/main.py CHANGED
@@ -14,7 +14,7 @@ from .color_log import ColorHandler
14
14
  from .utils import Config
15
15
 
16
16
  DEFAULT_CONFIG_PATH = (
17
- Path(getenv("XDG_CONFIG_PATH", Path.home() / ".config"))
17
+ Path(getenv("XDG_CONFIG_HOME", Path.home() / ".config"))
18
18
  / __package__.replace("_", "-")
19
19
  / "config.json"
20
20
  )
@@ -23,12 +23,10 @@ logger = logging.getLogger(__package__)
23
23
 
24
24
 
25
25
  class BaseOperation(metaclass=ABCMeta):
26
- def setup_parser(self, parser: argparse.ArgumentParser) -> None:
27
- ...
26
+ def setup_parser(self, parser: argparse.ArgumentParser) -> None: ...
28
27
 
29
28
  @abstractmethod
30
- def run(self, args: argparse.Namespace) -> None | int:
31
- ...
29
+ def run(self, args: argparse.Namespace) -> None | int: ...
32
30
 
33
31
 
34
32
  OPERATIONS = "operations"
@@ -41,12 +39,16 @@ class Namespace(argparse.Namespace):
41
39
 
42
40
  class HHApplicantTool:
43
41
  """Утилита для автоматизации действий соискателя на сайте hh.ru.
44
- Описание, исходники и предложения: <https://github.com/s3rgeym/hh-applicant-tool>.
42
+
43
+ Исходники и предложения: <https://github.com/s3rgeym/hh-applicant-tool>
44
+
45
+ Группа поддержки: <https://t.me/vaitishniki>
45
46
  """
46
47
 
47
48
  def create_parser(self) -> argparse.ArgumentParser:
48
49
  parser = argparse.ArgumentParser(
49
50
  description=self.__doc__,
51
+ formatter_class=argparse.RawDescriptionHelpFormatter,
50
52
  )
51
53
  parser.add_argument(
52
54
  "-c",
@@ -82,9 +84,7 @@ class HHApplicantTool:
82
84
  logger.setLevel(log_level)
83
85
  handler = ColorHandler()
84
86
  # [C] Critical Error Occurred
85
- handler.setFormatter(
86
- logging.Formatter("[%(levelname).1s] %(message)s")
87
- )
87
+ handler.setFormatter(logging.Formatter("[%(levelname).1s] %(message)s"))
88
88
  logger.addHandler(handler)
89
89
  if args.run:
90
90
  try:
@@ -87,11 +87,22 @@ class Operation(BaseOperation):
87
87
  page_min_interval, page_max_interval = args.page_interval
88
88
 
89
89
  self._apply_similar(
90
- api, resume_id, args.force_message, application_messages, apply_min_interval, apply_max_interval, page_min_interval, page_max_interval
90
+ api,
91
+ resume_id,
92
+ args.force_message,
93
+ application_messages,
94
+ apply_min_interval,
95
+ apply_max_interval,
96
+ page_min_interval,
97
+ page_max_interval,
91
98
  )
92
99
 
93
100
  def _get_vacancies(
94
- self, api: ApiClient, resume_id: str, page_min_interval: float, page_max_interval: float
101
+ self,
102
+ api: ApiClient,
103
+ resume_id: str,
104
+ page_min_interval: float,
105
+ page_max_interval: float,
95
106
  ) -> list[VacancyItem]:
96
107
  rv = []
97
108
  per_page = 100
@@ -125,24 +136,45 @@ class Operation(BaseOperation):
125
136
  page_max_interval: float,
126
137
  ) -> None:
127
138
  item: VacancyItem
128
- for item in self._get_vacancies(api, resume_id, page_min_interval, page_max_interval):
129
- if item["has_test"]:
130
- continue
131
-
132
- # Задержка перед отправкой отклика
133
- interval = random.uniform(apply_min_interval, apply_max_interval)
134
- time.sleep(interval)
135
-
136
- params = {
137
- "resume_id": resume_id,
138
- "vacancy_id": item["id"],
139
- "message": (
140
- random.choice(application_messages) % item
141
- if force_message or item["response_letter_required"]
142
- else ""
143
- ),
144
- }
139
+ for item in self._get_vacancies(
140
+ api, resume_id, page_min_interval, page_max_interval
141
+ ):
145
142
  try:
143
+ if item["has_test"]:
144
+ print("Пропускаем тест", item["alternate_url"])
145
+ continue
146
+
147
+ relations = item.get("relations", [])
148
+
149
+ # Там черезжопно нужно хеш отклика получать чтобы его отменить
150
+ # if "got_response" in relations:
151
+ # # Тупая пизда ее даже не рассматривала
152
+ # print(
153
+ # "Отменяем заявку чтобы отправить ее снова",
154
+ # item["alternate_url"],
155
+ # )
156
+ # api.delete(f"/negotiations/active/{item['id']}")
157
+ # elif relations:
158
+ if relations:
159
+ print("Пропускаем ответ на заявку", item["alternate_url"])
160
+ continue
161
+
162
+ # Задержка перед отправкой отклика
163
+ interval = random.uniform(
164
+ apply_min_interval, apply_max_interval
165
+ )
166
+ time.sleep(interval)
167
+
168
+ params = {
169
+ "resume_id": resume_id,
170
+ "vacancy_id": item["id"],
171
+ "message": (
172
+ random.choice(application_messages) % item
173
+ if force_message or item["response_letter_required"]
174
+ else ""
175
+ ),
176
+ }
177
+
146
178
  res = api.post("/negotiations", params)
147
179
  assert res == {}
148
180
  print(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hh-applicant-tool
3
- Version: 0.2.3
3
+ Version: 0.2.5
4
4
  Summary:
5
5
  Author: Senior YAML Developer
6
6
  Author-email: yamldeveloper@proton.me
@@ -9,6 +9,7 @@ Classifier: Programming Language :: Python :: 3
9
9
  Classifier: Programming Language :: Python :: 3.10
10
10
  Classifier: Programming Language :: Python :: 3.11
11
11
  Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Programming Language :: Python :: 3.13
12
13
  Requires-Dist: prettytable (>=3.6.0,<4.0.0)
13
14
  Requires-Dist: requests (>=2.28.2,<3.0.0)
14
15
  Description-Content-Type: text/markdown
@@ -24,7 +25,7 @@ Description-Content-Type: text/markdown
24
25
  [![PyPI - Downloads](https://img.shields.io/pypi/dm/hh-applicant-tool)]()
25
26
  [![Total Downloads](https://static.pepy.tech/badge/hh-applicant-tool)]()
26
27
 
27
- Утилита для автоматизации действий на HH.RU таких как рассылка откликов на подходящие вакансии и обновление всех резюме.
28
+ Утилита для автоматизации действий на HH.RU таких как рассылка откликов на подходящие вакансии и обновление всех резюме. Поддержка осуществляется строго в группе https://t.me/vaitishniki (в ней разрешены мат, п*рнография, оскорбления всех участников кроме админа, а так же слив любой информации про хуевых работодателей и нерадивых херок).
28
29
 
29
30
  Системные требования:
30
31
 
@@ -43,11 +44,11 @@ yay -S socat
43
44
  ![image](https://github.com/user-attachments/assets/55ab24ba-5325-40b4-9bd9-69ebcbc011c4)
44
45
 
45
46
 
46
- Данная утилита работает только в Linux. Для авторизации требуется наличие графического окружения (это не совсем верно, но мне лень расписывать...), после нее вы можете перенести `~/.config/hh-applicant-tool/config.json` на сервер и запускать утилиту через systemd или cron, либо же вообще делать это через **WSL**. Так же при наличии рутованного телефона можно вытащить `access` и `refresh` токены из официального приложения и добавить их в конфиг.
47
+ Данная утилита работает только в Linux. Для авторизации требуется наличие какого-то окружения для взаимодейсвия с браузерос, после нее вы можете перенести `~/.config/hh-applicant-tool/config.json` на сервер и запускать утилиту через systemd или cron, либо же вообще делать это через **WSL**. Столь странный процесс связан с тем, что на странице авторизации запускается море скриптов, которые шифруют данные на клиенте перед отправкой на сервер, а так же выполняется куча запросов чтобы проверить не бот ли ты (хорошо, что после авторизации никаких проверок по факту нет, даже айпи не проверяется на соответсвие тому с какого была авторизация). В этой лапше мне лень разбираться, так же человек, вызвавшийся осилить этот процесс скрылся в закате, а мне и так нормально. Выходом могло бы стать использование безмозглого Хромиума, тогда можно было бы сделать авторизацию полностью через терминал без всяких socat'ов (если не блоканет, так как запущенный в таком режиме браузер все же можно определить). Так же при наличии рутованного телефона можно вытащить `access` и `refresh` токены из официального приложения и добавить их в конфиг.
47
48
 
48
49
  Предыстория.
49
50
 
50
- Был один знакомый знакомого, который работал хрюшей. Этот чувак не заморачивался с чтением резюме, а тупо скриптами рассылал предложения о работе... Бывают, конечно, филологини, которые не могут отлчить Java от JavaScript, но я думаю, что в значительном числе случаев, тут имеют место такие вот рассылки... И я перенял эту порочную практику. Мне уже просто лень читать весь этот бред, что пишут в описании вакансий. Там стандартное ООП, алгоритмы и прочая хуета... Вроде все подходят, а вроде хз — все не мое. Поэтому тупло спамлю в надежде на идеальную работу. Долгое время (пару недель в октябре 2022) я делал массовые заявки с помощью консоли браузера:
51
+ Был один знакомый знакомого, который работал хрюшей. Этот чувак не заморачивался с чтением резюме, а тупо скриптами рассылал предложения о работе... Бывают, конечно, филологини, которые не могут отличить Java от JavaScript, но я думаю, что <s>в значительном числе случаев, тут имеют место такие вот рассылки</s> они просто идиотки... И я перенял эту порочную практику. Мне уже просто лень читать весь этот бред, что пишут в описании вакансий. Там стандартное ООП, алгоритмы и прочая хуета... Вроде все подходят, а вроде хз — все не мое. Поэтому тупло спамлю в надежде на идеальную работу. Долгое время (пару недель в октябре 2022) я делал массовые заявки с помощью консоли браузера:
51
52
 
52
53
  ```js
53
54
  $$('[data-qa="vacancy-serp__vacancy_response"]').forEach((el) => el.click());
@@ -4,11 +4,11 @@ hh_applicant_tool/api/__init__.py,sha256=kgFSHibRaAugN2BA3U1djEa20qgKJUUVouwJzjE
4
4
  hh_applicant_tool/api/client.py,sha256=z_YMsd5zL4-1_aIbkEKqm_1m_mZkm3BMxlAQuCoNj2Y,7040
5
5
  hh_applicant_tool/api/errors.py,sha256=0SoWKnsSUA0K2YgQA8GwGhe-pRMwtfK94MR6_MgbORQ,1722
6
6
  hh_applicant_tool/color_log.py,sha256=gN6j1Ayy1G7qOMI_e3WvfYw_ublzeQbKgsVLhqGg_3s,823
7
- hh_applicant_tool/constants.py,sha256=EPtdv-60NSMUpYOUcPR2ZnLQ2P_rxrPuvbOqATw9w8w,512
8
- hh_applicant_tool/main.py,sha256=Gzk1K1jJpO7aazgdXtXAgBhkfFtrteBRx895V5lf07E,3016
7
+ hh_applicant_tool/constants.py,sha256=mdPsqauhlFHB4CsDS-qr-CeRX6bSonJM1aT_qycwfrM,512
8
+ hh_applicant_tool/main.py,sha256=LtLa0U0FGC6qseXLpk39vNL0dDoQ5ultIjDdfk-JAEM,3091
9
9
  hh_applicant_tool/operations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
10
  hh_applicant_tool/operations/add_handler.py,sha256=e28O0pSLIgSTwv5n0I2GHDMKYPV-dNWHYFmhbkVzq34,2288
11
- hh_applicant_tool/operations/apply_similar.py,sha256=79kGig-hlLZR2rZ0YReP1CNWO9SMoGFvXJnNWa6kk2E,6590
11
+ hh_applicant_tool/operations/apply_similar.py,sha256=VEyl7YmX2sxXrH4rtyt9OvbVKyHLiMfn24PdgZE7cGM,7709
12
12
  hh_applicant_tool/operations/authorize.py,sha256=JEL8dlDQfy6i1YFWNUjvDpJ__Ea_PFazz0lYt_r9Afw,3782
13
13
  hh_applicant_tool/operations/call_api.py,sha256=oWAfvy4LwbsQ8HsgI_3en3sMTlu3ZWU7NzpxssrUNSU,1472
14
14
  hh_applicant_tool/operations/clear_negotiations.py,sha256=5ybdJMUfV9XYxnn2y4zvWdS_ZE8yXAbFJoXOMyqetw8,4041
@@ -18,7 +18,7 @@ hh_applicant_tool/operations/update_resumes.py,sha256=FKtwEL7i0vaOxLEn1nARi72SuM
18
18
  hh_applicant_tool/operations/whoami.py,sha256=kdLQ_FjYzpJPKxFlocxf7vgXhW1zocb0bd5IAWmsQuA,861
19
19
  hh_applicant_tool/types.py,sha256=q3yaIcq-UOkPzjxws0OFa4w9fTty-yx79_dic70_dUM,843
20
20
  hh_applicant_tool/utils.py,sha256=FVmE5U7eKONx7G7NIOvu5RJUqLvAr2ThOTOtch-txBs,1347
21
- hh_applicant_tool-0.2.3.dist-info/METADATA,sha256=YJ25EGECBhEoinI3bRAvPp9LrvvPJs5p3i_T1I7x41k,15604
22
- hh_applicant_tool-0.2.3.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
23
- hh_applicant_tool-0.2.3.dist-info/entry_points.txt,sha256=Vb7M2YaYLMtKYJZh8chIrXZApMzSRFT1-rQw-U9r10g,65
24
- hh_applicant_tool-0.2.3.dist-info/RECORD,,
21
+ hh_applicant_tool-0.2.5.dist-info/METADATA,sha256=lMrh-6hAJnB8JTSMgYGC2zuxIX8463yjUMYrkZa9IzU,17326
22
+ hh_applicant_tool-0.2.5.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
23
+ hh_applicant_tool-0.2.5.dist-info/entry_points.txt,sha256=Vb7M2YaYLMtKYJZh8chIrXZApMzSRFT1-rQw-U9r10g,65
24
+ hh_applicant_tool-0.2.5.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.9.0
2
+ Generator: poetry-core 1.9.1
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any