notify-tls-client 0.1.6__tar.gz → 0.1.9__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.
Files changed (41) hide show
  1. {notify_tls_client-0.1.6 → notify_tls_client-0.1.9}/MANIFEST.in +2 -2
  2. {notify_tls_client-0.1.6 → notify_tls_client-0.1.9}/PKG-INFO +14 -16
  3. notify_tls_client-0.1.9/README.md +2 -0
  4. {notify_tls_client-0.1.6 → notify_tls_client-0.1.9}/notify_tls_client/__init__.py +2 -2
  5. notify_tls_client-0.1.9/notify_tls_client/core/client/__init__.py +1 -0
  6. notify_tls_client-0.1.9/notify_tls_client/core/client/decorators.py +239 -0
  7. notify_tls_client-0.1.9/notify_tls_client/core/client_identifiers_manager.py +45 -0
  8. notify_tls_client-0.1.9/notify_tls_client/core/notifytlsclient.py +196 -0
  9. notify_tls_client-0.1.9/notify_tls_client/core/proxiesmanager/__init__.py +2 -0
  10. {notify_tls_client-0.1.6 → notify_tls_client-0.1.9}/notify_tls_client/core/proxiesmanager/proxiesmanager.py +67 -67
  11. {notify_tls_client-0.1.6 → notify_tls_client-0.1.9}/notify_tls_client/core/proxiesmanager/proxiesmanagerloader.py +33 -33
  12. {notify_tls_client-0.1.6 → notify_tls_client-0.1.9}/notify_tls_client/tls_client/__init__.py +14 -14
  13. {notify_tls_client-0.1.6 → notify_tls_client-0.1.9}/notify_tls_client/tls_client/__version__.py +10 -10
  14. notify_tls_client-0.1.9/notify_tls_client/tls_client/cffi.py +38 -0
  15. {notify_tls_client-0.1.6 → notify_tls_client-0.1.9}/notify_tls_client/tls_client/cookies.py +456 -456
  16. notify_tls_client-0.1.6/notify_tls_client/tls_client/dependencies/tls-client-xgo-1.11.0-darwin-arm64.dylib → notify_tls_client-0.1.9/notify_tls_client/tls_client/dependencies/tls-client-darwin-amd64-1.12.0.dylib +0 -0
  17. notify_tls_client-0.1.9/notify_tls_client/tls_client/dependencies/tls-client-linux-arm64-1.12.0.so +0 -0
  18. notify_tls_client-0.1.6/notify_tls_client/tls_client/dependencies/tls-client-xgo-1.11.0-linux-amd64.so → notify_tls_client-0.1.9/notify_tls_client/tls_client/dependencies/tls-client-linux-ubuntu-amd64-1.12.0.so +0 -0
  19. notify_tls_client-0.1.6/notify_tls_client/tls_client/dependencies/tls-client-windows-1.11.0-64.dll → notify_tls_client-0.1.9/notify_tls_client/tls_client/dependencies/tls-client-windows-64-1.12.0.dll +0 -0
  20. notify_tls_client-0.1.9/notify_tls_client/tls_client/exceptions.py +3 -0
  21. {notify_tls_client-0.1.6 → notify_tls_client-0.1.9}/notify_tls_client/tls_client/response.py +83 -78
  22. {notify_tls_client-0.1.6 → notify_tls_client-0.1.9}/notify_tls_client/tls_client/sessions.py +522 -513
  23. {notify_tls_client-0.1.6 → notify_tls_client-0.1.9}/notify_tls_client/tls_client/settings.py +69 -69
  24. {notify_tls_client-0.1.6 → notify_tls_client-0.1.9}/notify_tls_client/tls_client/structures.py +74 -74
  25. {notify_tls_client-0.1.6 → notify_tls_client-0.1.9}/notify_tls_client.egg-info/PKG-INFO +14 -16
  26. {notify_tls_client-0.1.6 → notify_tls_client-0.1.9}/notify_tls_client.egg-info/SOURCES.txt +5 -4
  27. {notify_tls_client-0.1.6 → notify_tls_client-0.1.9}/pyproject.toml +31 -28
  28. {notify_tls_client-0.1.6 → notify_tls_client-0.1.9}/setup.cfg +4 -4
  29. notify_tls_client-0.1.6/README.md +0 -2
  30. notify_tls_client-0.1.6/notify_tls_client/core/client/__init__.py +0 -6
  31. notify_tls_client-0.1.6/notify_tls_client/core/client/decorators.py +0 -90
  32. notify_tls_client-0.1.6/notify_tls_client/core/notifytlsclient.py +0 -146
  33. notify_tls_client-0.1.6/notify_tls_client/core/proxiesmanager/__init__.py +0 -2
  34. notify_tls_client-0.1.6/notify_tls_client/tls_client/cffi.py +0 -62
  35. notify_tls_client-0.1.6/notify_tls_client/tls_client/exceptions.py +0 -3
  36. notify_tls_client-0.1.6/setup.py +0 -14
  37. {notify_tls_client-0.1.6 → notify_tls_client-0.1.9}/notify_tls_client/core/__init__.py +0 -0
  38. {notify_tls_client-0.1.6 → notify_tls_client-0.1.9}/notify_tls_client/tls_client/dependencies/__init__.py +0 -0
  39. {notify_tls_client-0.1.6 → notify_tls_client-0.1.9}/notify_tls_client.egg-info/dependency_links.txt +0 -0
  40. {notify_tls_client-0.1.6 → notify_tls_client-0.1.9}/notify_tls_client.egg-info/requires.txt +0 -0
  41. {notify_tls_client-0.1.6 → notify_tls_client-0.1.9}/notify_tls_client.egg-info/top_level.txt +0 -0
@@ -1,3 +1,3 @@
1
- exclude proxies.txt
2
- exclude notify_tls_client/main.py
1
+ exclude proxies.txt
2
+ exclude notify_tls_client/main.py
3
3
  include notify_tls_client/tls_client/dependencies/*
@@ -1,16 +1,14 @@
1
- Metadata-Version: 2.4
2
- Name: notify_tls_client
3
- Version: 0.1.6
4
- Summary: Sem descrição
5
- Author: Jeferson Albara
6
- Author-email: Naruto Uzumaki <naruto_uzumaki@gmail.com>
7
- License: MIT
8
- Project-URL: Homepage, https://github.com/jefersonAlbara/notify-tls-client
9
- Requires-Python: >=3.12
10
- Description-Content-Type: text/markdown
11
- Requires-Dist: dataclasses_json
12
- Requires-Dist: typing_extensions
13
- Dynamic: author
14
-
15
- # MY TLS Client
16
- Pacote python privado com modificações na classe 'tls client'
1
+ Metadata-Version: 2.4
2
+ Name: notify_tls_client
3
+ Version: 0.1.9
4
+ Summary: Sem descrição
5
+ Author-email: Naruto Uzumaki <naruto_uzumaki@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/jefersonAlbara/notify-tls-client
8
+ Requires-Python: >=3.12
9
+ Description-Content-Type: text/markdown
10
+ Requires-Dist: dataclasses_json
11
+ Requires-Dist: typing_extensions
12
+
13
+ # MY TLS Client
14
+ Pacote python privado com modificações na classe 'tls client'
@@ -0,0 +1,2 @@
1
+ # MY TLS Client
2
+ Pacote python privado com modificações na classe 'tls client'
@@ -1,2 +1,2 @@
1
- from .core.notifytlsclient import NotifyTLSClient
2
- from .tls_client import Session
1
+ from .core.notifytlsclient import NotifyTLSClient
2
+ from .tls_client import Session
@@ -0,0 +1 @@
1
+ from .decorators import (request_guard_decorator)
@@ -0,0 +1,239 @@
1
+ import logging
2
+ from datetime import datetime
3
+ from typing import Optional
4
+ from urllib.parse import urlparse
5
+
6
+ from notify_tls_client.tls_client.response import Response
7
+
8
+ logger = logging.getLogger(__name__)
9
+
10
+
11
+ def __is_valid_url(url: str) -> bool:
12
+ if not isinstance(url, str):
13
+ return False
14
+
15
+ parsed = urlparse(url)
16
+ return all([parsed.scheme, parsed.netloc])
17
+
18
+
19
+ def request_guard_decorator(callback):
20
+ def wrapper(*args, **kwargs):
21
+ self = args[0]
22
+ self.free = False
23
+ request_url = None
24
+ request_headers = {}
25
+ res = None
26
+
27
+ for arg in args:
28
+ if isinstance(arg, str) and __is_valid_url(arg):
29
+ request_url = arg
30
+ break
31
+
32
+ for key, value in kwargs.items():
33
+ if key == 'url':
34
+ request_url = value
35
+ break
36
+
37
+ if key == 'headers':
38
+ request_headers = value
39
+
40
+ try:
41
+ self.requests_amount += 1
42
+ res = callback(*args, **kwargs)
43
+ _log_request_info(self, res, request_url, request_headers)
44
+ _requests_handler(self, res)
45
+ return res
46
+
47
+ except Exception as e:
48
+ logging.exception("Exception occurred during TLS request")
49
+ _log_request_info(self, res, request_url, request_headers)
50
+ _recover_on_exception(self)
51
+ _requests_handler(self, res)
52
+
53
+ finally:
54
+ self.free = True
55
+
56
+ # _forbidden_request_handler(self, res)
57
+
58
+ return None
59
+
60
+ return wrapper
61
+
62
+
63
+ def _recover_on_exception(self):
64
+ if self.instantiate_new_client_on_exception:
65
+ logging.info("Instantiating new TLS client due to exception...")
66
+ self.get_tls().close()
67
+ self._create_new_client()
68
+
69
+ if self.proxies_manager:
70
+ logging.info("Changing proxy due to exception...")
71
+ self.change_proxy()
72
+
73
+
74
+ def _log_request_info(self,
75
+ response: Optional[Response],
76
+ request_url: Optional[str],
77
+ request_headers: dict):
78
+ if response:
79
+ logger.debug(f"""Request finished
80
+ client_identifier={self.get_current_client_identifier()}
81
+ request_url={request_url}
82
+ request_headers={request_headers}
83
+ response_url={response.url}
84
+ status_code={response.status_code}
85
+ response_time={response.elapsed}ms
86
+ response_headers={dict(response.headers)}
87
+ proxy={self.client.proxies['http'] if self.client.proxies else None}
88
+ """,
89
+ extra={
90
+ "date": datetime.now().strftime("%d-%m-%Y %H:%M:%S.%f")[:-3],
91
+ "request_url": request_url,
92
+ "request_headers": request_headers,
93
+ "response_url": response.url,
94
+ "status_code": response.status_code,
95
+ "response_headers": dict(response.headers),
96
+ "response_elapsed_ms": response.elapsed,
97
+ "proxy": self.client.proxies['http'] if self.client.proxies else None,
98
+ "client_identifier": self.get_current_client_identifier()
99
+
100
+ })
101
+
102
+ if not response:
103
+ logger.debug(f"""Request failed before getting a response
104
+ client_identifier={self.get_current_client_identifier()}
105
+ request_url={request_url}
106
+ request_headers={request_headers}
107
+ response_url=None
108
+ status_code=None
109
+ response_headers=None
110
+ response_time=0
111
+ proxy={self.client.proxies['http'] if self.client.proxies else None}
112
+ """,
113
+ extra={
114
+ "date": datetime.now().strftime("%d-%m-%Y %H:%M:%S.%f")[:-3],
115
+ "request_url": request_url,
116
+ "request_headers": request_headers,
117
+ "response_url": None,
118
+ "status_code": None,
119
+ "response_headers": None,
120
+ "response_elapsed_ms": 0,
121
+ "proxy": self.client.proxies['http'] if self.client.proxies else None,
122
+ "client_identifier": self.get_current_client_identifier()
123
+
124
+ })
125
+
126
+
127
+ def _forbidden_request_handler(self, response: Optional[Response]):
128
+ if not response:
129
+ return
130
+
131
+ if response.status_code in self.status_codes_to_forbidden_response_handle:
132
+ if self.instantiate_new_client_on_forbidden_response:
133
+ logging.info("Instantiating new TLS client due to forbidden response...")
134
+ self.get_tls().close()
135
+ self._create_new_client()
136
+
137
+ if self.proxies_manager:
138
+ logging.info("Changing proxy due to forbidden response...")
139
+ self.change_proxy()
140
+
141
+
142
+ # tem casos que está retornando 403 como erro da API, tenho que estudar o que fazer nesses casos
143
+ def _requests_handler(self, response: Optional[Response]):
144
+ self.requests_amount_with_current_client_identifier += 1
145
+
146
+ if self.proxies_manager:
147
+ self.requests_amount_with_current_proxy += 1
148
+
149
+ if not response:
150
+ return
151
+
152
+ client_identifier_changed_by_limit = self.is_client_identifier_changeable_by_requests_limit_reached()
153
+ is_same_proxy_limit = self.is_same_proxy_request_limit_reached()
154
+ is_forbidden_request_status = self.is_forbidden_request_status(response.status_code)
155
+ create_new_client_on_forbidden = self.instantiate_new_client_on_forbidden_response
156
+ change_client_identifier_on_forbidden = self.change_client_identifier_on_forbidden_response
157
+ has_proxies_manager = self.has_proxies_manager()
158
+
159
+ if client_identifier_changed_by_limit:
160
+ logging.info("Requests limit reached for current client identifier")
161
+ if is_forbidden_request_status or is_same_proxy_limit:
162
+ self._create_new_client(self.client_identifiers_manager.get_next(),
163
+ proxy=None if not has_proxies_manager else self.proxies_manager.get_next())
164
+
165
+ else:
166
+ self._create_new_client(self.client_identifiers_manager.get_next(),
167
+ proxy=None if not has_proxies_manager else self.proxies_manager.get_current_proxy())
168
+
169
+ return
170
+
171
+ if is_forbidden_request_status:
172
+
173
+ if not create_new_client_on_forbidden:
174
+ if has_proxies_manager:
175
+ logging.info("Changing proxy due to forbidden response...")
176
+ self.change_proxy()
177
+
178
+ return
179
+
180
+ if create_new_client_on_forbidden:
181
+ if change_client_identifier_on_forbidden:
182
+ logging.info("Instantiating new TLS client due to forbidden response and changing client identifier...")
183
+ self._create_new_client(self.client_identifiers_manager.get_next(),
184
+ proxy=None if not has_proxies_manager else self.proxies_manager.get_next())
185
+
186
+ else:
187
+ logging.info("Instantiating new TLS client due to forbidden response...")
188
+ item = self.client_identifiers_manager.get_current_item()
189
+ self._create_new_client(str(item),
190
+ proxy=None if not has_proxies_manager else self.proxies_manager.get_next())
191
+
192
+
193
+ if is_same_proxy_limit:
194
+ if has_proxies_manager:
195
+ logging.info("Changing proxy due to requests limit reached...")
196
+ self.change_proxy()
197
+
198
+ # if client_identifier_changed_by_limit:
199
+ # logging.info("Requests limit reached for current client identifier")
200
+ # logging.info("Changing client identifier due to requests limit reached...")
201
+ # # self._create_new_client(self.client_identifiers_manager.get_next(),
202
+ # # proxy=self.proxies_manager.get_current_proxy() if self.proxies_manager else None)
203
+ #
204
+ #
205
+ #
206
+ #
207
+ # if self.requests_limit_with_same_proxy and self.requests_amount_with_current_proxy >= self.requests_limit_with_same_proxy:
208
+ # logging.info("Requests limit reached for current proxy")
209
+ # if self.proxies_manager:
210
+ # proxy_changed_by_limit = True
211
+ # logging.info("Changing proxy due to requests limit reached...")
212
+ #
213
+ # if response.status_code in self.status_codes_to_forbidden_response_handle and self.instantiate_new_client_on_forbidden_response:
214
+ # logging.info("Instantiating new TLS client due to forbidden response before changing proxy...")
215
+ # self.get_tls().close()
216
+ # if self.change_client_identifier_on_forbidden_response:
217
+ # self._create_new_client(self.client_identifiers_manager.get_next())
218
+ # else:
219
+ # self._create_new_client(self.client_identifiers_manager.get_current())
220
+ #
221
+ # self.change_proxy()
222
+ #
223
+ # # Metodo vai ter que ser usado para não trocar o proxy duas vezes, uma pelo status 403 e outra pelo limite de requests
224
+ # if not proxy_changed_by_limit:
225
+ # return
226
+ #
227
+ # if response.status_code in self.status_codes_to_forbidden_response_handle:
228
+ # if self.instantiate_new_client_on_forbidden_response:
229
+ # logging.info("Instantiating new TLS client due to forbidden response...")
230
+ # self.get_tls().close()
231
+ #
232
+ # if self.change_client_identifier_on_forbidden_response:
233
+ # self._create_new_client(self.client_identifiers_manager.get_next())
234
+ # else:
235
+ # self._create_new_client()
236
+ #
237
+ # if self.proxies_manager:
238
+ # logging.info("Changing proxy due to forbidden response...")
239
+ # self.change_proxy()
@@ -0,0 +1,45 @@
1
+ from dataclasses import dataclass, field
2
+ from typing import Optional
3
+
4
+ from dataclasses_json import dataclass_json
5
+
6
+ from notify_tls_client.tls_client.settings import ClientIdentifiers
7
+
8
+
9
+ @dataclass_json
10
+ @dataclass
11
+ class ClientIdentifiersManager:
12
+ _items: list[ClientIdentifiers] = field(default_factory=list)
13
+ _current_index: int = 0
14
+ _current_item: Optional[ClientIdentifiers] = None
15
+
16
+ def get_next(self) -> ClientIdentifiers:
17
+ if not self._items:
18
+ raise Exception('No items available')
19
+
20
+ if self._current_index < len(self._items):
21
+ _item = self._items[self._current_index]
22
+ self._current_index += 1
23
+ else:
24
+ self._current_index = 0
25
+ _item = self._items[self._current_index]
26
+
27
+ return _item
28
+
29
+ def get_current_item(self) -> Optional[ClientIdentifiers]:
30
+ if not self._items:
31
+ return None
32
+
33
+ return self._items[0] if self._current_index == 0 else self._items[self._current_index - 1]
34
+
35
+
36
+ def set_items(self, items: list[ClientIdentifiers]):
37
+ self._items = items
38
+ self._current_proxy_index = 0
39
+ self._current_proxy = None
40
+
41
+ def get_item(self) -> list[ClientIdentifiers]:
42
+ return self._items
43
+
44
+ def get_total_items(self) -> int:
45
+ return len(self._items)
@@ -0,0 +1,196 @@
1
+ import logging
2
+ from typing import Optional
3
+
4
+ from typing_extensions import TypeAlias, Literal
5
+
6
+ from notify_tls_client.core.client import *
7
+ from notify_tls_client.core.client_identifiers_manager import ClientIdentifiersManager
8
+ from notify_tls_client.core.proxiesmanager import ProxiesManager, Proxy
9
+ from notify_tls_client.tls_client.response import Response
10
+ from notify_tls_client.tls_client.sessions import Session
11
+ from notify_tls_client.tls_client.settings import ClientIdentifiers
12
+ from notify_tls_client.tls_client.structures import CaseInsensitiveDict
13
+
14
+ HttpMethods: TypeAlias = Literal["GET", "POST", "PUT", "DELETE", "PATCH"]
15
+ logger = logging.Logger(__name__)
16
+
17
+
18
+ class NotifyTLSClient:
19
+ def __init__(self,
20
+ proxies_manager: Optional[ProxiesManager] = None,
21
+ client_identifiers: list[ClientIdentifiers] = None,
22
+ requests_limit_same_proxy: int = 1000,
23
+ random_tls_extension_order: bool = True,
24
+ requests_limit_with_same_client_identifier: int = -1,
25
+ instantiate_new_client_on_forbidden_response: bool = False,
26
+ instantiate_new_client_on_exception: bool = False,
27
+ debug_mode: bool = False,
28
+ status_codes_to_forbidden_response_handle: list[int] = None,
29
+ change_client_identifier_on_forbidden_response: bool = False,
30
+ default_headers: dict = None,
31
+ disable_http3: bool = False
32
+ ):
33
+
34
+ self.client: Optional[Session] = None
35
+ self.change_client_identifier_on_forbidden_response = change_client_identifier_on_forbidden_response
36
+ self.client_identifiers_manager = ClientIdentifiersManager(client_identifiers or ["chrome_133"])
37
+ self.status_codes_to_forbidden_response_handle = status_codes_to_forbidden_response_handle or [403]
38
+ self.free = True
39
+ self.requests_amount = 0
40
+ self.requests_amount_with_current_proxy = 0
41
+ self.requests_amount_with_current_client_identifier = 0
42
+ self.last_request_status = 0
43
+ self.headers = default_headers or CaseInsensitiveDict({
44
+ "User-Agent": f"tls-client/1.0.0",
45
+ "Accept-Encoding": "gzip, deflate, br",
46
+ "Accept": "image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8",
47
+ "Connection": "keep-alive",
48
+ })
49
+
50
+ self.disable_http3 = disable_http3
51
+ self.proxies_manager = proxies_manager
52
+ self.requests_limit_with_same_proxy = requests_limit_same_proxy
53
+ self.requests_limit_with_same_client_identifier = requests_limit_with_same_client_identifier
54
+ self.debug_mode = debug_mode
55
+
56
+ self.instantiate_new_client_on_forbidden_response = instantiate_new_client_on_forbidden_response
57
+ self.instantiate_new_client_on_exception = instantiate_new_client_on_exception
58
+
59
+ self.current_proxy = None
60
+ self._create_new_client(self.client_identifiers_manager.get_next(),
61
+ random_tls_extension_order,
62
+ proxy=self.proxies_manager.get_next() if self.proxies_manager else None)
63
+
64
+
65
+ def _create_new_client(self,
66
+ client_identifier: ClientIdentifiers = 'chrome_133',
67
+ random_tls_extension_order: bool = False,
68
+ proxy: Optional[Proxy] = None):
69
+
70
+
71
+
72
+ if self.client:
73
+ self.client.close()
74
+
75
+ old_client_identifier = self.client.client_identifier if self.client else None
76
+
77
+ self.client = Session(client_identifier=client_identifier,
78
+ random_tls_extension_order=random_tls_extension_order)
79
+
80
+ if old_client_identifier != client_identifier:
81
+ self.requests_amount_with_current_client_identifier = 0
82
+
83
+ if proxy:
84
+
85
+ self.client.proxies = proxy.to_proxy_dict()
86
+
87
+ if self.current_proxy != proxy:
88
+ self.current_proxy = proxy
89
+ self.requests_amount_with_current_proxy = 0
90
+
91
+
92
+ def set_requests_limit_same_proxy(self, requests_limit_same_proxy: int):
93
+ self.requests_limit_with_same_proxy = requests_limit_same_proxy
94
+
95
+ def set_proxies_manager(self, proxies_manager: ProxiesManager):
96
+ self.proxies_manager = proxies_manager
97
+
98
+ def change_proxy(self):
99
+ if self.proxies_manager and self.proxies_manager.get_proxies():
100
+ self.current_proxy = self.proxies_manager.get_next()
101
+ self.client.proxies = self.current_proxy.to_proxy_dict()
102
+ self.requests_amount_with_current_proxy = 0
103
+
104
+ def set_proxies(self, proxies: Proxy):
105
+ self.client.proxies = proxies.to_proxy_dict()
106
+
107
+ def set_headers(self, headers: dict):
108
+ self.client.headers = CaseInsensitiveDict(headers)
109
+
110
+ def get_cookies(self):
111
+ return self.client.cookies
112
+
113
+ def get_cookie_by_name(self, name: str) -> Optional[str]:
114
+ try:
115
+ return self.client.cookies.get(name)
116
+ except Exception as e:
117
+ logging.exception(f"Error getting cookie '{name}': {e}")
118
+
119
+ @request_guard_decorator
120
+ def execute_request(self, method: HttpMethods, url: str, **kwargs) -> Optional[Response]:
121
+ method = method.upper()
122
+ if method == "GET":
123
+ return self.client.get(url, **kwargs)
124
+ elif method == "POST":
125
+ return self.client.post(url, **kwargs)
126
+ elif method == "PUT":
127
+ return self.client.put(url, **kwargs)
128
+ elif method == "DELETE":
129
+ return self.client.delete(url, **kwargs)
130
+ elif method == "PATCH":
131
+ return self.client.delete(url, **kwargs)
132
+ else:
133
+ raise ValueError(f"Unsupported HTTP method: {method}")
134
+
135
+ def get(self, url: str, **kwargs) -> Optional[Response]:
136
+ return self.execute_request("GET", url, **kwargs)
137
+
138
+ def post(self, url: str, **kwargs) -> Optional[Response]:
139
+ return self.execute_request("POST", url, **kwargs)
140
+
141
+ def put(self, url: str, **kwargs) -> Optional[Response]:
142
+ return self.execute_request("PUT", url, **kwargs)
143
+
144
+ def delete(self, url: str, **kwargs) -> Optional[Response]:
145
+ return self.execute_request("DELETE", url, **kwargs)
146
+
147
+ def patch(self, url: str, **kwargs) -> Optional[Response]:
148
+ return self.execute_request("PATCH", url, **kwargs)
149
+
150
+ def _change_to_free(self):
151
+ self.free = True
152
+
153
+ def _change_to_busy(self):
154
+ self.free = False
155
+
156
+ def get_cookie_value_by_name(self, name: str):
157
+ return self.client.cookies.get(name)
158
+
159
+ def set_cookie(self, name: str, value: str):
160
+ self.client.cookies.set(name, value)
161
+
162
+ def get_tls(self):
163
+ return self.client
164
+
165
+ def get_current_client_identifier(self) -> ClientIdentifiers:
166
+ return self.client.client_identifier
167
+
168
+ def is_same_proxy_request_limit_reached(self) -> bool:
169
+ if self.requests_limit_with_same_proxy == -1:
170
+ return False
171
+
172
+ return self.requests_amount_with_current_proxy >= self.requests_limit_with_same_proxy
173
+
174
+ def is_same_client_identifier_request_limit_reached(self) -> bool:
175
+ if self.requests_limit_with_same_client_identifier == -1:
176
+ return False
177
+
178
+ return self.requests_amount_with_current_client_identifier >= self.requests_limit_with_same_client_identifier
179
+
180
+ def is_client_identifier_changeable_by_requests_limit_reached(self) -> bool:
181
+ return self.is_same_client_identifier_request_limit_reached() and self.has_multiple_client_identifiers()
182
+
183
+
184
+ def has_multiple_client_identifiers(self) -> bool:
185
+ return self.client_identifiers_manager.get_total_items() > 1
186
+
187
+
188
+ def is_forbidden_request_status(self, status_code: int) -> bool:
189
+ return status_code in self.status_codes_to_forbidden_response_handle
190
+
191
+ def has_proxies_manager(self) -> bool:
192
+ return self.proxies_manager is not None and self.proxies_manager.get_proxies()
193
+
194
+ def set_default_headers(self, headers: dict):
195
+ self.headers = headers
196
+ self.client.headers = self.headers
@@ -0,0 +1,2 @@
1
+ from .proxiesmanager import ProxiesManager, Proxy
2
+ from .proxiesmanagerloader import ProxiesManagerLoader
@@ -1,67 +1,67 @@
1
- from dataclasses import dataclass, field
2
- from typing import Optional
3
-
4
- from dataclasses_json import dataclass_json
5
-
6
-
7
- @dataclass_json
8
- @dataclass
9
- class Proxy:
10
- host: str
11
- port: int
12
- username: Optional[str] = None
13
- password: Optional[str] = None
14
-
15
- def to_proxy_dict(self):
16
- if self.username is None:
17
- return {
18
- 'http': f'http://{self.host}:{self.port}',
19
- 'https': f'https://{self.host}:{self.port}'
20
- }
21
-
22
- return {
23
- 'http': f'http://{self.username}:{self.password}@{self.host}:{self.port}',
24
- 'https': f'https://{self.username}:{self.password}@{self.host}:{self.port}'
25
- }
26
-
27
-
28
- @dataclass_json
29
- @dataclass
30
- class ProxiesManager:
31
- _proxies: list[Proxy] = field(default_factory=list)
32
- _current_proxy_index: int = 0
33
- _current_proxy: Optional[Proxy] = None
34
-
35
- def get_next(self) -> Proxy:
36
-
37
- if not self._proxies:
38
- raise Exception('No proxies available')
39
-
40
- if self._current_proxy_index < len(self._proxies):
41
- proxy = self._proxies[self._current_proxy_index]
42
- self._current_proxy_index += 1
43
- else:
44
- self._current_proxy_index = 0
45
- proxy = self._proxies[self._current_proxy_index]
46
-
47
- return proxy
48
-
49
- def get_current_proxy(self) -> Optional[Proxy]:
50
- if not self._current_proxy:
51
- return None
52
-
53
- return self._current_proxy
54
-
55
- def set_proxies(self, proxies: list[Proxy]):
56
- self._proxies = proxies
57
- self._current_proxy_index = 0
58
- self._current_proxy = None
59
-
60
- def add_proxy(self, proxy: Proxy):
61
- self._proxies.append(proxy)
62
- self._current_proxy_index = 0
63
- def get_proxies(self) -> list[Proxy]:
64
- return self._proxies
65
-
66
-
67
-
1
+ from dataclasses import dataclass, field
2
+ from typing import Optional
3
+
4
+ from dataclasses_json import dataclass_json
5
+
6
+
7
+ @dataclass_json
8
+ @dataclass
9
+ class Proxy:
10
+ host: str
11
+ port: int
12
+ username: Optional[str] = None
13
+ password: Optional[str] = None
14
+
15
+ def to_proxy_dict(self):
16
+ if self.username is None:
17
+ return {
18
+ 'http': f'http://{self.host}:{self.port}',
19
+ 'https': f'https://{self.host}:{self.port}'
20
+ }
21
+
22
+ return {
23
+ 'http': f'http://{self.username}:{self.password}@{self.host}:{self.port}',
24
+ 'https': f'https://{self.username}:{self.password}@{self.host}:{self.port}'
25
+ }
26
+
27
+
28
+ @dataclass_json
29
+ @dataclass
30
+ class ProxiesManager:
31
+ _proxies: list[Proxy] = field(default_factory=list)
32
+ _current_proxy_index: int = 0
33
+ _current_proxy: Optional[Proxy] = None
34
+
35
+ def get_next(self) -> Proxy:
36
+
37
+ if not self._proxies:
38
+ raise Exception('No proxies available')
39
+
40
+ if self._current_proxy_index < len(self._proxies):
41
+ proxy = self._proxies[self._current_proxy_index]
42
+ self._current_proxy_index += 1
43
+ else:
44
+ self._current_proxy_index = 0
45
+ proxy = self._proxies[self._current_proxy_index]
46
+
47
+ return proxy
48
+
49
+ def get_current_proxy(self) -> Optional[Proxy]:
50
+ if not self._current_proxy:
51
+ return None
52
+
53
+ return self._current_proxy
54
+
55
+ def set_proxies(self, proxies: list[Proxy]):
56
+ self._proxies = proxies
57
+ self._current_proxy_index = 0
58
+ self._current_proxy = None
59
+
60
+ def add_proxy(self, proxy: Proxy):
61
+ self._proxies.append(proxy)
62
+ self._current_proxy_index = 0
63
+ def get_proxies(self) -> list[Proxy]:
64
+ return self._proxies
65
+
66
+
67
+