hh-applicant-tool 0.3.7__tar.gz → 0.3.8__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 (23) hide show
  1. {hh_applicant_tool-0.3.7 → hh_applicant_tool-0.3.8}/PKG-INFO +8 -9
  2. {hh_applicant_tool-0.3.7 → hh_applicant_tool-0.3.8}/README.md +6 -7
  3. {hh_applicant_tool-0.3.7 → hh_applicant_tool-0.3.8}/hh_applicant_tool/api/client.py +5 -1
  4. {hh_applicant_tool-0.3.7 → hh_applicant_tool-0.3.8}/hh_applicant_tool/main.py +21 -4
  5. {hh_applicant_tool-0.3.7 → hh_applicant_tool-0.3.8}/hh_applicant_tool/operations/apply_similar.py +9 -6
  6. {hh_applicant_tool-0.3.7 → hh_applicant_tool-0.3.8}/hh_applicant_tool/telemetry_client.py +0 -6
  7. {hh_applicant_tool-0.3.7 → hh_applicant_tool-0.3.8}/hh_applicant_tool/utils.py +2 -1
  8. {hh_applicant_tool-0.3.7 → hh_applicant_tool-0.3.8}/pyproject.toml +2 -2
  9. {hh_applicant_tool-0.3.7 → hh_applicant_tool-0.3.8}/hh_applicant_tool/__init__.py +0 -0
  10. {hh_applicant_tool-0.3.7 → hh_applicant_tool-0.3.8}/hh_applicant_tool/__main__.py +0 -0
  11. {hh_applicant_tool-0.3.7 → hh_applicant_tool-0.3.8}/hh_applicant_tool/api/__init__.py +0 -0
  12. {hh_applicant_tool-0.3.7 → hh_applicant_tool-0.3.8}/hh_applicant_tool/api/errors.py +0 -0
  13. {hh_applicant_tool-0.3.7 → hh_applicant_tool-0.3.8}/hh_applicant_tool/color_log.py +0 -0
  14. {hh_applicant_tool-0.3.7 → hh_applicant_tool-0.3.8}/hh_applicant_tool/constants.py +0 -0
  15. {hh_applicant_tool-0.3.7 → hh_applicant_tool-0.3.8}/hh_applicant_tool/operations/__init__.py +0 -0
  16. {hh_applicant_tool-0.3.7 → hh_applicant_tool-0.3.8}/hh_applicant_tool/operations/authorize.py +0 -0
  17. {hh_applicant_tool-0.3.7 → hh_applicant_tool-0.3.8}/hh_applicant_tool/operations/call_api.py +0 -0
  18. {hh_applicant_tool-0.3.7 → hh_applicant_tool-0.3.8}/hh_applicant_tool/operations/clear_negotiations.py +0 -0
  19. {hh_applicant_tool-0.3.7 → hh_applicant_tool-0.3.8}/hh_applicant_tool/operations/list_resumes.py +0 -0
  20. {hh_applicant_tool-0.3.7 → hh_applicant_tool-0.3.8}/hh_applicant_tool/operations/refresh_token.py +0 -0
  21. {hh_applicant_tool-0.3.7 → hh_applicant_tool-0.3.8}/hh_applicant_tool/operations/update_resumes.py +0 -0
  22. {hh_applicant_tool-0.3.7 → hh_applicant_tool-0.3.8}/hh_applicant_tool/operations/whoami.py +0 -0
  23. {hh_applicant_tool-0.3.7 → hh_applicant_tool-0.3.8}/hh_applicant_tool/types.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hh-applicant-tool
3
- Version: 0.3.7
3
+ Version: 0.3.8
4
4
  Summary:
5
5
  Author: Senior YAML Developer
6
6
  Author-email: yamldeveloper@proton.me
@@ -14,7 +14,7 @@ Provides-Extra: qt
14
14
  Requires-Dist: prettytable (>=3.6.0,<4.0.0)
15
15
  Requires-Dist: pyqt6 (>=6.7.1,<7.0.0) ; extra == "qt"
16
16
  Requires-Dist: pyqt6-webengine (>=6.7.0,<7.0.0) ; extra == "qt"
17
- Requires-Dist: requests (>=2.28.2,<3.0.0)
17
+ Requires-Dist: requests[socks] (>=2.32.3,<3.0.0)
18
18
  Description-Content-Type: text/markdown
19
19
 
20
20
  ## HH Applicant Tool
@@ -168,13 +168,12 @@ $ hh-applicant-tool refresh-token
168
168
  | **Linux** | `~/.config/hh-applicant-tool/config.json` |
169
169
 
170
170
 
171
- Через этот файл, например, можно задать кастомный `user_agent`:
171
+ Через конфиг можно задать дополнительные настройки:
172
172
 
173
- ```json
174
- {
175
- "user_agent": "Mozilla/5.0 YablanBrowser"
176
- }
177
- ```
173
+ | Имя атрибута | Описание |
174
+ | `user_agent` | Кастомный юзерагент, передаваемый при кажом запросе, например, `Mozilla/5.0 YablanBrowser` |
175
+ | `proxy_url` | Прокси, используемый для всех запросов, например, `socks5h://127.0.0.1:9050` |
176
+ | `reply_message` | Сообщение для ответа работодателю при отклике на вакансии, см. формат сообщений |
178
177
 
179
178
  ### Описание команд
180
179
 
@@ -261,7 +260,7 @@ https://hh.ru/employer/1918903
261
260
  Эти плейсхолдеры могут быть использованы в сообщениях для отклика на вакансии, чтобы динамически подставлять соответствующие данные в текст сообщения. Например:
262
261
 
263
262
  ```
264
- "Меня заинтересовала ваша вакансия %(vacancy_name)s. Прошу рассмотреть мою кандидатуру. С уважением, %(first_name)s %(last_name)s."
263
+ Меня заинтересовала ваша вакансия %(vacancy_name)s. Прошу рассмотреть мою кандидатуру. С уважением, %(first_name)s %(last_name)s.
265
264
  ```
266
265
 
267
266
  Так же можно делать текст уникальным с помощью `{}`. Внутри них через `|` перечисляются варианты, один из которых будет случайно выбран:
@@ -149,13 +149,12 @@ $ hh-applicant-tool refresh-token
149
149
  | **Linux** | `~/.config/hh-applicant-tool/config.json` |
150
150
 
151
151
 
152
- Через этот файл, например, можно задать кастомный `user_agent`:
152
+ Через конфиг можно задать дополнительные настройки:
153
153
 
154
- ```json
155
- {
156
- "user_agent": "Mozilla/5.0 YablanBrowser"
157
- }
158
- ```
154
+ | Имя атрибута | Описание |
155
+ | `user_agent` | Кастомный юзерагент, передаваемый при кажом запросе, например, `Mozilla/5.0 YablanBrowser` |
156
+ | `proxy_url` | Прокси, используемый для всех запросов, например, `socks5h://127.0.0.1:9050` |
157
+ | `reply_message` | Сообщение для ответа работодателю при отклике на вакансии, см. формат сообщений |
159
158
 
160
159
  ### Описание команд
161
160
 
@@ -242,7 +241,7 @@ https://hh.ru/employer/1918903
242
241
  Эти плейсхолдеры могут быть использованы в сообщениях для отклика на вакансии, чтобы динамически подставлять соответствующие данные в текст сообщения. Например:
243
242
 
244
243
  ```
245
- "Меня заинтересовала ваша вакансия %(vacancy_name)s. Прошу рассмотреть мою кандидатуру. С уважением, %(first_name)s %(last_name)s."
244
+ Меня заинтересовала ваша вакансия %(vacancy_name)s. Прошу рассмотреть мою кандидатуру. С уважением, %(first_name)s %(last_name)s.
246
245
  ```
247
246
 
248
247
  Так же можно делать текст уникальным с помощью `{}`. Внутри них через `|` перечисляются варианты, один из которых будет случайно выбран:
@@ -37,6 +37,7 @@ class BaseClient:
37
37
  _: dataclasses.KW_ONLY
38
38
  # TODO: сделать генерацию User-Agent'а как в приложении
39
39
  user_agent: str | None = None
40
+ proxies: dict | None = None
40
41
  session: Session | None = None
41
42
  previous_request_time: float = 0.0
42
43
  delay: float = 0.334
@@ -47,8 +48,8 @@ class BaseClient:
47
48
  self.session = session = requests.session()
48
49
  session.headers.update(
49
50
  {
50
- **self.additional_headers(),
51
51
  "User-Agent": self.user_agent or self.default_user_agent(),
52
+ **self.additional_headers(),
52
53
  }
53
54
  )
54
55
  logger.debug("Default Headers: %r", session.headers)
@@ -101,10 +102,13 @@ class BaseClient:
101
102
  logger.debug("wait %fs before request", delay)
102
103
  time.sleep(delay)
103
104
  has_body = method in ["POST", "PUT"]
105
+ user_agent = self.user_agent or self.default_user_agent()
106
+ logger.debug(f"{user_agent = }")
104
107
  response = self.session.request(
105
108
  method,
106
109
  url,
107
110
  **{"data" if has_body else "params": params},
111
+ proxies=self.proxies,
108
112
  allow_redirects=False,
109
113
  )
110
114
  try:
@@ -5,13 +5,13 @@ import logging
5
5
  import sys
6
6
  from abc import ABCMeta, abstractmethod
7
7
  from importlib import import_module
8
- from os import getenv
9
8
  from pathlib import Path
10
9
  from pkgutil import iter_modules
11
- from typing import Sequence
10
+ from typing import Sequence, Literal
12
11
  from .api import ApiClient
13
12
  from .color_log import ColorHandler
14
13
  from .utils import Config, get_config_path
14
+ from os import getenv
15
15
 
16
16
  DEFAULT_CONFIG_PATH = (
17
17
  get_config_path() / __package__.replace("_", "-") / "config.json"
@@ -34,6 +34,15 @@ class Namespace(argparse.Namespace):
34
34
  config: Config
35
35
  verbosity: int
36
36
  delay: float
37
+ user_agent: str
38
+ proxy_url: str
39
+
40
+
41
+ def get_proxies(args: Namespace) -> dict[Literal["http", "https"], str | None]:
42
+ return {
43
+ "http": args.config["proxy_url"] or getenv("HTTP_PROXY"),
44
+ "https": args.config["proxy_url"] or getenv("HTTPS_PROXY"),
45
+ }
37
46
 
38
47
 
39
48
  def get_api(args: Namespace) -> ApiClient:
@@ -41,8 +50,9 @@ def get_api(args: Namespace) -> ApiClient:
41
50
  api = ApiClient(
42
51
  access_token=token.get("access_token"),
43
52
  refresh_token=token.get("refresh_token"),
44
- user_agent=args.config["user_agent"],
45
53
  delay=args.delay,
54
+ user_agent=args.config["user_agent"],
55
+ proxies=get_proxies(args),
46
56
  )
47
57
  return api
48
58
 
@@ -87,6 +97,12 @@ class HHApplicantTool:
87
97
  default=0.334,
88
98
  help="Задержка между запросами к API HH",
89
99
  )
100
+ parser.add_argument(
101
+ "--user-agent", help="User-Agent для каждого запроса"
102
+ )
103
+ parser.add_argument(
104
+ "--proxy-url", help="Прокси, используемый для запросов к API"
105
+ )
90
106
  subparsers = parser.add_subparsers(help="commands")
91
107
  package_dir = Path(__file__).resolve().parent / OPERATIONS
92
108
  for _, module_name, _ in iter_modules([str(package_dir)]):
@@ -94,7 +110,8 @@ class HHApplicantTool:
94
110
  op: BaseOperation = mod.Operation()
95
111
  op_parser = subparsers.add_parser(
96
112
  module_name.replace("_", "-"),
97
- description=op.__doc__, formatter_class=self.ArgumentFormatter
113
+ description=op.__doc__,
114
+ formatter_class=self.ArgumentFormatter,
98
115
  )
99
116
  op_parser.set_defaults(run=op.run)
100
117
  op.setup_parser(op_parser)
@@ -9,10 +9,10 @@ from typing import TextIO, Tuple
9
9
  from ..api import ApiClient, ApiError, BadRequest
10
10
  from ..main import BaseOperation
11
11
  from ..main import Namespace as BaseNamespace, get_api
12
- from ..telemetry_client import TelemetryError
13
- from ..telemetry_client import get_client as get_telemetry_client
12
+ from ..telemetry_client import TelemetryClient, TelemetryError
14
13
  from ..types import ApiListResponse, VacancyItem
15
- from ..utils import fix_datetime, print_err, truncate_string, random_text
14
+ from ..utils import fix_datetime, truncate_string, random_text
15
+ from requests import Session
16
16
 
17
17
  logger = logging.getLogger(__package__)
18
18
 
@@ -159,7 +159,11 @@ class Operation(BaseOperation):
159
159
  search: str | None = None,
160
160
  reply_message: str | None = None,
161
161
  ) -> None:
162
- telemetry_client = get_telemetry_client()
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)
163
167
  telemetry_data = defaultdict(dict)
164
168
 
165
169
  vacancies = self._get_vacancies(
@@ -346,8 +350,7 @@ class Operation(BaseOperation):
346
350
 
347
351
  print("📝 Отклики на вакансии разосланы!")
348
352
 
349
- # Я собираюсь задеанонить всех хрюш яндексов и прочей хуеты, которую
350
- # считаю вселенским злом, так что телеметирию не трогайте
353
+ # Я собираюсь выложить контакты херок в общественный доступ
351
354
  self._send_telemetry(telemetry_client, telemetry_data)
352
355
 
353
356
  def _get_vacancies(
@@ -3,7 +3,6 @@ import json
3
3
  from urllib.parse import urljoin
4
4
  import requests
5
5
  from typing import Optional, Dict, Any
6
- from functools import cache
7
6
  import logging
8
7
  import base64
9
8
 
@@ -64,8 +63,3 @@ class TelemetryClient:
64
63
  json.JSONDecodeError,
65
64
  ) as ex:
66
65
  raise TelemetryError(str(ex)) from ex
67
-
68
-
69
- @cache
70
- def get_client() -> TelemetryClient:
71
- return TelemetryClient()
@@ -10,7 +10,8 @@ from threading import Lock
10
10
  from typing import Any
11
11
  from os import getenv
12
12
  from .constants import INVALID_ISO8601_FORMAT
13
- import re, random
13
+ import re
14
+ import random
14
15
 
15
16
  print_err = partial(print, file=sys.stderr, flush=True)
16
17
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "hh-applicant-tool"
3
- version = "0.3.7"
3
+ version = "0.3.8"
4
4
  description = ""
5
5
  authors = ["Senior YAML Developer <yamldeveloper@proton.me>"]
6
6
  readme = "README.md"
@@ -8,7 +8,7 @@ packages = [{include = "hh_applicant_tool"}]
8
8
 
9
9
  [tool.poetry.dependencies]
10
10
  python = "^3.10"
11
- requests = "^2.28.2"
11
+ requests = {extras = ["socks"], version = "^2.32.3"}
12
12
  prettytable = "^3.6.0"
13
13
  pyqt6 = { version = "^6.7.1", optional = true }
14
14
  pyqt6-webengine = { version = "^6.7.0", optional = true }