notify-tls-client 0.1.6__py3-none-any.whl → 0.1.9__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.
Files changed (26) hide show
  1. notify_tls_client/__init__.py +2 -2
  2. notify_tls_client/core/client/__init__.py +1 -6
  3. notify_tls_client/core/client/decorators.py +239 -90
  4. notify_tls_client/core/client_identifiers_manager.py +45 -0
  5. notify_tls_client/core/notifytlsclient.py +196 -146
  6. notify_tls_client/core/proxiesmanager/__init__.py +1 -1
  7. notify_tls_client/core/proxiesmanager/proxiesmanager.py +67 -67
  8. notify_tls_client/core/proxiesmanager/proxiesmanagerloader.py +33 -33
  9. notify_tls_client/tls_client/__init__.py +14 -14
  10. notify_tls_client/tls_client/__version__.py +10 -10
  11. notify_tls_client/tls_client/cffi.py +38 -62
  12. notify_tls_client/tls_client/cookies.py +456 -456
  13. notify_tls_client/tls_client/dependencies/{tls-client-xgo-1.11.0-darwin-arm64.dylib → tls-client-darwin-amd64-1.12.0.dylib} +0 -0
  14. notify_tls_client/tls_client/dependencies/tls-client-linux-arm64-1.12.0.so +0 -0
  15. notify_tls_client/tls_client/dependencies/{tls-client-xgo-1.11.0-linux-amd64.so → tls-client-linux-ubuntu-amd64-1.12.0.so} +0 -0
  16. notify_tls_client/tls_client/dependencies/{tls-client-windows-1.11.0-64.dll → tls-client-windows-64-1.12.0.dll} +0 -0
  17. notify_tls_client/tls_client/exceptions.py +2 -2
  18. notify_tls_client/tls_client/response.py +83 -78
  19. notify_tls_client/tls_client/sessions.py +522 -513
  20. notify_tls_client/tls_client/settings.py +69 -69
  21. notify_tls_client/tls_client/structures.py +74 -74
  22. {notify_tls_client-0.1.6.dist-info → notify_tls_client-0.1.9.dist-info}/METADATA +14 -16
  23. notify_tls_client-0.1.9.dist-info/RECORD +27 -0
  24. notify_tls_client-0.1.6.dist-info/RECORD +0 -25
  25. {notify_tls_client-0.1.6.dist-info → notify_tls_client-0.1.9.dist-info}/WHEEL +0 -0
  26. {notify_tls_client-0.1.6.dist-info → notify_tls_client-0.1.9.dist-info}/top_level.txt +0 -0
@@ -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
@@ -1,6 +1 @@
1
- from .decorators import (
2
- increment_requests_decorator,
3
- handle_forbidden_requests_decorator,
4
- print_request_infos_decorator,
5
- change_state_decorator,
6
- handle_exception_requests_decorator)
1
+ from .decorators import (request_guard_decorator)
@@ -1,90 +1,239 @@
1
- import time
2
- import traceback
3
- from datetime import datetime
4
-
5
-
6
-
7
- def change_state_decorator(callback):
8
- def wrapper(*args, **kwargs):
9
- self = args[0]
10
- self.free = False
11
- response = callback(*args, **kwargs)
12
- self.free = True
13
- return response
14
-
15
- return wrapper
16
-
17
-
18
- def print_request_infos_decorator(callback):
19
- def wrapper(*args, **kwargs):
20
- start = time.time()
21
- response = callback(*args, **kwargs)
22
- response.elapsed = round((time.time() - start) * 1000, 2)
23
- self = args[0]
24
-
25
- print("Date: ", datetime.now().strftime("%d-%m-%Y %H:%M:%S.%f")[:-3])
26
- print(f"Request URL: {response.url}")
27
- print(f"Response Status Code: {response.status_code}")
28
- print(f"Response Headers: {response.headers}")
29
- print(f"Response Elapsed Time: {response.elapsed} ms")
30
-
31
- if self.client.proxies:
32
- print(f"Proxy: {self.client.proxies['http']}")
33
-
34
- print(f"-")
35
-
36
- return response
37
-
38
- return wrapper
39
-
40
-
41
- def handle_exception_requests_decorator(callback):
42
- def wrapper(*args, **kwargs):
43
- response = None
44
- try:
45
- response = callback(*args, **kwargs)
46
- except Exception as e:
47
- print(traceback.format_exc())
48
- self = args[0]
49
- self.get_tls().close()
50
- self._create_new_client(self.client_identifier,self.random_tls_extension_order)
51
- self.change_proxy()
52
-
53
- return response
54
-
55
- return wrapper
56
-
57
-
58
- def handle_forbidden_requests_decorator(callback):
59
- def wrapper(*args, **kwargs):
60
- response = callback(*args, **kwargs)
61
- if response.status_code == 403 or response.status_code == 429:
62
- self = args[0]
63
- self.get_tls().close()
64
- self._create_new_client(self.client_identifier,self.random_tls_extension_order)
65
-
66
- if self.proxies_manager:
67
- self.change_proxy()
68
-
69
- return response
70
-
71
- return wrapper
72
-
73
-
74
- def increment_requests_decorator(callback):
75
- def wrapper(*args, **kwargs):
76
-
77
- self = args[0]
78
- response = callback(*args, **kwargs)
79
- self.requests_amount += 1
80
-
81
- if self.requests_amount >= self.requests_limit_same_proxy:
82
- self.get_tls().close()
83
- self._create_new_client(self.client_identifier,self.random_tls_extension_order)
84
- self.change_proxy()
85
-
86
- return response
87
-
88
- return wrapper
89
-
90
-
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)