atomicshop 3.3.28__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 +18 -43
- atomicshop/mitm/connection_thread_worker.py +376 -162
- 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 +79 -88
- atomicshop/mitm/initialize_engines.py +1 -2
- atomicshop/mitm/message.py +5 -4
- atomicshop/mitm/mitm_main.py +222 -121
- atomicshop/mitm/recs_files.py +61 -5
- atomicshop/mitm/ssh_tester.py +82 -0
- atomicshop/networks.py +108 -93
- atomicshop/package_mains_processor.py +84 -0
- atomicshop/permissions/ubuntu_permissions.py +47 -0
- atomicshop/print_api.py +3 -5
- atomicshop/python_functions.py +23 -108
- atomicshop/speech_recognize.py +8 -0
- atomicshop/ssh_remote.py +115 -51
- atomicshop/web.py +20 -7
- 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/factw/install/pre_install_and_install_before_restart.py +5 -5
- atomicshop/wrappers/githubw.py +175 -63
- atomicshop/wrappers/loggingw/handlers.py +1 -1
- atomicshop/wrappers/loggingw/loggingw.py +17 -1
- 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 +30 -7
- atomicshop/wrappers/socketw/dns_server.py +6 -6
- atomicshop/wrappers/socketw/exception_wrapper.py +3 -3
- 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 +23 -6
- atomicshop/wrappers/socketw/{base.py → socket_base.py} +33 -1
- atomicshop/wrappers/socketw/socket_client.py +6 -8
- atomicshop/wrappers/socketw/socket_wrapper.py +82 -21
- atomicshop/wrappers/socketw/ssl_base.py +6 -2
- atomicshop/wrappers/win_auditw.py +189 -0
- {atomicshop-3.3.28.dist-info → atomicshop-3.10.0.dist-info}/METADATA +25 -30
- {atomicshop-3.3.28.dist-info → atomicshop-3.10.0.dist-info}/RECORD +74 -88
- 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/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/ffmpegw.py +0 -125
- atomicshop/wrappers/process_wrapper_pbtk.py +0 -16
- atomicshop/wrappers/socketw/get_process.py +0 -123
- /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.28.dist-info → atomicshop-3.10.0.dist-info}/WHEEL +0 -0
- {atomicshop-3.3.28.dist-info → atomicshop-3.10.0.dist-info}/licenses/LICENSE.txt +0 -0
- {atomicshop-3.3.28.dist-info → atomicshop-3.10.0.dist-info}/top_level.txt +0 -0
atomicshop/python_functions.py
CHANGED
|
@@ -4,7 +4,7 @@ from typing import Union
|
|
|
4
4
|
from .print_api import print_api
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
def
|
|
7
|
+
def get_python_version_string() -> str:
|
|
8
8
|
"""
|
|
9
9
|
Function gets version MAJOR.MINOR.MICRO from 'sys.version_info' object and returns it as a string.
|
|
10
10
|
:return: python MAJOR.MINOR.MICRO version string.
|
|
@@ -13,120 +13,35 @@ def get_current_python_version_string() -> str:
|
|
|
13
13
|
return f'{sys.version_info[0]}.{sys.version_info[1]}.{sys.version_info[2]}'
|
|
14
14
|
|
|
15
15
|
|
|
16
|
-
# noinspection PyUnusedLocal
|
|
17
|
-
def check_if_version_object_is_tuple_or_string(version_object: any,
|
|
18
|
-
**kwargs) -> tuple:
|
|
19
|
-
"""
|
|
20
|
-
Function checks if 'version_object' that was passed is tuple or string.
|
|
21
|
-
If it's tuple then returns it back. If it's string, converts to tuple then returns it.
|
|
22
|
-
If the object is none of the above, returns None.
|
|
23
|
-
|
|
24
|
-
:param version_object: Can be string ('3.10') or tuple of integers ((3, 10)).
|
|
25
|
-
:return:
|
|
26
|
-
"""
|
|
27
|
-
# Check if tuple was passed.
|
|
28
|
-
if isinstance(version_object, tuple):
|
|
29
|
-
return version_object
|
|
30
|
-
else:
|
|
31
|
-
# Then check if a string was passed.
|
|
32
|
-
if isinstance(version_object, str):
|
|
33
|
-
# The check will be against tuple of integers, so we'll convert a string to tuple of integers.
|
|
34
|
-
return tuple(map(int, version_object.split('.')))
|
|
35
|
-
else:
|
|
36
|
-
message = f'[*] Function: [check_if_version_object_is_tuple_or_string]\n' \
|
|
37
|
-
f'[*] [version_object] object passed is not tuple or string.\n' \
|
|
38
|
-
f'[*] Object type: {type(version_object)}\n' \
|
|
39
|
-
f'[*] Object content {version_object}\n' \
|
|
40
|
-
f'Exiting...'
|
|
41
|
-
print_api(message, error_type=True, logger_method='critical', **kwargs)
|
|
42
|
-
|
|
43
|
-
return None
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
# noinspection PyUnusedLocal
|
|
47
16
|
def check_python_version_compliance(
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
**kwargs
|
|
52
|
-
) -> bool:
|
|
17
|
+
min_ver: tuple = None,
|
|
18
|
+
max_ver: tuple = None,
|
|
19
|
+
) -> str | None:
|
|
53
20
|
"""
|
|
54
21
|
Python version check. Should be executed before importing external libraries, since they depend on Python version.
|
|
55
22
|
|
|
56
|
-
:param
|
|
57
|
-
:param
|
|
23
|
+
:param min_ver: tuple of integers (3, 10).
|
|
24
|
+
:param max_ver: tuple of integers (3, 10).
|
|
58
25
|
If maximum version is not specified, it will be considered as all versions above the minimum are compliant.
|
|
59
|
-
:
|
|
60
|
-
If minor version is specified, it will be considered as all the versions with the same major, minor version
|
|
61
|
-
are compliant. Example: if minor_version is '3.10', then all the versions with '3.10.x' are compliant.
|
|
62
|
-
:return:
|
|
26
|
+
:return: If version is not compliant, returns string with error message. Otherwise, returns None.
|
|
63
27
|
"""
|
|
64
28
|
|
|
65
|
-
if not
|
|
29
|
+
if not min_ver and not max_ver:
|
|
66
30
|
raise ValueError("At least one of the version parameters should be passed.")
|
|
67
31
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
# If 'minor_version' object was passed, check it for string or tuple and get the tuple.
|
|
83
|
-
if minor_version:
|
|
84
|
-
minor_version_scheme: tuple = check_if_version_object_is_tuple_or_string(minor_version, **kwargs)
|
|
32
|
+
current_version_info: tuple = sys.version_info[:3]
|
|
33
|
+
if min_ver and not max_ver:
|
|
34
|
+
if current_version_info < min_ver:
|
|
35
|
+
return f'Python version {".".join(map(str, min_ver))} or higher is required. '\
|
|
36
|
+
f'Current version is {".".join(map(str, current_version_info))}.'
|
|
37
|
+
elif max_ver and not min_ver:
|
|
38
|
+
if current_version_info > max_ver:
|
|
39
|
+
return f'Python version up to {".".join(map(str, max_ver))} is required. '\
|
|
40
|
+
f'Current version is {".".join(map(str, current_version_info))}.'
|
|
41
|
+
elif min_ver and max_ver:
|
|
42
|
+
if not (min_ver <= current_version_info <= max_ver):
|
|
43
|
+
return f'Python version between {".".join(map(str, min_ver))} and '\
|
|
44
|
+
f'{".".join(map(str, max_ver))} is required. '\
|
|
45
|
+
f'Current version is {".".join(map(str, current_version_info))}.'
|
|
85
46
|
else:
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
# Get current python version.
|
|
89
|
-
python_version_full: str = get_current_python_version_string()
|
|
90
|
-
|
|
91
|
-
message = f"[*] Current Python Version: {python_version_full}"
|
|
92
|
-
print_api(message, logger_method='info', **kwargs)
|
|
93
|
-
|
|
94
|
-
if minor_version_scheme:
|
|
95
|
-
# Check if current python version is later or equals to the minimum required version.
|
|
96
|
-
if sys.version_info[:2] != minor_version_scheme:
|
|
97
|
-
message = f"[!!!] YOU NEED TO INSTALL ANY PYTHON " \
|
|
98
|
-
f"[{'.'.join(str(i) for i in minor_version_scheme)}] version, " \
|
|
99
|
-
f"to work properly."
|
|
100
|
-
print_api(message, error_type=True, logger_method='critical', **kwargs)
|
|
101
|
-
|
|
102
|
-
return False
|
|
103
|
-
elif minimum_version_scheme and maximum_version_scheme:
|
|
104
|
-
if not sys.version_info >= minimum_version_scheme or not sys.version_info < maximum_version_scheme:
|
|
105
|
-
message = f"[!!!] YOU NEED TO INSTALL AT LEAST PYTHON " \
|
|
106
|
-
f"[{'.'.join(str(i) for i in minimum_version_scheme)}], " \
|
|
107
|
-
f"AND EARLIER THAN [{'.'.join(str(i) for i in maximum_version_scheme)}], " \
|
|
108
|
-
f"to work properly."
|
|
109
|
-
print_api(message, error_type=True, logger_method='critical', **kwargs)
|
|
110
|
-
|
|
111
|
-
return False
|
|
112
|
-
elif minimum_version_scheme and not maximum_version_scheme:
|
|
113
|
-
if not sys.version_info >= minimum_version_scheme:
|
|
114
|
-
message = f"[!!!] YOU NEED TO INSTALL AT LEAST PYTHON " \
|
|
115
|
-
f"[{'.'.join(str(i) for i in minimum_version_scheme)}], " \
|
|
116
|
-
f"to work properly."
|
|
117
|
-
print_api(message, error_type=True, logger_method='critical', **kwargs)
|
|
118
|
-
|
|
119
|
-
return False
|
|
120
|
-
elif not minimum_version_scheme and maximum_version_scheme:
|
|
121
|
-
if not sys.version_info < maximum_version_scheme:
|
|
122
|
-
message = f"[!!!] YOU NEED TO INSTALL EARLIER THAN PYTHON " \
|
|
123
|
-
f"[{'.'.join(str(i) for i in maximum_version_scheme)}], " \
|
|
124
|
-
f"to work properly."
|
|
125
|
-
print_api(message, error_type=True, logger_method='critical', **kwargs)
|
|
126
|
-
|
|
127
|
-
return False
|
|
128
|
-
|
|
129
|
-
message = "[*] Version Check PASSED."
|
|
130
|
-
print_api(message, logger_method='info', **kwargs)
|
|
131
|
-
|
|
132
|
-
return True
|
|
47
|
+
return None
|
atomicshop/speech_recognize.py
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
# TODO: Change manual wrapper to:
|
|
2
|
+
# from ffmpy import FFmpeg
|
|
3
|
+
# ff = FFmpeg(
|
|
4
|
+
# inputs={'input.mp4': None},
|
|
5
|
+
# outputs={'output.avi': None}
|
|
6
|
+
# )
|
|
7
|
+
# ff.run()
|
|
8
|
+
|
|
1
9
|
from .wrappers.ffmpegw import FFmpegWrapper
|
|
2
10
|
from .tempfiles import TempFile
|
|
3
11
|
from .web import download
|
atomicshop/ssh_remote.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import sys
|
|
2
|
-
import base64
|
|
3
2
|
import logging
|
|
4
3
|
from pathlib import Path
|
|
4
|
+
import shlex
|
|
5
5
|
|
|
6
6
|
try:
|
|
7
7
|
import paramiko
|
|
@@ -11,7 +11,12 @@ except ImportError as exception_object:
|
|
|
11
11
|
|
|
12
12
|
from .print_api import print_api
|
|
13
13
|
from .wrappers.loggingw import loggingw
|
|
14
|
-
from .wrappers.socketw import
|
|
14
|
+
from .wrappers.socketw import socket_base
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class SSHRemoteWrapperNoPythonFound(Exception):
|
|
18
|
+
"""Raised when no usable Python 3 interpreter found on remote host."""
|
|
19
|
+
pass
|
|
15
20
|
|
|
16
21
|
|
|
17
22
|
class SSHRemote:
|
|
@@ -100,17 +105,23 @@ class SSHRemote:
|
|
|
100
105
|
# Initializing paramiko SSHClient class
|
|
101
106
|
self.ssh_client = paramiko.SSHClient()
|
|
102
107
|
|
|
108
|
+
# Variable to store detected python command on remote (python3 / python).
|
|
109
|
+
self.python_cmd: str | None = None
|
|
110
|
+
|
|
103
111
|
if logger:
|
|
104
112
|
# Create child logger for the provided logger with the module's name.
|
|
105
113
|
self.logger: logging.Logger = loggingw.get_logger_with_level(f'{logger.name}.{Path(__file__).stem}')
|
|
106
114
|
else:
|
|
107
115
|
self.logger: logging.Logger = logger
|
|
108
116
|
|
|
109
|
-
def connect(
|
|
117
|
+
def connect(
|
|
118
|
+
self,
|
|
119
|
+
timeout: int = 60
|
|
120
|
+
):
|
|
110
121
|
error: str = str()
|
|
111
122
|
|
|
112
123
|
# Get all local interfaces IPv4 addresses.
|
|
113
|
-
local_interfaces_ipv4 =
|
|
124
|
+
local_interfaces_ipv4 = socket_base.get_local_network_interfaces_ip_address("ipv4", True)
|
|
114
125
|
# Check if the target IP address is in the list of local interfaces.
|
|
115
126
|
if self.ip_address in local_interfaces_ipv4:
|
|
116
127
|
# If it is, we don't need to connect to it via SSH, it means that we want to connect to ourselves.
|
|
@@ -130,7 +141,7 @@ class SSHRemote:
|
|
|
130
141
|
self.ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
|
131
142
|
|
|
132
143
|
# Executing SSH connection to client.
|
|
133
|
-
self.ssh_client.connect(self.ip_address, username=self.username, password=self.password, timeout=
|
|
144
|
+
self.ssh_client.connect(self.ip_address, username=self.username, password=self.password, timeout=timeout)
|
|
134
145
|
|
|
135
146
|
return error
|
|
136
147
|
|
|
@@ -151,17 +162,50 @@ class SSHRemote:
|
|
|
151
162
|
if "ModuleNotFoundError: No module named" in line:
|
|
152
163
|
function_result = f"Python library is not installed - {line}"
|
|
153
164
|
break
|
|
165
|
+
else:
|
|
166
|
+
function_result = console_output_string
|
|
154
167
|
|
|
155
168
|
return function_result
|
|
156
169
|
|
|
157
|
-
def remote_execution(
|
|
170
|
+
def remote_execution(
|
|
171
|
+
self,
|
|
172
|
+
command: str,
|
|
173
|
+
script_string: str = None
|
|
174
|
+
) -> tuple[str, str]:
|
|
175
|
+
"""
|
|
176
|
+
Function to execute any command over SSH.
|
|
177
|
+
|
|
178
|
+
:param command: command to execute over SSH.
|
|
179
|
+
:param script_string: string representation of script to execute as input.
|
|
180
|
+
Example:
|
|
181
|
+
command = "python - 56734"
|
|
182
|
+
script_string = "import sys;print(f'sys.argv[0]')"
|
|
183
|
+
|
|
184
|
+
Under ssh in terminal it would execute like this:
|
|
185
|
+
ssh User@HostIpv4
|
|
186
|
+
|
|
187
|
+
python - 56734 << EOF
|
|
188
|
+
import sys;print(f'sys.argv[0]')
|
|
189
|
+
EOF
|
|
190
|
+
|
|
191
|
+
Or as onliner:
|
|
192
|
+
ssh User@HostIpv4 "python - 56734 << EOF import sys;print(f'sys.argv[0]') EOF"
|
|
193
|
+
|
|
194
|
+
or using a specific file path:
|
|
195
|
+
ssh User@HostIpv4 "python - 56734" < /path/to/script.py
|
|
196
|
+
|
|
197
|
+
:return: SSH console output, Error output
|
|
198
|
+
"""
|
|
158
199
|
output_result: str = str()
|
|
159
200
|
error_result: str = str()
|
|
160
201
|
|
|
161
202
|
# Execute the command over SSH remotely.
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
203
|
+
stdin, stdout, stderr = self.ssh_client.exec_command(command=command, timeout=30)
|
|
204
|
+
|
|
205
|
+
# Writing the script string into stdin buffer.
|
|
206
|
+
if script_string:
|
|
207
|
+
stdin.write(script_string)
|
|
208
|
+
stdin.channel.shutdown_write()
|
|
165
209
|
|
|
166
210
|
# Reading the buffer of stdout.
|
|
167
211
|
output_lines: list = stdout.readlines()
|
|
@@ -182,53 +226,68 @@ class SSHRemote:
|
|
|
182
226
|
|
|
183
227
|
return output_result, error_result
|
|
184
228
|
|
|
185
|
-
def
|
|
229
|
+
def _detect_remote_python_cmd_name(self) -> str:
|
|
186
230
|
"""
|
|
187
|
-
|
|
231
|
+
Try 'python3' then 'python' on the remote, return the one that is Python 3.
|
|
232
|
+
Raises if neither works.
|
|
233
|
+
"""
|
|
234
|
+
for candidate in ("python3", "python"):
|
|
235
|
+
# Use a simple version check that works on both Windows and Linux
|
|
236
|
+
cmd = f'{candidate} -c "import sys; print(sys.version_info[0])"'
|
|
237
|
+
stdin, stdout, stderr = self.ssh_client.exec_command(cmd, timeout=5)
|
|
238
|
+
|
|
239
|
+
out = stdout.read().decode().strip()
|
|
240
|
+
exit_status = stdout.channel.recv_exit_status()
|
|
188
241
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
# Execute the python script on remote computer over SSH.
|
|
209
|
-
remote_output, remote_error = ssh_client.remote_execution_python(script_string)
|
|
210
|
-
|
|
211
|
-
# If there was an error during execution, put it in process name.
|
|
212
|
-
if remote_error:
|
|
213
|
-
client_message.process_name = remote_error
|
|
214
|
-
# If there was no error during execution, put the output of the ssh to process name.
|
|
215
|
-
else:
|
|
216
|
-
client_message.process_name = remote_output
|
|
217
|
-
network.logger.info(f"Remote SSH: Client executing Command Line: {client_message.process_name}")
|
|
242
|
+
if exit_status == 0 and out == "3":
|
|
243
|
+
print_api(f"Detected remote Python 3 interpreter (once per client port): {candidate}", logger=self.logger)
|
|
244
|
+
return candidate
|
|
245
|
+
|
|
246
|
+
raise SSHRemoteWrapperNoPythonFound("No usable Python 3 interpreter found on remote host")
|
|
247
|
+
|
|
248
|
+
def _get_python_cmd(self) -> str:
|
|
249
|
+
if self.python_cmd is None:
|
|
250
|
+
self.python_cmd = self._detect_remote_python_cmd_name()
|
|
251
|
+
return self.python_cmd
|
|
252
|
+
|
|
253
|
+
def remote_execution_python(
|
|
254
|
+
self,
|
|
255
|
+
script_string: str,
|
|
256
|
+
script_arg_values: tuple = None,
|
|
257
|
+
script_kwargs: dict = None,
|
|
258
|
+
):
|
|
259
|
+
"""
|
|
260
|
+
Function to execute python script over SSH.
|
|
218
261
|
|
|
219
262
|
:param script_string: string representation of python script.
|
|
263
|
+
:param script_arg_values: values arguments to pass to the script. Example for first argument: 56734
|
|
264
|
+
:param script_kwargs: keyword arguments to pass to the script.
|
|
265
|
+
Example: {'-r': None}
|
|
266
|
+
Interpreted as: -r
|
|
267
|
+
Example: {'-f': 'value'}
|
|
268
|
+
Interpreted as: -f value
|
|
269
|
+
Example: {'--arg': value}
|
|
270
|
+
Interpreted as: --arg value
|
|
271
|
+
|
|
220
272
|
:return: SSH console output, Error output
|
|
221
273
|
"""
|
|
222
274
|
# Defining variables.
|
|
223
275
|
error_result: str | None = None
|
|
224
276
|
|
|
225
|
-
|
|
226
|
-
|
|
277
|
+
python_cmd = self._get_python_cmd()
|
|
278
|
+
command: str = f"{python_cmd} -"
|
|
227
279
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
280
|
+
if script_arg_values:
|
|
281
|
+
for arg in script_arg_values:
|
|
282
|
+
command += " " + shlex.quote(str(arg))
|
|
283
|
+
|
|
284
|
+
if script_kwargs:
|
|
285
|
+
for key, value in script_kwargs.items():
|
|
286
|
+
command += f" {shlex.quote(str(key))}"
|
|
287
|
+
if value is not None:
|
|
288
|
+
command += " " + shlex.quote(str(value))
|
|
289
|
+
|
|
290
|
+
remote_output, remote_error = self.remote_execution(command=command, script_string=script_string)
|
|
232
291
|
|
|
233
292
|
# If there was an error during remote execution
|
|
234
293
|
if remote_error:
|
|
@@ -238,10 +297,15 @@ class SSHRemote:
|
|
|
238
297
|
if console_check:
|
|
239
298
|
# 'execution_error' variable will be that full error.
|
|
240
299
|
error_result = console_check
|
|
300
|
+
else:
|
|
301
|
+
error_result = remote_error
|
|
241
302
|
|
|
242
303
|
return remote_output, error_result
|
|
243
304
|
|
|
244
|
-
def connect_get_client_commandline(
|
|
305
|
+
def connect_get_client_commandline(
|
|
306
|
+
self,
|
|
307
|
+
port: int,
|
|
308
|
+
script_string: str):
|
|
245
309
|
# Defining locals.
|
|
246
310
|
execution_output: str | None = None
|
|
247
311
|
|
|
@@ -249,18 +313,18 @@ class SSHRemote:
|
|
|
249
313
|
execution_error = self.connect()
|
|
250
314
|
# if there was an error, try to connect again.
|
|
251
315
|
if execution_error:
|
|
252
|
-
|
|
316
|
+
print_api("Retrying SSH Connection Initialization.", logger=self.logger, logger_method='info')
|
|
253
317
|
execution_error = self.connect()
|
|
254
318
|
|
|
255
319
|
# If there was still an error, we won't be executing the script. And the error will be passed to
|
|
256
320
|
# 'process_name'.
|
|
257
321
|
if not execution_error:
|
|
258
|
-
|
|
322
|
+
print_api("Executing SSH command to acquire the calling process.", logger=self.logger, logger_method='info')
|
|
259
323
|
|
|
260
|
-
execution_output, execution_error = self.remote_execution_python(script_string)
|
|
324
|
+
execution_output, execution_error = self.remote_execution_python(script_string=script_string, script_arg_values=(str(port),))
|
|
261
325
|
|
|
262
326
|
# Closing SSH connection at this stage.
|
|
263
327
|
self.close()
|
|
264
|
-
|
|
328
|
+
print_api("Acquired. Closed SSH connection.", logger=self.logger, logger_method='info')
|
|
265
329
|
|
|
266
330
|
return execution_output, execution_error
|
atomicshop/web.py
CHANGED
|
@@ -7,8 +7,8 @@ import http.client
|
|
|
7
7
|
|
|
8
8
|
# noinspection PyPackageRequirements
|
|
9
9
|
import certifi
|
|
10
|
+
from dkarchiver.arch_wrappers import zips
|
|
10
11
|
|
|
11
|
-
from .archiver import zips
|
|
12
12
|
from .urls import url_parser
|
|
13
13
|
from .file_io import file_io
|
|
14
14
|
from .wrappers.playwrightw import scenarios
|
|
@@ -18,10 +18,12 @@ from . import filesystem, print_api
|
|
|
18
18
|
# https://www.useragents.me/
|
|
19
19
|
# https://user-agents.net/
|
|
20
20
|
USER_AGENTS = {
|
|
21
|
-
'
|
|
21
|
+
'Chrome 111.0.0 Windows_10/11 x64':
|
|
22
22
|
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36',
|
|
23
|
-
'Chrome 132.0.0
|
|
24
|
-
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36'
|
|
23
|
+
'Chrome 132.0.0 Windows 10/11 x64':
|
|
24
|
+
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36',
|
|
25
|
+
'Chrome 142.0.0 Windows 10/11 x64':
|
|
26
|
+
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36'
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
|
|
@@ -75,7 +77,7 @@ def get_page_bytes(
|
|
|
75
77
|
raise ValueError('ERROR: [user_agent] specified and [chrome_user_agent] usage is [True]. Choose one.')
|
|
76
78
|
|
|
77
79
|
if chrome_user_agent:
|
|
78
|
-
user_agent = USER_AGENTS['
|
|
80
|
+
user_agent = USER_AGENTS['Chrome 142.0.0 Windows 10/11 x64']
|
|
79
81
|
|
|
80
82
|
if user_agent:
|
|
81
83
|
# Create a 'Request' object with the URL and user agent.
|
|
@@ -159,6 +161,7 @@ def download(
|
|
|
159
161
|
target_directory: str = None,
|
|
160
162
|
file_name: str = None,
|
|
161
163
|
headers: dict = None,
|
|
164
|
+
overwrite: bool = False,
|
|
162
165
|
# use_certifi_ca_repository: bool = False,
|
|
163
166
|
**kwargs
|
|
164
167
|
) -> str | None:
|
|
@@ -174,6 +177,9 @@ def download(
|
|
|
174
177
|
:param file_name: string, file name (example: file.zip) that you want the downloaded file to be saved as.
|
|
175
178
|
If not specified, the default filename from 'file_url' will be used.
|
|
176
179
|
:param headers: dictionary, HTTP headers to use when downloading the file.
|
|
180
|
+
:param overwrite: boolean, if True, the file will be overwritten if it already exists.
|
|
181
|
+
If False, the file will not be overwritten and the function will return None if the file already exists.
|
|
182
|
+
Default is False.
|
|
177
183
|
:param use_certifi_ca_repository: boolean, if True, the certifi CA store will be used for SSL context
|
|
178
184
|
instead of the system's default CA store.
|
|
179
185
|
:return: string, full file path of downloaded file. If download failed, 'None' will be returned.
|
|
@@ -201,6 +207,13 @@ def download(
|
|
|
201
207
|
# Build full path to file.
|
|
202
208
|
file_path: str = f'{target_directory}{os.sep}{file_name}'
|
|
203
209
|
|
|
210
|
+
if os.path.exists(file_path):
|
|
211
|
+
if overwrite:
|
|
212
|
+
print_api.print_api(f'File already exists: {file_path}. Overwriting...', **kwargs)
|
|
213
|
+
else:
|
|
214
|
+
print_api.print_api(f'File already exists: {file_path}. Skipping download.', **kwargs)
|
|
215
|
+
return file_path
|
|
216
|
+
|
|
204
217
|
print_api.print_api(f'Downloading: {file_url}', **kwargs)
|
|
205
218
|
print_api.print_api(f'To: {file_path}', **kwargs)
|
|
206
219
|
|
|
@@ -301,7 +314,7 @@ def download_and_extract_file(
|
|
|
301
314
|
Default is empty. If it is empty, then the filename will be extracted from 'file_url'.
|
|
302
315
|
:param target_directory: string, target directory where to save the file.
|
|
303
316
|
:param archive_remove_first_directory: boolean, sets if archive extract function will extract the archive without
|
|
304
|
-
first directory in the archive. Check reference in the 'extract_archive_with_zipfile' function.
|
|
317
|
+
first directory in the archive. Check reference in the 'dkarchiver.arch_wrappers.zips.extract_archive_with_zipfile' function.
|
|
305
318
|
:param headers: dictionary, HTTP headers to use when downloading the file.
|
|
306
319
|
:return:
|
|
307
320
|
"""
|
|
@@ -313,7 +326,7 @@ def download_and_extract_file(
|
|
|
313
326
|
# Extract the archive and remove the first directory.
|
|
314
327
|
zips.extract_archive_with_zipfile(
|
|
315
328
|
archive_path=f'{file_path}', extract_directory=target_directory,
|
|
316
|
-
remove_first_directory=archive_remove_first_directory
|
|
329
|
+
remove_first_directory=archive_remove_first_directory)
|
|
317
330
|
|
|
318
331
|
# Remove the archive file.
|
|
319
332
|
filesystem.remove_file(file_path=f'{file_path}', **kwargs)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import os
|
|
2
1
|
from typing import Literal
|
|
3
2
|
|
|
4
|
-
|
|
3
|
+
from google import genai
|
|
4
|
+
from google.genai.types import GenerateContentConfig
|
|
5
5
|
|
|
6
6
|
from . import google_custom_search
|
|
7
7
|
from ..wrappers.playwrightw import scenarios
|
|
@@ -11,6 +11,14 @@ from .. import urls
|
|
|
11
11
|
class GoogleCustomSearchError(Exception):
|
|
12
12
|
pass
|
|
13
13
|
|
|
14
|
+
class GoogleLLMNoContentError(Exception):
|
|
15
|
+
pass
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
"""
|
|
19
|
+
Rate Limits and Quotas: https://ai.google.dev/gemini-api/docs/rate-limits
|
|
20
|
+
"""
|
|
21
|
+
|
|
14
22
|
|
|
15
23
|
class GoogleLLM:
|
|
16
24
|
def __init__(
|
|
@@ -26,13 +34,10 @@ class GoogleLLM:
|
|
|
26
34
|
:param search_engine_id: str, the search engine ID for the Google Custom Search API.
|
|
27
35
|
"""
|
|
28
36
|
|
|
29
|
-
self.
|
|
37
|
+
self.client = genai.Client(api_key=llm_api_key)
|
|
30
38
|
self.search_api_key: str = search_api_key
|
|
31
39
|
self.search_engine_id: str = search_engine_id
|
|
32
40
|
|
|
33
|
-
os.environ["API_KEY"] = llm_api_key
|
|
34
|
-
genai.configure(api_key=os.environ["API_KEY"])
|
|
35
|
-
|
|
36
41
|
def get_current_models(
|
|
37
42
|
self,
|
|
38
43
|
full_info: bool = False
|
|
@@ -43,7 +48,7 @@ class GoogleLLM:
|
|
|
43
48
|
:param full_info: bool, if True, returns the full information about the models, otherwise only the names for API usage.
|
|
44
49
|
"""
|
|
45
50
|
result_list: list = []
|
|
46
|
-
for model in self.
|
|
51
|
+
for model in self.client.models.list():
|
|
47
52
|
if full_info:
|
|
48
53
|
result_list.append(model)
|
|
49
54
|
else:
|
|
@@ -68,7 +73,7 @@ class GoogleLLM:
|
|
|
68
73
|
temperature: float = 0,
|
|
69
74
|
# max_output_tokens: int = 4096,
|
|
70
75
|
# model_name: str = 'gemini-2.0-flash-thinking-exp-01-21'
|
|
71
|
-
model_name: str = '
|
|
76
|
+
model_name: str = 'gemini-2.5-pro'
|
|
72
77
|
) -> str:
|
|
73
78
|
"""
|
|
74
79
|
Function to get the answer to a question by searching Google Custom Console API and processing the content using Gemini API.
|
|
@@ -112,6 +117,9 @@ class GoogleLLM:
|
|
|
112
117
|
urls=links[:number_of_top_links], number_of_characters_per_link=number_of_characters_per_link,
|
|
113
118
|
text_fetch_method=text_fetch_method)
|
|
114
119
|
|
|
120
|
+
if not contents:
|
|
121
|
+
raise GoogleLLMNoContentError("No content was fetched from the provided URL(s).")
|
|
122
|
+
|
|
115
123
|
combined_content = ""
|
|
116
124
|
for content in contents:
|
|
117
125
|
combined_content += f'{content}\n\n\n\n================================================================'
|
|
@@ -126,12 +134,12 @@ class GoogleLLM:
|
|
|
126
134
|
gemini_response = self.ask_gemini(final_question, temperature, model_name)
|
|
127
135
|
return gemini_response
|
|
128
136
|
|
|
129
|
-
@staticmethod
|
|
130
137
|
def ask_gemini(
|
|
138
|
+
self,
|
|
131
139
|
question: str,
|
|
132
140
|
temperature: float,
|
|
133
141
|
# max_output_tokens: int,
|
|
134
|
-
model_name: str = 'gemini-2.
|
|
142
|
+
model_name: str = 'gemini-2.5-pro'
|
|
135
143
|
) -> str:
|
|
136
144
|
"""
|
|
137
145
|
Function to ask the Gemini API a question and get the response.
|
|
@@ -161,8 +169,8 @@ class GoogleLLM:
|
|
|
161
169
|
# "max_output_tokens": max_output_tokens,
|
|
162
170
|
}
|
|
163
171
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
172
|
+
response = self.client.models.generate_content(
|
|
173
|
+
model=model_name,
|
|
174
|
+
contents=question,
|
|
175
|
+
config=GenerateContentConfig(**model_config))
|
|
168
176
|
return response.text
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import argparse
|
|
3
3
|
|
|
4
|
+
from dkarchiver.arch_wrappers import sevenz_app_w
|
|
5
|
+
|
|
4
6
|
from .base import msi
|
|
5
7
|
from . import base, tables, cabs
|
|
6
8
|
from ... import olefilew
|
|
7
9
|
from ....print_api import print_api
|
|
8
|
-
from ....archiver import sevenz_app_w
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
# Directory names.
|
|
@@ -68,8 +68,8 @@ def change_image_content(
|
|
|
68
68
|
dockerw.change_image_content(
|
|
69
69
|
image_id_or_name="your_docker_image_id_or_name",
|
|
70
70
|
list_of_commands=[
|
|
71
|
-
"apt
|
|
72
|
-
"apt
|
|
71
|
+
"apt update",
|
|
72
|
+
"apt install -y python3"
|
|
73
73
|
]
|
|
74
74
|
)
|
|
75
75
|
----------------------
|