hyper-sdk 0.1.1__tar.gz → 0.2.0__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.
- {hyper_sdk-0.1.1 → hyper_sdk-0.2.0}/PKG-INFO +97 -1
- {hyper_sdk-0.1.1 → hyper_sdk-0.2.0}/README.md +96 -0
- {hyper_sdk-0.1.1 → hyper_sdk-0.2.0}/hyper_sdk/__init__.py +2 -0
- {hyper_sdk-0.1.1 → hyper_sdk-0.2.0}/hyper_sdk/akamai/sec_cpt.py +17 -1
- hyper_sdk-0.2.0/hyper_sdk/datadome/__init__.py +1 -0
- hyper_sdk-0.2.0/hyper_sdk/datadome/parse.py +82 -0
- hyper_sdk-0.2.0/hyper_sdk/datadome_input.py +50 -0
- hyper_sdk-0.2.0/hyper_sdk/kasada/__init__.py +1 -0
- hyper_sdk-0.2.0/hyper_sdk/kasada/parse.py +27 -0
- hyper_sdk-0.2.0/hyper_sdk/kasada_input.py +37 -0
- {hyper_sdk-0.1.1 → hyper_sdk-0.2.0}/hyper_sdk/session.py +77 -1
- {hyper_sdk-0.1.1 → hyper_sdk-0.2.0}/hyper_sdk.egg-info/PKG-INFO +97 -1
- {hyper_sdk-0.1.1 → hyper_sdk-0.2.0}/hyper_sdk.egg-info/SOURCES.txt +7 -1
- {hyper_sdk-0.1.1 → hyper_sdk-0.2.0}/pyproject.toml +2 -2
- {hyper_sdk-0.1.1 → hyper_sdk-0.2.0}/LICENSE +0 -0
- {hyper_sdk-0.1.1 → hyper_sdk-0.2.0}/hyper_sdk/akamai/__init__.py +0 -0
- {hyper_sdk-0.1.1 → hyper_sdk-0.2.0}/hyper_sdk/akamai/pixel.py +0 -0
- {hyper_sdk-0.1.1 → hyper_sdk-0.2.0}/hyper_sdk/akamai/script_path.py +0 -0
- {hyper_sdk-0.1.1 → hyper_sdk-0.2.0}/hyper_sdk/akamai/stop_signal.py +0 -0
- {hyper_sdk-0.1.1 → hyper_sdk-0.2.0}/hyper_sdk/akamai_input.py +0 -0
- {hyper_sdk-0.1.1 → hyper_sdk-0.2.0}/hyper_sdk/incapsula/__init__.py +0 -0
- {hyper_sdk-0.1.1 → hyper_sdk-0.2.0}/hyper_sdk/incapsula/utmvc.py +0 -0
- {hyper_sdk-0.1.1 → hyper_sdk-0.2.0}/hyper_sdk/incapsula_input.py +0 -0
- {hyper_sdk-0.1.1 → hyper_sdk-0.2.0}/hyper_sdk.egg-info/dependency_links.txt +0 -0
- {hyper_sdk-0.1.1 → hyper_sdk-0.2.0}/hyper_sdk.egg-info/requires.txt +0 -0
- {hyper_sdk-0.1.1 → hyper_sdk-0.2.0}/hyper_sdk.egg-info/top_level.txt +0 -0
- {hyper_sdk-0.1.1 → hyper_sdk-0.2.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: hyper_sdk
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Hyper Solutions Python SDK
|
|
5
5
|
Project-URL: homepage, https://github.com/Hyper-Solutions/hyper-sdk-py
|
|
6
6
|
Classifier: Intended Audience :: Developers
|
|
@@ -192,3 +192,99 @@ from hyper_sdk.incapsula.utmvc import get_utmvc_submit_path
|
|
|
192
192
|
|
|
193
193
|
submit_path = get_utmvc_submit_path()
|
|
194
194
|
```
|
|
195
|
+
|
|
196
|
+
## Kasada
|
|
197
|
+
|
|
198
|
+
The Kasada package provides functions for interacting with Kasada Bot Manager, including parsing script path.
|
|
199
|
+
|
|
200
|
+
### Generating Payload Data (CT)
|
|
201
|
+
|
|
202
|
+
To generate payload data required for generating valid `x-kpsdk-ct` tokens, use the `generate_kasada_payload` function:
|
|
203
|
+
|
|
204
|
+
```python
|
|
205
|
+
payload, headers = hyper_session.generate_kasada_payload(hyper_sdk.KasadaPayloadInput(
|
|
206
|
+
user_agent=USER_AGENT,
|
|
207
|
+
ips_link=ips_link,
|
|
208
|
+
script=ips_script,
|
|
209
|
+
language="en-US"
|
|
210
|
+
))
|
|
211
|
+
# Use payload and headers for the next request
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### Generating Pow Data (CD)
|
|
215
|
+
|
|
216
|
+
To generate POW data (`x-kpsdk-cd`) tokens, use the `generate_kasada_pow` function:
|
|
217
|
+
|
|
218
|
+
```python
|
|
219
|
+
cd = hyper_session.generate_kasada_pow(hyper_sdk.KasadaPowInput(
|
|
220
|
+
st=st,
|
|
221
|
+
work_time=None
|
|
222
|
+
))
|
|
223
|
+
# Use cd as the x-kpsdk-cd header in the next request
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### Parsing Script Path
|
|
227
|
+
|
|
228
|
+
To parse the Kasada script path from the given blocked page (status code 429) HTML code, use the `parse_script_path` function:
|
|
229
|
+
|
|
230
|
+
```python
|
|
231
|
+
from hyper_sdk.kasada import parse_script_path
|
|
232
|
+
|
|
233
|
+
script_path = parse_script_path(html_content)
|
|
234
|
+
# script_path will look like: /ips.js?...
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
## DataDome
|
|
238
|
+
|
|
239
|
+
The DataDome package provides functions for interacting with DataDome Bot Manager, including parsing device link URLs
|
|
240
|
+
for interstitial and slider challenges.
|
|
241
|
+
|
|
242
|
+
### Generating Interstitial Payload
|
|
243
|
+
|
|
244
|
+
To generate payload data required for solving interstitial challenges, use the `generate_interstitial_payload` function:
|
|
245
|
+
|
|
246
|
+
```python
|
|
247
|
+
payload = hyper_session.generate_interstitial_payload(hyper_sdk.DataDomeInterstitialInput(
|
|
248
|
+
user_agent=USER_AGENT,
|
|
249
|
+
device_link=device_check_link,
|
|
250
|
+
html=html_content
|
|
251
|
+
))
|
|
252
|
+
# Use the payload to POST to https://geo.captcha-delivery.com/interstitial/
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### Generating Slider Payload
|
|
256
|
+
|
|
257
|
+
To solve DataDome Slider challenges, use the `generate_slider_payload` function:
|
|
258
|
+
|
|
259
|
+
```python
|
|
260
|
+
payload = hyper_session.generate_slider_payload(hyper_sdk.DataDomeSliderInput(
|
|
261
|
+
user_agent=USER_AGENT,
|
|
262
|
+
device_link=device_check_link,
|
|
263
|
+
html=html_content,
|
|
264
|
+
puzzle=base64_encoded_puzzle,
|
|
265
|
+
piece=base64_encoded_piece
|
|
266
|
+
))
|
|
267
|
+
# Create a GET request to the payload URL
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### Parsing Interstitial DeviceLink URL
|
|
271
|
+
|
|
272
|
+
To parse the Interstitial DeviceLink URL from the HTML code, use the `parse_interstitial_device_check_link` function:
|
|
273
|
+
|
|
274
|
+
```python
|
|
275
|
+
from hyper_sdk.datadome import parse_interstitial_device_check_link
|
|
276
|
+
|
|
277
|
+
device_link = parse_interstitial_device_check_link(html_content, datadome_cookie, referer)
|
|
278
|
+
# device_link will look like: https://geo.captcha-delivery.com/interstitial/?...
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### Parsing Slider DeviceLink URL
|
|
282
|
+
|
|
283
|
+
To parse the Slider DeviceLink URL from the HTML code, use the `parse_slider_device_check_link` function:
|
|
284
|
+
|
|
285
|
+
```python
|
|
286
|
+
from hyper_sdk.datadome import parse_slider_device_check_link
|
|
287
|
+
|
|
288
|
+
device_link = parse_slider_device_check_link(html_content, datadome_cookie, referer)
|
|
289
|
+
# device_link will look like: https://geo.captcha-delivery.com/captcha/?...
|
|
290
|
+
```
|
|
@@ -172,4 +172,100 @@ To generate a unique UTMVC submit path with a random query parameter, use the `g
|
|
|
172
172
|
from hyper_sdk.incapsula.utmvc import get_utmvc_submit_path
|
|
173
173
|
|
|
174
174
|
submit_path = get_utmvc_submit_path()
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Kasada
|
|
178
|
+
|
|
179
|
+
The Kasada package provides functions for interacting with Kasada Bot Manager, including parsing script path.
|
|
180
|
+
|
|
181
|
+
### Generating Payload Data (CT)
|
|
182
|
+
|
|
183
|
+
To generate payload data required for generating valid `x-kpsdk-ct` tokens, use the `generate_kasada_payload` function:
|
|
184
|
+
|
|
185
|
+
```python
|
|
186
|
+
payload, headers = hyper_session.generate_kasada_payload(hyper_sdk.KasadaPayloadInput(
|
|
187
|
+
user_agent=USER_AGENT,
|
|
188
|
+
ips_link=ips_link,
|
|
189
|
+
script=ips_script,
|
|
190
|
+
language="en-US"
|
|
191
|
+
))
|
|
192
|
+
# Use payload and headers for the next request
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Generating Pow Data (CD)
|
|
196
|
+
|
|
197
|
+
To generate POW data (`x-kpsdk-cd`) tokens, use the `generate_kasada_pow` function:
|
|
198
|
+
|
|
199
|
+
```python
|
|
200
|
+
cd = hyper_session.generate_kasada_pow(hyper_sdk.KasadaPowInput(
|
|
201
|
+
st=st,
|
|
202
|
+
work_time=None
|
|
203
|
+
))
|
|
204
|
+
# Use cd as the x-kpsdk-cd header in the next request
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Parsing Script Path
|
|
208
|
+
|
|
209
|
+
To parse the Kasada script path from the given blocked page (status code 429) HTML code, use the `parse_script_path` function:
|
|
210
|
+
|
|
211
|
+
```python
|
|
212
|
+
from hyper_sdk.kasada import parse_script_path
|
|
213
|
+
|
|
214
|
+
script_path = parse_script_path(html_content)
|
|
215
|
+
# script_path will look like: /ips.js?...
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## DataDome
|
|
219
|
+
|
|
220
|
+
The DataDome package provides functions for interacting with DataDome Bot Manager, including parsing device link URLs
|
|
221
|
+
for interstitial and slider challenges.
|
|
222
|
+
|
|
223
|
+
### Generating Interstitial Payload
|
|
224
|
+
|
|
225
|
+
To generate payload data required for solving interstitial challenges, use the `generate_interstitial_payload` function:
|
|
226
|
+
|
|
227
|
+
```python
|
|
228
|
+
payload = hyper_session.generate_interstitial_payload(hyper_sdk.DataDomeInterstitialInput(
|
|
229
|
+
user_agent=USER_AGENT,
|
|
230
|
+
device_link=device_check_link,
|
|
231
|
+
html=html_content
|
|
232
|
+
))
|
|
233
|
+
# Use the payload to POST to https://geo.captcha-delivery.com/interstitial/
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### Generating Slider Payload
|
|
237
|
+
|
|
238
|
+
To solve DataDome Slider challenges, use the `generate_slider_payload` function:
|
|
239
|
+
|
|
240
|
+
```python
|
|
241
|
+
payload = hyper_session.generate_slider_payload(hyper_sdk.DataDomeSliderInput(
|
|
242
|
+
user_agent=USER_AGENT,
|
|
243
|
+
device_link=device_check_link,
|
|
244
|
+
html=html_content,
|
|
245
|
+
puzzle=base64_encoded_puzzle,
|
|
246
|
+
piece=base64_encoded_piece
|
|
247
|
+
))
|
|
248
|
+
# Create a GET request to the payload URL
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### Parsing Interstitial DeviceLink URL
|
|
252
|
+
|
|
253
|
+
To parse the Interstitial DeviceLink URL from the HTML code, use the `parse_interstitial_device_check_link` function:
|
|
254
|
+
|
|
255
|
+
```python
|
|
256
|
+
from hyper_sdk.datadome import parse_interstitial_device_check_link
|
|
257
|
+
|
|
258
|
+
device_link = parse_interstitial_device_check_link(html_content, datadome_cookie, referer)
|
|
259
|
+
# device_link will look like: https://geo.captcha-delivery.com/interstitial/?...
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### Parsing Slider DeviceLink URL
|
|
263
|
+
|
|
264
|
+
To parse the Slider DeviceLink URL from the HTML code, use the `parse_slider_device_check_link` function:
|
|
265
|
+
|
|
266
|
+
```python
|
|
267
|
+
from hyper_sdk.datadome import parse_slider_device_check_link
|
|
268
|
+
|
|
269
|
+
device_link = parse_slider_device_check_link(html_content, datadome_cookie, referer)
|
|
270
|
+
# device_link will look like: https://geo.captcha-delivery.com/captcha/?...
|
|
175
271
|
```
|
|
@@ -34,6 +34,22 @@ class SecCptChallenge:
|
|
|
34
34
|
|
|
35
35
|
return SecCptChallenge(duration, challenge_path, challenge_data)
|
|
36
36
|
|
|
37
|
+
@staticmethod
|
|
38
|
+
def parse_from_json(json_payload: str) -> 'SecCptChallenge':
|
|
39
|
+
api_response = json.loads(json_payload)
|
|
40
|
+
|
|
41
|
+
challenge_data = SecCptChallengeData(
|
|
42
|
+
api_response.get('token', ''),
|
|
43
|
+
api_response.get('timestamp', 0),
|
|
44
|
+
api_response.get('nonce', ''),
|
|
45
|
+
api_response.get('difficulty', 0)
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
duration = api_response.get('chlg_duration', 0)
|
|
49
|
+
challenge_path = api_response.get('branding_url_content', '')
|
|
50
|
+
|
|
51
|
+
return SecCptChallenge(duration, challenge_path, challenge_data)
|
|
52
|
+
|
|
37
53
|
@staticmethod
|
|
38
54
|
def _parse_challenge_data(src: str) -> SecCptChallengeData:
|
|
39
55
|
challenge_match = sec_challenge_expr.search(src)
|
|
@@ -109,4 +125,4 @@ class SecCptChallenge:
|
|
|
109
125
|
break
|
|
110
126
|
continue
|
|
111
127
|
|
|
112
|
-
return answers
|
|
128
|
+
return answers
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .parse import *
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from urllib.parse import urlencode
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def parse_slider_device_check_link(src: str, datadome_cookie: str, referer: str) -> str:
|
|
6
|
+
"""
|
|
7
|
+
Parse the device check URL for DataDome slider captcha from a blocked response body.
|
|
8
|
+
|
|
9
|
+
This function extracts the necessary parameters from the DataDome JavaScript object
|
|
10
|
+
embedded in the HTML source and constructs the URL for the slider captcha challenge.
|
|
11
|
+
|
|
12
|
+
Args:
|
|
13
|
+
src (str): The HTML source of the blocked page containing the DataDome JavaScript object.
|
|
14
|
+
datadome_cookie (str): The current value of the 'datadome' cookie.
|
|
15
|
+
referer (str): The referer URL to be included in the device check link.
|
|
16
|
+
|
|
17
|
+
Returns:
|
|
18
|
+
str: The constructed device check URL for the slider captcha.
|
|
19
|
+
|
|
20
|
+
Raises:
|
|
21
|
+
RuntimeError: If the dd object cannot be extracted or parsed,
|
|
22
|
+
or if the proxy is blocked (indicated by 't' == 'bv').
|
|
23
|
+
"""
|
|
24
|
+
try:
|
|
25
|
+
dd_object = src.split("var dd=")[1].split("</script>")[0]
|
|
26
|
+
dd_object = dd_object.replace("'", '"')
|
|
27
|
+
dd_object_parsed = json.loads(dd_object)
|
|
28
|
+
except Exception as _:
|
|
29
|
+
raise RuntimeError("Failed to parse dd object.")
|
|
30
|
+
|
|
31
|
+
if dd_object_parsed.get("t") == "bv":
|
|
32
|
+
raise RuntimeError("proxy blocked")
|
|
33
|
+
|
|
34
|
+
params = {
|
|
35
|
+
"initialCid": dd_object_parsed.get("cid"),
|
|
36
|
+
"hash": dd_object_parsed.get("hsh"),
|
|
37
|
+
"cid": datadome_cookie,
|
|
38
|
+
"t": dd_object_parsed.get("t"),
|
|
39
|
+
"referer": referer,
|
|
40
|
+
"s": str(dd_object_parsed.get("s")),
|
|
41
|
+
"e": dd_object_parsed.get("e"),
|
|
42
|
+
"dm": "cd",
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return f"https://geo.captcha-delivery.com/captcha/?{urlencode(params)}"
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def parse_interstitial_device_check_link(src: str, datadome_cookie: str, referer: str) -> str:
|
|
49
|
+
"""
|
|
50
|
+
Parse the device check URL for DataDome interstitial challenge from a blocked response body.
|
|
51
|
+
|
|
52
|
+
This function extracts the necessary parameters from the DataDome JavaScript object
|
|
53
|
+
embedded in the HTML source and constructs the URL for the interstitial challenge.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
src (str): The HTML source of the blocked page containing the DataDome JavaScript object.
|
|
57
|
+
datadome_cookie (str): The current value of the 'datadome' cookie.
|
|
58
|
+
referer (str): The referer URL to be included in the device check link.
|
|
59
|
+
|
|
60
|
+
Returns:
|
|
61
|
+
str: The constructed device check URL for the interstitial challenge.
|
|
62
|
+
|
|
63
|
+
Raises:
|
|
64
|
+
RuntimeError: If the DataDome dd object cannot be extracted or parsed.
|
|
65
|
+
"""
|
|
66
|
+
try:
|
|
67
|
+
dd_object = src.split("var dd=")[1].split("</script>")[0]
|
|
68
|
+
dd_object = dd_object.replace("'", '"')
|
|
69
|
+
dd_object_parsed = json.loads(dd_object)
|
|
70
|
+
except Exception as _:
|
|
71
|
+
raise RuntimeError("Failed to parse dd object.")
|
|
72
|
+
|
|
73
|
+
params = {
|
|
74
|
+
"initialCid": dd_object_parsed.get("cid"),
|
|
75
|
+
"hash": dd_object_parsed.get("hsh"),
|
|
76
|
+
"cid": datadome_cookie,
|
|
77
|
+
"referer": referer,
|
|
78
|
+
"s": str(dd_object_parsed.get("s")),
|
|
79
|
+
"b": str(dd_object_parsed.get("b")),
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return f"https://geo.captcha-delivery.com/interstitial/?{urlencode(params)}"
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
class DataDomeSliderInput:
|
|
2
|
+
def __init__(self, user_agent: str, device_link: str, html: str, puzzle: str, piece: str):
|
|
3
|
+
# UserAgent must be a Chrome Windows User-Agent.
|
|
4
|
+
self.user_agent = user_agent
|
|
5
|
+
|
|
6
|
+
# DeviceLink is the URL that contains the script and starts like this:
|
|
7
|
+
# https://geo.captcha-delivery.com/captcha/?initialCid
|
|
8
|
+
self.device_link = device_link
|
|
9
|
+
|
|
10
|
+
# Html is the response body of the GET request to the DeviceLink
|
|
11
|
+
self.html = html
|
|
12
|
+
|
|
13
|
+
# Puzzle is the captcha puzzle image bytes, base64 encoded.
|
|
14
|
+
# The URL that returns the puzzle looks like this:
|
|
15
|
+
# https://dd.prod.captcha-delivery.com/image/2024-xx-xx/hash.jpg
|
|
16
|
+
self.puzzle = puzzle
|
|
17
|
+
|
|
18
|
+
# Piece is the captcha puzzle piece image bytes, base64 encoded.
|
|
19
|
+
# The URL that returns the puzzle looks like this:
|
|
20
|
+
# https://dd.prod.captcha-delivery.com/image/2024-xx-xx/hash.frag.png
|
|
21
|
+
self.piece = piece
|
|
22
|
+
|
|
23
|
+
def to_dict(self):
|
|
24
|
+
return {
|
|
25
|
+
"userAgent": self.user_agent,
|
|
26
|
+
"deviceLink": self.device_link,
|
|
27
|
+
"html": self.html,
|
|
28
|
+
"puzzle": self.puzzle,
|
|
29
|
+
"piece": self.piece
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class DataDomeInterstitialInput:
|
|
34
|
+
def __init__(self, user_agent: str, device_link: str, html: str):
|
|
35
|
+
# UserAgent must be a Chrome Windows User-Agent.
|
|
36
|
+
self.user_agent = user_agent
|
|
37
|
+
|
|
38
|
+
# DeviceLink is the URL that contains the script and starts like this:
|
|
39
|
+
# https://geo.captcha-delivery.com/captcha/?initialCid
|
|
40
|
+
self.device_link = device_link
|
|
41
|
+
|
|
42
|
+
# Html is the response body of the GET request to the DeviceLink
|
|
43
|
+
self.html = html
|
|
44
|
+
|
|
45
|
+
def to_dict(self):
|
|
46
|
+
return {
|
|
47
|
+
"userAgent": self.user_agent,
|
|
48
|
+
"deviceLink": self.device_link,
|
|
49
|
+
"html": self.html
|
|
50
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .parse import *
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import re
|
|
2
|
+
|
|
3
|
+
# Precompiled regular expression
|
|
4
|
+
script_path_expr = re.compile(r'<script\s+src="([^"]+)"')
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def parse_script_path(src: str) -> str:
|
|
8
|
+
"""
|
|
9
|
+
Gets the Akamai Bot Manager web SDK path from the given HTML code src.
|
|
10
|
+
|
|
11
|
+
This function searches the provided HTML source code for the path of a JavaScript script tag that matches the
|
|
12
|
+
specified regular expression pattern.
|
|
13
|
+
|
|
14
|
+
Args:
|
|
15
|
+
src (str): The HTML source code as a string.
|
|
16
|
+
|
|
17
|
+
Returns:
|
|
18
|
+
str: The path of the script extracted from the script tag.
|
|
19
|
+
|
|
20
|
+
Raises:
|
|
21
|
+
Exception: If the script path is not found in the source.
|
|
22
|
+
"""
|
|
23
|
+
match = script_path_expr.search(src)
|
|
24
|
+
if match:
|
|
25
|
+
return match.group(1)
|
|
26
|
+
else:
|
|
27
|
+
raise "hyper-sdk: script path not found"
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
class KasadaPowInput:
|
|
2
|
+
def __init__(self, st: int, work_time: int = None):
|
|
3
|
+
# St is the x-kpsdk-st value returned by the /tl POST request
|
|
4
|
+
self.st = st
|
|
5
|
+
# WorkTime can be used to pre-generate POW strings
|
|
6
|
+
self.work_time = work_time
|
|
7
|
+
|
|
8
|
+
def to_dict(self):
|
|
9
|
+
result = {"st": self.st}
|
|
10
|
+
if self.work_time is not None:
|
|
11
|
+
result["workTime"] = self.work_time
|
|
12
|
+
return result
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class KasadaPayloadInput:
|
|
16
|
+
def __init__(self, user_agent: str, ips_link: str, script: str, language: str = "en-US"):
|
|
17
|
+
# UserAgent must be a Chrome Windows User-Agent.
|
|
18
|
+
self.user_agent = user_agent
|
|
19
|
+
|
|
20
|
+
# IpsLink is the ips.js script link, parsed from the block page (429 status code)
|
|
21
|
+
self.ips_link = ips_link
|
|
22
|
+
|
|
23
|
+
# Script is the ips.js script retrieved using the IpsLink url
|
|
24
|
+
self.script = script
|
|
25
|
+
|
|
26
|
+
# Language is the first language of your accept-language header, it defaults to "en-US" if left empty.
|
|
27
|
+
self.language = language
|
|
28
|
+
|
|
29
|
+
def to_dict(self):
|
|
30
|
+
result = {
|
|
31
|
+
"userAgent": self.user_agent,
|
|
32
|
+
"ipsLink": self.ips_link,
|
|
33
|
+
"script": self.script
|
|
34
|
+
}
|
|
35
|
+
if self.language != "en-US":
|
|
36
|
+
result["language"] = self.language
|
|
37
|
+
return result
|
|
@@ -6,6 +6,8 @@ import jwt
|
|
|
6
6
|
from datetime import datetime, timedelta, timezone
|
|
7
7
|
|
|
8
8
|
from .akamai_input import SensorInput, PixelInput
|
|
9
|
+
from .kasada_input import KasadaPowInput, KasadaPayloadInput
|
|
10
|
+
from .datadome_input import DataDomeSliderInput, DataDomeInterstitialInput
|
|
9
11
|
from .incapsula_input import UtmvcInput
|
|
10
12
|
|
|
11
13
|
|
|
@@ -103,10 +105,84 @@ class Session:
|
|
|
103
105
|
'script': input_data.script,
|
|
104
106
|
})
|
|
105
107
|
|
|
108
|
+
def generate_kasada_pow(self, input_data: KasadaPowInput) -> str:
|
|
109
|
+
"""
|
|
110
|
+
Returns the x-kpsdk-cd value using the Hyper Solutions API.
|
|
111
|
+
|
|
112
|
+
Args:
|
|
113
|
+
session (Session): An instance of Session to handle the network request.
|
|
114
|
+
input_data (Input): An instance of Input containing the st and optionally workTime.
|
|
115
|
+
|
|
116
|
+
Returns:
|
|
117
|
+
str: The x-kpsdk-cd value as a string.
|
|
118
|
+
"""
|
|
119
|
+
return self._send_request("https://kasada.justhyped.dev/cd", input_data.to_dict())
|
|
120
|
+
|
|
121
|
+
def generate_kasada_payload(self, input_data: KasadaPayloadInput) -> tuple[str, dict]:
|
|
122
|
+
"""
|
|
123
|
+
Returns a base64 encoded payload and headers using the Hyper Solutions API.
|
|
124
|
+
|
|
125
|
+
Args: input_data (KasadaPayloadInput): An instance of KasadaPayloadInput containing the userAgent,
|
|
126
|
+
ipsLink and script.
|
|
127
|
+
|
|
128
|
+
Returns: tuple[str, dict]: A tuple containing the base64 encoded payload (to POST to /tl) as a string and a
|
|
129
|
+
dictionary of headers.
|
|
130
|
+
"""
|
|
131
|
+
if not self.api_key:
|
|
132
|
+
raise ValueError("Missing API key")
|
|
133
|
+
|
|
134
|
+
headers = {
|
|
135
|
+
'Content-Type': 'application/json',
|
|
136
|
+
'Accept-Encoding': 'gzip',
|
|
137
|
+
'X-Api-Key': self.api_key
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if self.jwt_key:
|
|
141
|
+
signature = self.generate_signature()
|
|
142
|
+
headers['X-Signature'] = signature
|
|
143
|
+
|
|
144
|
+
response = self.client.post("https://kasada.justhyped.dev/payload", headers=headers, json=input_data.to_dict())
|
|
145
|
+
|
|
146
|
+
response_data = response.json()
|
|
147
|
+
|
|
148
|
+
if "error" in response_data and response_data["error"]:
|
|
149
|
+
raise Exception(f"API returned with error: {response_data['error']}")
|
|
150
|
+
|
|
151
|
+
if response.status_code != 200:
|
|
152
|
+
raise Exception(f"API returned with status code: {response.status_code}")
|
|
153
|
+
|
|
154
|
+
return response_data["payload"], response_data["headers"]
|
|
155
|
+
|
|
156
|
+
def generate_interstitial_payload(self, input_data: DataDomeInterstitialInput) -> str:
|
|
157
|
+
"""
|
|
158
|
+
Returns the DataDome interstitial payload value using the Hyper Solutions API.
|
|
159
|
+
|
|
160
|
+
Args:
|
|
161
|
+
session (Session): An instance of Session to handle the network request.
|
|
162
|
+
input_data (Input): An instance of Input containing the st and optionally workTime.
|
|
163
|
+
|
|
164
|
+
Returns:
|
|
165
|
+
str: The payload to post to /interstitial/
|
|
166
|
+
"""
|
|
167
|
+
return self._send_request("https://datadome.justhyped.dev/interstitial", input_data.to_dict())
|
|
168
|
+
|
|
169
|
+
def generate_slider_payload(self, input_data: DataDomeSliderInput) -> str:
|
|
170
|
+
"""
|
|
171
|
+
Returns the DataDome Slider URL value using the Hyper Solutions API.
|
|
172
|
+
|
|
173
|
+
Args:
|
|
174
|
+
session (Session): An instance of Session to handle the network request.
|
|
175
|
+
input_data (Input): An instance of Input containing the st and optionally workTime.
|
|
176
|
+
|
|
177
|
+
Returns:
|
|
178
|
+
str: The URL to make a GET request to and returns a solved datadome cookie.
|
|
179
|
+
"""
|
|
180
|
+
return self._send_request("https://datadome.justhyped.dev/slider", input_data.to_dict())
|
|
181
|
+
|
|
106
182
|
def generate_signature(self) -> str:
|
|
107
183
|
claims = {
|
|
108
184
|
"key": self.api_key,
|
|
109
|
-
"exp": datetime.now(timezone.utc) + timedelta(seconds=
|
|
185
|
+
"exp": datetime.now(timezone.utc) + timedelta(seconds=60)
|
|
110
186
|
}
|
|
111
187
|
token = jwt.encode(claims, self.jwt_key, algorithm='HS256')
|
|
112
188
|
return token.decode('utf-8')
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: hyper_sdk
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Hyper Solutions Python SDK
|
|
5
5
|
Project-URL: homepage, https://github.com/Hyper-Solutions/hyper-sdk-py
|
|
6
6
|
Classifier: Intended Audience :: Developers
|
|
@@ -192,3 +192,99 @@ from hyper_sdk.incapsula.utmvc import get_utmvc_submit_path
|
|
|
192
192
|
|
|
193
193
|
submit_path = get_utmvc_submit_path()
|
|
194
194
|
```
|
|
195
|
+
|
|
196
|
+
## Kasada
|
|
197
|
+
|
|
198
|
+
The Kasada package provides functions for interacting with Kasada Bot Manager, including parsing script path.
|
|
199
|
+
|
|
200
|
+
### Generating Payload Data (CT)
|
|
201
|
+
|
|
202
|
+
To generate payload data required for generating valid `x-kpsdk-ct` tokens, use the `generate_kasada_payload` function:
|
|
203
|
+
|
|
204
|
+
```python
|
|
205
|
+
payload, headers = hyper_session.generate_kasada_payload(hyper_sdk.KasadaPayloadInput(
|
|
206
|
+
user_agent=USER_AGENT,
|
|
207
|
+
ips_link=ips_link,
|
|
208
|
+
script=ips_script,
|
|
209
|
+
language="en-US"
|
|
210
|
+
))
|
|
211
|
+
# Use payload and headers for the next request
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### Generating Pow Data (CD)
|
|
215
|
+
|
|
216
|
+
To generate POW data (`x-kpsdk-cd`) tokens, use the `generate_kasada_pow` function:
|
|
217
|
+
|
|
218
|
+
```python
|
|
219
|
+
cd = hyper_session.generate_kasada_pow(hyper_sdk.KasadaPowInput(
|
|
220
|
+
st=st,
|
|
221
|
+
work_time=None
|
|
222
|
+
))
|
|
223
|
+
# Use cd as the x-kpsdk-cd header in the next request
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### Parsing Script Path
|
|
227
|
+
|
|
228
|
+
To parse the Kasada script path from the given blocked page (status code 429) HTML code, use the `parse_script_path` function:
|
|
229
|
+
|
|
230
|
+
```python
|
|
231
|
+
from hyper_sdk.kasada import parse_script_path
|
|
232
|
+
|
|
233
|
+
script_path = parse_script_path(html_content)
|
|
234
|
+
# script_path will look like: /ips.js?...
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
## DataDome
|
|
238
|
+
|
|
239
|
+
The DataDome package provides functions for interacting with DataDome Bot Manager, including parsing device link URLs
|
|
240
|
+
for interstitial and slider challenges.
|
|
241
|
+
|
|
242
|
+
### Generating Interstitial Payload
|
|
243
|
+
|
|
244
|
+
To generate payload data required for solving interstitial challenges, use the `generate_interstitial_payload` function:
|
|
245
|
+
|
|
246
|
+
```python
|
|
247
|
+
payload = hyper_session.generate_interstitial_payload(hyper_sdk.DataDomeInterstitialInput(
|
|
248
|
+
user_agent=USER_AGENT,
|
|
249
|
+
device_link=device_check_link,
|
|
250
|
+
html=html_content
|
|
251
|
+
))
|
|
252
|
+
# Use the payload to POST to https://geo.captcha-delivery.com/interstitial/
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### Generating Slider Payload
|
|
256
|
+
|
|
257
|
+
To solve DataDome Slider challenges, use the `generate_slider_payload` function:
|
|
258
|
+
|
|
259
|
+
```python
|
|
260
|
+
payload = hyper_session.generate_slider_payload(hyper_sdk.DataDomeSliderInput(
|
|
261
|
+
user_agent=USER_AGENT,
|
|
262
|
+
device_link=device_check_link,
|
|
263
|
+
html=html_content,
|
|
264
|
+
puzzle=base64_encoded_puzzle,
|
|
265
|
+
piece=base64_encoded_piece
|
|
266
|
+
))
|
|
267
|
+
# Create a GET request to the payload URL
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### Parsing Interstitial DeviceLink URL
|
|
271
|
+
|
|
272
|
+
To parse the Interstitial DeviceLink URL from the HTML code, use the `parse_interstitial_device_check_link` function:
|
|
273
|
+
|
|
274
|
+
```python
|
|
275
|
+
from hyper_sdk.datadome import parse_interstitial_device_check_link
|
|
276
|
+
|
|
277
|
+
device_link = parse_interstitial_device_check_link(html_content, datadome_cookie, referer)
|
|
278
|
+
# device_link will look like: https://geo.captcha-delivery.com/interstitial/?...
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### Parsing Slider DeviceLink URL
|
|
282
|
+
|
|
283
|
+
To parse the Slider DeviceLink URL from the HTML code, use the `parse_slider_device_check_link` function:
|
|
284
|
+
|
|
285
|
+
```python
|
|
286
|
+
from hyper_sdk.datadome import parse_slider_device_check_link
|
|
287
|
+
|
|
288
|
+
device_link = parse_slider_device_check_link(html_content, datadome_cookie, referer)
|
|
289
|
+
# device_link will look like: https://geo.captcha-delivery.com/captcha/?...
|
|
290
|
+
```
|
|
@@ -3,7 +3,9 @@ README.md
|
|
|
3
3
|
pyproject.toml
|
|
4
4
|
hyper_sdk/__init__.py
|
|
5
5
|
hyper_sdk/akamai_input.py
|
|
6
|
+
hyper_sdk/datadome_input.py
|
|
6
7
|
hyper_sdk/incapsula_input.py
|
|
8
|
+
hyper_sdk/kasada_input.py
|
|
7
9
|
hyper_sdk/session.py
|
|
8
10
|
hyper_sdk.egg-info/PKG-INFO
|
|
9
11
|
hyper_sdk.egg-info/SOURCES.txt
|
|
@@ -15,5 +17,9 @@ hyper_sdk/akamai/pixel.py
|
|
|
15
17
|
hyper_sdk/akamai/script_path.py
|
|
16
18
|
hyper_sdk/akamai/sec_cpt.py
|
|
17
19
|
hyper_sdk/akamai/stop_signal.py
|
|
20
|
+
hyper_sdk/datadome/__init__.py
|
|
21
|
+
hyper_sdk/datadome/parse.py
|
|
18
22
|
hyper_sdk/incapsula/__init__.py
|
|
19
|
-
hyper_sdk/incapsula/utmvc.py
|
|
23
|
+
hyper_sdk/incapsula/utmvc.py
|
|
24
|
+
hyper_sdk/kasada/__init__.py
|
|
25
|
+
hyper_sdk/kasada/parse.py
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "hyper_sdk"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.2.0"
|
|
8
8
|
description = "Hyper Solutions Python SDK"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.6"
|
|
@@ -27,4 +27,4 @@ dependencies = [
|
|
|
27
27
|
homepage = "https://github.com/Hyper-Solutions/hyper-sdk-py"
|
|
28
28
|
|
|
29
29
|
[tool.setuptools]
|
|
30
|
-
packages = ["hyper_sdk", "hyper_sdk.akamai", "hyper_sdk.incapsula"]
|
|
30
|
+
packages = ["hyper_sdk", "hyper_sdk.akamai", "hyper_sdk.incapsula", "hyper_sdk.kasada", "hyper_sdk.datadome"]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|