Open-AutoTools 0.0.3rc5__py3-none-any.whl → 0.0.4rc1__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.
Files changed (44) hide show
  1. autotools/autocaps/commands.py +3 -7
  2. autotools/autocaps/core.py +5 -4
  3. autotools/autoip/commands.py +6 -11
  4. autotools/autoip/core.py +151 -200
  5. autotools/autolower/commands.py +3 -7
  6. autotools/autolower/core.py +4 -3
  7. autotools/autopassword/commands.py +27 -33
  8. autotools/autopassword/core.py +32 -73
  9. autotools/autotest/__init__.py +2 -0
  10. autotools/autotest/commands.py +205 -0
  11. autotools/cli.py +123 -62
  12. autotools/utils/commands.py +13 -0
  13. autotools/utils/loading.py +14 -6
  14. autotools/utils/performance.py +392 -0
  15. autotools/utils/updates.py +30 -22
  16. autotools/utils/version.py +69 -63
  17. open_autotools-0.0.4rc1.dist-info/METADATA +103 -0
  18. open_autotools-0.0.4rc1.dist-info/RECORD +28 -0
  19. {Open_AutoTools-0.0.3rc5.dist-info → open_autotools-0.0.4rc1.dist-info}/WHEEL +1 -1
  20. {Open_AutoTools-0.0.3rc5.dist-info → open_autotools-0.0.4rc1.dist-info}/entry_points.txt +0 -3
  21. Open_AutoTools-0.0.3rc5.dist-info/METADATA +0 -317
  22. Open_AutoTools-0.0.3rc5.dist-info/RECORD +0 -44
  23. autotools/autocaps/tests/__init__.py +0 -1
  24. autotools/autocaps/tests/test_autocaps_core.py +0 -45
  25. autotools/autocaps/tests/test_autocaps_integration.py +0 -46
  26. autotools/autodownload/__init__.py +0 -0
  27. autotools/autodownload/commands.py +0 -38
  28. autotools/autodownload/core.py +0 -433
  29. autotools/autoip/tests/__init__.py +0 -1
  30. autotools/autoip/tests/test_autoip_core.py +0 -72
  31. autotools/autoip/tests/test_autoip_integration.py +0 -92
  32. autotools/autolower/tests/__init__.py +0 -1
  33. autotools/autolower/tests/test_autolower_core.py +0 -45
  34. autotools/autolower/tests/test_autolower_integration.py +0 -46
  35. autotools/autospell/__init__.py +0 -3
  36. autotools/autospell/commands.py +0 -123
  37. autotools/autospell/core.py +0 -222
  38. autotools/autotranslate/__init__.py +0 -3
  39. autotools/autotranslate/commands.py +0 -42
  40. autotools/autotranslate/core.py +0 -52
  41. autotools/test/__init__.py +0 -3
  42. autotools/test/commands.py +0 -118
  43. {Open_AutoTools-0.0.3rc5.dist-info → open_autotools-0.0.4rc1.dist-info/licenses}/LICENSE +0 -0
  44. {Open_AutoTools-0.0.3rc5.dist-info → open_autotools-0.0.4rc1.dist-info}/top_level.txt +0 -0
@@ -3,15 +3,11 @@ from .core import autocaps_transform
3
3
  from ..utils.loading import LoadingAnimation
4
4
  from ..utils.updates import check_for_updates
5
5
 
6
+ # CLI COMMAND TO TRANSFORM TEXT TO UPPERCASE
6
7
  @click.command()
7
8
  @click.argument('text', nargs=-1)
8
9
  def autocaps(text):
9
- """Convert text to UPPERCASE."""
10
- with LoadingAnimation():
11
- result = autocaps_transform(" ".join(text))
10
+ with LoadingAnimation(): result = autocaps_transform(" ".join(text))
12
11
  click.echo(result)
13
-
14
- # UPDATE CHECK AT THE END
15
12
  update_msg = check_for_updates()
16
- if update_msg:
17
- click.echo(update_msg)
13
+ if update_msg: click.echo(update_msg)
@@ -1,7 +1,8 @@
1
1
  import pyperclip
2
2
 
3
- # AUTOCAPS CORE FUNCTION DEFINITION
3
+ # TRANSFORMS TEXT TO UPPERCASE AND COPIES IT TO CLIPBOARD
4
4
  def autocaps_transform(text):
5
- transformed_text = text.upper() # TRANSFORM TEXT TO UPPERCASE
6
- pyperclip.copy(transformed_text) # COPY TRANSFORMED TEXT TO CLIPBOARD
7
- return transformed_text
5
+ transformed_text = text.upper()
6
+ try: pyperclip.copy(transformed_text)
7
+ except pyperclip.PyperclipException: pass
8
+ return transformed_text
@@ -3,6 +3,7 @@ from .core import run
3
3
  from ..utils.loading import LoadingAnimation
4
4
  from ..utils.updates import check_for_updates
5
5
 
6
+ # CLI COMMAND TO DISPLAY NETWORK INFORMATION AND RUN DIAGNOSTICS
6
7
  @click.command()
7
8
  @click.option('--test', '-t', is_flag=True, help='Run connectivity tests')
8
9
  @click.option('--speed', '-s', is_flag=True, help='Run internet speed test')
@@ -13,17 +14,11 @@ from ..utils.updates import check_for_updates
13
14
  @click.option('--location', '-l', is_flag=True, help='Show IP location info')
14
15
  @click.option('--no-ip', '-n', is_flag=True, help='Hide IP addresses')
15
16
  def autoip(test, speed, monitor, interval, ports, dns, location, no_ip):
16
- """Display network information and diagnostics.
17
-
18
- Shows local and public IP addresses, runs network diagnostics,
19
- performs speed tests, monitors traffic with custom intervals,
20
- checks ports, displays DNS information and provides geolocation data."""
21
17
  with LoadingAnimation():
22
- output = run(test=test, speed=speed, monitor=monitor, interval=interval,
23
- ports=ports, dns=dns, location=location, no_ip=no_ip)
18
+ output = run(
19
+ test=test, speed=speed, monitor=monitor, interval=interval,
20
+ ports=ports, dns=dns, location=location, no_ip=no_ip
21
+ )
24
22
  click.echo(output)
25
-
26
- # UPDATE CHECK AT THE END
27
23
  update_msg = check_for_updates()
28
- if update_msg:
29
- click.echo(update_msg)
24
+ if update_msg: click.echo(update_msg)
autotools/autoip/core.py CHANGED
@@ -7,71 +7,61 @@ import time
7
7
  import speedtest
8
8
  import psutil
9
9
 
10
+ # EXTRACTS IPV4 ADDRESSES FROM INTERFACE ADDRESSES
11
+ def _extract_ipv4_addresses(addrs):
12
+ ipv4_list = []
13
+ if netifaces.AF_INET in addrs:
14
+ for addr in addrs[netifaces.AF_INET]:
15
+ if 'addr' in addr and not addr['addr'].startswith('127.'):
16
+ ipv4_list.append(addr['addr'])
17
+ return ipv4_list
18
+
19
+ # EXTRACTS IPV6 ADDRESSES FROM INTERFACE ADDRESSES
20
+ def _extract_ipv6_addresses(addrs):
21
+ ipv6_list = []
22
+ if netifaces.AF_INET6 in addrs:
23
+ for addr in addrs[netifaces.AF_INET6]:
24
+ if 'addr' in addr and not addr['addr'].startswith('fe80:'):
25
+ clean_addr = addr['addr'].split('%')[0]
26
+ ipv6_list.append(clean_addr)
27
+ return ipv6_list
28
+
29
+ # RETRIEVES ALL LOCAL IP ADDRESSES (IPV4 AND IPV6) FROM NETWORK INTERFACES
10
30
  def get_local_ips():
11
- """GET LOCAL IPS"""
12
- ips = {'ipv4': [], 'ipv6': []} # INITIALIZE WITH EMPTY LISTS
13
-
14
- # GET LOCAL IPS
31
+ ips = {'ipv4': [], 'ipv6': []}
32
+
15
33
  for interface in netifaces.interfaces():
16
34
  addrs = netifaces.ifaddresses(interface)
17
-
18
- # GET IPV4
19
- if netifaces.AF_INET in addrs:
20
- for addr in addrs[netifaces.AF_INET]:
21
- if 'addr' in addr and not addr['addr'].startswith('127.'):
22
- ips['ipv4'].append(addr['addr'])
23
-
24
- # GET IPV6
25
- if netifaces.AF_INET6 in addrs:
26
- for addr in addrs[netifaces.AF_INET6]:
27
- if 'addr' in addr and not addr['addr'].startswith('fe80:'):
28
- # REMOVE SCOPE ID IF PRESENT
29
- clean_addr = addr['addr'].split('%')[0]
30
- ips['ipv6'].append(clean_addr)
31
-
35
+ ips['ipv4'].extend(_extract_ipv4_addresses(addrs))
36
+ ips['ipv6'].extend(_extract_ipv6_addresses(addrs))
37
+
32
38
  return ips
33
39
 
40
+ # RETRIEVES PUBLIC IP ADDRESSES (IPV4 AND IPV6) FROM EXTERNAL SERVICES
34
41
  def get_public_ips():
35
- """GET PUBLIC IPS"""
36
- ips = {'ipv4': None, 'ipv6': None} # INITIALIZE WITH NONE
37
-
38
- # TEST MULTIPLE IPV4 SERVICES
39
- ipv4_services = [
40
- 'https://api.ipify.org',
41
- 'https://ipv4.icanhazip.com',
42
- 'https://v4.ident.me'
43
- ]
44
-
45
- # GET PUBLIC IPV4
42
+ ips = {'ipv4': None, 'ipv6': None}
43
+ ipv4_services = ['https://api.ipify.org', 'https://ipv4.icanhazip.com', 'https://v4.ident.me']
44
+ ipv6_services = ['https://api6.ipify.org', 'https://ipv6.icanhazip.com', 'https://v6.ident.me']
45
+
46
46
  for service in ipv4_services:
47
47
  try:
48
48
  ips['ipv4'] = requests.get(service, timeout=2).text.strip()
49
49
  if ips['ipv4']: break
50
- except:
50
+ except (requests.RequestException, requests.Timeout, requests.ConnectionError):
51
51
  continue
52
52
 
53
- # TEST MULTIPLE IPV6 SERVICES
54
- ipv6_services = [
55
- 'https://api6.ipify.org',
56
- 'https://ipv6.icanhazip.com',
57
- 'https://v6.ident.me'
58
- ]
59
-
60
- # GET PUBLIC IPV6
61
53
  for service in ipv6_services:
62
54
  try:
63
55
  ips['ipv6'] = requests.get(service, timeout=2).text.strip()
64
56
  if ips['ipv6']: break
65
- except:
57
+ except (requests.RequestException, requests.Timeout, requests.ConnectionError):
66
58
  continue
67
59
 
68
60
  return ips
69
61
 
70
- # TEST CONNECTIVITY TO POPULAR SERVICES
62
+ # TESTS NETWORK CONNECTIVITY TO COMMON HOSTS
71
63
  def test_connectivity():
72
- """TEST CONNECTIVITY TO POPULAR SERVICES"""
73
-
74
- # TEST HOSTS
64
+ results = []
75
65
  test_hosts = {
76
66
  'Google DNS': ('8.8.8.8', 53),
77
67
  'CloudFlare DNS': ('1.1.1.1', 53),
@@ -79,10 +69,7 @@ def test_connectivity():
79
69
  'Cloudflare': ('cloudflare.com', 443),
80
70
  'GitHub': ('github.com', 443),
81
71
  }
82
-
83
- results = [] # INITIALIZE WITH EMPTY LIST
84
-
85
- # TEST EACH HOST
72
+
86
73
  for name, (host, port) in test_hosts.items():
87
74
  try:
88
75
  start = time.time()
@@ -90,31 +77,25 @@ def test_connectivity():
90
77
  latency = round((time.time() - start) * 1000, 2)
91
78
  s.close()
92
79
  results.append((name, True, latency))
93
- except:
80
+ except OSError:
94
81
  results.append((name, False, None))
95
-
82
+
96
83
  return results
97
84
 
98
- # RUN INTERNET SPEED TEST
85
+ # RUNS INTERNET SPEED TEST AND DISPLAYS RESULTS INCLUDING PING
99
86
  def run_speedtest():
100
- """RUN INTERNET SPEED TEST"""
101
87
  print("\nRunning speed test (this may take a minute)...")
102
-
103
- # RUN SPEED TEST
104
88
  try:
105
- # GET BEST SERVER
106
89
  st = speedtest.Speedtest()
107
90
  st.get_best_server()
108
-
109
- # TEST DOWNLOAD
91
+
110
92
  print("Testing download speed...")
111
- download_speed = st.download() / 1_000_000 # Convert to Mbps
112
-
113
- # TEST UPLOAD
93
+ download_speed = st.download() / 1_000_000 # CONVERT TO MBPS
94
+
114
95
  print("Testing upload speed...")
115
- upload_speed = st.upload() / 1_000_000 # Convert to Mbps
116
-
117
- # GET PING
96
+ upload_speed = st.upload() / 1_000_000 # CONVERT TO MBPS
97
+
98
+ print("Testing ping...")
118
99
  ping = st.results.ping
119
100
 
120
101
  print("\nSpeed Test Results:")
@@ -127,185 +108,155 @@ def run_speedtest():
127
108
  print(f"\nSpeed test failed: {str(e)}")
128
109
  return False
129
110
 
130
- # GET PUBLIC IP ADDRESS USING IPIFY API
111
+ # GETS PUBLIC IP ADDRESS USING EXTERNAL API SERVICES
131
112
  def get_public_ip():
132
- """GET PUBLIC IP ADDRESS USING IPIFY API"""
133
113
  try:
134
114
  response = requests.get('https://api.ipify.org')
135
115
  return response.text
136
116
  except requests.RequestException:
137
- # FALLBACK TO ANOTHER SERVICE IF IPIFY FAILS
138
117
  try:
139
118
  response = requests.get('https://api.ipapi.com/api/check')
140
119
  return response.json()['ip']
141
- except:
120
+ except (requests.RequestException, KeyError, ValueError):
142
121
  return None
143
122
 
144
- # GET LOCAL IP ADDRESS
123
+ # GETS LOCAL IP ADDRESS OF DEFAULT NETWORK INTERFACE
145
124
  def get_local_ip():
146
- """GET LOCAL IP ADDRESS"""
147
125
  try:
148
- # GET DEFAULT INTERFACE
149
126
  gateways = netifaces.gateways()
150
127
  default_interface = gateways['default'][netifaces.AF_INET][1]
151
-
152
- # GET IP FROM DEFAULT INTERFACE
153
128
  addrs = netifaces.ifaddresses(default_interface)
154
129
  return addrs[netifaces.AF_INET][0]['addr']
155
- except:
156
- # FALLBACK METHOD
130
+ except (KeyError, IndexError, OSError):
157
131
  try:
158
132
  s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
159
133
  s.connect(("8.8.8.8", 80))
160
134
  ip = s.getsockname()[0]
161
135
  s.close()
162
136
  return ip
163
- except:
137
+ except OSError:
164
138
  return None
165
139
 
166
- # GET IP INFORMATION USING IPAPI.CO
140
+ # RETRIEVES DETAILED INFORMATION ABOUT AN IP ADDRESS
167
141
  def get_ip_info(ip=None):
168
- """GET IP INFORMATION USING IPAPI.CO
169
-
170
- Args:
171
- ip (str, optional): IP address to get info for. If None, uses current IP.
172
-
173
- Returns:
174
- dict: Dictionary containing IP information
175
-
176
- Raises:
177
- ValueError: If IP is invalid or private
178
- """
179
142
  if ip:
180
- # VALIDATE IP
181
143
  try:
182
144
  ip_obj = ipaddress.ip_address(ip)
183
145
  if ip_obj.is_private:
184
146
  raise ValueError("Cannot get info for private IP addresses")
185
147
  except ValueError as e:
186
148
  raise ValueError(f"Invalid IP address: {str(e)}")
187
-
149
+
188
150
  try:
189
- # USE IPAPI.CO FOR IP INFO
190
151
  url = f'https://ipapi.co/{ip}/json' if ip else 'https://ipapi.co/json'
191
152
  response = requests.get(url)
192
153
  data = response.json()
193
-
194
- if 'error' in data:
195
- raise ValueError(f"Error getting IP info: {data['error']}")
196
-
154
+
155
+ if 'error' in data: raise ValueError(f"Error getting IP info: {data['error']}")
156
+
197
157
  return data
198
158
  except requests.RequestException as e:
199
159
  raise ValueError(f"Error connecting to IP info service: {str(e)}")
200
160
 
201
- # MAIN FUNCTION TO RUN IP TOOLS
202
- def run(test=False, speed=False, monitor=False, interval=1, ports=False, dns=False, location=False, no_ip=False):
203
- """MAIN FUNCTION TO RUN IP TOOLS
204
-
205
- Args:
206
- test (bool): Run connectivity tests
207
- speed (bool): Run speed test
208
- monitor (bool): Monitor network traffic
209
- interval (int): Monitoring interval in seconds
210
- ports (bool): Check common ports status
211
- dns (bool): Show DNS servers
212
- location (bool): Show IP location info
213
- no_ip (bool): Hide IP addresses
214
- """
215
- output = []
216
-
217
- # GET IP ADDRESSES IF NOT HIDDEN
218
- if not no_ip:
219
- local_ips = get_local_ips()
220
- public_ips = get_public_ips()
221
-
222
- output.append("\nLocal IPs:")
223
- if local_ips['ipv4']:
224
- for ip in local_ips['ipv4']:
225
- output.append(f"IPv4: {ip}")
226
- else:
227
- output.append("IPv4: Not available")
228
-
229
- if local_ips['ipv6']:
230
- for ip in local_ips['ipv6']:
231
- output.append(f"IPv6: {ip}")
232
- else:
233
- output.append("IPv6: Not available")
161
+ # DISPLAYS LOCAL AND PUBLIC IP ADDRESSES
162
+ def _display_ip_addresses(output):
163
+ local_ips = get_local_ips()
164
+ public_ips = get_public_ips()
165
+ output.append("\nLocal IPs:")
166
+
167
+ if local_ips['ipv4']:
168
+ for ip in local_ips['ipv4']: output.append(f"IPv4: {ip}")
169
+ else:
170
+ output.append("IPv4: Not available")
234
171
 
235
- output.append("\nPublic IPs:")
236
- output.append(f"IPv4: {public_ips['ipv4'] or 'Not available'}")
237
- output.append(f"IPv6: {public_ips['ipv6'] or 'Not available'}")
238
-
239
- # RUN CONNECTIVITY TESTS IF REQUESTED
240
- if test:
241
- output.append("\nConnectivity Tests:")
242
- results = test_connectivity()
243
- for name, success, latency in results:
244
- status = f"✓ {latency}ms" if success else "✗ Failed"
245
- output.append(f"{name:<15} {status}")
172
+ if local_ips['ipv6']:
173
+ for ip in local_ips['ipv6']: output.append(f"IPv6: {ip}")
174
+ else:
175
+ output.append("IPv6: Not available")
246
176
 
247
- # RUN SPEED TEST IF REQUESTED
177
+ output.append("\nPublic IPs:")
178
+ output.append(f"IPv4: {public_ips['ipv4'] or 'Not available'}")
179
+ output.append(f"IPv6: {public_ips['ipv6'] or 'Not available'}")
180
+
181
+ # DISPLAYS CONNECTIVITY TEST RESULTS
182
+ def _display_connectivity_tests(output):
183
+ output.append("\nConnectivity Tests:")
184
+ results = test_connectivity()
185
+ for name, success, latency in results:
186
+ status = f"✓ {latency}ms" if success else "✗ Failed"
187
+ output.append(f"{name:<15} {status}")
188
+
189
+ # DISPLAYS LOCATION INFORMATION
190
+ def _display_location_info(output):
191
+ try:
192
+ loc = get_ip_info()
193
+ output.append("\nLocation Info:")
194
+ output.append(f"City: {loc.get('city', 'Unknown')}")
195
+ output.append(f"Region: {loc.get('region', 'Unknown')}")
196
+ output.append(f"Country: {loc.get('country', 'Unknown')}")
197
+ output.append(f"ISP: {loc.get('org', 'Unknown')}")
198
+ except Exception as e:
199
+ output.append(f"\nLocation lookup failed: {str(e)}")
200
+
201
+ # DISPLAYS DNS SERVER INFORMATION
202
+ def _display_dns_servers(output):
203
+ output.append("\nDNS Servers:")
204
+ try:
205
+ with open('/etc/resolv.conf', 'r') as f:
206
+ for line in f:
207
+ if 'nameserver' in line: output.append(f"DNS: {line.split()[1]}")
208
+ except OSError:
209
+ output.append("Could not read DNS configuration")
210
+
211
+ # CHECKS AND DISPLAYS COMMON PORTS STATUS
212
+ def _display_ports_status(output):
213
+ common_ports = [80, 443, 22, 21, 25, 3306]
214
+ output.append("\nCommon Ports Status (localhost):")
215
+
216
+ for port in common_ports:
217
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
218
+ result = sock.connect_ex(('127.0.0.1', port))
219
+ status = "Open" if result == 0 else "Closed"
220
+ output.append(f"Port {port}: {status}")
221
+ sock.close()
222
+
223
+ # MONITORS NETWORK TRAFFIC
224
+ def _monitor_network_traffic(output, interval):
225
+ output.append("\nNetwork Monitor (Press Ctrl+C to stop):")
226
+ try:
227
+ prev_bytes_sent = psutil.net_io_counters().bytes_sent
228
+ prev_bytes_recv = psutil.net_io_counters().bytes_recv
229
+
230
+ while True:
231
+ time.sleep(interval)
232
+ bytes_sent = psutil.net_io_counters().bytes_sent
233
+ bytes_recv = psutil.net_io_counters().bytes_recv
234
+
235
+ upload_speed = (bytes_sent - prev_bytes_sent) / (1024 * interval)
236
+ download_speed = (bytes_recv - prev_bytes_recv) / (1024 * interval)
237
+
238
+ output.append(f"\rUp: {upload_speed:.2f} KB/s | Down: {download_speed:.2f} KB/s")
239
+
240
+ prev_bytes_sent = bytes_sent
241
+ prev_bytes_recv = bytes_recv
242
+
243
+ except KeyboardInterrupt:
244
+ output.append("\nMonitoring stopped")
245
+
246
+ # MAIN FUNCTION TO RUN NETWORK DIAGNOSTICS AND DISPLAY RESULTS
247
+ def run(test=False, speed=False, monitor=False, interval=1, ports=False, dns=False, location=False, no_ip=False):
248
+ output = []
249
+
250
+ if not no_ip: _display_ip_addresses(output)
251
+ if test: _display_connectivity_tests(output)
252
+ if location: _display_location_info(output)
253
+ if dns: _display_dns_servers(output)
254
+ if ports: _display_ports_status(output)
255
+ if monitor: _monitor_network_traffic(output, interval)
256
+
248
257
  if speed:
249
258
  output.append("\nRunning speed test...")
250
- if run_speedtest():
251
- output.append("Speed test completed successfully")
252
- else:
253
- output.append("Speed test failed")
254
-
255
- # DISPLAY LOCATION INFO IF REQUESTED
256
- if location:
257
- try:
258
- loc = get_ip_info()
259
- output.append("\nLocation Info:")
260
- output.append(f"City: {loc.get('city', 'Unknown')}")
261
- output.append(f"Region: {loc.get('region', 'Unknown')}")
262
- output.append(f"Country: {loc.get('country', 'Unknown')}")
263
- output.append(f"ISP: {loc.get('org', 'Unknown')}")
264
- except Exception as e:
265
- output.append(f"\nLocation lookup failed: {str(e)}")
266
-
267
- # DISPLAY DNS SERVERS IF REQUESTED
268
- if dns:
269
- output.append("\nDNS Servers:")
270
- try:
271
- with open('/etc/resolv.conf', 'r') as f:
272
- for line in f:
273
- if 'nameserver' in line:
274
- output.append(f"DNS: {line.split()[1]}")
275
- except:
276
- output.append("Could not read DNS configuration")
277
-
278
- # CHECK COMMON PORTS IF REQUESTED
279
- if ports:
280
- common_ports = [80, 443, 22, 21, 25, 3306]
281
- output.append("\nCommon Ports Status (localhost):")
282
- for port in common_ports:
283
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
284
- result = sock.connect_ex(('127.0.0.1', port))
285
- status = "Open" if result == 0 else "Closed"
286
- output.append(f"Port {port}: {status}")
287
- sock.close()
288
-
289
- # MONITOR NETWORK TRAFFIC IF REQUESTED
290
- if monitor:
291
- output.append("\nNetwork Monitor (Press Ctrl+C to stop):")
292
- try:
293
- prev_bytes_sent = psutil.net_io_counters().bytes_sent
294
- prev_bytes_recv = psutil.net_io_counters().bytes_recv
295
- while True:
296
- time.sleep(interval)
297
- bytes_sent = psutil.net_io_counters().bytes_sent
298
- bytes_recv = psutil.net_io_counters().bytes_recv
299
-
300
- # CALCULATE UPLOAD AND DOWNLOAD SPEEDS
301
- upload_speed = (bytes_sent - prev_bytes_sent) / (1024 * interval)
302
- download_speed = (bytes_recv - prev_bytes_recv) / (1024 * interval)
303
-
304
- output.append(f"\rUp: {upload_speed:.2f} KB/s | Down: {download_speed:.2f} KB/s")
305
-
306
- prev_bytes_sent = bytes_sent
307
- prev_bytes_recv = bytes_recv
308
- except KeyboardInterrupt:
309
- output.append("\nMonitoring stopped")
310
-
259
+ if run_speedtest(): output.append("Speed test completed successfully")
260
+ else: output.append("Speed test failed")
261
+
311
262
  return "\n".join(output)
@@ -3,15 +3,11 @@ from .core import autolower_transform
3
3
  from ..utils.loading import LoadingAnimation
4
4
  from ..utils.updates import check_for_updates
5
5
 
6
+ # CLI COMMAND TO TRANSFORM TEXT TO LOWERCASE
6
7
  @click.command()
7
8
  @click.argument('text', nargs=-1)
8
9
  def autolower(text):
9
- """Convert text to lowercase."""
10
- with LoadingAnimation():
11
- result = autolower_transform(" ".join(text))
10
+ with LoadingAnimation(): result = autolower_transform(" ".join(text))
12
11
  click.echo(result)
13
-
14
- # UPDATE CHECK AT THE END
15
12
  update_msg = check_for_updates()
16
- if update_msg:
17
- click.echo(update_msg)
13
+ if update_msg: click.echo(update_msg)
@@ -1,7 +1,8 @@
1
1
  import pyperclip
2
2
 
3
- # AUTOLOWERCASE CORE FUNCTION DEFINITION
3
+ # TRANSFORMS TEXT TO LOWERCASE AND COPIES IT TO CLIPBOARD
4
4
  def autolower_transform(text):
5
- transformed_text = text.lower() # TRANSFORM TEXT TO LOWERCASE
6
- pyperclip.copy(transformed_text) # COPY TRANSFORMED TEXT TO CLIPBOARD
5
+ transformed_text = text.lower()
6
+ try: pyperclip.copy(transformed_text)
7
+ except pyperclip.PyperclipException: pass
7
8
  return transformed_text
@@ -1,9 +1,10 @@
1
1
  import click
2
2
  import base64
3
- from .core import generate_password, generate_encryption_key, analyze_password_strength
4
3
  from ..utils.loading import LoadingAnimation
5
4
  from ..utils.updates import check_for_updates
5
+ from .core import generate_password, generate_encryption_key, analyze_password_strength
6
6
 
7
+ # CLI COMMAND TO GENERATE PASSWORDS OR ENCRYPTION KEYS
7
8
  @click.command()
8
9
  @click.option('--length', '-l', default=12, help='Password length (default: 12)')
9
10
  @click.option('--no-uppercase', '-u', is_flag=True, help='Exclude uppercase letters')
@@ -14,48 +15,44 @@ from ..utils.updates import check_for_updates
14
15
  @click.option('--analyze', '-a', is_flag=True, help='Analyze password strength')
15
16
  @click.option('--gen-key', '-g', is_flag=True, help='Generate encryption key')
16
17
  @click.option('--password-key', '-p', help='Generate key from password')
17
- def autopassword(length, no_uppercase, no_numbers, no_special,
18
- min_special, min_numbers, analyze, gen_key, password_key):
19
- """Generate secure passwords and encryption keys."""
20
-
18
+ def autopassword(length, no_uppercase, no_numbers, no_special, min_special, min_numbers, analyze, gen_key, password_key):
19
+ # DISPLAYS PASSWORD STRENGTH ANALYSIS RESULTS
21
20
  def show_analysis(text, prefix=""):
22
- """Helper function to show password/key analysis"""
23
- if analyze:
24
- with LoadingAnimation():
25
- analysis = analyze_password_strength(text)
26
- click.echo(f"\n{prefix}Strength Analysis:")
27
- click.echo(f"Strength: {analysis['strength']}")
28
- click.echo(f"Score: {analysis['score']}/5")
29
- if analysis['suggestions']:
30
- click.echo("\nSuggestions for improvement:")
31
- for suggestion in analysis['suggestions']:
32
- click.echo(f"- {suggestion}")
33
-
34
- # GENERATE KEY
21
+ if not analyze: return
22
+ with LoadingAnimation(): analysis = analyze_password_strength(text)
23
+
24
+ click.echo(f"\n{prefix}Strength Analysis:")
25
+ click.echo(f"Strength: {analysis['strength']}")
26
+ click.echo(f"Score: {analysis['score']}/5")
27
+
28
+ if analysis['suggestions']:
29
+ click.echo("\nSuggestions for improvement:")
30
+ for suggestion in analysis['suggestions']: click.echo(f"- {suggestion}")
31
+
32
+ # GENERATES ENCRYPTION KEY IF GEN_KEY FLAG IS SET
35
33
  if gen_key:
36
- with LoadingAnimation():
37
- key = generate_encryption_key()
34
+ with LoadingAnimation(): key = generate_encryption_key()
38
35
  key_str = key.decode()
39
36
  click.echo(f"Encryption Key: {key_str}")
40
- if analyze:
41
- show_analysis(key_str, "Key ")
37
+ if analyze: show_analysis(key_str, "Key ")
42
38
  return
43
39
 
44
- # GENERATE KEY FROM PASSWORD
40
+ # GENERATES ENCRYPTION KEY FROM PASSWORD IF PASSWORD_KEY FLAG IS SET
45
41
  if password_key:
46
- with LoadingAnimation():
47
- key, salt = generate_encryption_key(password_key)
42
+ with LoadingAnimation(): key, salt = generate_encryption_key(password_key)
48
43
  key_str = key.decode()
49
44
  click.echo(f"Derived Key: {key_str}")
50
45
  click.echo(f"Salt: {base64.b64encode(salt).decode()}")
46
+
51
47
  if analyze:
52
48
  click.echo("\nAnalyzing source password:")
53
49
  show_analysis(password_key, "Password ")
54
50
  click.echo("\nAnalyzing generated key:")
55
51
  show_analysis(key_str, "Key ")
52
+
56
53
  return
57
-
58
- # GENERATE PASSWORD
54
+
55
+ # GENERATES PASSWORD IF NO OTHER OPTIONS ARE SET
59
56
  with LoadingAnimation():
60
57
  password = generate_password(
61
58
  length=length,
@@ -65,12 +62,9 @@ def autopassword(length, no_uppercase, no_numbers, no_special,
65
62
  min_special=min_special,
66
63
  min_numbers=min_numbers,
67
64
  )
68
-
69
- # SHOW PASSWORD
65
+
70
66
  click.echo(f"Generated Password: {password}")
71
67
  show_analysis(password, "Password ")
72
-
73
- # UPDATE CHECK AT THE END
68
+
74
69
  update_msg = check_for_updates()
75
- if update_msg:
76
- click.echo(update_msg)
70
+ if update_msg: click.echo(update_msg)