atomicshop 3.3.5__py3-none-any.whl → 3.3.6__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/networks.py +68 -7
- {atomicshop-3.3.5.dist-info → atomicshop-3.3.6.dist-info}/METADATA +1 -1
- {atomicshop-3.3.5.dist-info → atomicshop-3.3.6.dist-info}/RECORD +8 -9
- atomicshop/a_installs/win/robocorp.py +0 -82
- {atomicshop-3.3.5.dist-info → atomicshop-3.3.6.dist-info}/WHEEL +0 -0
- {atomicshop-3.3.5.dist-info → atomicshop-3.3.6.dist-info}/entry_points.txt +0 -0
- {atomicshop-3.3.5.dist-info → atomicshop-3.3.6.dist-info}/licenses/LICENSE.txt +0 -0
- {atomicshop-3.3.5.dist-info → atomicshop-3.3.6.dist-info}/top_level.txt +0 -0
atomicshop/__init__.py
CHANGED
atomicshop/networks.py
CHANGED
|
@@ -3,6 +3,7 @@ import time
|
|
|
3
3
|
from typing import Union
|
|
4
4
|
import os
|
|
5
5
|
import psutil
|
|
6
|
+
import ctypes
|
|
6
7
|
|
|
7
8
|
from icmplib import ping
|
|
8
9
|
from icmplib.models import Host
|
|
@@ -20,9 +21,12 @@ MICROSOFT_LOOPBACK_DEVICE_HARDWARE_ID = "*MSLOOP"
|
|
|
20
21
|
GUID_DEVCLASS_NET: str = '{4d36e972-e325-11ce-bfc1-08002be10318}'
|
|
21
22
|
|
|
22
23
|
|
|
23
|
-
def
|
|
24
|
+
def is_ip_in_use_ping(ip_address: str, timeout: int = 1) -> bool:
|
|
24
25
|
"""
|
|
25
|
-
Returns True if
|
|
26
|
+
Returns True if the IP address is pingable, False otherwise.
|
|
27
|
+
:param ip_address: string, IP address to check.
|
|
28
|
+
:param timeout: int, timeout in seconds. Default is 1 second.
|
|
29
|
+
:return: bool, True if the IP address is pingable, False otherwise.
|
|
26
30
|
"""
|
|
27
31
|
|
|
28
32
|
host_object: Host = ping(ip_address, count=1, timeout=timeout)
|
|
@@ -30,15 +34,72 @@ def is_ip_alive(ip_address: str, timeout: int = 1) -> bool:
|
|
|
30
34
|
return host_object.is_alive
|
|
31
35
|
|
|
32
36
|
|
|
33
|
-
def
|
|
37
|
+
def is_ip_in_use_arp(
|
|
38
|
+
ipv4: str,
|
|
39
|
+
gateway_ip: str = None
|
|
40
|
+
) -> tuple[
|
|
41
|
+
Union[str, None],
|
|
42
|
+
Union[bool, None]
|
|
43
|
+
]:
|
|
34
44
|
"""
|
|
45
|
+
Windows only.
|
|
46
|
+
Check if an IPv4 address is in use on the local network using ARP.
|
|
47
|
+
:param ipv4: string, IPv4 address to check.
|
|
48
|
+
:param gateway_ip: string, IPv4 address of the default gateway.
|
|
49
|
+
How it works: If you provide the gateway_ip, the function will get yje MAC of the gateway,
|
|
50
|
+
then it will get the MAC of the target IP address. If the MACs are the same, it means that the target IP's
|
|
51
|
+
ARP reply is an ARP proxy reply from the gateway.
|
|
52
|
+
:return: tuple (mac_address: str | None, via_gateway: bool | None)
|
|
53
|
+
If the IP address is in use, mac_address will be the MAC address of the device using the IP address,
|
|
54
|
+
else None. If gateway_ip is provided, via_gateway will be True if the MAC address is the same as the gateway's MAC address,
|
|
55
|
+
False if it's different, and None if gateway_ip is not provided.
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
iphlpapi = ctypes.windll.iphlpapi
|
|
59
|
+
ws2_32 = ctypes.windll.ws2_32
|
|
60
|
+
|
|
61
|
+
def _send_arp(ip: str) -> str | None:
|
|
62
|
+
"""Return MAC string like 'aa:bb:cc:dd:ee:ff' if IP is claimed on the LAN, else None."""
|
|
63
|
+
# inet_addr returns DWORD in network byte order
|
|
64
|
+
dest_ip = ws2_32.inet_addr(ip.encode('ascii'))
|
|
65
|
+
if dest_ip == 0xFFFFFFFF: # INVALID
|
|
66
|
+
raise ValueError(f"Bad IPv4 address: {ip}")
|
|
67
|
+
|
|
68
|
+
mac_buf = ctypes.c_uint64(0) # storage for up to 8 bytes
|
|
69
|
+
mac_len = ctypes.c_ulong(ctypes.sizeof(mac_buf)) # in/out len
|
|
70
|
+
# SrcIP=0 lets Windows pick the right interface
|
|
71
|
+
rc = iphlpapi.SendARP(dest_ip, 0, ctypes.byref(mac_buf), ctypes.byref(mac_len))
|
|
72
|
+
if rc != 0: # Non-zero means no ARP reply / not on-link / other error
|
|
73
|
+
return None
|
|
74
|
+
|
|
75
|
+
# Extract the first 6 bytes from little-endian integer
|
|
76
|
+
mac_int = mac_buf.value
|
|
77
|
+
mac_bytes = mac_int.to_bytes(8, 'little')[:6]
|
|
78
|
+
return ':'.join(f'{b:02x}' for b in mac_bytes)
|
|
79
|
+
|
|
80
|
+
mac = _send_arp(ipv4)
|
|
81
|
+
if mac is None:
|
|
82
|
+
return None, None
|
|
83
|
+
via_gateway = None
|
|
84
|
+
if gateway_ip:
|
|
85
|
+
gw_mac = _send_arp(gateway_ip)
|
|
86
|
+
via_gateway = (gw_mac is not None and gw_mac.lower() == mac.lower())
|
|
87
|
+
return mac, via_gateway
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def __get_default_internet_ipv4() -> str:
|
|
91
|
+
"""
|
|
92
|
+
FOR REFERENCE ONLY, DO NOT USE.
|
|
93
|
+
DOESN'T WORK UNDER ALL CIRCUMSTANCES, CAN'T PINPOINT THE REASON.
|
|
94
|
+
|
|
35
95
|
Get the default IPv4 address of the interface that is being used for internet.
|
|
36
96
|
:return: string, default IPv4 address.
|
|
37
97
|
"""
|
|
38
98
|
|
|
39
99
|
return socket.gethostbyname(socket.gethostname())
|
|
40
100
|
|
|
41
|
-
|
|
101
|
+
|
|
102
|
+
def get_default_internet_ipv4(target: str = "8.8.8.8") -> str:
|
|
42
103
|
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
|
|
43
104
|
s.connect((target, 80)) # no packet sent; OS just chooses a route
|
|
44
105
|
return s.getsockname()[0] # local address of that route
|
|
@@ -296,9 +357,9 @@ def generate_unused_ipv4_addresses_by_vlan(
|
|
|
296
357
|
for i in range(number_of_ips):
|
|
297
358
|
# Create the IP address.
|
|
298
359
|
while True:
|
|
299
|
-
ip_address = f"{vlan}.{counter}"
|
|
360
|
+
ip_address: str = f"{vlan}.{counter}"
|
|
300
361
|
counter += 1
|
|
301
|
-
is_ip_in_use
|
|
362
|
+
is_ip_in_use, _ = is_ip_in_use_arp(ip_address)
|
|
302
363
|
if not is_ip_in_use and not ip_address in skip_ips:
|
|
303
364
|
# print("[+] Found IP to assign: ", ip_address)
|
|
304
365
|
generated_ips.append(ip_address)
|
|
@@ -506,7 +567,7 @@ def add_virtual_ips_to_default_adapter_by_current_setting(
|
|
|
506
567
|
dns_gateways = default_adapter_info['dns_gateways']
|
|
507
568
|
|
|
508
569
|
# We will get the default IP address of the machine.
|
|
509
|
-
default_ip_address: str =
|
|
570
|
+
default_ip_address: str = get_default_internet_ipv4()
|
|
510
571
|
# So we can make it the first IP in the list, but first remove it from the list.
|
|
511
572
|
_ = ips.pop(ips.index(default_ip_address))
|
|
512
573
|
# At this point we will copy the list of IPs that we will set the SkipAsSource flag for.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
atomicshop/__init__.py,sha256=
|
|
1
|
+
atomicshop/__init__.py,sha256=PKxHKogNO1jVrjMDxPohtYhd5093pVEONPVfmujNgfw,122
|
|
2
2
|
atomicshop/_basics_temp.py,sha256=6cu2dd6r2dLrd1BRNcVDKTHlsHs_26Gpw8QS6v32lQ0,3699
|
|
3
3
|
atomicshop/_create_pdf_demo.py,sha256=Yi-PGZuMg0RKvQmLqVeLIZYadqEZwUm-4A9JxBl_vYA,3713
|
|
4
4
|
atomicshop/_patch_import.py,sha256=ENp55sKVJ0e6-4lBvZnpz9PQCt3Otbur7F6aXDlyje4,6334
|
|
@@ -23,7 +23,7 @@ atomicshop/http_parse.py,sha256=1Tna9YbOM0rE3t6i_M-klBlwd1KNSA9skA_BqKGXDFc,1186
|
|
|
23
23
|
atomicshop/inspect_wrapper.py,sha256=sGRVQhrJovNygHTydqJj0hxES-aB2Eg9KbIk3G31apw,11429
|
|
24
24
|
atomicshop/ip_addresses.py,sha256=penRFeJ1-LDVTko4Q0EwK4JiN5cU-KzCBR2VXg9qbUY,1238
|
|
25
25
|
atomicshop/keyboard_press.py,sha256=1W5kRtOB75fulVx-uF2yarBhW0_IzdI1k73AnvXstk0,452
|
|
26
|
-
atomicshop/networks.py,sha256=
|
|
26
|
+
atomicshop/networks.py,sha256=fwOMMHwn-XMq0WgYCFbo34NXW-Xu-4nDfWl3T5EsE9U,24807
|
|
27
27
|
atomicshop/on_exit.py,sha256=9XlOnzoAG8zlI8wBF4AB8hyrC6Q1b84gkhqpAhhdN9g,6977
|
|
28
28
|
atomicshop/pbtkmultifile_argparse.py,sha256=aEk8nhvoQVu-xyfZosK3ma17CwIgOjzO1erXXdjwtS4,4574
|
|
29
29
|
atomicshop/print_api.py,sha256=SJNQIMqSLlYaPtjHnALySAI-jQYuYHOCGgfP7oe96fU,10957
|
|
@@ -58,7 +58,6 @@ atomicshop/a_installs/ubuntu/pycharm.py,sha256=Ld7YQBwPxrjuZcTG1K4kZqjbBdt8aooCV
|
|
|
58
58
|
atomicshop/a_installs/win/fibratus.py,sha256=TU4e9gdZ_zI73C40uueJ59pD3qmN-UFGdX5GFoVf6cM,179
|
|
59
59
|
atomicshop/a_installs/win/mongodb.py,sha256=AqyItXu19aaoe49pppDxtEkXey6PMy0PoT2Y_RmPpPE,179
|
|
60
60
|
atomicshop/a_installs/win/pycharm.py,sha256=j_RSd7aDOyC3yDd-_GUTMLlQTmDrqtVFG--oUfGLiZk,140
|
|
61
|
-
atomicshop/a_installs/win/robocorp.py,sha256=Ob8X9Czwd-OR3pudFIFft1dcUjDM0Pw0X03yfPaf3yw,3280
|
|
62
61
|
atomicshop/a_installs/win/wsl_ubuntu_lts.py,sha256=dZbPRLNKFeMd6MotjkE6UDY9cOiIaaclIdR1kGYWI50,139
|
|
63
62
|
atomicshop/a_mains/dns_gateway_setting.py,sha256=ncc2rFQCChxlNP59UshwmTonLqC6MWblrVAzbbz-13M,149
|
|
64
63
|
atomicshop/a_mains/github_wrapper.py,sha256=F-PoZknVCxWPN0PTO6l7ZNiaYvo7OVFKFI_zlPt56ps,169
|
|
@@ -331,9 +330,9 @@ atomicshop/wrappers/socketw/statistics_csv.py,sha256=_gA8bMX6Sw_UCXKi2y9wNAwlqif
|
|
|
331
330
|
atomicshop/wrappers/winregw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
332
331
|
atomicshop/wrappers/winregw/winreg_installed_software.py,sha256=Qzmyktvob1qp6Tjk2DjLfAqr_yXV0sgWzdMW_9kwNjY,2345
|
|
333
332
|
atomicshop/wrappers/winregw/winreg_network.py,sha256=ih0BVNwByLvf9F_Lac4EdmDYYJA3PzMvmG0PieDZrsE,9905
|
|
334
|
-
atomicshop-3.3.
|
|
335
|
-
atomicshop-3.3.
|
|
336
|
-
atomicshop-3.3.
|
|
337
|
-
atomicshop-3.3.
|
|
338
|
-
atomicshop-3.3.
|
|
339
|
-
atomicshop-3.3.
|
|
333
|
+
atomicshop-3.3.6.dist-info/licenses/LICENSE.txt,sha256=lLU7EYycfYcK2NR_1gfnhnRC8b8ccOTElACYplgZN88,1094
|
|
334
|
+
atomicshop-3.3.6.dist-info/METADATA,sha256=IL5-xRKSd3KMQq1-z8F1hdeVTz9jNmhxtEdbXTAeKtM,9311
|
|
335
|
+
atomicshop-3.3.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
336
|
+
atomicshop-3.3.6.dist-info/entry_points.txt,sha256=SJEgEP0KoFtfxuGwe5tOzKfXkjR9Dv6YYug33KNYxyY,69
|
|
337
|
+
atomicshop-3.3.6.dist-info/top_level.txt,sha256=EgKJB-7xcrAPeqTRF2laD_Np2gNGYkJkd4OyXqpJphA,11
|
|
338
|
+
atomicshop-3.3.6.dist-info/RECORD,,
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import sys
|
|
2
|
-
import subprocess
|
|
3
|
-
import tempfile
|
|
4
|
-
|
|
5
|
-
from atomicshop.print_api import print_api
|
|
6
|
-
from atomicshop.wrappers import githubw
|
|
7
|
-
from atomicshop.permissions import permissions
|
|
8
|
-
from atomicshop.wrappers.nodejsw import install_nodejs_windows
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
WINDOWS_TESSERACT_DEFAULT_INSTALLATION_DIRECTORY: str = r"C:\Program Files\Tesseract-OCR"
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def main():
|
|
15
|
-
if not permissions.is_admin():
|
|
16
|
-
print_api("Please run this script as an Administrator.", color="red")
|
|
17
|
-
return 1
|
|
18
|
-
|
|
19
|
-
if not install_nodejs_windows.is_nodejs_installed():
|
|
20
|
-
install_nodejs_windows.install_nodejs_windows()
|
|
21
|
-
install_nodejs_windows.add_nodejs_to_path()
|
|
22
|
-
if not install_nodejs_windows.is_nodejs_installed():
|
|
23
|
-
print_api("Node.js installation failed.", color="red")
|
|
24
|
-
return 1
|
|
25
|
-
|
|
26
|
-
print_api("PIP Installing Robocorp.", color="blue")
|
|
27
|
-
subprocess.check_call(["pip", "install", "--upgrade", "rpaframework"])
|
|
28
|
-
|
|
29
|
-
print_api("PIP Installing Robocorp-Browser.", color="blue")
|
|
30
|
-
subprocess.check_call(["pip", "install", "--upgrade", "robotframework-browser"])
|
|
31
|
-
|
|
32
|
-
print_api("PIP Installing Robocorp-Recognition.", color="blue")
|
|
33
|
-
subprocess.check_call(["pip", "install", "--upgrade", "rpaframework-recognition"])
|
|
34
|
-
|
|
35
|
-
print_api("PIP Installing pynput.", color="blue")
|
|
36
|
-
subprocess.check_call(["pip", "install", "--upgrade", "pynput"])
|
|
37
|
-
|
|
38
|
-
print_api("Installing Playwright browsers.", color="blue")
|
|
39
|
-
subprocess.check_call(["playwright", "install"])
|
|
40
|
-
|
|
41
|
-
print_api("Initializing Robocorp Browser.", color="blue")
|
|
42
|
-
subprocess.check_call(["rfbrowser", "init"])
|
|
43
|
-
|
|
44
|
-
print_api("Installing Additional modules.", color="blue")
|
|
45
|
-
subprocess.check_call(["pip", "install", "--upgrade", "matplotlib", "imagehash"])
|
|
46
|
-
|
|
47
|
-
print_api("Installing Tesseract OCR.", color="blue")
|
|
48
|
-
github_wrapper = githubw.GitHubWrapper(
|
|
49
|
-
user_name="tesseract-ocr",
|
|
50
|
-
repo_name="tesseract",
|
|
51
|
-
branch="main")
|
|
52
|
-
github_wrapper.build_links_from_user_and_repo()
|
|
53
|
-
temp_file_path: str = tempfile.gettempdir()
|
|
54
|
-
tesseract_installer = github_wrapper.download_latest_release(
|
|
55
|
-
target_directory=temp_file_path,
|
|
56
|
-
string_pattern="*tesseract*exe")
|
|
57
|
-
|
|
58
|
-
# The Admin needed to install Tesseract.
|
|
59
|
-
subprocess.check_call([tesseract_installer, "/S"])
|
|
60
|
-
|
|
61
|
-
# Add Tesseract to the PATH.
|
|
62
|
-
subprocess.check_call(["setx", "PATH", f"%PATH%;{WINDOWS_TESSERACT_DEFAULT_INSTALLATION_DIRECTORY}"])
|
|
63
|
-
|
|
64
|
-
# Patch robocorp: Remove mouse to the center of the screen on control command.
|
|
65
|
-
# Import the library to find its path.
|
|
66
|
-
print_api("Patching: .\RPA\Windows\keywords\window.py", color="blue")
|
|
67
|
-
import RPA.Windows.keywords.window as window
|
|
68
|
-
window_file_path = window.__file__
|
|
69
|
-
|
|
70
|
-
# Patch the file.
|
|
71
|
-
with open(window_file_path, "r") as file:
|
|
72
|
-
file_content = file.read()
|
|
73
|
-
file_content = file_content.replace(
|
|
74
|
-
"window.item.MoveCursorToMyCenter(simulateMove=self.ctx.simulate_move)",
|
|
75
|
-
"# window.item.MoveCursorToMyCenter(simulateMove=self.ctx.simulate_move) # Patched to remove center placement during foreground window control."
|
|
76
|
-
)
|
|
77
|
-
with open(window_file_path, "w") as file:
|
|
78
|
-
file.write(file_content)
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
if __name__ == '__main__':
|
|
82
|
-
sys.exit(main())
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|