├── LICENSE
├── README.md
├── hyper_sdk
├── __init__.py
├── akamai
│ ├── __init__.py
│ ├── pixel.py
│ ├── script_path.py
│ ├── sec_cpt.py
│ └── stop_signal.py
├── akamai_input.py
├── datadome
│ ├── __init__.py
│ └── parse.py
├── datadome_input.py
├── incapsula
│ ├── __init__.py
│ ├── dynamic.py
│ └── utmvc.py
├── incapsula_input.py
├── kasada
│ ├── __init__.py
│ └── parse.py
├── kasada_input.py
└── session.py
└── pyproject.toml
/LICENSE:
--------------------------------------------------------------------------------
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.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
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 | ## Documentation
12 |
13 | For detailed documentation on how to use the SDK, including examples and API reference, please visit our documentation website:
14 |
15 | [https://docs.justhyped.dev/](https://docs.justhyped.dev/)
16 |
17 | ## Contributing
18 |
19 | If you find any issues or have suggestions for improvement, please open an issue or submit a pull request.
20 |
21 | ## License
22 |
23 | This SDK is licensed under the [MIT License](LICENSE).
--------------------------------------------------------------------------------
/hyper_sdk/__init__.py:
--------------------------------------------------------------------------------
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 .incapsula.dynamic import *
7 | from .session import *
8 | from .kasada.parse import *
9 | from .datadome.parse import *
10 |
--------------------------------------------------------------------------------
/hyper_sdk/akamai/__init__.py:
--------------------------------------------------------------------------------
1 | from .pixel import *
2 | from .script_path import *
3 | from .sec_cpt import *
4 | from .stop_signal import *
5 |
--------------------------------------------------------------------------------
/hyper_sdk/akamai/pixel.py:
--------------------------------------------------------------------------------
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
84 |
--------------------------------------------------------------------------------
/hyper_sdk/akamai/script_path.py:
--------------------------------------------------------------------------------
1 | import re
2 |
3 | # Precompiled regular expressions
4 | script_path_expr = re.compile(r'',
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"
29 |
--------------------------------------------------------------------------------
/hyper_sdk/akamai/sec_cpt.py:
--------------------------------------------------------------------------------
1 | import base64
2 | import hashlib
3 | import json
4 | import os
5 | import re
6 | import time
7 | from collections import OrderedDict
8 | from typing import List
9 |
10 | sec_duration_expr = re.compile(r'data-duration=(\d+)')
11 | sec_challenge_expr = re.compile(r'challenge="(.*?)"')
12 | sec_page_expr = re.compile(r'data-duration=\d+\s+src="([^"]+)"')
13 |
14 |
15 | class SecCptChallengeData:
16 | def __init__(self, token: str, timestamp: int, nonce: str, difficulty: int, count: int):
17 | self.token = token
18 | self.timestamp = timestamp
19 | self.nonce = nonce
20 | self.difficulty = difficulty
21 | self.count = count
22 |
23 |
24 | class SecCptChallenge:
25 | def __init__(self, duration: int, challenge_path: str, challenge_data: SecCptChallengeData):
26 | self.duration = duration
27 | self.challenge_path = challenge_path
28 | self.challenge_data = challenge_data
29 |
30 | @staticmethod
31 | def parse(html: str) -> 'SecCptChallenge':
32 | challenge_data = SecCptChallenge._parse_challenge_data(html)
33 | duration = SecCptChallenge._parse_duration(html)
34 | challenge_path = SecCptChallenge._parse_challenge_path(html)
35 |
36 | return SecCptChallenge(duration, challenge_path, challenge_data)
37 |
38 | @staticmethod
39 | def parse_from_json(json_payload: str) -> 'SecCptChallenge':
40 | api_response = json.loads(json_payload)
41 |
42 | challenge_data = SecCptChallengeData(
43 | api_response.get('token', ''),
44 | api_response.get('timestamp', 0),
45 | api_response.get('nonce', ''),
46 | api_response.get('difficulty', 0)
47 | )
48 |
49 | duration = api_response.get('chlg_duration', 0)
50 | challenge_path = api_response.get('branding_url_content', '')
51 |
52 | return SecCptChallenge(duration, challenge_path, challenge_data)
53 |
54 | @staticmethod
55 | def _parse_challenge_data(src: str) -> SecCptChallengeData:
56 | challenge_match = sec_challenge_expr.search(src)
57 | if not challenge_match:
58 | raise Exception("hyper-sdk: Challenge data not found.")
59 |
60 | decoded_challenge = base64.b64decode(challenge_match.group(1))
61 | challenge_data = json.loads(decoded_challenge)
62 |
63 | return SecCptChallengeData(
64 | challenge_data.get('token', ''),
65 | challenge_data.get('timestamp', 0),
66 | challenge_data.get('nonce', ''),
67 | challenge_data.get('difficulty', 0),
68 | challenge_data.get('count', 0)
69 | )
70 |
71 | @staticmethod
72 | def _parse_duration(src: str) -> int:
73 | duration_match = sec_duration_expr.search(src)
74 | if not duration_match:
75 | raise Exception("hyper-sdk: Duration not found.")
76 |
77 | try:
78 | duration = int(duration_match.group(1))
79 | except ValueError as e:
80 | raise Exception(f"hyper-sdk: Invalid duration value: {e}")
81 |
82 | return duration
83 |
84 | @staticmethod
85 | def _parse_challenge_path(src: str) -> str:
86 | page_match = sec_page_expr.search(src)
87 | if not page_match:
88 | raise Exception("hyper-sdk: Challenge path not found.")
89 |
90 | return page_match.group(1)
91 |
92 | def generate_sec_cpt_payload(self, sec_cpt_cookie: str) -> str:
93 | sec, _, _ = sec_cpt_cookie.partition("~")
94 | if sec == sec_cpt_cookie:
95 | raise Exception("hyper-sdk: Malformed sec_cpt cookie.")
96 |
97 | answers = self._generate_sec_cpt_answers(sec)
98 |
99 | payload = OrderedDict([
100 | ("token", self.challenge_data.token),
101 | ("answers", answers)
102 | ])
103 |
104 | return json.dumps(payload)
105 |
106 | def sleep(self):
107 | time.sleep(self.duration)
108 |
109 | def _generate_sec_cpt_answers(self, sec: str) -> List[str]:
110 | answers = []
111 | difficulty = self.challenge_data.difficulty
112 |
113 | while True:
114 | answer = f"0.{os.urandom(8).hex()}"
115 | hash_input = f"{sec}{self.challenge_data.timestamp}{self.challenge_data.nonce}{difficulty}{answer}"
116 |
117 | output = 0
118 | for byte in hashlib.sha256(hash_input.encode('ascii')).digest():
119 | output = (output << 8) | byte
120 | output %= difficulty
121 |
122 | if output == 0:
123 | difficulty += 1
124 | answers.append(answer)
125 |
126 | if len(answers) == self.challenge_data.count:
127 | break
128 | continue
129 |
130 | return answers
--------------------------------------------------------------------------------
/hyper_sdk/akamai/stop_signal.py:
--------------------------------------------------------------------------------
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
53 |
--------------------------------------------------------------------------------
/hyper_sdk/akamai_input.py:
--------------------------------------------------------------------------------
1 | class SensorInput:
2 | def __init__(self, abck: str, bmsz: str, version: str, page_url: str, user_agent: str, ip: str, acceptLanguage: str, context: str, script_hash="", dynamic_values=""):
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 | self.dynamic_values = dynamic_values
10 | self.context = context
11 | self.ip = ip
12 | self.acceptLanguage = acceptLanguage
13 |
14 |
15 | class PixelInput:
16 | def __init__(self, user_agent: str, html_var: str, script_var: str, acceptLanguage: str, ip: str):
17 | self.user_agent = user_agent
18 | self.html_var = html_var
19 | self.script_var = script_var
20 | self.acceptLanguage = acceptLanguage
21 | self.ip = ip
22 |
23 |
24 | class DynamicInput:
25 | def __init__(self, script: str):
26 | self.script = script
27 |
28 |
29 | class SbsdInput:
30 | def __init__(self, user_agent: str, uuid: str, page_url: str, o_cookie: str, script: str, acceptLanguage: str, ip: str):
31 | self.user_agent = user_agent
32 | self.uuid = uuid
33 | self.page_url = page_url
34 | self.o_cookie = o_cookie
35 | self.script = script
36 | self.acceptLanguage = acceptLanguage
37 | self.ip = ip
38 |
--------------------------------------------------------------------------------
/hyper_sdk/datadome/__init__.py:
--------------------------------------------------------------------------------
1 | from .parse import *
2 |
--------------------------------------------------------------------------------
/hyper_sdk/datadome/parse.py:
--------------------------------------------------------------------------------
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("")[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("")[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 | "dm": "cd",
81 | }
82 |
83 | return f"https://geo.captcha-delivery.com/interstitial/?{urlencode(params)}"
84 |
--------------------------------------------------------------------------------
/hyper_sdk/datadome_input.py:
--------------------------------------------------------------------------------
1 |
2 | class DataDomeSliderInput:
3 | def __init__(self, user_agent: str, device_link: str, html: str, puzzle: str, piece: str, parent_url: str, acceptLanguage: str, ip: str):
4 | # UserAgent must be a Chrome Windows User-Agent.
5 | self.user_agent = user_agent
6 |
7 | # DeviceLink is the URL that contains the script and starts like this:
8 | # https://geo.captcha-delivery.com/captcha/?initialCid
9 | self.device_link = device_link
10 |
11 | # Html is the response body of the GET request to the DeviceLink
12 | self.html = html
13 |
14 | # Puzzle is the captcha puzzle image bytes, base64 encoded.
15 | # The URL that returns the puzzle looks like this:
16 | # https://dd.prod.captcha-delivery.com/image/2024-xx-xx/hash.jpg
17 | self.puzzle = puzzle
18 |
19 | # Piece is the captcha puzzle piece image bytes, base64 encoded.
20 | # The URL that returns the puzzle looks like this:
21 | # https://dd.prod.captcha-delivery.com/image/2024-xx-xx/hash.frag.png
22 | self.piece = piece
23 |
24 | self.parent_url = parent_url
25 | self.acceptLanguage = acceptLanguage
26 | self.ip = ip
27 |
28 | def to_dict(self):
29 | return {
30 | "userAgent": self.user_agent,
31 | "deviceLink": self.device_link,
32 | "html": self.html,
33 | "puzzle": self.puzzle,
34 | "piece": self.piece,
35 | "parentUrl": self.parent_url,
36 | "acceptLanguage": self.acceptLanguage,
37 | "ip": self.ip,
38 | }
39 |
40 |
41 | class DataDomeInterstitialInput:
42 | def __init__(self, user_agent: str, device_link: str, html: str, acceptLanguage: str, ip: str):
43 | # UserAgent must be a Chrome Windows User-Agent.
44 | self.user_agent = user_agent
45 |
46 | # DeviceLink is the URL that contains the script and starts like this:
47 | # https://geo.captcha-delivery.com/captcha/?initialCid
48 | self.device_link = device_link
49 |
50 | # Html is the response body of the GET request to the DeviceLink
51 | self.html = html
52 |
53 | self.acceptLanguage = acceptLanguage
54 | self.ip = ip
55 |
56 | def to_dict(self):
57 | return {
58 | "userAgent": self.user_agent,
59 | "deviceLink": self.device_link,
60 | "html": self.html,
61 | "acceptLanguage": self.acceptLanguage,
62 | "ip": self.ip,
63 | }
64 |
65 |
66 | class DataDomeTagsInput:
67 | def __init__(self, user_agent: str, cid: str, ddk: str, referer: str, tags_type: str, version: str, acceptLanguage: str, ip: str):
68 | # UserAgent must be a Chrome Windows User-Agent.
69 | self.user_agent = user_agent
70 | self.cid = cid
71 | self.ddk = ddk
72 | self.referer = referer
73 | self.tags_type = tags_type
74 | self.version = version
75 | self.acceptLanguage = acceptLanguage
76 | self.ip = ip
77 |
78 | def to_dict(self):
79 | return {
80 | "userAgent": self.user_agent,
81 | "cid": self.cid,
82 | "ddk": self.ddk,
83 | "referer": self.referer,
84 | "type": self.tags_type,
85 | "acceptLanguage": self.acceptLanguage,
86 | "ip": self.ip,
87 | "version": self.version,
88 | }
--------------------------------------------------------------------------------
/hyper_sdk/incapsula/__init__.py:
--------------------------------------------------------------------------------
1 | from .utmvc import *
2 | from .dynamic import *
3 |
--------------------------------------------------------------------------------
/hyper_sdk/incapsula/dynamic.py:
--------------------------------------------------------------------------------
1 | import re
2 | from urllib.parse import urlparse
3 |
4 | # Precompiled regular expressions
5 | reese_script_regex = re.compile(r'src\s*=\s*"((/[^/]+/\d+)(?:\?.*)?)"')
6 |
7 |
8 | def parse_dynamic_reese_script(html_content: str, url_str: str) -> tuple[str, str]:
9 | """
10 | Parses the sensor path and script path from the given HTML content.
11 |
12 | This function searches the provided HTML for a script element containing a specific pattern
13 | and extracts both the sensor path (shortened path) and script path (the full path).
14 | It requires that the HTML contains "Pardon Our Interruption" to confirm it's the correct page type.
15 | It also takes a URL string, extracts the hostname, and appends it to the sensor path.
16 |
17 | Args:
18 | html_content (str): The HTML content to parse.
19 | url_str (str): The URL string to extract the hostname from.
20 |
21 | Returns:
22 | tuple[str, str]: A tuple containing the sensor path (with hostname) and script path.
23 |
24 | Raises:
25 | ValueError: If the URL is invalid.
26 | Exception: If the page is not an interruption page or if the Reese script is not found.
27 | """
28 | # Parse the URL to extract hostname
29 | try:
30 | parsed_url = urlparse(url_str)
31 | hostname = parsed_url.netloc
32 | except Exception:
33 | raise ValueError("hyper-sdk: invalid URL")
34 |
35 | # Verify this is an interruption page
36 | if "Pardon Our Interruption" not in html_content:
37 | raise Exception("hyper-sdk: not an interruption page")
38 |
39 | # Find the Reese script
40 | match = reese_script_regex.search(html_content)
41 | if not match or len(match.groups()) < 2:
42 | raise Exception("hyper-sdk: reese script not found")
43 |
44 | script_path = match.group(1)
45 | sensor_path = match.group(2)
46 |
47 | # Append the hostname to the sensor path
48 | return f"{sensor_path}?d={hostname}", script_path
--------------------------------------------------------------------------------
/hyper_sdk/incapsula/utmvc.py:
--------------------------------------------------------------------------------
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}"
43 |
--------------------------------------------------------------------------------
/hyper_sdk/incapsula_input.py:
--------------------------------------------------------------------------------
1 | from typing import List
2 |
3 |
4 | class UtmvcInput:
5 | def __init__(self, user_agent: str, session_ids: List[str], script: str):
6 | self.user_agent = user_agent
7 | self.session_ids = session_ids
8 | self.script = script
9 |
10 | class ReeseInput:
11 | def __init__(self, user_agent: str, acceptLanguage: str, ip: str, pageUrl: str, scriptUrl: str = ""):
12 | self.user_agent = user_agent
13 | self.acceptLanguage = acceptLanguage
14 | self.ip = ip
15 | self.scriptUrl = scriptUrl
16 | self.pageUrl = pageUrl
17 |
--------------------------------------------------------------------------------
/hyper_sdk/kasada/__init__.py:
--------------------------------------------------------------------------------
1 | from .parse import *
2 |
--------------------------------------------------------------------------------
/hyper_sdk/kasada/parse.py:
--------------------------------------------------------------------------------
1 | import re
2 |
3 | # Precompiled regular expression
4 | script_path_expr = re.compile(r'