atomicshop 3.3.8__py3-none-any.whl → 3.10.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of atomicshop might be problematic. Click here for more details.
- atomicshop/__init__.py +1 -1
- atomicshop/a_mains/get_local_tcp_ports.py +85 -0
- atomicshop/a_mains/install_ca_certificate.py +172 -0
- atomicshop/a_mains/process_from_port.py +119 -0
- atomicshop/a_mains/set_default_dns_gateway.py +90 -0
- atomicshop/basics/strings.py +1 -1
- atomicshop/certificates.py +2 -2
- atomicshop/dns.py +26 -28
- atomicshop/etws/traces/trace_tcp.py +1 -2
- atomicshop/mitm/centered_settings.py +133 -0
- atomicshop/mitm/config_static.py +22 -44
- atomicshop/mitm/connection_thread_worker.py +383 -165
- atomicshop/mitm/engines/__parent/recorder___parent.py +1 -1
- atomicshop/mitm/engines/__parent/requester___parent.py +1 -1
- atomicshop/mitm/engines/__parent/responder___parent.py +15 -2
- atomicshop/mitm/engines/create_module_template.py +1 -2
- atomicshop/mitm/import_config.py +91 -89
- atomicshop/mitm/initialize_engines.py +1 -2
- atomicshop/mitm/message.py +5 -4
- atomicshop/mitm/mitm_main.py +238 -122
- atomicshop/mitm/recs_files.py +61 -5
- atomicshop/mitm/ssh_tester.py +82 -0
- atomicshop/mitm/statistic_analyzer.py +33 -12
- atomicshop/mitm/statistic_analyzer_helper/moving_average_helper.py +104 -31
- atomicshop/networks.py +160 -92
- atomicshop/package_mains_processor.py +84 -0
- atomicshop/permissions/ubuntu_permissions.py +47 -0
- atomicshop/print_api.py +3 -5
- atomicshop/process.py +11 -4
- atomicshop/python_functions.py +23 -108
- atomicshop/speech_recognize.py +8 -0
- atomicshop/ssh_remote.py +140 -164
- atomicshop/web.py +63 -22
- atomicshop/web_apis/google_llm.py +22 -14
- atomicshop/wrappers/ctyping/msi_windows_installer/cabs.py +2 -1
- atomicshop/wrappers/ctyping/msi_windows_installer/extract_msi_main.py +2 -1
- atomicshop/wrappers/dockerw/dockerw.py +2 -2
- atomicshop/wrappers/elasticsearchw/config_basic.py +0 -12
- atomicshop/wrappers/elasticsearchw/elastic_infra.py +0 -190
- atomicshop/wrappers/factw/install/pre_install_and_install_before_restart.py +5 -5
- atomicshop/wrappers/githubw.py +180 -68
- atomicshop/wrappers/loggingw/consts.py +1 -1
- atomicshop/wrappers/loggingw/handlers.py +1 -1
- atomicshop/wrappers/loggingw/loggingw.py +20 -4
- atomicshop/wrappers/loggingw/reading.py +18 -0
- atomicshop/wrappers/mongodbw/mongo_infra.py +0 -38
- atomicshop/wrappers/netshw.py +124 -3
- atomicshop/wrappers/playwrightw/scenarios.py +1 -1
- atomicshop/wrappers/powershell_networking.py +80 -0
- atomicshop/wrappers/psutilw/psutil_networks.py +9 -0
- atomicshop/wrappers/pywin32w/win_event_log/fetch.py +174 -0
- atomicshop/wrappers/pywin32w/win_event_log/subscribes/process_create.py +3 -105
- atomicshop/wrappers/pywin32w/win_event_log/subscribes/process_terminate.py +3 -57
- atomicshop/wrappers/pywin32w/wmis/win32_networkadapterconfiguration.py +12 -27
- atomicshop/wrappers/pywin32w/wmis/win32networkadapter.py +15 -9
- atomicshop/wrappers/socketw/certificator.py +19 -9
- atomicshop/wrappers/socketw/creator.py +101 -14
- atomicshop/wrappers/socketw/dns_server.py +17 -5
- atomicshop/wrappers/socketw/exception_wrapper.py +21 -16
- atomicshop/wrappers/socketw/process_getter.py +86 -0
- atomicshop/wrappers/socketw/receiver.py +29 -9
- atomicshop/wrappers/socketw/sender.py +10 -9
- atomicshop/wrappers/socketw/sni.py +31 -10
- atomicshop/wrappers/socketw/{base.py → socket_base.py} +33 -1
- atomicshop/wrappers/socketw/socket_client.py +11 -10
- atomicshop/wrappers/socketw/socket_wrapper.py +125 -32
- atomicshop/wrappers/socketw/ssl_base.py +6 -2
- atomicshop/wrappers/ubuntu_terminal.py +21 -18
- atomicshop/wrappers/win_auditw.py +189 -0
- {atomicshop-3.3.8.dist-info → atomicshop-3.10.0.dist-info}/METADATA +25 -30
- {atomicshop-3.3.8.dist-info → atomicshop-3.10.0.dist-info}/RECORD +83 -109
- atomicshop/_basics_temp.py +0 -101
- atomicshop/a_installs/ubuntu/docker_rootless.py +0 -11
- atomicshop/a_installs/ubuntu/docker_sudo.py +0 -11
- atomicshop/a_installs/ubuntu/elastic_search_and_kibana.py +0 -10
- atomicshop/a_installs/ubuntu/mongodb.py +0 -12
- atomicshop/a_installs/win/fibratus.py +0 -9
- atomicshop/a_installs/win/mongodb.py +0 -9
- atomicshop/a_installs/win/wsl_ubuntu_lts.py +0 -10
- atomicshop/addons/a_setup_scripts/install_psycopg2_ubuntu.sh +0 -3
- atomicshop/addons/package_setup/CreateWheel.cmd +0 -7
- atomicshop/addons/package_setup/Setup in Edit mode.cmd +0 -6
- atomicshop/addons/package_setup/Setup.cmd +0 -7
- atomicshop/archiver/__init__.py +0 -0
- atomicshop/archiver/_search_in_zip.py +0 -189
- atomicshop/archiver/search_in_archive.py +0 -284
- atomicshop/archiver/sevenz_app_w.py +0 -86
- atomicshop/archiver/sevenzs.py +0 -73
- atomicshop/archiver/shutils.py +0 -34
- atomicshop/archiver/zips.py +0 -353
- atomicshop/file_types.py +0 -24
- atomicshop/pbtkmultifile_argparse.py +0 -88
- atomicshop/script_as_string_processor.py +0 -42
- atomicshop/ssh_scripts/process_from_ipv4.py +0 -37
- atomicshop/ssh_scripts/process_from_port.py +0 -27
- atomicshop/wrappers/_process_wrapper_curl.py +0 -27
- atomicshop/wrappers/_process_wrapper_tar.py +0 -21
- atomicshop/wrappers/dockerw/install_docker.py +0 -449
- atomicshop/wrappers/elasticsearchw/install_elastic.py +0 -233
- atomicshop/wrappers/ffmpegw.py +0 -125
- atomicshop/wrappers/fibratusw/__init__.py +0 -0
- atomicshop/wrappers/fibratusw/install.py +0 -80
- atomicshop/wrappers/mongodbw/install_mongodb_ubuntu.py +0 -100
- atomicshop/wrappers/mongodbw/install_mongodb_win.py +0 -244
- atomicshop/wrappers/process_wrapper_pbtk.py +0 -16
- atomicshop/wrappers/socketw/get_process.py +0 -123
- atomicshop/wrappers/wslw.py +0 -192
- atomicshop-3.3.8.dist-info/entry_points.txt +0 -2
- /atomicshop/{addons → a_mains/addons}/PlayWrightCodegen.cmd +0 -0
- /atomicshop/{addons → a_mains/addons}/ScriptExecution.cmd +0 -0
- /atomicshop/{addons → a_mains/addons}/inits/init_to_import_all_modules.py +0 -0
- /atomicshop/{addons → a_mains/addons}/process_list/ReadMe.txt +0 -0
- /atomicshop/{addons → a_mains/addons}/process_list/compile.cmd +0 -0
- /atomicshop/{addons → a_mains/addons}/process_list/compiled/Win10x64/process_list.dll +0 -0
- /atomicshop/{addons → a_mains/addons}/process_list/compiled/Win10x64/process_list.exp +0 -0
- /atomicshop/{addons → a_mains/addons}/process_list/compiled/Win10x64/process_list.lib +0 -0
- /atomicshop/{addons → a_mains/addons}/process_list/process_list.cpp +0 -0
- {atomicshop-3.3.8.dist-info → atomicshop-3.10.0.dist-info}/WHEEL +0 -0
- {atomicshop-3.3.8.dist-info → atomicshop-3.10.0.dist-info}/licenses/LICENSE.txt +0 -0
- {atomicshop-3.3.8.dist-info → atomicshop-3.10.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import subprocess
|
|
2
|
+
import winreg
|
|
3
|
+
|
|
4
|
+
from ..print_api import print_api
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
AUDITING_REG_PATH: str = r"Software\Microsoft\Windows\CurrentVersion\Policies\System\Audit"
|
|
8
|
+
PROCESS_CREATION_INCLUDE_CMDLINE_VALUE: str = "ProcessCreationIncludeCmdLine_Enabled"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def enable_command_line_auditing(print_kwargs: dict = None):
|
|
12
|
+
"""
|
|
13
|
+
Enable the 'Include command line in process creation events' policy.
|
|
14
|
+
|
|
15
|
+
reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\Audit" /v ProcessCreationIncludeCmdLine_Enabled /t REG_DWORD /d 1 /f
|
|
16
|
+
|
|
17
|
+
:param print_kwargs: Optional keyword arguments for the print function.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
if is_command_line_auditing_enabled():
|
|
21
|
+
print_api(
|
|
22
|
+
"[Include command line in process creation events] is already enabled.", color='blue',
|
|
23
|
+
**(print_kwargs or {}))
|
|
24
|
+
return
|
|
25
|
+
|
|
26
|
+
try:
|
|
27
|
+
# Open the registry key
|
|
28
|
+
with winreg.CreateKey(winreg.HKEY_LOCAL_MACHINE, AUDITING_REG_PATH) as reg_key:
|
|
29
|
+
# Set the value
|
|
30
|
+
winreg.SetValueEx(reg_key, PROCESS_CREATION_INCLUDE_CMDLINE_VALUE, 0, winreg.REG_DWORD, 1)
|
|
31
|
+
|
|
32
|
+
print_api(
|
|
33
|
+
"Successfully enabled [Include command line in process creation events].",
|
|
34
|
+
color='green', **(print_kwargs or {}))
|
|
35
|
+
except WindowsError as e:
|
|
36
|
+
print_api(
|
|
37
|
+
f"Failed to enable [Include command line in process creation events]: {e}", error_type=True,
|
|
38
|
+
color='red', **(print_kwargs or {}))
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def is_command_line_auditing_enabled():
|
|
42
|
+
try:
|
|
43
|
+
# Open the registry key
|
|
44
|
+
with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, AUDITING_REG_PATH, 0, winreg.KEY_READ) as reg_key:
|
|
45
|
+
# Query the value
|
|
46
|
+
value, reg_type = winreg.QueryValueEx(reg_key, PROCESS_CREATION_INCLUDE_CMDLINE_VALUE)
|
|
47
|
+
# Check if the value is 1 (enabled)
|
|
48
|
+
return value == 1
|
|
49
|
+
except FileNotFoundError:
|
|
50
|
+
# Key or value not found, assume it's not enabled
|
|
51
|
+
return False
|
|
52
|
+
except WindowsError as e:
|
|
53
|
+
print(f"Failed to read the 'Include command line in process creation events' setting: {e}")
|
|
54
|
+
return False
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def enable_audit_process_creation(print_kwargs: dict = None):
|
|
58
|
+
"""
|
|
59
|
+
Enable the 'Audit Process Creation' policy.
|
|
60
|
+
Log: Security
|
|
61
|
+
Event ID: 4688 - A new process has been created.
|
|
62
|
+
|
|
63
|
+
auditpol /set /subcategory:"Process Creation" /success:enable /failure:enable
|
|
64
|
+
|
|
65
|
+
:param print_kwargs: Optional keyword arguments for the print function.
|
|
66
|
+
"""
|
|
67
|
+
if is_audit_process_creation_enabled():
|
|
68
|
+
print_api("Audit Process Creation is already enabled.", color='blue', **(print_kwargs or {}))
|
|
69
|
+
return
|
|
70
|
+
|
|
71
|
+
# Enable "Audit Process Creation" policy
|
|
72
|
+
audit_policy_command = [
|
|
73
|
+
"auditpol", "/set", "/subcategory:Process Creation", "/success:enable", "/failure:enable"
|
|
74
|
+
]
|
|
75
|
+
try:
|
|
76
|
+
subprocess.run(audit_policy_command, check=True)
|
|
77
|
+
print_api("Successfully enabled 'Audit Process Creation'.", color='green', **(print_kwargs or {}))
|
|
78
|
+
except subprocess.CalledProcessError as e:
|
|
79
|
+
print_api(f"Failed to enable 'Audit Process Creation': {e}", error_type=True, color='red', **(print_kwargs or {}))
|
|
80
|
+
raise e
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def is_audit_process_creation_enabled(print_kwargs: dict = None) -> bool:
|
|
84
|
+
"""
|
|
85
|
+
Check if the 'Audit Process Creation' policy is enabled.
|
|
86
|
+
|
|
87
|
+
:param print_kwargs: Optional keyword arguments for the print function.
|
|
88
|
+
"""
|
|
89
|
+
# Command to check the "Audit Process Creation" policy
|
|
90
|
+
audit_policy_check_command = [
|
|
91
|
+
"auditpol", "/get", "/subcategory:Process Creation"
|
|
92
|
+
]
|
|
93
|
+
try:
|
|
94
|
+
result = subprocess.run(audit_policy_check_command, check=True, capture_output=True, text=True)
|
|
95
|
+
output = result.stdout
|
|
96
|
+
# print_api(output) # Print the output for inspection
|
|
97
|
+
|
|
98
|
+
if "Process Creation" in output and "Success and Failure" in output:
|
|
99
|
+
# print_api(
|
|
100
|
+
# "'Audit Process Creation' is enabled for both success and failure.",
|
|
101
|
+
# color='green', **(print_kwargs or {}))
|
|
102
|
+
return True
|
|
103
|
+
else:
|
|
104
|
+
# print_api(output, **(print_kwargs or {}))
|
|
105
|
+
# print_api(
|
|
106
|
+
# "'Audit Process Creation' is not fully enabled. Check the output above for details.",
|
|
107
|
+
# color='yellow', **(print_kwargs or {}))
|
|
108
|
+
return False
|
|
109
|
+
except subprocess.CalledProcessError as e:
|
|
110
|
+
print_api(f"Failed to check 'Audit Process Creation': {e}", color='red', error_type=True, **(print_kwargs or {}))
|
|
111
|
+
return False
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def enable_audit_process_termination(print_kwargs: dict = None):
|
|
115
|
+
"""
|
|
116
|
+
Enable the 'Audit Process Termination' policy.
|
|
117
|
+
|
|
118
|
+
:param print_kwargs: Optional keyword arguments for the print function.
|
|
119
|
+
"""
|
|
120
|
+
if is_audit_process_termination_enabled():
|
|
121
|
+
print_api("Audit Process Termination is already enabled.", color='blue', **(print_kwargs or {}))
|
|
122
|
+
return
|
|
123
|
+
|
|
124
|
+
audit_policy_command = [
|
|
125
|
+
"auditpol", "/set", "/subcategory:Process Termination", "/success:enable", "/failure:enable"
|
|
126
|
+
]
|
|
127
|
+
try:
|
|
128
|
+
subprocess.run(audit_policy_command, check=True)
|
|
129
|
+
print_api("Successfully enabled 'Audit Process Termination'.", color='green', **(print_kwargs or {}))
|
|
130
|
+
except subprocess.CalledProcessError as e:
|
|
131
|
+
print_api(f"Failed to enable 'Audit Process Termination': {e}", error_type=True, color='red', **(print_kwargs or {}))
|
|
132
|
+
raise e
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def is_audit_process_termination_enabled(print_kwargs: dict = None) -> bool:
|
|
136
|
+
"""
|
|
137
|
+
Check if the 'Audit Process Termination' policy is enabled.
|
|
138
|
+
|
|
139
|
+
:param print_kwargs: Optional keyword arguments for the print function.
|
|
140
|
+
"""
|
|
141
|
+
# Command to check the "Audit Process Creation" policy
|
|
142
|
+
audit_policy_check_command = [
|
|
143
|
+
"auditpol", "/get", "/subcategory:Process Termination"
|
|
144
|
+
]
|
|
145
|
+
try:
|
|
146
|
+
result = subprocess.run(audit_policy_check_command, check=True, capture_output=True, text=True)
|
|
147
|
+
output = result.stdout
|
|
148
|
+
# print_api(output) # Print the output for inspection
|
|
149
|
+
|
|
150
|
+
if "Process Termination" in output and "Success and Failure" in output:
|
|
151
|
+
# print_api(
|
|
152
|
+
# "'Audit Process Termination' is enabled for both success and failure.",
|
|
153
|
+
# color='green', **(print_kwargs or {}))
|
|
154
|
+
return True
|
|
155
|
+
else:
|
|
156
|
+
# print_api(output, **(print_kwargs or {}))
|
|
157
|
+
# print_api(
|
|
158
|
+
# "'Audit Process Termination' is not fully enabled. Check the output above for details.",
|
|
159
|
+
# color='yellow', **(print_kwargs or {}))
|
|
160
|
+
return False
|
|
161
|
+
except subprocess.CalledProcessError as e:
|
|
162
|
+
print_api(f"Failed to check 'Audit Process Termination': {e}", color='red', error_type=True, **(print_kwargs or {}))
|
|
163
|
+
return False
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def enable_audit_filtering_platform_connection(print_kwargs: dict = None):
|
|
167
|
+
"""
|
|
168
|
+
Enable the 'Filtering Platform Connection' policy.
|
|
169
|
+
This enables you to fetch connection creations and deletions from the Windows Security Event Log.
|
|
170
|
+
Log: Security
|
|
171
|
+
Event IDs:
|
|
172
|
+
5156 - The Windows Filtering Platform has permitted a connection.
|
|
173
|
+
5158 - The Windows Filtering Platform has blocked a connection.
|
|
174
|
+
Events include information about source and destination IP addresses and ports.
|
|
175
|
+
|
|
176
|
+
auditpol /set /subcategory:"Filtering Platform Connection" /success:enable /failure:enable
|
|
177
|
+
|
|
178
|
+
:param print_kwargs: Optional keyword arguments for the print function.
|
|
179
|
+
"""
|
|
180
|
+
|
|
181
|
+
audit_policy_command = [
|
|
182
|
+
"auditpol", "/set", '/subcategory:"Filtering Platform Connection"', "/success:enable", "/failure:enable"
|
|
183
|
+
]
|
|
184
|
+
try:
|
|
185
|
+
subprocess.run(audit_policy_command, check=True)
|
|
186
|
+
print_api("Successfully enabled 'Audit Filtering Platform Connection'.", color='green', **(print_kwargs or {}))
|
|
187
|
+
except subprocess.CalledProcessError as e:
|
|
188
|
+
print_api(f"Failed to enable 'Audit Filtering Platform Connection': {e}", error_type=True, color='red', **(print_kwargs or {}))
|
|
189
|
+
raise e
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: atomicshop
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.10.0
|
|
4
4
|
Summary: Atomic functions and classes to make developer life easier
|
|
5
5
|
Author: Denis Kras
|
|
6
6
|
License-Expression: MIT
|
|
@@ -8,44 +8,39 @@ Project-URL: Homepage, https://github.com/BugSec-Official/atomicshop
|
|
|
8
8
|
Classifier: Intended Audience :: Developers
|
|
9
9
|
Classifier: Programming Language :: Python :: 3
|
|
10
10
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
11
|
-
Requires-Python:
|
|
11
|
+
Requires-Python: <3.14,>=3.12
|
|
12
12
|
Description-Content-Type: text/markdown
|
|
13
13
|
License-File: LICENSE.txt
|
|
14
14
|
Requires-Dist: wheel
|
|
15
|
-
Requires-Dist:
|
|
16
|
-
Requires-Dist:
|
|
15
|
+
Requires-Dist: setuptools
|
|
16
|
+
Requires-Dist: beautifulsoup4==4.14.3
|
|
17
|
+
Requires-Dist: cryptography==46.0.3
|
|
18
|
+
Requires-Dist: dkarchiver==1.0.1
|
|
17
19
|
Requires-Dist: dkinst
|
|
18
|
-
Requires-Dist: dnslib
|
|
19
|
-
Requires-Dist: dnspython
|
|
20
|
-
Requires-Dist: docker
|
|
21
|
-
Requires-Dist: flask_socketio
|
|
22
|
-
Requires-Dist: google-api-python-client
|
|
23
|
-
Requires-Dist: google-
|
|
24
|
-
Requires-Dist: icmplib
|
|
20
|
+
Requires-Dist: dnslib==0.9.26
|
|
21
|
+
Requires-Dist: dnspython==2.8.0
|
|
22
|
+
Requires-Dist: docker==7.1.0
|
|
23
|
+
Requires-Dist: flask_socketio==5.5.1
|
|
24
|
+
Requires-Dist: google-api-python-client==2.187.0
|
|
25
|
+
Requires-Dist: google-genai==1.53.0
|
|
26
|
+
Requires-Dist: icmplib==3.0.4
|
|
25
27
|
Requires-Dist: numpy
|
|
26
|
-
Requires-Dist: olefile
|
|
27
|
-
Requires-Dist: openpyxl
|
|
28
|
-
Requires-Dist: pandas
|
|
29
|
-
Requires-Dist: paramiko
|
|
30
|
-
Requires-Dist: pefile
|
|
31
|
-
Requires-Dist: playwright
|
|
32
|
-
Requires-Dist:
|
|
33
|
-
Requires-Dist:
|
|
34
|
-
Requires-Dist:
|
|
35
|
-
Requires-Dist: pyautogui
|
|
36
|
-
Requires-Dist: pymongo
|
|
37
|
-
Requires-Dist: pyopenssl
|
|
38
|
-
Requires-Dist: python-bidi
|
|
28
|
+
Requires-Dist: olefile==0.47
|
|
29
|
+
Requires-Dist: openpyxl==3.1.5
|
|
30
|
+
Requires-Dist: pandas==2.3.3
|
|
31
|
+
Requires-Dist: paramiko==4.0.0
|
|
32
|
+
Requires-Dist: pefile==2024.8.26
|
|
33
|
+
Requires-Dist: playwright==1.56.0
|
|
34
|
+
Requires-Dist: psutil==7.1.3
|
|
35
|
+
Requires-Dist: pymongo==4.15.5
|
|
36
|
+
Requires-Dist: pyopenssl==25.3.0
|
|
39
37
|
Requires-Dist: python-docx
|
|
40
|
-
Requires-Dist:
|
|
41
|
-
Requires-Dist: pywin32; platform_system == "Windows"
|
|
42
|
-
Requires-Dist: reportlab
|
|
43
|
-
Requires-Dist: setuptools
|
|
38
|
+
Requires-Dist: pywin32==311; platform_system == "Windows"
|
|
44
39
|
Requires-Dist: SoundCard
|
|
45
40
|
Requires-Dist: soundfile
|
|
46
41
|
Requires-Dist: SpeechRecognition
|
|
47
|
-
Requires-Dist: tldextract
|
|
48
|
-
Requires-Dist: websockets
|
|
42
|
+
Requires-Dist: tldextract==5.3.0
|
|
43
|
+
Requires-Dist: websockets==15.0.1
|
|
49
44
|
Dynamic: license-file
|
|
50
45
|
|
|
51
46
|
<h1 align="center">Atomic Workshop</h1>
|