hyper-sdk 0.1.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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Hyper Solutions
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,194 @@
1
+ Metadata-Version: 2.1
2
+ Name: hyper_sdk
3
+ Version: 0.1.0
4
+ Summary: Hyper Solutions Python SDK
5
+ Project-URL: homepage, https://github.com/Hyper-Solutions/hyper-sdk-py
6
+ Classifier: Intended Audience :: Developers
7
+ Classifier: License :: OSI Approved :: MIT License
8
+ Classifier: Programming Language :: Python :: 3
9
+ Requires-Python: >=3.6
10
+ Description-Content-Type: text/markdown
11
+ License-File: LICENSE
12
+ Requires-Dist: certifi==2024.2.2
13
+ Requires-Dist: charset-normalizer==3.3.2
14
+ Requires-Dist: idna==3.6
15
+ Requires-Dist: jsonpickle==3.0.3
16
+ Requires-Dist: PyJWT==2.8.0
17
+ Requires-Dist: requests==2.31.0
18
+ Requires-Dist: urllib3==2.2.1
19
+
20
+ # Hyper Solutions SDK for Python
21
+
22
+ ## Installation
23
+
24
+ To use the Hyper Solutions SDK in your Python project, you need to install it using the following command:
25
+
26
+ ```
27
+ pip install hyper-sdk
28
+ ```
29
+
30
+ ## Usage
31
+
32
+ ### Creating a Session
33
+
34
+ To start using the SDK, you need to create a new `Session` instance by providing your API key:
35
+
36
+ ```python
37
+ from hyper_sdk import Session
38
+
39
+ session = Session(api_key="your-api-key")
40
+ ```
41
+
42
+ You can also optionally set a JWT key and a custom HTTP client:
43
+
44
+ ```python
45
+ from hyper_sdk import Session
46
+
47
+ session = Session(api_key="your-api-key", jwt_key="your-jwt-key", client=custom_http_client)
48
+ ```
49
+
50
+ ## Akamai
51
+
52
+ The Akamai package provides functions for interacting with Akamai Bot Manager, including generating sensor data, parsing script path, parsing pixel challenges, and handling sec-cpt challenges.
53
+
54
+ ### Generating Sensor Data
55
+
56
+ To generate sensor data required for generating valid Akamai cookies, use the `generate_sensor_data` method:
57
+
58
+ ```python
59
+ from hyper_sdk import SensorInput
60
+
61
+ sensor_input = SensorInput(
62
+ page_url="https://example.com/",
63
+ user_agent="your-user-agent",
64
+ abck="your-abck-cookie",
65
+ bmsz="your-bmsz-cookie",
66
+ version="2.0"
67
+ )
68
+ sensor_data = session.generate_sensor_data(sensor_input)
69
+ ```
70
+
71
+ ### Parsing Script Path
72
+
73
+ To parse the Akamai Bot Manager script path from the given HTML code, use the `parse_script_path` function from the `script_path` module:
74
+
75
+ ```python
76
+ from hyper_sdk.akamai.script_path import parse_script_path
77
+
78
+ script_path = parse_script_path(html_source)
79
+ ```
80
+
81
+ ### Handling Sec-Cpt Challenges
82
+
83
+ The Akamai package provides functions for handling sec-cpt challenges:
84
+
85
+ - `SecCptChallenge.parse`: Parses a sec-cpt challenge from an HTML source.
86
+ - `generate_sec_cpt_payload`: Generates a sec-cpt payload using the provided sec-cpt cookie.
87
+ - `update_sec_cpt_challenge_data`: Updates the challenge data of a `SecCptChallenge` instance from a response body.
88
+
89
+ Example usage:
90
+
91
+ ```python
92
+ from hyper_sdk.akamai.sec_cpt import SecCptChallenge
93
+
94
+ challenge = SecCptChallenge.parse(html_source)
95
+ payload = challenge.generate_sec_cpt_payload(sec_cpt_cookie)
96
+ challenge.update_sec_cpt_challenge_data(response_body)
97
+ ```
98
+
99
+ ### Validating Cookies
100
+
101
+ The Akamai package provides functions for validating cookies:
102
+
103
+ - `is_cookie_valid`: Determines if the provided `_abck` cookie value is valid based on the given request count.
104
+ - `is_cookie_invalidated`: Determines if the current session requires more sensors to be sent.
105
+
106
+ Example usage:
107
+
108
+ ```python
109
+ from hyper_sdk.akamai.stop_signal import is_cookie_valid, is_cookie_invalidated
110
+
111
+ is_valid = is_cookie_valid(abck_cookie, request_count)
112
+ is_invalidated = is_cookie_invalidated(abck_cookie)
113
+ ```
114
+
115
+ ### Generating Pixel Data
116
+
117
+ To generate pixel data, use the `generate_pixel_data` method:
118
+
119
+ ```python
120
+ from hyper_sdk import PixelInput
121
+
122
+ pixel_input = PixelInput(
123
+ user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36",
124
+ html_var="your-html-var",
125
+ script_var="your-script-var"
126
+ )
127
+ pixel_data = session.generate_pixel_data(pixel_input)
128
+ ```
129
+
130
+ ### Parsing Pixel Challenges
131
+
132
+ The Akamai package provides functions for parsing pixel challenges:
133
+
134
+ - `parse_pixel_html_var`: Parses the required pixel challenge variable from the given HTML code.
135
+ - `parse_pixel_script_url`: Parses the script URL of the pixel challenge script and the URL to post a generated payload to from the given HTML code.
136
+ - `parse_pixel_script_var`: Parses the dynamic value from the pixel script.
137
+
138
+ Example usage:
139
+
140
+ ```python
141
+ from hyper_sdk.akamai.pixel import parse_pixel_html_var, parse_pixel_script_url, parse_pixel_script_var
142
+
143
+ html_var = parse_pixel_html_var(html_source)
144
+ script_url, post_url = parse_pixel_script_url(html_source)
145
+ script_var = parse_pixel_script_var(script_source)
146
+ ```
147
+
148
+
149
+ ## Incapsula
150
+
151
+ The Incapsula package provides functions for interacting with Imperva Incapsula, including generating Reese84 sensor data, UTMVC cookies, and parsing UTMVC script paths.
152
+
153
+ ### Generating Reese84 Sensor
154
+
155
+ To generate sensor data required for generating valid Reese84 cookies, use the `generate_reese84_sensor` method:
156
+
157
+ ```python
158
+ sensor_data = session.generate_reese84_sensor(site="example.com", user_agent="your-user-agent")
159
+ ```
160
+
161
+ ### Generating UTMVC Cookie
162
+
163
+ To generate the UTMVC cookie using the Hyper Solutions API, use the `generate_utmvc_cookie` method:
164
+
165
+ ```python
166
+ from hyper_sdk import UtmvcInput
167
+
168
+ utmvc_input = UtmvcInput(
169
+ user_agent="your-user-agent",
170
+ session_ids=["session-id-1", "session-id-2"],
171
+ script="your-script"
172
+ )
173
+ utmvc_cookie = session.generate_utmvc_cookie(utmvc_input)
174
+ ```
175
+
176
+ ### Parsing UTMVC Script Path
177
+
178
+ To parse the UTMVC script path from a given script content, use the `parse_utmvc_script_path` function from the `utmvc` module:
179
+
180
+ ```python
181
+ from hyper_sdk.incapsula.utmvc import parse_utmvc_script_path
182
+
183
+ script_path = parse_utmvc_script_path(script_content)
184
+ ```
185
+
186
+ ### Generating UTMVC Submit Path
187
+
188
+ To generate a unique UTMVC submit path with a random query parameter, use the `get_utmvc_submit_path` function from the `utmvc` module:
189
+
190
+ ```python
191
+ from hyper_sdk.incapsula.utmvc import get_utmvc_submit_path
192
+
193
+ submit_path = get_utmvc_submit_path()
194
+ ```
@@ -0,0 +1,175 @@
1
+ # Hyper Solutions SDK for Python
2
+
3
+ ## Installation
4
+
5
+ To use the Hyper Solutions SDK in your Python project, you need to install it using the following command:
6
+
7
+ ```
8
+ pip install hyper-sdk
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### Creating a Session
14
+
15
+ To start using the SDK, you need to create a new `Session` instance by providing your API key:
16
+
17
+ ```python
18
+ from hyper_sdk import Session
19
+
20
+ session = Session(api_key="your-api-key")
21
+ ```
22
+
23
+ You can also optionally set a JWT key and a custom HTTP client:
24
+
25
+ ```python
26
+ from hyper_sdk import Session
27
+
28
+ session = Session(api_key="your-api-key", jwt_key="your-jwt-key", client=custom_http_client)
29
+ ```
30
+
31
+ ## Akamai
32
+
33
+ The Akamai package provides functions for interacting with Akamai Bot Manager, including generating sensor data, parsing script path, parsing pixel challenges, and handling sec-cpt challenges.
34
+
35
+ ### Generating Sensor Data
36
+
37
+ To generate sensor data required for generating valid Akamai cookies, use the `generate_sensor_data` method:
38
+
39
+ ```python
40
+ from hyper_sdk import SensorInput
41
+
42
+ sensor_input = SensorInput(
43
+ page_url="https://example.com/",
44
+ user_agent="your-user-agent",
45
+ abck="your-abck-cookie",
46
+ bmsz="your-bmsz-cookie",
47
+ version="2.0"
48
+ )
49
+ sensor_data = session.generate_sensor_data(sensor_input)
50
+ ```
51
+
52
+ ### Parsing Script Path
53
+
54
+ To parse the Akamai Bot Manager script path from the given HTML code, use the `parse_script_path` function from the `script_path` module:
55
+
56
+ ```python
57
+ from hyper_sdk.akamai.script_path import parse_script_path
58
+
59
+ script_path = parse_script_path(html_source)
60
+ ```
61
+
62
+ ### Handling Sec-Cpt Challenges
63
+
64
+ The Akamai package provides functions for handling sec-cpt challenges:
65
+
66
+ - `SecCptChallenge.parse`: Parses a sec-cpt challenge from an HTML source.
67
+ - `generate_sec_cpt_payload`: Generates a sec-cpt payload using the provided sec-cpt cookie.
68
+ - `update_sec_cpt_challenge_data`: Updates the challenge data of a `SecCptChallenge` instance from a response body.
69
+
70
+ Example usage:
71
+
72
+ ```python
73
+ from hyper_sdk.akamai.sec_cpt import SecCptChallenge
74
+
75
+ challenge = SecCptChallenge.parse(html_source)
76
+ payload = challenge.generate_sec_cpt_payload(sec_cpt_cookie)
77
+ challenge.update_sec_cpt_challenge_data(response_body)
78
+ ```
79
+
80
+ ### Validating Cookies
81
+
82
+ The Akamai package provides functions for validating cookies:
83
+
84
+ - `is_cookie_valid`: Determines if the provided `_abck` cookie value is valid based on the given request count.
85
+ - `is_cookie_invalidated`: Determines if the current session requires more sensors to be sent.
86
+
87
+ Example usage:
88
+
89
+ ```python
90
+ from hyper_sdk.akamai.stop_signal import is_cookie_valid, is_cookie_invalidated
91
+
92
+ is_valid = is_cookie_valid(abck_cookie, request_count)
93
+ is_invalidated = is_cookie_invalidated(abck_cookie)
94
+ ```
95
+
96
+ ### Generating Pixel Data
97
+
98
+ To generate pixel data, use the `generate_pixel_data` method:
99
+
100
+ ```python
101
+ from hyper_sdk import PixelInput
102
+
103
+ pixel_input = PixelInput(
104
+ user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36",
105
+ html_var="your-html-var",
106
+ script_var="your-script-var"
107
+ )
108
+ pixel_data = session.generate_pixel_data(pixel_input)
109
+ ```
110
+
111
+ ### Parsing Pixel Challenges
112
+
113
+ The Akamai package provides functions for parsing pixel challenges:
114
+
115
+ - `parse_pixel_html_var`: Parses the required pixel challenge variable from the given HTML code.
116
+ - `parse_pixel_script_url`: Parses the script URL of the pixel challenge script and the URL to post a generated payload to from the given HTML code.
117
+ - `parse_pixel_script_var`: Parses the dynamic value from the pixel script.
118
+
119
+ Example usage:
120
+
121
+ ```python
122
+ from hyper_sdk.akamai.pixel import parse_pixel_html_var, parse_pixel_script_url, parse_pixel_script_var
123
+
124
+ html_var = parse_pixel_html_var(html_source)
125
+ script_url, post_url = parse_pixel_script_url(html_source)
126
+ script_var = parse_pixel_script_var(script_source)
127
+ ```
128
+
129
+
130
+ ## Incapsula
131
+
132
+ The Incapsula package provides functions for interacting with Imperva Incapsula, including generating Reese84 sensor data, UTMVC cookies, and parsing UTMVC script paths.
133
+
134
+ ### Generating Reese84 Sensor
135
+
136
+ To generate sensor data required for generating valid Reese84 cookies, use the `generate_reese84_sensor` method:
137
+
138
+ ```python
139
+ sensor_data = session.generate_reese84_sensor(site="example.com", user_agent="your-user-agent")
140
+ ```
141
+
142
+ ### Generating UTMVC Cookie
143
+
144
+ To generate the UTMVC cookie using the Hyper Solutions API, use the `generate_utmvc_cookie` method:
145
+
146
+ ```python
147
+ from hyper_sdk import UtmvcInput
148
+
149
+ utmvc_input = UtmvcInput(
150
+ user_agent="your-user-agent",
151
+ session_ids=["session-id-1", "session-id-2"],
152
+ script="your-script"
153
+ )
154
+ utmvc_cookie = session.generate_utmvc_cookie(utmvc_input)
155
+ ```
156
+
157
+ ### Parsing UTMVC Script Path
158
+
159
+ To parse the UTMVC script path from a given script content, use the `parse_utmvc_script_path` function from the `utmvc` module:
160
+
161
+ ```python
162
+ from hyper_sdk.incapsula.utmvc import parse_utmvc_script_path
163
+
164
+ script_path = parse_utmvc_script_path(script_content)
165
+ ```
166
+
167
+ ### Generating UTMVC Submit Path
168
+
169
+ To generate a unique UTMVC submit path with a random query parameter, use the `get_utmvc_submit_path` function from the `utmvc` module:
170
+
171
+ ```python
172
+ from hyper_sdk.incapsula.utmvc import get_utmvc_submit_path
173
+
174
+ submit_path = get_utmvc_submit_path()
175
+ ```
@@ -0,0 +1,6 @@
1
+ from .akamai.pixel import *
2
+ from .akamai.script_path import *
3
+ from .akamai.sec_cpt import *
4
+ from .akamai.stop_signal import *
5
+ from .incapsula.utmvc import *
6
+ from .session import *
@@ -0,0 +1,4 @@
1
+ from .pixel import *
2
+ from .script_path import *
3
+ from .sec_cpt import *
4
+ from .stop_signal import *
@@ -0,0 +1,83 @@
1
+ import re
2
+
3
+ pixel_html_expr = re.compile(r'bazadebezolkohpepadr="(\d+)"')
4
+ pixel_script_url_expr = re.compile(r'src="(https?://.+/akam/\d+/\w+)"')
5
+ pixel_script_var_expr = re.compile(r'g=_\[(\d+)]')
6
+ pixel_script_string_array_expr = re.compile(r'var _=\[(.+?)];')
7
+ pixel_script_strings_expr = re.compile(r'("[^",]*")')
8
+
9
+
10
+ def parse_pixel_html_var(src: str) -> int:
11
+ """
12
+ ParsePixelHtmlVar gets the required pixel challenge variable from the given HTML code src.
13
+
14
+ Args:
15
+ src (str): HTML source code as a string.
16
+
17
+ Returns:
18
+ int: The parsed pixel HTML variable.
19
+
20
+ Raises:
21
+ Exception: If the pixel HTML var is not found in the source.
22
+ """
23
+ match = pixel_html_expr.search(src)
24
+ if match:
25
+ return int(match.group(1))
26
+ else:
27
+ raise Exception("hyper-sdk: pixel HTML var not found")
28
+
29
+
30
+ def parse_pixel_script_url(src: str) -> tuple[str, str]:
31
+ """
32
+ ParsePixelScriptURL gets the script URL of the pixel challenge script and the URL
33
+ to post a generated payload to from the given HTML code src.
34
+
35
+ Args:
36
+ src (str): HTML source code as a string.
37
+
38
+ Returns:
39
+ tuple[str, str]: A tuple containing the script URL and the post URL.
40
+
41
+ Raises:
42
+ Exception: If the script URL is not found in the source.
43
+ """
44
+ match = pixel_script_url_expr.search(src)
45
+ if match:
46
+ script_url = match.group(1)
47
+ # Create post_url
48
+ parts = script_url.split("/")
49
+ parts[-1] = "pixel_" + parts[-1]
50
+ post_url = "/".join(parts)
51
+ return script_url, post_url
52
+ else:
53
+ raise Exception("hyper-sdk: script URL not found")
54
+
55
+
56
+ def parse_pixel_script_var(src: str) -> str:
57
+ """
58
+ Gets the dynamic value from the pixel script.
59
+
60
+ Args:
61
+ src (str): HTML source code as a string.
62
+
63
+ Returns:
64
+ str: The dynamic value extracted from the pixel script.
65
+
66
+ Raises:
67
+ Exception: If the script variable is not found or if there are issues extracting it.
68
+ """
69
+ index_match = pixel_script_var_expr.search(src)
70
+ if not index_match:
71
+ raise Exception("hyper-sdk: script var not found")
72
+ string_index = int(index_match.group(1))
73
+
74
+ array_declaration_match = pixel_script_string_array_expr.search(src)
75
+ if not array_declaration_match:
76
+ raise Exception("hyper-sdk: script var not found")
77
+
78
+ raw_strings = pixel_script_strings_expr.findall(array_declaration_match.group(1))
79
+ if string_index >= len(raw_strings):
80
+ raise Exception("hyper-sdk: script var not found")
81
+
82
+ string_value = raw_strings[string_index].strip('"')
83
+ return string_value
@@ -0,0 +1,28 @@
1
+ import re
2
+
3
+ # Precompiled regular expressions
4
+ script_path_expr = re.compile(r'<script type="text/javascript"\s+(?:nonce=".*?")?\s+src="([a-z\d/\-_]+)"></script>',
5
+ re.IGNORECASE)
6
+
7
+
8
+ def parse_script_path(src: str) -> str:
9
+ """
10
+ Gets the Akamai Bot Manager web SDK path from the given HTML code src.
11
+
12
+ This function searches the provided HTML source code for the path of a JavaScript script tag that matches the
13
+ specified regular expression pattern.
14
+
15
+ Args:
16
+ src (str): The HTML source code as a string.
17
+
18
+ Returns:
19
+ str: The path of the script extracted from the script tag.
20
+
21
+ Raises:
22
+ Exception: If the script path is not found in the source.
23
+ """
24
+ match = script_path_expr.search(src)
25
+ if match:
26
+ return match.group(1)
27
+ else:
28
+ raise "hyper-sdk: script path not found"
@@ -0,0 +1,115 @@
1
+ import base64
2
+ import hashlib
3
+ import json
4
+ import os
5
+ import re
6
+ from collections import OrderedDict
7
+ from typing import List
8
+
9
+ sec_duration_expr = re.compile(r'data-duration=(\d+)')
10
+ sec_challenge_expr = re.compile(r'challenge="(.*?)"')
11
+ sec_page_expr = re.compile(r'src="(/_sec/cp_challenge/ak-challenge-\d+-\d+.htm)"')
12
+
13
+
14
+ class SecCptChallengeData:
15
+ def __init__(self, token: str, timestamp: int, nonce: str, difficulty: int):
16
+ self.token = token
17
+ self.timestamp = timestamp
18
+ self.nonce = nonce
19
+ self.difficulty = difficulty
20
+
21
+
22
+ class SecCptChallenge:
23
+ def __init__(self, duration: int, challenge_path: str, challenge_data: SecCptChallengeData):
24
+ self.duration = duration
25
+ self.challenge_path = challenge_path
26
+ self.challenge_data = challenge_data
27
+
28
+ @staticmethod
29
+ def parse(html: str) -> 'SecCptChallenge':
30
+ challenge_data = SecCptChallenge._parse_challenge_data(html)
31
+ duration = SecCptChallenge._parse_duration(html)
32
+ challenge_path = SecCptChallenge._parse_challenge_path(html)
33
+
34
+ return SecCptChallenge(duration, challenge_path, challenge_data)
35
+
36
+ @staticmethod
37
+ def _parse_challenge_data(src: str) -> SecCptChallengeData:
38
+ challenge_match = sec_challenge_expr.search(src)
39
+ if not challenge_match:
40
+ raise Exception("hyper-sdk: Challenge data not found.")
41
+
42
+ decoded_challenge = base64.b64decode(challenge_match.group(1))
43
+ challenge_data = json.loads(decoded_challenge)
44
+
45
+ return SecCptChallengeData(
46
+ challenge_data.get('token', ''),
47
+ challenge_data.get('timestamp', 0),
48
+ challenge_data.get('nonce', ''),
49
+ challenge_data.get('difficulty', 0)
50
+ )
51
+
52
+ @staticmethod
53
+ def _parse_duration(src: str) -> int:
54
+ duration_match = sec_duration_expr.search(src)
55
+ if not duration_match:
56
+ raise Exception("hyper-sdk: Duration not found.")
57
+
58
+ try:
59
+ duration = int(duration_match.group(1))
60
+ except ValueError as e:
61
+ raise Exception(f"hyper-sdk: Invalid duration value: {e}")
62
+
63
+ return duration
64
+
65
+ @staticmethod
66
+ def _parse_challenge_path(src: str) -> str:
67
+ page_match = sec_page_expr.search(src)
68
+ if not page_match:
69
+ raise Exception("hyper-sdk: Challenge path not found.")
70
+
71
+ return page_match.group(1)
72
+
73
+ def generate_sec_cpt_payload(self, sec_cpt_cookie: str) -> str:
74
+ sec, _, _ = sec_cpt_cookie.partition("~")
75
+
76
+ answers = self._generate_sec_cpt_answers(sec)
77
+
78
+ payload = OrderedDict([
79
+ ("token", self.challenge_data.token),
80
+ ("answers", answers)
81
+ ])
82
+
83
+ return json.dumps(payload)
84
+
85
+ def update_sec_cpt_challenge_data(self, response_body: str):
86
+ challenge_data = json.loads(response_body)
87
+ self.challenge_data = SecCptChallengeData(
88
+ challenge_data.get('token', ''),
89
+ challenge_data.get('timestamp', 0),
90
+ challenge_data.get('nonce', ''),
91
+ challenge_data.get('difficulty', 0)
92
+ )
93
+
94
+ def _generate_sec_cpt_answers(self, sec: str) -> List[str]:
95
+ answers = []
96
+ difficulty = self.challenge_data.difficulty
97
+
98
+ while True:
99
+ answer = f"0.{os.urandom(8).hex()}"
100
+ hash_input = f"{sec}{self.challenge_data.timestamp}{self.challenge_data.nonce}{difficulty}{answer}"
101
+
102
+ output = 0
103
+ for byte in hashlib.sha256(hash_input.encode('ascii')).digest():
104
+ output = (output << 8) | byte
105
+ output %= difficulty
106
+
107
+ if output == 0:
108
+ difficulty += 1
109
+ answers.append(answer)
110
+
111
+ if len(answers) == 10:
112
+ break
113
+ continue
114
+
115
+ return answers
@@ -0,0 +1,52 @@
1
+ def is_cookie_valid(cookie: str, request_count: int) -> bool:
2
+ """
3
+ Determines if the provided _abck cookie value is valid, based on Akamai Bot Manager's
4
+ client-side stop signal mechanism using the given request count. If the result is true, the client is ADVISED
5
+ to halt further sensor data submissions. Submitting further would still produce a valid cookie but is unnecessary.
6
+
7
+ The stop signal mechanism in the Akamai Bot Manager's client-side script informs a client that the cookie received is
8
+ valid and that any additional submissions are superfluous.
9
+
10
+ Args:
11
+ cookie (str): The _abck cookie value.
12
+ request_count (int): The number of requests made.
13
+
14
+ Returns:
15
+ bool: True if the cookie is valid, False otherwise.
16
+ """
17
+ parts = cookie.split("~")
18
+ if len(parts) < 2:
19
+ return False
20
+
21
+ try:
22
+ request_threshold = int(parts[1])
23
+ except ValueError:
24
+ request_threshold = -1
25
+
26
+ return request_threshold != -1 and request_count >= request_threshold
27
+
28
+
29
+ def is_cookie_invalidated(cookie: str) -> bool:
30
+ """
31
+ Determines if the current session requires more sensors to be sent.
32
+
33
+ Protected endpoints can invalidate a session by setting a new _abck cookie that ends in '~0~-1~-1' or similar.
34
+ This function returns if such an invalidated cookie is present, if it is present you should be able to make the
35
+ cookie valid again with only 1 sensor post.
36
+
37
+ Args:
38
+ cookie (str): The _abck cookie value.
39
+
40
+ Returns:
41
+ bool: True if the cookie has been invalidated, False otherwise.
42
+ """
43
+ parts = cookie.split("~")
44
+ if len(parts) < 4:
45
+ return False
46
+
47
+ try:
48
+ signal = int(parts[3])
49
+ except ValueError:
50
+ signal = -1
51
+
52
+ return signal > -1
@@ -0,0 +1,15 @@
1
+ class SensorInput:
2
+ def __init__(self, abck: str, bmsz: str, version: str, page_url: str, user_agent: str, script_hash=""):
3
+ self.abck = abck
4
+ self.bmsz = bmsz
5
+ self.version = version
6
+ self.page_url = page_url
7
+ self.user_agent = user_agent
8
+ self.script_hash = script_hash
9
+
10
+
11
+ class PixelInput:
12
+ def __init__(self, user_agent: str, html_var: str, script_var: str):
13
+ self.user_agent = user_agent
14
+ self.html_var = html_var
15
+ self.script_var = script_var
@@ -0,0 +1 @@
1
+ from .utmvc import *
@@ -0,0 +1,42 @@
1
+ import re
2
+ import random
3
+
4
+ # Precompiled regular expressions
5
+ script_regex = re.compile(r'src="(/_Incapsula_Resource\?[^"]*)"')
6
+
7
+
8
+ def parse_utmvc_script_path(script_content: str) -> str:
9
+ """
10
+ Parses the UTMVC script path from the given script content.
11
+
12
+ This function searches the provided script content for a specific pattern matching the UTMVC script path
13
+ using a precompiled regular expression. It extracts and returns the first match if found.
14
+
15
+ Args:
16
+ script_content (str): The content of the script from which the UTMVC script path is to be extracted.
17
+
18
+ Returns:
19
+ str: The extracted UTMVC script path.
20
+
21
+ Raises:
22
+ Exception: If the UTMVC script path is not found in the script content.
23
+ """
24
+ match = script_regex.search(script_content)
25
+ if match:
26
+ return match.group(1)
27
+ else:
28
+ raise Exception("hyper-sdk: utmvc script not found")
29
+
30
+
31
+ def get_utmvc_submit_path() -> str:
32
+ """
33
+ Generates a UTMVC submit path with a unique random query parameter.
34
+
35
+ This function constructs a submit path for the UTMVC script by appending a random floating-point number as a query
36
+ parameter. The random number is used to ensure uniqueness of the request.
37
+
38
+ Returns:
39
+ str: A unique UTMVC submit path.
40
+ """
41
+ random_float = random.random()
42
+ return f"/_Incapsula_Resource?SWKMTFSR=1&e={random_float:g}"
@@ -0,0 +1,5 @@
1
+ class UtmvcInput:
2
+ def __init__(self, user_agent, session_ids, script):
3
+ self.user_agent = user_agent
4
+ self.session_ids = session_ids
5
+ self.script = script
@@ -0,0 +1,138 @@
1
+ from typing import Optional, Dict, Any
2
+ from urllib.parse import quote
3
+
4
+ import requests
5
+ import jwt
6
+ from datetime import datetime, timedelta, timezone
7
+
8
+ from .akamai_input import SensorInput, PixelInput
9
+ from .incapsula_input import UtmvcInput
10
+
11
+
12
+ class Session:
13
+ def __init__(self, api_key: str, jwt_key: Optional[str] = None, client: Optional[requests.Session] = None) -> None:
14
+ self.api_key = api_key
15
+ self.jwt_key = jwt_key
16
+ self.client = requests.Session() if client is None else client
17
+
18
+ def generate_sensor_data(self, input_data: SensorInput) -> str:
19
+ """
20
+ Returns the sensor data required to generate valid akamai cookies using the Hyper Solutions API.
21
+
22
+ Args:
23
+ input_data (SensorInput): An instance of SensorInput containing the necessary data for generating the sensor data.
24
+
25
+ Returns:
26
+ str: Sensor data as a string.
27
+ """
28
+ sensor_endpoint = "https://akm.justhyped.dev/sensor"
29
+ return self._send_request(sensor_endpoint, {
30
+ 'userAgent': input_data.user_agent,
31
+ 'abck': input_data.abck,
32
+ 'bmsz': input_data.bmsz,
33
+ 'version': input_data.version,
34
+ 'pageUrl': input_data.page_url,
35
+ 'scriptHash': input_data.script_hash,
36
+ })
37
+
38
+ def generate_pixel_data(self, input_data: PixelInput) -> str:
39
+ """
40
+ Returns the pixel data using the Hyper Solutions API.
41
+
42
+ Args:
43
+ session (Session): An instance of Session to handle the network request.
44
+ input_data (PixelInput): An instance of PixelInput containing the necessary data for generating the pixel data.
45
+
46
+ Returns:
47
+ str: Pixel data as a string.
48
+ """
49
+ pixel_endpoint = "https://akm.justhyped.dev/pixel"
50
+ return self._send_request(pixel_endpoint, {
51
+ 'userAgent': input_data.user_agent,
52
+ 'htmlVar': input_data.html_var,
53
+ 'scriptVar': input_data.script_var,
54
+ })
55
+
56
+ def generate_reese84_sensor(self, site: str, user_agent: str) -> str:
57
+ """
58
+ Returns the sensor data required to generate valid reese84 cookies using the Hyper Solutions API.
59
+
60
+ This function sends a request to the specified sensor endpoint with the necessary data to generate the reese84 sensor data.
61
+
62
+ Args:
63
+ site (str): The name of the site that will be used to generate the sensor data.
64
+ user_agent (str): The user agent string used to generate the sensor data.
65
+
66
+ Returns:
67
+ str: Sensor data as a string.
68
+
69
+ Raises:
70
+ ValueError: If the script attribute in input_data is empty.
71
+ """
72
+ return self._send_request("https://incapsula.justhyped.dev/reese84/" + quote(site),
73
+ {
74
+ 'userAgent': user_agent,
75
+ })
76
+
77
+ def generate_utmvc_cookie(self, input_data: UtmvcInput) -> str:
78
+ """
79
+ Returns the utmvc cookie using the Hyper Solutions API.
80
+
81
+ This function sends a request to the utmvc sensor endpoint with the necessary data to generate the utmvc cookie.
82
+ The input data must include a non-empty script and session IDs.
83
+
84
+ Args:
85
+ session (Session): An instance of Session to handle the network request.
86
+ input_data (Input): An instance of Input containing the user agent, session IDs, and script.
87
+
88
+ Returns:
89
+ str: The utmvc cookie as a string.
90
+
91
+ Raises:
92
+ ValueError: If the script attribute or session IDs in input_data are empty.
93
+ """
94
+ if not input_data.script:
95
+ raise ValueError("script must be non empty")
96
+
97
+ if not input_data.session_ids:
98
+ raise ValueError("no session ids set")
99
+
100
+ return self._send_request("https://incapsula.justhyped.dev/utmvc", {
101
+ 'userAgent': input_data.user_agent,
102
+ 'sessionIds': input_data.session_ids,
103
+ 'script': input_data.script,
104
+ })
105
+
106
+ def generate_signature(self) -> str:
107
+ claims = {
108
+ "key": self.api_key,
109
+ "exp": datetime.now(timezone.utc) + timedelta(seconds=15)
110
+ }
111
+ token = jwt.encode(claims, self.jwt_key, algorithm='HS256')
112
+ return token.decode('utf-8')
113
+
114
+ def _send_request(self, url: str, input_data: Dict[str, Any]) -> str:
115
+ if not self.api_key:
116
+ raise ValueError("Missing API key")
117
+
118
+ headers = {
119
+ 'Content-Type': 'application/json',
120
+ 'Accept-Encoding': 'gzip',
121
+ 'X-Api-Key': self.api_key
122
+ }
123
+
124
+ if self.jwt_key:
125
+ signature = self.generate_signature()
126
+ headers['X-Signature'] = signature
127
+
128
+ response = self.client.post(url, headers=headers, json=input_data)
129
+
130
+ response_data = response.json()
131
+
132
+ if "error" in response_data and response_data["error"]:
133
+ raise Exception(f"API returned with error: {response_data['error']}")
134
+
135
+ if response.status_code != 200:
136
+ raise Exception(f"API returned with status code: {response.status_code}")
137
+
138
+ return response_data["payload"]
@@ -0,0 +1,194 @@
1
+ Metadata-Version: 2.1
2
+ Name: hyper_sdk
3
+ Version: 0.1.0
4
+ Summary: Hyper Solutions Python SDK
5
+ Project-URL: homepage, https://github.com/Hyper-Solutions/hyper-sdk-py
6
+ Classifier: Intended Audience :: Developers
7
+ Classifier: License :: OSI Approved :: MIT License
8
+ Classifier: Programming Language :: Python :: 3
9
+ Requires-Python: >=3.6
10
+ Description-Content-Type: text/markdown
11
+ License-File: LICENSE
12
+ Requires-Dist: certifi==2024.2.2
13
+ Requires-Dist: charset-normalizer==3.3.2
14
+ Requires-Dist: idna==3.6
15
+ Requires-Dist: jsonpickle==3.0.3
16
+ Requires-Dist: PyJWT==2.8.0
17
+ Requires-Dist: requests==2.31.0
18
+ Requires-Dist: urllib3==2.2.1
19
+
20
+ # Hyper Solutions SDK for Python
21
+
22
+ ## Installation
23
+
24
+ To use the Hyper Solutions SDK in your Python project, you need to install it using the following command:
25
+
26
+ ```
27
+ pip install hyper-sdk
28
+ ```
29
+
30
+ ## Usage
31
+
32
+ ### Creating a Session
33
+
34
+ To start using the SDK, you need to create a new `Session` instance by providing your API key:
35
+
36
+ ```python
37
+ from hyper_sdk import Session
38
+
39
+ session = Session(api_key="your-api-key")
40
+ ```
41
+
42
+ You can also optionally set a JWT key and a custom HTTP client:
43
+
44
+ ```python
45
+ from hyper_sdk import Session
46
+
47
+ session = Session(api_key="your-api-key", jwt_key="your-jwt-key", client=custom_http_client)
48
+ ```
49
+
50
+ ## Akamai
51
+
52
+ The Akamai package provides functions for interacting with Akamai Bot Manager, including generating sensor data, parsing script path, parsing pixel challenges, and handling sec-cpt challenges.
53
+
54
+ ### Generating Sensor Data
55
+
56
+ To generate sensor data required for generating valid Akamai cookies, use the `generate_sensor_data` method:
57
+
58
+ ```python
59
+ from hyper_sdk import SensorInput
60
+
61
+ sensor_input = SensorInput(
62
+ page_url="https://example.com/",
63
+ user_agent="your-user-agent",
64
+ abck="your-abck-cookie",
65
+ bmsz="your-bmsz-cookie",
66
+ version="2.0"
67
+ )
68
+ sensor_data = session.generate_sensor_data(sensor_input)
69
+ ```
70
+
71
+ ### Parsing Script Path
72
+
73
+ To parse the Akamai Bot Manager script path from the given HTML code, use the `parse_script_path` function from the `script_path` module:
74
+
75
+ ```python
76
+ from hyper_sdk.akamai.script_path import parse_script_path
77
+
78
+ script_path = parse_script_path(html_source)
79
+ ```
80
+
81
+ ### Handling Sec-Cpt Challenges
82
+
83
+ The Akamai package provides functions for handling sec-cpt challenges:
84
+
85
+ - `SecCptChallenge.parse`: Parses a sec-cpt challenge from an HTML source.
86
+ - `generate_sec_cpt_payload`: Generates a sec-cpt payload using the provided sec-cpt cookie.
87
+ - `update_sec_cpt_challenge_data`: Updates the challenge data of a `SecCptChallenge` instance from a response body.
88
+
89
+ Example usage:
90
+
91
+ ```python
92
+ from hyper_sdk.akamai.sec_cpt import SecCptChallenge
93
+
94
+ challenge = SecCptChallenge.parse(html_source)
95
+ payload = challenge.generate_sec_cpt_payload(sec_cpt_cookie)
96
+ challenge.update_sec_cpt_challenge_data(response_body)
97
+ ```
98
+
99
+ ### Validating Cookies
100
+
101
+ The Akamai package provides functions for validating cookies:
102
+
103
+ - `is_cookie_valid`: Determines if the provided `_abck` cookie value is valid based on the given request count.
104
+ - `is_cookie_invalidated`: Determines if the current session requires more sensors to be sent.
105
+
106
+ Example usage:
107
+
108
+ ```python
109
+ from hyper_sdk.akamai.stop_signal import is_cookie_valid, is_cookie_invalidated
110
+
111
+ is_valid = is_cookie_valid(abck_cookie, request_count)
112
+ is_invalidated = is_cookie_invalidated(abck_cookie)
113
+ ```
114
+
115
+ ### Generating Pixel Data
116
+
117
+ To generate pixel data, use the `generate_pixel_data` method:
118
+
119
+ ```python
120
+ from hyper_sdk import PixelInput
121
+
122
+ pixel_input = PixelInput(
123
+ user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36",
124
+ html_var="your-html-var",
125
+ script_var="your-script-var"
126
+ )
127
+ pixel_data = session.generate_pixel_data(pixel_input)
128
+ ```
129
+
130
+ ### Parsing Pixel Challenges
131
+
132
+ The Akamai package provides functions for parsing pixel challenges:
133
+
134
+ - `parse_pixel_html_var`: Parses the required pixel challenge variable from the given HTML code.
135
+ - `parse_pixel_script_url`: Parses the script URL of the pixel challenge script and the URL to post a generated payload to from the given HTML code.
136
+ - `parse_pixel_script_var`: Parses the dynamic value from the pixel script.
137
+
138
+ Example usage:
139
+
140
+ ```python
141
+ from hyper_sdk.akamai.pixel import parse_pixel_html_var, parse_pixel_script_url, parse_pixel_script_var
142
+
143
+ html_var = parse_pixel_html_var(html_source)
144
+ script_url, post_url = parse_pixel_script_url(html_source)
145
+ script_var = parse_pixel_script_var(script_source)
146
+ ```
147
+
148
+
149
+ ## Incapsula
150
+
151
+ The Incapsula package provides functions for interacting with Imperva Incapsula, including generating Reese84 sensor data, UTMVC cookies, and parsing UTMVC script paths.
152
+
153
+ ### Generating Reese84 Sensor
154
+
155
+ To generate sensor data required for generating valid Reese84 cookies, use the `generate_reese84_sensor` method:
156
+
157
+ ```python
158
+ sensor_data = session.generate_reese84_sensor(site="example.com", user_agent="your-user-agent")
159
+ ```
160
+
161
+ ### Generating UTMVC Cookie
162
+
163
+ To generate the UTMVC cookie using the Hyper Solutions API, use the `generate_utmvc_cookie` method:
164
+
165
+ ```python
166
+ from hyper_sdk import UtmvcInput
167
+
168
+ utmvc_input = UtmvcInput(
169
+ user_agent="your-user-agent",
170
+ session_ids=["session-id-1", "session-id-2"],
171
+ script="your-script"
172
+ )
173
+ utmvc_cookie = session.generate_utmvc_cookie(utmvc_input)
174
+ ```
175
+
176
+ ### Parsing UTMVC Script Path
177
+
178
+ To parse the UTMVC script path from a given script content, use the `parse_utmvc_script_path` function from the `utmvc` module:
179
+
180
+ ```python
181
+ from hyper_sdk.incapsula.utmvc import parse_utmvc_script_path
182
+
183
+ script_path = parse_utmvc_script_path(script_content)
184
+ ```
185
+
186
+ ### Generating UTMVC Submit Path
187
+
188
+ To generate a unique UTMVC submit path with a random query parameter, use the `get_utmvc_submit_path` function from the `utmvc` module:
189
+
190
+ ```python
191
+ from hyper_sdk.incapsula.utmvc import get_utmvc_submit_path
192
+
193
+ submit_path = get_utmvc_submit_path()
194
+ ```
@@ -0,0 +1,19 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ hyper_sdk/__init__.py
5
+ hyper_sdk/akamai_input.py
6
+ hyper_sdk/incapsula_input.py
7
+ hyper_sdk/session.py
8
+ hyper_sdk.egg-info/PKG-INFO
9
+ hyper_sdk.egg-info/SOURCES.txt
10
+ hyper_sdk.egg-info/dependency_links.txt
11
+ hyper_sdk.egg-info/requires.txt
12
+ hyper_sdk.egg-info/top_level.txt
13
+ hyper_sdk/akamai/__init__.py
14
+ hyper_sdk/akamai/pixel.py
15
+ hyper_sdk/akamai/script_path.py
16
+ hyper_sdk/akamai/sec_cpt.py
17
+ hyper_sdk/akamai/stop_signal.py
18
+ hyper_sdk/incapsula/__init__.py
19
+ hyper_sdk/incapsula/utmvc.py
@@ -0,0 +1,7 @@
1
+ certifi==2024.2.2
2
+ charset-normalizer==3.3.2
3
+ idna==3.6
4
+ jsonpickle==3.0.3
5
+ PyJWT==2.8.0
6
+ requests==2.31.0
7
+ urllib3==2.2.1
@@ -0,0 +1 @@
1
+ hyper_sdk
@@ -0,0 +1,30 @@
1
+ [build-system]
2
+ requires = ["setuptools>=42", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "hyper_sdk"
7
+ version = "0.1.0"
8
+ description = "Hyper Solutions Python SDK"
9
+ readme = "README.md"
10
+ requires-python = ">=3.6"
11
+ classifiers = [
12
+ "Intended Audience :: Developers",
13
+ "License :: OSI Approved :: MIT License",
14
+ "Programming Language :: Python :: 3",
15
+ ]
16
+ dependencies = [
17
+ "certifi==2024.2.2",
18
+ "charset-normalizer==3.3.2",
19
+ "idna==3.6",
20
+ "jsonpickle==3.0.3",
21
+ "PyJWT==2.8.0",
22
+ "requests==2.31.0",
23
+ "urllib3==2.2.1",
24
+ ]
25
+
26
+ [project.urls]
27
+ homepage = "https://github.com/Hyper-Solutions/hyper-sdk-py"
28
+
29
+ [tool.setuptools]
30
+ packages = ["hyper_sdk", "hyper_sdk.akamai", "hyper_sdk.incapsula"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+