hh-applicant-tool 0.3.8__py3-none-any.whl → 0.4.0__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.

@@ -102,8 +102,6 @@ class BaseClient:
102
102
  logger.debug("wait %fs before request", delay)
103
103
  time.sleep(delay)
104
104
  has_body = method in ["POST", "PUT"]
105
- user_agent = self.user_agent or self.default_user_agent()
106
- logger.debug(f"{user_agent = }")
107
105
  response = self.session.request(
108
106
  method,
109
107
  url,
hh_applicant_tool/main.py CHANGED
@@ -36,6 +36,7 @@ class Namespace(argparse.Namespace):
36
36
  delay: float
37
37
  user_agent: str
38
38
  proxy_url: str
39
+ disable_telemetry: bool
39
40
 
40
41
 
41
42
  def get_proxies(args: Namespace) -> dict[Literal["http", "https"], str | None]:
@@ -103,6 +104,12 @@ class HHApplicantTool:
103
104
  parser.add_argument(
104
105
  "--proxy-url", help="Прокси, используемый для запросов к API"
105
106
  )
107
+ parser.add_argument(
108
+ "--disable-telemetry",
109
+ default=False,
110
+ action=argparse.BooleanOptionalAction,
111
+ help="Отключить телеметрию",
112
+ )
106
113
  subparsers = parser.add_subparsers(help="commands")
107
114
  package_dir = Path(__file__).resolve().parent / OPERATIONS
108
115
  for _, module_name, _ in iter_modules([str(package_dir)]):
@@ -99,6 +99,20 @@ class Operation(BaseOperation):
99
99
  return min(min_interval, max_interval), max(min_interval, max_interval)
100
100
 
101
101
  def run(self, args: Namespace) -> None:
102
+ self.enable_telemetry = True
103
+ if args.disable_telemetry:
104
+ print(
105
+ "👁️ Телеметрия используется только для сбора данных о работодателях и их вакансиях, персональные данные пользователей не передаются на сервер."
106
+ )
107
+ if (
108
+ input("Вы действительно хотите отключить телеметрию (д/Н)? ")
109
+ .lower()
110
+ .startswith(("д", "y"))
111
+ ):
112
+ self.enable_telemetry = False
113
+ logger.info("Телеметрия отключена")
114
+ else:
115
+ logger.info("Телеметрия включена")
102
116
  api = get_api(args)
103
117
  resume_id = self._get_resume_id(args, api)
104
118
  application_messages = self._get_application_messages(args)
@@ -156,14 +170,10 @@ class Operation(BaseOperation):
156
170
  message_min_interval: float,
157
171
  message_max_interval: float,
158
172
  order_by: str,
159
- search: str | None = None,
160
- reply_message: str | None = None,
173
+ search: str | None,
174
+ reply_message: str | None,
161
175
  ) -> None:
162
- # TODO: вынести куда-нибудь в функцию
163
- session = Session()
164
- session.headers["User-Agent"] = "Mozilla/5.0 (HHApplicantTelemetry/1.0)"
165
- session.proxies = dict(api.session.proxies)
166
- telemetry_client = TelemetryClient(session=session)
176
+ telemetry_client = TelemetryClient(proxies=api.proxies)
167
177
  telemetry_data = defaultdict(dict)
168
178
 
169
179
  vacancies = self._get_vacancies(
@@ -176,7 +186,8 @@ class Operation(BaseOperation):
176
186
  search=search,
177
187
  )
178
188
 
179
- self._collect_vacancy_telemetry(telemetry_data, vacancies)
189
+ if self.enable_telemetry:
190
+ self._collect_vacancy_telemetry(telemetry_data, vacancies)
180
191
 
181
192
  me = api.get("/me")
182
193
 
@@ -291,7 +302,8 @@ class Operation(BaseOperation):
291
302
  employer_id = vacancy.get("employer", {}).get("id")
292
303
 
293
304
  if (
294
- employer_id
305
+ self.enable_telemetry
306
+ and employer_id
295
307
  and employer_id not in telemetry_data["employers"]
296
308
  and 200 > len(telemetry_data["employers"])
297
309
  ):
@@ -350,8 +362,9 @@ class Operation(BaseOperation):
350
362
 
351
363
  print("📝 Отклики на вакансии разосланы!")
352
364
 
353
- # Я собираюсь выложить контакты херок в общественный доступ
354
- self._send_telemetry(telemetry_client, telemetry_data)
365
+ if self.enable_telemetry:
366
+ # Я собираюсь выложить контакты херок в общественный доступ
367
+ self._send_telemetry(telemetry_client, telemetry_data)
355
368
 
356
369
  def _get_vacancies(
357
370
  self,
@@ -4,7 +4,10 @@ from urllib.parse import urljoin
4
4
  import requests
5
5
  from typing import Optional, Dict, Any
6
6
  import logging
7
- import base64
7
+ from functools import partialmethod
8
+ import warnings
9
+
10
+ warnings.filterwarnings('ignore', message='Unverified HTTPS request')
8
11
 
9
12
  logger = logging.getLogger(__package__)
10
13
 
@@ -18,40 +21,42 @@ class TelemetryError(Exception):
18
21
  class TelemetryClient:
19
22
  """Клиент для отправки телеметрии на сервер."""
20
23
 
21
- server_address = base64.b64decode(
22
- "aHR0cDovLzMxLjEzMS4yNTEuMTA3OjU0MTU2"
23
- ).decode()
24
+ server_address: str = "https://hh-applicant-tool.mooo.com:54157/"
24
25
 
25
26
  def __init__(
26
27
  self,
27
28
  server_address: Optional[str] = None,
29
+ *,
28
30
  session: Optional[requests.Session] = None,
31
+ user_agent: str = "Mozilla/5.0 (HHApplicantTelemetry/1.0)",
32
+ proxies: dict | None = None,
29
33
  ) -> None:
30
- """
31
- Инициализация клиента.
32
-
33
- :param server_address: Адрес сервера для отправки телеметрии.
34
- :param session: Сессия для повторного использования соединения.
35
- """
36
- self.session = session or requests.Session()
37
34
  self.server_address = os.getenv(
38
35
  "TELEMETRY_SERVER", server_address or self.server_address
39
36
  )
37
+ self.session = session or requests.Session()
38
+ self.user_agent = user_agent
39
+ self.proxies = proxies
40
40
 
41
- def send_telemetry(
42
- self, endpoint: str, data: Dict[str, Any]
41
+ def request(
42
+ self,
43
+ method: str,
44
+ endpoint: str,
45
+ data: Dict[str, Any] | None = None,
43
46
  ) -> Dict[str, Any]:
44
- """
45
- Отправка телеметрии на сервер.
46
-
47
- :param endpoint: Конечная точка на сервере.
48
- :param data: Данные для отправки.
49
- :return: Ответ сервера в формате JSON.
50
- :raises TelemetryError: Если произошла ошибка при отправке или декодировании JSON.
51
- """
47
+ method = method.upper()
52
48
  url = urljoin(self.server_address, endpoint)
49
+ has_body = method in ["POST", "PUT", "PATCH"]
53
50
  try:
54
- response = self.session.post(url, json=data)
51
+ response = self.session.request(
52
+ method,
53
+ url,
54
+ headers={"User-Agent": self.user_agent},
55
+ proxies=self.proxies,
56
+ params=data if not has_body else None,
57
+ json=data if has_body else None,
58
+ verify=False, # Игнорирование истекшего сертификата
59
+ )
55
60
  # response.raise_for_status()
56
61
  result = response.json()
57
62
  if "error" in result:
@@ -63,3 +68,5 @@ class TelemetryClient:
63
68
  json.JSONDecodeError,
64
69
  ) as ex:
65
70
  raise TelemetryError(str(ex)) from ex
71
+
72
+ send_telemetry = partialmethod(request, "POST")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hh-applicant-tool
3
- Version: 0.3.8
3
+ Version: 0.4.0
4
4
  Summary:
5
5
  Author: Senior YAML Developer
6
6
  Author-email: yamldeveloper@proton.me
@@ -171,6 +171,7 @@ $ hh-applicant-tool refresh-token
171
171
  Через конфиг можно задать дополнительные настройки:
172
172
 
173
173
  | Имя атрибута | Описание |
174
+ | --- | --- |
174
175
  | `user_agent` | Кастомный юзерагент, передаваемый при кажом запросе, например, `Mozilla/5.0 YablanBrowser` |
175
176
  | `proxy_url` | Прокси, используемый для всех запросов, например, `socks5h://127.0.0.1:9050` |
176
177
  | `reply_message` | Сообщение для ответа работодателю при отклике на вакансии, см. формат сообщений |
@@ -283,6 +284,8 @@ https://hh.ru/employer/1918903
283
284
 
284
285
  ### Сбор данных
285
286
 
287
+ > Данный функционал можно отключить с помощью специльного флага, но ради котят и из-за ненависти к херкам не делайте этого!
288
+
286
289
  Утилита собирает и передает на сервер разработчика следующую информацию:
287
290
 
288
291
  1. Название вакансии.
@@ -296,11 +299,9 @@ https://hh.ru/employer/1918903
296
299
  1. Название компании.
297
300
  1. Тип компании.
298
301
  1. Описание компании.
299
- 1. Ссылка на сайт компании.
302
+ 1. Ссылка на сайт компании.
300
303
  1. Город, в котором находится компания.
301
304
 
302
- [Исходники сервера](https://gist.github.com/s3rgeym/b9fb04ef529a511326413c1090597ac5)
303
-
304
- !!! УТИЛИТА НЕ СОБИРАЕТ НИКАКИХ ПЕРСОНАЛЬНЫХ ДАННЫХ ПОЛЬЗОВАТЕЛЕЙ (IP ТОЖЕ НЕ СОХРАНЯЕТ) — ТОЛЬКО ДАННЫЕ ВСЯКИХ РАБОТАДАТЕЛЕЙ И ИХ ОВЧАРОК. ТАК ЖЕ Я ОБЕЩАЮ, ЧТО УТИЛИТА ВСЕГДА БУДЕТ БЕСПЛАТНОЙ, ВСЕ КТО ЕЮ ПЫТАЮТСЯ ТОРГОВАТЬ — УЕБКИ И У НИХ ПОЧЕРНЕЕТ И ОТВАЛИТСЯ ХУЙ. ЕДИНСТВЕННАЯ ПЛАТА ЗА ЕЕ ИСПОЛЬЗОВАНИЕ — ЭТО ПОМОЩЬ В ПАРСИНГЕ САЙТА HEADHUNTER (МЕНЯ ИНТЕРЕСУЕТ ЕГО БАЗА КОМПАНИЙ)
305
+ **УТИЛИТА НЕ ПЕРЕДАЕТ НИКАКИХ ПЕРСОНАЛЬНЫХ ДАННЫХ ПОЛЬЗОВАТЕЛЕЙ — ТОЛЬКО ДАННЫЕ ВСЯКИХ РАБОТАДАТЕЛЕЙ И ИХ ОВЧАРОК. СЕРВЕР НЕ ХРАНИТ IP ОТПРАВИТЕЛЯ. ЛОГИ НА СЕРВЕРЕ НЕ ВЕДУТСЯ. ТАК ЖЕ Я ОБЕЩАЮ, ЧТО УТИЛИТА ВСЕГДА БУДЕТ БЕСПЛАТНОЙ, ВСЕ КТО ЕЮ ПЫТАЮТСЯ ТОРГОВАТЬ — УЕБКИ, И У НИХ ПОЧЕРНЕЕТ И ОТВАЛИТСЯ ХУЙ. ЕДИНСТВЕННАЯ ПЛАТА ЗА ЕЕ ИСПОЛЬЗОВАНИЕ — ЭТО ПОМОЩЬ В ПАРСИНГЕ САЙТА HEADHUNTER (МЕНЯ ИНТЕРЕСУЕТ ЕГО БАЗА КОМПАНИЙ).**
305
306
 
306
307
 
@@ -1,13 +1,13 @@
1
1
  hh_applicant_tool/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  hh_applicant_tool/__main__.py,sha256=cwKJAAML0RRKT9Qbzcwf07HHcuSd8oh7kx4P1apndWQ,84
3
3
  hh_applicant_tool/api/__init__.py,sha256=kgFSHibRaAugN2BA3U1djEa20qgKJUUVouwJzjEB0DU,84
4
- hh_applicant_tool/api/client.py,sha256=o_9hDdtCH3xHgBKwqoriNy0wncgUANDR8y--ZxVPQGM,8112
4
+ hh_applicant_tool/api/client.py,sha256=um9NX22hNOtSuPCobCKf1anIFp-jiZlIXm4BuqN-L7k,7997
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
7
  hh_applicant_tool/constants.py,sha256=lpgKkP2chWgTnBXvzxbSPWpKcfzp8VxMTlkssFcQhH4,469
8
- hh_applicant_tool/main.py,sha256=B_kI9MlaT_064r5CL7Pjlzu76QPB-hXCaMpFtB-BOfg,4596
8
+ hh_applicant_tool/main.py,sha256=0PeUmWSyKAhAtTK1w5HDwywSbPckOK4oOXWDKo2oxnM,4836
9
9
  hh_applicant_tool/operations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
- hh_applicant_tool/operations/apply_similar.py,sha256=9dPvO_3o9rGgaUKxEChgc1cL69YpXuJY8tpP_4iD6TY,17249
10
+ hh_applicant_tool/operations/apply_similar.py,sha256=AwEyG8VdlcbF1JCb2B2EvKiXGa6GtBY5VwHe1O0TPY0,17944
11
11
  hh_applicant_tool/operations/authorize.py,sha256=TyUTCSOGwSYVJMEd5vSI981LRRI-RZf8hnlVYhtRVwA,3184
12
12
  hh_applicant_tool/operations/call_api.py,sha256=qwPDrWP9tiqHkaYYWYBZtymj9AaxObB86Eny-Bf5q_c,1314
13
13
  hh_applicant_tool/operations/clear_negotiations.py,sha256=98Yuw9xP4dN5sUnUKlZxqfhU40TQ-aCjK4vj4LRTeYo,3894
@@ -15,10 +15,10 @@ hh_applicant_tool/operations/list_resumes.py,sha256=XBrVFTnl45BUtuvjVm70h_CXZrOv
15
15
  hh_applicant_tool/operations/refresh_token.py,sha256=hYTmzBzJFSsb-LDO2_w0Y30WVWsctIH7vTzirkLwzWo,1267
16
16
  hh_applicant_tool/operations/update_resumes.py,sha256=gGxMYMoT9GqJjwn4AgrOAEJCZu4sdhaV0VmPr3jG-q8,1049
17
17
  hh_applicant_tool/operations/whoami.py,sha256=sg0r7m6oKkpMEmGt4QdtYdS-1gf-1KKdnk32yblbRJs,714
18
- hh_applicant_tool/telemetry_client.py,sha256=8R5cdB8971j1rz0v0nhh1TBbqHHD9LYdBUnd5sh-kik,2165
18
+ hh_applicant_tool/telemetry_client.py,sha256=nNNr1drXY9Z01u5tJX---BXxBg1y06nJpNbhU45DmE0,2239
19
19
  hh_applicant_tool/types.py,sha256=q3yaIcq-UOkPzjxws0OFa4w9fTty-yx79_dic70_dUM,843
20
20
  hh_applicant_tool/utils.py,sha256=lHQh94CEwWp14Ty50ecZPcR3YyqLDVlmgmZlrBiBgHQ,2557
21
- hh_applicant_tool-0.3.8.dist-info/METADATA,sha256=8Y-ENQv2YFch_NRkreNl594ZqtAygTcVdNGTxBcHk8M,20561
22
- hh_applicant_tool-0.3.8.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
23
- hh_applicant_tool-0.3.8.dist-info/entry_points.txt,sha256=Vb7M2YaYLMtKYJZh8chIrXZApMzSRFT1-rQw-U9r10g,65
24
- hh_applicant_tool-0.3.8.dist-info/RECORD,,
21
+ hh_applicant_tool-0.4.0.dist-info/METADATA,sha256=XqFSSxWsouQbKDxRO8hYLLF17HaCphCu3EAgmlnM2GE,20770
22
+ hh_applicant_tool-0.4.0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
23
+ hh_applicant_tool-0.4.0.dist-info/entry_points.txt,sha256=Vb7M2YaYLMtKYJZh8chIrXZApMzSRFT1-rQw-U9r10g,65
24
+ hh_applicant_tool-0.4.0.dist-info/RECORD,,