Open-AutoTools 0.0.3rc5__py3-none-any.whl → 0.0.4__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.
- autotools/autocaps/commands.py +3 -7
- autotools/autocaps/core.py +5 -4
- autotools/autoip/commands.py +8 -12
- autotools/autoip/core.py +151 -200
- autotools/autolower/commands.py +3 -7
- autotools/autolower/core.py +4 -3
- autotools/autopassword/commands.py +27 -33
- autotools/autopassword/core.py +32 -73
- autotools/autotest/__init__.py +2 -0
- autotools/autotest/commands.py +206 -0
- autotools/cli.py +123 -62
- autotools/utils/commands.py +13 -0
- autotools/utils/loading.py +14 -6
- autotools/utils/performance.py +424 -0
- autotools/utils/requirements.py +21 -0
- autotools/utils/text.py +16 -0
- autotools/utils/updates.py +30 -22
- autotools/utils/version.py +69 -63
- open_autotools-0.0.4.dist-info/METADATA +84 -0
- open_autotools-0.0.4.dist-info/RECORD +30 -0
- {Open_AutoTools-0.0.3rc5.dist-info → open_autotools-0.0.4.dist-info}/WHEEL +1 -1
- {Open_AutoTools-0.0.3rc5.dist-info → open_autotools-0.0.4.dist-info}/entry_points.txt +0 -3
- Open_AutoTools-0.0.3rc5.dist-info/METADATA +0 -317
- Open_AutoTools-0.0.3rc5.dist-info/RECORD +0 -44
- autotools/autocaps/tests/__init__.py +0 -1
- autotools/autocaps/tests/test_autocaps_core.py +0 -45
- autotools/autocaps/tests/test_autocaps_integration.py +0 -46
- autotools/autodownload/__init__.py +0 -0
- autotools/autodownload/commands.py +0 -38
- autotools/autodownload/core.py +0 -433
- autotools/autoip/tests/__init__.py +0 -1
- autotools/autoip/tests/test_autoip_core.py +0 -72
- autotools/autoip/tests/test_autoip_integration.py +0 -92
- autotools/autolower/tests/__init__.py +0 -1
- autotools/autolower/tests/test_autolower_core.py +0 -45
- autotools/autolower/tests/test_autolower_integration.py +0 -46
- autotools/autospell/__init__.py +0 -3
- autotools/autospell/commands.py +0 -123
- autotools/autospell/core.py +0 -222
- autotools/autotranslate/__init__.py +0 -3
- autotools/autotranslate/commands.py +0 -42
- autotools/autotranslate/core.py +0 -52
- autotools/test/__init__.py +0 -3
- autotools/test/commands.py +0 -118
- {Open_AutoTools-0.0.3rc5.dist-info → open_autotools-0.0.4.dist-info/licenses}/LICENSE +0 -0
- {Open_AutoTools-0.0.3rc5.dist-info → open_autotools-0.0.4.dist-info}/top_level.txt +0 -0
autotools/autocaps/commands.py
CHANGED
|
@@ -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
|
-
|
|
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)
|
autotools/autocaps/core.py
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import pyperclip
|
|
2
2
|
|
|
3
|
-
#
|
|
3
|
+
# TRANSFORMS TEXT TO UPPERCASE AND COPIES IT TO CLIPBOARD
|
|
4
4
|
def autocaps_transform(text):
|
|
5
|
-
transformed_text = text.upper()
|
|
6
|
-
pyperclip.copy(transformed_text)
|
|
7
|
-
|
|
5
|
+
transformed_text = text.upper()
|
|
6
|
+
try: pyperclip.copy(transformed_text)
|
|
7
|
+
except pyperclip.PyperclipException: pass
|
|
8
|
+
return transformed_text
|
autotools/autoip/commands.py
CHANGED
|
@@ -2,7 +2,9 @@ import click
|
|
|
2
2
|
from .core import run
|
|
3
3
|
from ..utils.loading import LoadingAnimation
|
|
4
4
|
from ..utils.updates import check_for_updates
|
|
5
|
+
from ..utils.text import safe_text
|
|
5
6
|
|
|
7
|
+
# CLI COMMAND TO DISPLAY NETWORK INFORMATION AND RUN DIAGNOSTICS
|
|
6
8
|
@click.command()
|
|
7
9
|
@click.option('--test', '-t', is_flag=True, help='Run connectivity tests')
|
|
8
10
|
@click.option('--speed', '-s', is_flag=True, help='Run internet speed test')
|
|
@@ -13,17 +15,11 @@ from ..utils.updates import check_for_updates
|
|
|
13
15
|
@click.option('--location', '-l', is_flag=True, help='Show IP location info')
|
|
14
16
|
@click.option('--no-ip', '-n', is_flag=True, help='Hide IP addresses')
|
|
15
17
|
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
18
|
with LoadingAnimation():
|
|
22
|
-
output = run(
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
19
|
+
output = run(
|
|
20
|
+
test=test, speed=speed, monitor=monitor, interval=interval,
|
|
21
|
+
ports=ports, dns=dns, location=location, no_ip=no_ip
|
|
22
|
+
)
|
|
23
|
+
click.echo(safe_text(output))
|
|
27
24
|
update_msg = check_for_updates()
|
|
28
|
-
if update_msg:
|
|
29
|
-
click.echo(update_msg)
|
|
25
|
+
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
|
-
|
|
12
|
-
|
|
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
|
-
|
|
19
|
-
|
|
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
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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
|
-
#
|
|
62
|
+
# TESTS NETWORK CONNECTIVITY TO COMMON HOSTS
|
|
71
63
|
def test_connectivity():
|
|
72
|
-
|
|
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
|
-
#
|
|
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
|
|
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
|
|
116
|
-
|
|
117
|
-
|
|
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
|
-
#
|
|
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
|
-
#
|
|
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
|
-
#
|
|
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
|
-
|
|
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
|
-
#
|
|
202
|
-
def
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
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
|
-
|
|
236
|
-
output.append(f"
|
|
237
|
-
|
|
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
|
-
|
|
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"OK {latency}ms" if success else "X 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
|
-
|
|
252
|
-
|
|
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)
|
autotools/autolower/commands.py
CHANGED
|
@@ -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
|
-
|
|
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)
|
autotools/autolower/core.py
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import pyperclip
|
|
2
2
|
|
|
3
|
-
#
|
|
3
|
+
# TRANSFORMS TEXT TO LOWERCASE AND COPIES IT TO CLIPBOARD
|
|
4
4
|
def autolower_transform(text):
|
|
5
|
-
transformed_text = text.lower()
|
|
6
|
-
pyperclip.copy(transformed_text)
|
|
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
|
-
|
|
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
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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
|
-
#
|
|
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
|
-
#
|
|
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)
|