atomicshop 3.3.5__py3-none-any.whl → 3.3.7__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 CHANGED
@@ -1,4 +1,4 @@
1
1
  """Atomic Basic functions and classes to make developer life easier"""
2
2
 
3
3
  __author__ = "Den Kras"
4
- __version__ = '3.3.5'
4
+ __version__ = '3.3.7'
atomicshop/consoles.py ADDED
@@ -0,0 +1,9 @@
1
+ import msvcrt
2
+
3
+
4
+ # === WINDOWS ONLY FUNCTIONS ===========================================================================================
5
+ def wait_any_key(prompt="Press any key to continue..."):
6
+ print(prompt, end="", flush=True)
7
+ msvcrt.getch() # waits for one key press (no Enter needed)
8
+ print() # move to next line
9
+ # === EOF WINDOWS ONLY FUNCTIONS =======================================================================================
@@ -2,8 +2,12 @@ import os
2
2
  import argparse
3
3
  from typing import Literal
4
4
 
5
- from ... import filesystem
5
+ from ... import filesystem, consoles
6
6
  from ...basics import strings
7
+ from rich.console import Console
8
+
9
+
10
+ console = Console()
7
11
 
8
12
 
9
13
  GENERAL_CLASS_NAME: str = "General"
@@ -71,6 +75,8 @@ class CreateModuleTemplate:
71
75
 
72
76
  self.create_config_file()
73
77
 
78
+ consoles.wait_any_key()
79
+
74
80
  def create_config_file(self):
75
81
  # Defining variables.
76
82
  config_lines_list: list = list()
@@ -93,7 +99,7 @@ class CreateModuleTemplate:
93
99
  with open(config_file_path, 'w') as output_file:
94
100
  output_file.write('\n'.join(config_lines_list))
95
101
 
96
- print(f"Config File Created: {config_file_path}")
102
+ console.print(f"Config File Created: {config_file_path}", style="bright_blue")
97
103
 
98
104
  def _create_engine_module_from_reference(
99
105
  self,
@@ -113,7 +119,7 @@ class CreateModuleTemplate:
113
119
  raise ValueError(f"Module type is not recognized: {module_type}")
114
120
 
115
121
  # Reading the module file to string.
116
- with open(file_path, 'r') as input_file:
122
+ with open(file_path, 'r', encoding='utf-8') as input_file:
117
123
  file_content_string = input_file.read()
118
124
 
119
125
  new_module_full_path: str = str()
@@ -126,4 +132,4 @@ class CreateModuleTemplate:
126
132
  output_file.write(new_content_string)
127
133
 
128
134
  print(f"Converted: {file_path}")
129
- print(f"To: {new_module_full_path}")
135
+ console.print(f"To: {new_module_full_path}", style="green")
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 is_ip_alive(ip_address: str, timeout: int = 1) -> bool:
24
+ def is_ip_in_use_ping(ip_address: str, timeout: int = 1) -> bool:
24
25
  """
25
- Returns True if icmplib.models.Host.is_alive returns True.
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 get_default_internet_ipv4() -> str:
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
- def get_default_internet_ipv4_by_connect(target: str = "8.8.8.8") -> str:
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: bool = is_ip_alive(ip_address)
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 = socket.gethostbyname(socket.gethostname())
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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: atomicshop
3
- Version: 3.3.5
3
+ Version: 3.3.7
4
4
  Summary: Atomic functions and classes to make developer life easier
5
5
  Author: Denis Kras
6
6
  License-Expression: MIT
@@ -1,4 +1,4 @@
1
- atomicshop/__init__.py,sha256=lCOFyywOc7EF6Esxu6aQIR9lx9HA8beRu1ut7lEQ3oU,122
1
+ atomicshop/__init__.py,sha256=MIwc3VJrXSpw6OLpv-QypjAnF5OWyBPBQvLHLdy2SVA,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
@@ -8,6 +8,7 @@ atomicshop/command_line_processing.py,sha256=u5yT9Ger_cu7ni5ID0VFlRbVD46ARHeNC9t
8
8
  atomicshop/config_init.py,sha256=G6_f25zPxyPlht5jJC4ZDrrQiuJfjHiuPd22VBjd9Cg,2683
9
9
  atomicshop/console_output.py,sha256=AOSJjrRryE97PAGtgDL03IBtWSi02aNol8noDnW3k6M,4667
10
10
  atomicshop/console_user_response.py,sha256=OHcjuzWAys6WmfRnMIU_nkJA634kKmJh6T8w1VtUTJM,2714
11
+ atomicshop/consoles.py,sha256=jlEKqMV7OUCq_vCHMwePcSxRa5yZhrdEyfaVcoWj2_k,464
11
12
  atomicshop/datetimes.py,sha256=IQZ66lmta-ZqxYbyHzm_9eugbJFSilXK1e0kfMgoXGg,18371
12
13
  atomicshop/diff_check.py,sha256=vxTDccVbGZHEge6Ja9_ArLWwslOUgIoJAdYPylh4cZg,27176
13
14
  atomicshop/dns.py,sha256=XB0tijVi1bxWLWKV9hPzpt75jK4SrGbZCV5VJbiiQ74,7185
@@ -23,7 +24,7 @@ atomicshop/http_parse.py,sha256=1Tna9YbOM0rE3t6i_M-klBlwd1KNSA9skA_BqKGXDFc,1186
23
24
  atomicshop/inspect_wrapper.py,sha256=sGRVQhrJovNygHTydqJj0hxES-aB2Eg9KbIk3G31apw,11429
24
25
  atomicshop/ip_addresses.py,sha256=penRFeJ1-LDVTko4Q0EwK4JiN5cU-KzCBR2VXg9qbUY,1238
25
26
  atomicshop/keyboard_press.py,sha256=1W5kRtOB75fulVx-uF2yarBhW0_IzdI1k73AnvXstk0,452
26
- atomicshop/networks.py,sha256=dTh6T9vAnjYOEPdfpL6W6wN091HwRbVLeNscXWZX_DI,22151
27
+ atomicshop/networks.py,sha256=fwOMMHwn-XMq0WgYCFbo34NXW-Xu-4nDfWl3T5EsE9U,24807
27
28
  atomicshop/on_exit.py,sha256=9XlOnzoAG8zlI8wBF4AB8hyrC6Q1b84gkhqpAhhdN9g,6977
28
29
  atomicshop/pbtkmultifile_argparse.py,sha256=aEk8nhvoQVu-xyfZosK3ma17CwIgOjzO1erXXdjwtS4,4574
29
30
  atomicshop/print_api.py,sha256=SJNQIMqSLlYaPtjHnALySAI-jQYuYHOCGgfP7oe96fU,10957
@@ -49,16 +50,12 @@ atomicshop/versioning.py,sha256=e5W6m9AF3__M5nntqI9CqNAeHqkwY9JhlnpYeZ1CEus,970
49
50
  atomicshop/virtualization.py,sha256=LPP4vjE0Vr10R6DA4lqhfX_WaNdDGRAZUW0Am6VeGco,494
50
51
  atomicshop/web.py,sha256=hkAS0MeMW_mGgxhFCX1xckT3yslCJ2cMP2nx9ADpe3o,13024
51
52
  atomicshop/websocket_parse.py,sha256=aLHWyKqaYqEn_MRBWm2L6rIl6QPmqbVrjEXE_rBzwCw,16711
52
- atomicshop/a_installs/pywintrace.py,sha256=oZ9BATsJ2YsdIkZZWLar_dAUV32-oDiT7MJxthC0NnU,738
53
53
  atomicshop/a_installs/ubuntu/docker_rootless.py,sha256=9IPNtGZYjfy1_n6ZRt7gWz9KZgR6XCgevjqq02xk-o0,281
54
54
  atomicshop/a_installs/ubuntu/docker_sudo.py,sha256=JzayxeyKDtiuT4Icp2L2LyFRbx4wvpyN_bHLfZ-yX5E,281
55
55
  atomicshop/a_installs/ubuntu/elastic_search_and_kibana.py,sha256=yRB-l1zBxdiN6av-FwNkhcBlaeu4zrDPjQ0uPGgpK2I,244
56
56
  atomicshop/a_installs/ubuntu/mongodb.py,sha256=xuRJS1qqOZ0EZp7of5R3tTjSu6CwBIxYg8-NaM7othE,230
57
- atomicshop/a_installs/ubuntu/pycharm.py,sha256=Ld7YQBwPxrjuZcTG1K4kZqjbBdt8aooCVRa15u5FOmE,157
58
57
  atomicshop/a_installs/win/fibratus.py,sha256=TU4e9gdZ_zI73C40uueJ59pD3qmN-UFGdX5GFoVf6cM,179
59
58
  atomicshop/a_installs/win/mongodb.py,sha256=AqyItXu19aaoe49pppDxtEkXey6PMy0PoT2Y_RmPpPE,179
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
59
  atomicshop/a_installs/win/wsl_ubuntu_lts.py,sha256=dZbPRLNKFeMd6MotjkE6UDY9cOiIaaclIdR1kGYWI50,139
63
60
  atomicshop/a_mains/dns_gateway_setting.py,sha256=ncc2rFQCChxlNP59UshwmTonLqC6MWblrVAzbbz-13M,149
64
61
  atomicshop/a_mains/github_wrapper.py,sha256=F-PoZknVCxWPN0PTO6l7ZNiaYvo7OVFKFI_zlPt56ps,169
@@ -143,7 +140,7 @@ atomicshop/mitm/recs_files.py,sha256=tv8XFhYZMkBv4DauvpiAdPgvSo0Bcm1CghnmwO7dx8M
143
140
  atomicshop/mitm/shared_functions.py,sha256=0lzeyINd44sVEfFbahJxQmz6KAMWbYrW5ou3UYfItvw,1777
144
141
  atomicshop/mitm/statistic_analyzer.py,sha256=5_sAYGX2Xunzo_pS2W5WijNCwr_BlGJbbOO462y_wN4,27533
145
142
  atomicshop/mitm/engines/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
146
- atomicshop/mitm/engines/create_module_template.py,sha256=2ceRWPzofpRf-R8VAMgXrx2D7vumkhfsrr120YFGgH0,5764
143
+ atomicshop/mitm/engines/create_module_template.py,sha256=PHE2pVC9JNgaIh2o7M5dFMrkdOkmIyHLoO2mdzE5BdM,5938
147
144
  atomicshop/mitm/engines/create_module_template_main_example.py,sha256=LeQ44Rp2Gi_KbIDY_4OMS0odkSK3zFZWra_oAka5eJY,243
148
145
  atomicshop/mitm/engines/__parent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
149
146
  atomicshop/mitm/engines/__parent/parser___parent.py,sha256=HHaCXhScl3OlPjz6eUxsDpJaZyk6BNuDMc9xCkeo2Ws,661
@@ -293,9 +290,6 @@ atomicshop/wrappers/psutilw/processes.py,sha256=ihYnxfMTVEXHWy92iewktoZGxazx3v5Q
293
290
  atomicshop/wrappers/psutilw/psutil_networks.py,sha256=79FplDAj45ofBCudlft77O3lfi0RDwJ3ijye0ZGRR44,2870
294
291
  atomicshop/wrappers/psutilw/psutilw.py,sha256=q3EwgprqyrR4zLCjl4l5DHFOQoukEvQMIPjNB504oQ0,21262
295
292
  atomicshop/wrappers/psycopgw/psycopgw.py,sha256=XJvVf0oAUjCHkrYfKeFuGCpfn0Oxj3u4SbKMKA1508E,7118
296
- atomicshop/wrappers/pycharmw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
297
- atomicshop/wrappers/pycharmw/ubuntu.py,sha256=vOvGWvTbzvTja9tRrJW2yJb0_r1EV11RrENGHckzvVE,1051
298
- atomicshop/wrappers/pycharmw/win.py,sha256=hNP-d95z1zhcCpYqhHE5HZVYxaAlt8JJCNXh65jZsHc,2757
299
293
  atomicshop/wrappers/pywin32w/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
300
294
  atomicshop/wrappers/pywin32w/cert_store.py,sha256=dV1XyoKTFKZ-HCIVqU2Nd6CTZ8HANqjAXv26rsNzO6s,4365
301
295
  atomicshop/wrappers/pywin32w/console.py,sha256=LstHajPLgXp9qQxFNR44QfH10nOnNp3bCJquxaTquns,1175
@@ -331,9 +325,9 @@ atomicshop/wrappers/socketw/statistics_csv.py,sha256=_gA8bMX6Sw_UCXKi2y9wNAwlqif
331
325
  atomicshop/wrappers/winregw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
332
326
  atomicshop/wrappers/winregw/winreg_installed_software.py,sha256=Qzmyktvob1qp6Tjk2DjLfAqr_yXV0sgWzdMW_9kwNjY,2345
333
327
  atomicshop/wrappers/winregw/winreg_network.py,sha256=ih0BVNwByLvf9F_Lac4EdmDYYJA3PzMvmG0PieDZrsE,9905
334
- atomicshop-3.3.5.dist-info/licenses/LICENSE.txt,sha256=lLU7EYycfYcK2NR_1gfnhnRC8b8ccOTElACYplgZN88,1094
335
- atomicshop-3.3.5.dist-info/METADATA,sha256=QAiSikiYm60q_UBleSyptTY9jvGM6s_7fk2yrncVrec,9311
336
- atomicshop-3.3.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
337
- atomicshop-3.3.5.dist-info/entry_points.txt,sha256=SJEgEP0KoFtfxuGwe5tOzKfXkjR9Dv6YYug33KNYxyY,69
338
- atomicshop-3.3.5.dist-info/top_level.txt,sha256=EgKJB-7xcrAPeqTRF2laD_Np2gNGYkJkd4OyXqpJphA,11
339
- atomicshop-3.3.5.dist-info/RECORD,,
328
+ atomicshop-3.3.7.dist-info/licenses/LICENSE.txt,sha256=lLU7EYycfYcK2NR_1gfnhnRC8b8ccOTElACYplgZN88,1094
329
+ atomicshop-3.3.7.dist-info/METADATA,sha256=YtwfcbICVVpiUrkEndWY-sfDjaT6_bHn8b2JOi3N8QI,9311
330
+ atomicshop-3.3.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
331
+ atomicshop-3.3.7.dist-info/entry_points.txt,sha256=SJEgEP0KoFtfxuGwe5tOzKfXkjR9Dv6YYug33KNYxyY,69
332
+ atomicshop-3.3.7.dist-info/top_level.txt,sha256=EgKJB-7xcrAPeqTRF2laD_Np2gNGYkJkd4OyXqpJphA,11
333
+ atomicshop-3.3.7.dist-info/RECORD,,
@@ -1,26 +0,0 @@
1
- import argparse
2
- import subprocess
3
- import sys
4
-
5
-
6
- WHEEL = (
7
- "https://github.com/fireeye/pywintrace/releases/download/"
8
- "v0.3.0/pywintrace-0.3.0-py3-none-any.whl"
9
- )
10
-
11
-
12
- def main() -> None:
13
- parser = argparse.ArgumentParser(
14
- prog="pywintrace",
15
- description="Utility wrapper for installing FireEye’s pywintrace wheel"
16
- )
17
- sub = parser.add_subparsers(dest="command", required=True)
18
- sub.add_parser("install", help="Download and install pywintrace v0.3.0")
19
- args = parser.parse_args()
20
-
21
- if args.command == "install":
22
- subprocess.check_call([sys.executable, "-m", "pip", "install", WHEEL])
23
- print("pywintrace 0.3.0 installed")
24
-
25
- if __name__ == "__main__":
26
- main()
@@ -1,8 +0,0 @@
1
- #! /usr/bin/env python3
2
- import sys
3
-
4
- from atomicshop.wrappers.pycharmw import ubuntu
5
-
6
-
7
- if __name__ == '__main__':
8
- sys.exit(ubuntu.install_main())
@@ -1,9 +0,0 @@
1
- from atomicshop.wrappers.pycharmw import win
2
-
3
-
4
- def main():
5
- win.download_install_main()
6
-
7
-
8
- if __name__ == "__main__":
9
- main()
@@ -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
@@ -1,36 +0,0 @@
1
- import argparse
2
-
3
- from ... import process
4
- from ...print_api import print_api
5
-
6
-
7
- def parse_args():
8
- """
9
- Parse command line arguments.
10
-
11
- :return: Parsed arguments.
12
- """
13
- parser = argparse.ArgumentParser(description='Install PyCharm Community Edition.')
14
- parser.add_argument(
15
- '--enable_sudo_execution', action='store_true',
16
- help='There is a problem when trying to run snapd installed Pycharm as sudo, need to enable this.')
17
-
18
- return parser.parse_args()
19
-
20
-
21
- def install_main():
22
- """
23
- Main function to install the latest PyCharm Community Edition.
24
-
25
- Usage:
26
- python -m atomicshop.a_installs.ubuntu.pycharm
27
- """
28
-
29
- args = parse_args()
30
-
31
- process.execute_script('sudo snap install pycharm-professional --classic', shell=True)
32
-
33
- if args.enable_sudo_execution:
34
- process.execute_script('xhost +SI:localuser:root', shell=True)
35
- print_api('Run the following command to start PyCharm as root: [sudo snap run pycharm-professional]', color='blue')
36
- return 0
@@ -1,81 +0,0 @@
1
- import requests
2
- from bs4 import BeautifulSoup
3
- import subprocess
4
-
5
- from ... import web, filesystem
6
- from ...print_api import print_api
7
-
8
-
9
- # URL to the PyCharm Community Edition download page
10
- PYCHARM_DOWNLOAD_URL = 'https://www.jetbrains.com/pycharm/download/#section=windowsC'
11
-
12
-
13
- def download_install_main():
14
- """
15
- Main function to download and install the latest PyCharm Community Edition.
16
-
17
- Usage:
18
- python -m atomicshop.mains.installs.pycharm
19
-
20
- Or run the main function directly.
21
- from atomicshop.wrappers import pycharmw
22
-
23
-
24
- def main():
25
- pycharmw.download_install_main()
26
-
27
-
28
- if __name__ == "__main__":
29
- main()
30
- """
31
-
32
- def get_latest_pycharm_download_link():
33
- url = "https://www.jetbrains.com/pycharm/download/"
34
- headers = {
35
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
36
- }
37
-
38
- response = requests.get(url, headers=headers)
39
- if response.status_code != 200:
40
- raise Exception("Failed to load the download page")
41
-
42
- soup = BeautifulSoup(response.text, 'html.parser')
43
- download_link = None
44
-
45
- # Find the Professional version download link
46
- for a in soup.find_all('a', href=True):
47
- if '/download?code=PCC&platform=windows' in a['href']:
48
- download_link = a['href']
49
- break
50
-
51
- if not download_link:
52
- raise Exception("Could not find the download link for the latest version of PyCharm Professional")
53
-
54
- return f"https:{download_link}"
55
-
56
- installer_path: str = None
57
- try:
58
- print_api("Fetching the latest PyCharm download link...")
59
- download_url = get_latest_pycharm_download_link()
60
- print_api(f"Download URL: {download_url}")
61
-
62
- print_api("Starting the download...")
63
- file_name = "pycharm-latest.exe"
64
- # download_file(download_url, file_name)
65
- installer_path = web.download(file_url=download_url, file_name=file_name, use_certifi_ca_repository=True)
66
- print_api(f"Downloaded the latest version of PyCharm to {file_name}", color='green')
67
- except Exception as e:
68
- print_api(f"An error occurred: {e}")
69
-
70
- if not installer_path:
71
- print_api("Failed to download the latest version of PyCharm", color='red')
72
- return 1
73
-
74
- # Install PyCharm
75
- # Run the installer
76
- print_api("Running the installer...")
77
- subprocess.run([installer_path, '/S'], check=True) # /S for silent installation
78
- print_api("Installation complete.", color='green')
79
-
80
- # Remove the installer
81
- filesystem.remove_file(installer_path)