Open-AutoTools 0.0.1__py3-none-any.whl → 0.0.2__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.
@@ -0,0 +1,4 @@
1
+ Metadata-Version: 2.2
2
+ Name: Open-AutoTools
3
+ Version: 0.0.2
4
+ License-File: LICENSE
@@ -0,0 +1,20 @@
1
+ autotools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ autotools/cli.py,sha256=VWQgHF0WuAD9XGtqaF48EHF5pczrg7VCq-w_wylV9Tc,7167
3
+ autotools/autocaps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ autotools/autocaps/core.py,sha256=NnOacVp0kMoq__KHWi5UMcApSuq6Iyo5bFxN40dRw7U,253
5
+ autotools/autoip/__init__.py,sha256=T_5hz9G4reFPXDucdzRoMFPYlAKwTPt9TejOpkRPgn0,23
6
+ autotools/autoip/core.py,sha256=_Gy8QyDIUaQmfBF6CIP3Ju3_KYbZhs2mst9Vm0sPQUI,6940
7
+ autotools/autolower/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ autotools/autolower/core.py,sha256=vjM2ognA3tDCbv10a9vta9WPuAiqTPjOXZ1JHL_b-nk,260
9
+ autotools/autotranslate/__init__.py,sha256=6BxuZqhyQhfsZ5x7DkB1BAEpC08GT_5l5bl0AY_eLpU,64
10
+ autotools/autotranslate/core.py,sha256=-QdWBIF-eNbuN5qhf45BlOzaOkckwhaF4IMG3OOeRcw,1383
11
+ autotools/downloader/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
+ autotools/downloader/core.py,sha256=xmQSEEi3UYPkbbwsL-H4vGKcpqLCkwhIYlZxDWrIEpI,8266
13
+ autotools/password/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
14
+ autotools/password/core.py,sha256=GQrd-QGWpgxuq6Nf28URcTZRku8Gji1NfpbecXAsIF0,3146
15
+ Open_AutoTools-0.0.2.dist-info/LICENSE,sha256=SpbSRxNWos2l0-geleCa6d0L9G_bOsZRkY4rB9OduJ0,1069
16
+ Open_AutoTools-0.0.2.dist-info/METADATA,sha256=3voGwJ-WYx4RNm5sgB1o0SAyF8azU8UmwS91J-IXk9c,80
17
+ Open_AutoTools-0.0.2.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
18
+ Open_AutoTools-0.0.2.dist-info/entry_points.txt,sha256=NVN0wuAVjff3e4_MyceS5o22V_l7_0R_wT2adgvWAlY,282
19
+ Open_AutoTools-0.0.2.dist-info/top_level.txt,sha256=x5ZRvdQw7DQnVmR0YDqVSAuuS94KTHDmk6uIeW7YOPw,10
20
+ Open_AutoTools-0.0.2.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (74.1.2)
2
+ Generator: setuptools (75.8.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,6 +1,8 @@
1
1
  [console_scripts]
2
2
  autocaps = autotools.cli:autocaps
3
- autocorrect = autotools.cli:autocorrect
4
3
  autodownload = autotools.cli:autodownload
4
+ autoip = autotools.cli:autoip
5
+ autolower = autotools.cli:autolower
6
+ autopassword = autotools.cli:autopassword
5
7
  autotools = autotools.cli:autotools
6
8
  autotranslate = autotools.cli:autotranslate
@@ -0,0 +1 @@
1
+ from .core import run
@@ -0,0 +1,218 @@
1
+ import socket
2
+ import requests
3
+ import netifaces
4
+ import time
5
+ import speedtest
6
+ import psutil
7
+
8
+ def get_local_ips():
9
+ """GET LOCAL IPS"""
10
+ ips = {'ipv4': [], 'ipv6': []} # INITIALIZE WITH EMPTY LISTS
11
+
12
+ # GET LOCAL IPS
13
+ for interface in netifaces.interfaces():
14
+ addrs = netifaces.ifaddresses(interface)
15
+
16
+ # GET IPV4
17
+ if netifaces.AF_INET in addrs:
18
+ for addr in addrs[netifaces.AF_INET]:
19
+ if 'addr' in addr and not addr['addr'].startswith('127.'):
20
+ ips['ipv4'].append(addr['addr'])
21
+
22
+ # GET IPV6
23
+ if netifaces.AF_INET6 in addrs:
24
+ for addr in addrs[netifaces.AF_INET6]:
25
+ if 'addr' in addr and not addr['addr'].startswith('fe80:'):
26
+ # REMOVE SCOPE ID IF PRESENT
27
+ clean_addr = addr['addr'].split('%')[0]
28
+ ips['ipv6'].append(clean_addr)
29
+
30
+ return ips
31
+
32
+ def get_public_ips():
33
+ """GET PUBLIC IPS"""
34
+ ips = {'ipv4': None, 'ipv6': None} # INITIALIZE WITH NONE
35
+
36
+ # TEST MULTIPLE IPV4 SERVICES
37
+ ipv4_services = [
38
+ 'https://api.ipify.org',
39
+ 'https://ipv4.icanhazip.com',
40
+ 'https://v4.ident.me'
41
+ ]
42
+
43
+ # GET PUBLIC IPV4
44
+ for service in ipv4_services:
45
+ try:
46
+ ips['ipv4'] = requests.get(service, timeout=2).text.strip()
47
+ if ips['ipv4']: break
48
+ except:
49
+ continue
50
+
51
+ # TEST MULTIPLE IPV6 SERVICES
52
+ ipv6_services = [
53
+ 'https://api6.ipify.org',
54
+ 'https://ipv6.icanhazip.com',
55
+ 'https://v6.ident.me'
56
+ ]
57
+
58
+ # GET PUBLIC IPV6
59
+ for service in ipv6_services:
60
+ try:
61
+ ips['ipv6'] = requests.get(service, timeout=2).text.strip()
62
+ if ips['ipv6']: break
63
+ except:
64
+ continue
65
+
66
+ return ips
67
+
68
+ # TEST CONNECTIVITY TO POPULAR SERVICES
69
+ def test_connectivity():
70
+ """TEST CONNECTIVITY TO POPULAR SERVICES"""
71
+
72
+ # TEST HOSTS
73
+ test_hosts = {
74
+ 'Google DNS': ('8.8.8.8', 53),
75
+ 'CloudFlare DNS': ('1.1.1.1', 53),
76
+ 'Google': ('google.com', 443),
77
+ 'Cloudflare': ('cloudflare.com', 443),
78
+ 'GitHub': ('github.com', 443),
79
+ }
80
+
81
+ results = [] # INITIALIZE WITH EMPTY LIST
82
+
83
+ # TEST EACH HOST
84
+ for name, (host, port) in test_hosts.items():
85
+ try:
86
+ start = time.time()
87
+ s = socket.create_connection((host, port), timeout=2)
88
+ latency = round((time.time() - start) * 1000, 2)
89
+ s.close()
90
+ results.append((name, True, latency))
91
+ except:
92
+ results.append((name, False, None))
93
+
94
+ return results
95
+
96
+ # RUN INTERNET SPEED TEST
97
+ def run_speedtest():
98
+ """RUN INTERNET SPEED TEST"""
99
+ print("\nRunning speed test (this may take a minute)...")
100
+
101
+ # RUN SPEED TEST
102
+ try:
103
+ # GET BEST SERVER
104
+ st = speedtest.Speedtest()
105
+ st.get_best_server()
106
+
107
+ # TEST DOWNLOAD
108
+ print("Testing download speed...")
109
+ download_speed = st.download() / 1_000_000 # Convert to Mbps
110
+
111
+ # TEST UPLOAD
112
+ print("Testing upload speed...")
113
+ upload_speed = st.upload() / 1_000_000 # Convert to Mbps
114
+
115
+ # GET PING
116
+ ping = st.results.ping
117
+
118
+ print("\nSpeed Test Results:")
119
+ print(f"Download: {download_speed:.2f} Mbps")
120
+ print(f"Upload: {upload_speed:.2f} Mbps")
121
+ print(f"Ping: {ping:.0f} ms")
122
+
123
+ return True
124
+ except Exception as e:
125
+ print(f"\nSpeed test failed: {str(e)}")
126
+ return False
127
+
128
+ def run(test=False, speed=False, monitor=False, ports=False, dns=False, location=False, no_ip=False):
129
+ """MAIN FUNCTION"""
130
+ # GET LOCAL AND PUBLIC IPS
131
+ local = get_local_ips()
132
+ public = get_public_ips()
133
+
134
+ # DISPLAY IPS IF NOT HIDDEN
135
+ if not no_ip:
136
+ print("\nLocal IPs:")
137
+ if local['ipv4']:
138
+ for ip in local['ipv4']:
139
+ print(f"IPv4: {ip}")
140
+ else:
141
+ print("IPv4: Not available")
142
+
143
+ if local['ipv6']:
144
+ for ip in local['ipv6']:
145
+ print(f"IPv6: {ip}")
146
+ else:
147
+ print("IPv6: Not available")
148
+
149
+ print("\nPublic IPs:")
150
+ print(f"IPv4: {public['ipv4'] or 'Not available'}")
151
+ print(f"IPv6: {public['ipv6'] or 'Not available'}")
152
+
153
+ # RUN CONNECTIVITY TESTS IF REQUESTED
154
+ if test:
155
+ print("\nConnectivity Tests:")
156
+ results = test_connectivity()
157
+ for name, success, latency in results:
158
+ status = f"✓ {latency}ms" if success else "✗ Failed"
159
+ print(f"{name:<15} {status}")
160
+
161
+ # RUN SPEED TEST IF REQUESTED
162
+ if speed:
163
+ run_speedtest()
164
+
165
+ # DISPLAY LOCATION INFO IF REQUESTED
166
+ if location:
167
+ try:
168
+ loc = requests.get('https://ipapi.co/json/').json()
169
+ print("\nLocation Info:")
170
+ print(f"City: {loc.get('city', 'Unknown')}")
171
+ print(f"Region: {loc.get('region', 'Unknown')}")
172
+ print(f"Country: {loc.get('country_name', 'Unknown')}")
173
+ print(f"ISP: {loc.get('org', 'Unknown')}")
174
+ except:
175
+ print("\nLocation lookup failed")
176
+
177
+ # DISPLAY DNS SERVERS IF REQUESTED
178
+ if dns:
179
+ print("\nDNS Servers:")
180
+ try:
181
+ with open('/etc/resolv.conf', 'r') as f:
182
+ for line in f:
183
+ if 'nameserver' in line:
184
+ print(f"DNS: {line.split()[1]}")
185
+ except:
186
+ print("Could not read DNS configuration")
187
+
188
+ # CHECK COMMON PORTS IF REQUESTED
189
+ if ports:
190
+ common_ports = [80, 443, 22, 21, 25, 3306]
191
+ print("\nCommon Ports Status (localhost):")
192
+ for port in common_ports:
193
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
194
+ result = sock.connect_ex(('127.0.0.1', port))
195
+ status = "Open" if result == 0 else "Closed"
196
+ print(f"Port {port}: {status}")
197
+ sock.close()
198
+
199
+ # MONITOR NETWORK TRAFFIC IF REQUESTED
200
+ if monitor:
201
+ print("\nNetwork Monitor (Press Ctrl+C to stop):")
202
+ try:
203
+ prev_bytes_sent = psutil.net_io_counters().bytes_sent
204
+ prev_bytes_recv = psutil.net_io_counters().bytes_recv
205
+ while True:
206
+ time.sleep(1)
207
+ bytes_sent = psutil.net_io_counters().bytes_sent
208
+ bytes_recv = psutil.net_io_counters().bytes_recv
209
+
210
+ upload_speed = (bytes_sent - prev_bytes_sent) / 1024 # KB/s
211
+ download_speed = (bytes_recv - prev_bytes_recv) / 1024 # KB/s
212
+
213
+ print(f"\rUp: {upload_speed:.2f} KB/s | Down: {download_speed:.2f} KB/s", end='')
214
+
215
+ prev_bytes_sent = bytes_sent
216
+ prev_bytes_recv = bytes_recv
217
+ except KeyboardInterrupt:
218
+ print("\nMonitoring stopped")
@@ -0,0 +1,7 @@
1
+ import pyperclip
2
+
3
+ # AUTOLOWERCASE CORE FUNCTION DEFINITION
4
+ def autolower_transform(text):
5
+ transformed_text = text.lower() # TRANSFORM TEXT TO LOWERCASE
6
+ pyperclip.copy(transformed_text) # COPY TRANSFORMED TEXT TO CLIPBOARD
7
+ return transformed_text
@@ -0,0 +1,3 @@
1
+ from .core import translate_text
2
+
3
+ __all__ = ['translate_text']
@@ -1,39 +1,40 @@
1
- import requests
2
- import os
1
+ from deep_translator import GoogleTranslator
2
+ from langdetect import detect
3
3
  import pyperclip
4
4
 
5
- # PARAMETERS API
6
- BASE_URL = "https://google-translate113.p.rapidapi.com/api/v1/translator/{}"
7
- HEADERS = {
8
- "X-RapidAPI-Key": os.getenv('RAPIDAPI_API_KEY'),
9
- "X-RapidAPI-Host": "google-translate113.p.rapidapi.com"
10
- }
11
-
12
-
13
- # FUNCTION TO GET SUPPORTED LANGUAGES
14
- def autotranslate_supported_languages():
15
- endpoint = "support-languages"
16
- full_url = BASE_URL.format(endpoint)
17
- response = requests.get(full_url, headers=HEADERS)
18
- languages = response.json()
19
-
20
- language_codes = [lang['code'] for lang in languages]
21
- return language_codes
22
-
23
-
24
- # FUNCTION TO TRANSLATE TEXT AND COPY TO CLIPBOARD
25
- def autotranslate_text(text, language_target):
26
- endpoint = "text"
27
- full_url = BASE_URL.format(endpoint)
28
- payload = {"from": "auto", "to": language_target, "text": text}
29
- specific_headers = {
30
- **HEADERS, "content-type": "application/x-www-form-urlencoded"
31
- }
32
-
33
- response = requests.post(full_url, data=payload, headers=specific_headers)
34
- translated_text = response.json()['trans']
35
-
36
- # COPY TRANSLATED TEXT TO CLIPBOARD
37
- pyperclip.copy(translated_text)
38
-
39
- return translated_text
5
+ def get_supported_languages() -> dict:
6
+ """GET ALL SUPPORTED LANGUAGES FROM GOOGLE TRANSLATE"""
7
+ # GET LANGUAGES CODES
8
+ langs = GoogleTranslator().get_supported_languages(as_dict=True)
9
+ # SORT BY LANGUAGE NAME
10
+ return dict(sorted(langs.items(), key=lambda x: x[1].lower()))
11
+
12
+ def translate_text(text: str, to_lang: str = 'en', from_lang: str = None,
13
+ copy: bool = False, detect_lang: bool = False) -> str:
14
+ """TRANSLATE TEXT TO SPECIFIED LANGUAGE
15
+
16
+ ARGS:
17
+ text (str): TEXT TO TRANSLATE
18
+ to_lang (str): TARGET LANGUAGE CODE (DEFAULT: EN)
19
+ from_lang (str): SOURCE LANGUAGE CODE (DEFAULT: AUTO-DETECT)
20
+ copy (bool): COPY RESULT TO CLIPBOARD
21
+ detect_lang (bool): SHOW DETECTED SOURCE LANGUAGE
22
+
23
+ RETURNS:
24
+ str: TRANSLATED TEXT
25
+ """
26
+ # AUTO-DETECT SOURCE LANGUAGE IF NOT SPECIFIED
27
+ source_lang = from_lang or detect(text)
28
+
29
+ # TRANSLATE
30
+ translator = GoogleTranslator(source=source_lang, target=to_lang)
31
+ result = translator.translate(text)
32
+
33
+ # COPY TO CLIPBOARD IF REQUESTED
34
+ if copy:
35
+ pyperclip.copy(result)
36
+
37
+ # RETURN RESULT WITH DETECTED LANGUAGE IF REQUESTED
38
+ if detect_lang:
39
+ return f"[Detected: {source_lang}] {result}"
40
+ return result
autotools/cli.py CHANGED
@@ -1,17 +1,24 @@
1
- from dotenv import load_dotenv
2
- load_dotenv() # LOAD ENVIRONMENT VARIABLES BEFORE IMPORTING OTHER MODULES BECAUSE CERTAIN MODULES DEPEND ON ENVIRONMENT VARIABLES
3
-
4
1
  import os
5
2
  import click
6
- from autotools.autotranslate.core import autotranslate_text, autotranslate_supported_languages
7
- from autotools.autocorrect.core import autocorrect_text
3
+ import base64
8
4
  from autotools.autocaps.core import autocaps_transform
5
+ from autotools.autolower.core import autolower_transform
9
6
  from autotools.downloader.core import download_youtube_video, download_file
7
+ from autotools.password.core import (
8
+ generate_password,
9
+ generate_encryption_key,
10
+ analyze_password_strength
11
+ )
12
+ from translate import Translator
13
+ from autotools.autotranslate.core import translate_text, get_supported_languages
14
+ import yt_dlp
15
+ from autotools import downloader, autolower, autocaps, autoip
16
+ import argparse
10
17
 
11
18
  # CLI FUNCTION DEFINITION
12
19
  @click.group()
13
20
  def cli():
14
- """Autotools is a set of tools for text capitalization, correction and translation."""
21
+ """Autotools is a set of tools for text capitalization and file downloading."""
15
22
  pass
16
23
 
17
24
  # AUTOTOOLS COMMAND LINE INTERFACE FUNCTION DEFINITION FOR SHOW HELP MESSAGE
@@ -26,30 +33,13 @@ def autocaps(text):
26
33
  result = autocaps_transform(text)
27
34
  click.echo(result)
28
35
 
29
- # AUTOCORRECT COMMAND LINE INTERFACE FUNCTION DEFINITION
36
+ # AUTOLOWER CASE COMMAND LINE INTERFACE FUNCTION DEFINITION
30
37
  @cli.command()
31
38
  @click.argument('text')
32
- def autocorrect(text):
33
- result = autocorrect_text(text)
39
+ def autolower(text):
40
+ result = autolower_transform(text)
34
41
  click.echo(result)
35
42
 
36
- # AUTOTRANSLATE COMMAND LINE INTERFACE FUNCTION DEFINITION
37
- VALID_LANGUAGES = autotranslate_supported_languages() # VALID LANGUAGES FOR TRANSLATION
38
- @cli.command()
39
- @click.argument('text')
40
- #@click.option('--from', 'language_origin', required=True, help="Language of the source text")
41
- @click.option('--to', 'language_target', required=True, help="Target language for translation")
42
- def autotranslate(text, language_target):
43
- if language_target not in VALID_LANGUAGES:
44
- click.secho(f"Language code '{
45
- language_target}' is not supported.", fg='red')
46
- return
47
-
48
- # CALL TO AUTOTRANSLATE FUNCTION
49
- result = autotranslate_text(
50
- text, language_target=language_target)
51
- click.secho(result)
52
-
53
43
  # AUTODOWNLOAD COMMAND LINE INTERFACE FUNCTION DEFINITION
54
44
  @cli.command()
55
45
  @click.argument('url')
@@ -61,6 +51,133 @@ def autodownload(url, format, quality):
61
51
  else:
62
52
  download_file(url)
63
53
 
54
+ # AUTOPASSWORD COMMAND LINE INTERFACE FUNCTION DEFINITION
55
+ @cli.command()
56
+ @click.option('--length', '-l', default=12, help='Password length (default: 12)')
57
+ @click.option('--no-uppercase', is_flag=True, help='Exclude uppercase letters')
58
+ @click.option('--no-numbers', is_flag=True, help='Exclude numbers')
59
+ @click.option('--no-special', is_flag=True, help='Exclude special characters')
60
+ @click.option('--min-special', default=1, help='Minimum number of special characters')
61
+ @click.option('--min-numbers', default=1, help='Minimum number of numbers')
62
+ @click.option('--analyze', is_flag=True, help='Analyze password strength')
63
+ @click.option('--gen-key', is_flag=True, help='Generate encryption key')
64
+ @click.option('--password-key', help='Generate key from password')
65
+ def autopassword(length, no_uppercase, no_numbers, no_special,
66
+ min_special, min_numbers, analyze, gen_key, password_key):
67
+ """Generate secure passwords and encryption keys."""
68
+
69
+ ## HELPER FUNCTION TO SHOW PASSWORD/KEY ANALYSIS
70
+ def show_analysis(text, prefix=""):
71
+ """Helper function to show password/key analysis"""
72
+ if analyze:
73
+ analysis = analyze_password_strength(text)
74
+ click.echo(f"\n{prefix}Strength Analysis:")
75
+ click.echo(f"Strength: {analysis['strength']}")
76
+ click.echo(f"Score: {analysis['score']}/5")
77
+ if analysis['suggestions']:
78
+ click.echo("\nSuggestions for improvement:")
79
+ for suggestion in analysis['suggestions']:
80
+ click.echo(f"- {suggestion}")
81
+
82
+ # GENERATE KEY
83
+ if gen_key:
84
+ key = generate_encryption_key()
85
+ key_str = key.decode()
86
+ click.echo(f"Encryption Key: {key_str}")
87
+ if analyze:
88
+ show_analysis(key_str, "Key ")
89
+ return
90
+
91
+ # GENERATE KEY FROM PASSWORD
92
+ if password_key:
93
+ key, salt = generate_encryption_key(password_key)
94
+ key_str = key.decode()
95
+ click.echo(f"Derived Key: {key_str}")
96
+ click.echo(f"Salt: {base64.b64encode(salt).decode()}")
97
+ if analyze:
98
+ click.echo("\nAnalyzing source password:")
99
+ show_analysis(password_key, "Password ")
100
+ click.echo("\nAnalyzing generated key:")
101
+ show_analysis(key_str, "Key ")
102
+ return
103
+
104
+ # GENERATE PASSWORD
105
+ password = generate_password(
106
+ length=length,
107
+ use_uppercase=not no_uppercase,
108
+ use_numbers=not no_numbers,
109
+ use_special=not no_special,
110
+ min_special=min_special,
111
+ min_numbers=min_numbers,
112
+ )
113
+
114
+ # SHOW PASSWORD
115
+ click.echo(f"Generated Password: {password}")
116
+ show_analysis(password, "Password ")
117
+
118
+ # TRANSLATE COMMAND LINE INTERFACE FUNCTION DEFINITION
119
+ @cli.command()
120
+ @click.argument('text', required=False)
121
+ @click.option('--to', default='en', help='Target language (default: en)')
122
+ @click.option('--from', 'from_lang', help='Source language (default: auto-detect)')
123
+ @click.option('--list-languages', is_flag=True, help='List all supported languages')
124
+ @click.option('--copy', is_flag=True, help='Copy translation to clipboard')
125
+ @click.option('--detect', is_flag=True, help='Show detected source language')
126
+ def autotranslate(text: str, to: str, from_lang: str, list_languages: bool,
127
+ copy: bool, detect: bool):
128
+ """TRANSLATE TEXT TO SPECIFIED LANGUAGE (AUTO-DETECTS SOURCE LANGUAGE)"""
129
+
130
+ # LIST ALL SUPPORTED LANGUAGES
131
+ if list_languages:
132
+ click.echo("\nSupported Languages:")
133
+ for code, name in get_supported_languages().items():
134
+ click.echo(f"{code:<8} {name}")
135
+ return
136
+
137
+ # CHECK IF TEXT IS PROVIDED
138
+ if not text:
139
+ click.echo("Error: Please provide text to translate")
140
+ return
141
+
142
+ result = translate_text(text, to_lang=to, from_lang=from_lang,
143
+ copy=copy, detect_lang=detect)
144
+ click.echo(result)
145
+
146
+ # AUTOIP COMMAND LINE INTERFACE FUNCTION DEFINITION
147
+ @cli.command()
148
+ @click.option('--test', '-t', is_flag=True, help='Run connectivity tests')
149
+ @click.option('--speed', '-s', is_flag=True, help='Run internet speed test')
150
+ @click.option('--monitor', '-m', is_flag=True, help='Monitor network traffic')
151
+ @click.option('--ports', '-p', is_flag=True, help='Check common ports status')
152
+ @click.option('--dns', '-d', is_flag=True, help='Show DNS servers')
153
+ @click.option('--location', '-l', is_flag=True, help='Show IP location info')
154
+ @click.option('--no-ip', '-n', is_flag=True, help='Hide IP addresses display')
155
+ def autoip(test, speed, monitor, ports, dns, location, no_ip):
156
+ """DISPLAY LOCAL AND PUBLIC IP ADDRESSES"""
157
+ from autotools import autoip
158
+ autoip.run(test, speed, monitor, ports, dns, location, no_ip)
159
+
64
160
  # MAIN FUNCTION TO RUN CLI
65
161
  if __name__ == '__main__':
66
162
  cli()
163
+
164
+ def download_video(url):
165
+ try:
166
+ # CONFIGURE YT-DLP WITH COOKIES AND HEADERS
167
+ yt_opts = {
168
+ 'cookiefile': '~/cookies.txt',
169
+ 'headers': {
170
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
171
+ }
172
+ }
173
+ with yt_dlp.YoutubeDL(yt_opts) as ydl:
174
+ ydl.download([url])
175
+ return True
176
+ except Exception as e:
177
+ print(f"ERROR: {str(e)}")
178
+ return False
179
+
180
+ # REMOVE OR COMMENT OUT THE NEW ARGPARSE-BASED MAIN FUNCTION
181
+ # def main():
182
+ # parser = argparse.ArgumentParser()
183
+ # ...
@@ -6,6 +6,7 @@ from tqdm import tqdm
6
6
  import yt_dlp
7
7
  import platform
8
8
  import subprocess
9
+ import json
9
10
 
10
11
 
11
12
  # FUNCTION TO GET DEFAULT DOWNLOAD DIRECTORY
@@ -76,53 +77,91 @@ def download_file(url):
76
77
  except requests.exceptions.RequestException as e:
77
78
  print(f"Error during file download: {e}")
78
79
 
80
+ # FUNCTION TO GET CONSENT FILE PATH
81
+ def get_consent_file_path():
82
+ """GET PATH TO STORE CONSENT STATUS"""
83
+ return Path.home() / '.autotools' / 'consent.json'
84
+
85
+ # FUNCTION TO LOAD CONSENT STATUS
86
+ def load_consent_status():
87
+ """LOAD SAVED CONSENT STATUS"""
88
+ consent_file = get_consent_file_path()
89
+
90
+ # CHECK IF CONSENT FILE EXISTS
91
+ if consent_file.exists():
92
+ try:
93
+ with open(consent_file) as f:
94
+ return json.load(f).get('youtube_consent', False)
95
+ except:
96
+ return False
97
+ return False
98
+
99
+ # FUNCTION TO SAVE CONSENT STATUS
100
+ def save_consent_status(status):
101
+ """SAVE CONSENT STATUS"""
102
+ consent_file = get_consent_file_path()
103
+ consent_file.parent.mkdir(exist_ok=True)
104
+
105
+ # SAVE CONSENT STATUS TO FILE
106
+ with open(consent_file, 'w') as f:
107
+ json.dump({'youtube_consent': status}, f)
108
+
109
+ # FUNCTION TO GET USER CONSENT WITH INTERACTIVE PROMPT
110
+ def get_user_consent():
111
+ """GET USER CONSENT WITH INTERACTIVE PROMPT"""
112
+ print("\n⚠️ Important Notice:")
113
+ print("This tool will:")
114
+ print("1. Access your Chrome browser cookies")
115
+ print("2. Use them to authenticate with YouTube")
116
+ print("3. Download video content to your local machine")
117
+
118
+ # GET USER CONSENT WITH INTERACTIVE PROMPT
119
+ while True:
120
+ response = input("\nDo you consent to these actions? (yes/no): ").lower()
121
+ if response in ['yes', 'y']:
122
+ save_consent_status(True)
123
+ return True
124
+ elif response in ['no', 'n']:
125
+ save_consent_status(False)
126
+ return False
127
+ print("Please answer 'yes' or 'no'")
79
128
 
80
- # FUNCTION TO DOWNLOAD YOUTUBE VIDEOS WITH YT-DLP AND SPECIFIED FORMAT AND QUALITY
81
- def download_youtube_video(url, file_format='mp4', quality='best'):
82
- # First, validate the YouTube URL
83
- if not validate_youtube_url(url):
84
- print(f"Aborting download: Invalid URL {url}")
85
- return
86
-
87
- download_dir = get_default_download_dir()
88
129
 
89
- video_formats = {
90
- '1440p': 'bestvideo[height<=1440]+bestaudio/best[height<=1440]',
91
- '1080p': 'bestvideo[height<=1080]+bestaudio/best[height<=1080]',
92
- '720p': 'bestvideo[height<=720]+bestaudio/best[height<=720]',
93
- '480p': 'bestvideo[height<=480]+bestaudio/best[height<=480]',
94
- '360p': 'bestvideo[height<=360]+bestaudio/best[height<=360]',
95
- '240p': 'bestvideo[height<=240]+bestaudio/best[height<=240]',
96
- 'best': 'bestvideo+bestaudio/best'
97
- }
98
-
99
- selected_format = video_formats.get(quality, video_formats['best'])
130
+ # FUNCTION TO DOWNLOAD YOUTUBE VIDEOS WITH YT-DLP AND SPECIFIED FORMAT AND QUALITY
131
+ def download_youtube_video(url, format='mp4', quality='best'):
132
+ """DOWNLOAD VIDEO WITH CONSENT CHECK"""
133
+ # CHECK IF CONSENT IS REQUIRED
134
+ if not load_consent_status():
135
+ if not get_user_consent():
136
+ print("\n❌ Download cancelled by user")
137
+ return False
138
+
139
+ print(f"\n🎥 Downloading video from: {url}")
140
+ print(f"📋 Format: {format}, Quality: {quality}\n")
100
141
 
101
142
  ydl_opts = {
102
- 'format': selected_format if file_format == 'mp4' else 'bestaudio',
103
- 'outtmpl': str(download_dir / '%(title)s.%(ext)s'),
104
- 'progress_hooks': [tqdm_progress_hook],
105
- 'quiet': True, # SUPPRESS MOST OF YT-DLP OUTPUT EXCEPT PROGRESS
106
- 'no_warnings': True, # HIDE WARNINGS
107
- 'merge_output_format': 'mp4' # AUTOMATICALLY REMUX TO MP4 IF NEEDED
143
+ 'format': 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best' if format == 'mp4' else 'bestaudio[ext=mp3]/best',
144
+ 'quiet': False,
145
+ 'no_warnings': False,
146
+ 'cookiesfrombrowser': ('chrome',),
147
+ 'extractor_args': {'youtube': {'player_client': ['android']}},
148
+ 'http_headers': {
149
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
150
+ 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
151
+ 'Accept-Language': 'en-us,en;q=0.5',
152
+ 'Sec-Fetch-Mode': 'navigate'
153
+ },
154
+ 'progress_hooks': [lambda d: print(f"⏳ {d['_percent_str']} of {d.get('_total_bytes_str', 'Unknown size')}") if d['status'] == 'downloading' else None]
108
155
  }
109
156
 
110
- if file_format == 'mp3':
111
- ydl_opts['postprocessors'] = [{
112
- 'key': 'FFmpegExtractAudio',
113
- 'preferredcodec': 'mp3',
114
- 'preferredquality': '192'
115
- }]
116
-
117
157
  try:
118
158
  with yt_dlp.YoutubeDL(ydl_opts) as ydl:
119
159
  ydl.download([url])
120
- # AUTOMATICALLY OPEN DOWNLOAD FOLDER AFTER YOUTUBE DOWNLOAD IS COMPLETE
121
- open_download_folder(download_dir)
122
- except yt_dlp.utils.DownloadError as e:
123
- print(f"Error during YouTube download: {e}")
160
+ print("\n✅ Download completed successfully!")
161
+ return True
124
162
  except Exception as e:
125
- print(f"Unexpected error: {e}")
163
+ print(f"\n❌ ERROR: {str(e)}")
164
+ return False
126
165
 
127
166
 
128
167
  # FUNCTION TO LIST AVAILABLE FORMATS FOR A YOUTUBE VIDEO
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,102 @@
1
+ import string
2
+ import random
3
+ import secrets
4
+ import base64
5
+ from cryptography.fernet import Fernet
6
+ from cryptography.hazmat.primitives import hashes
7
+ from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
8
+
9
+ def generate_password(length=12, use_uppercase=True, use_numbers=True, use_special=True,
10
+ min_special=1, min_numbers=1):
11
+ """Generate a secure random password with specified requirements."""
12
+
13
+ # DEFINE CHARACTER SETS
14
+ lowercase = string.ascii_lowercase
15
+ uppercase = string.ascii_uppercase if use_uppercase else ''
16
+ numbers = string.digits if use_numbers else ''
17
+ special = "!@#$%^&*()_+-=[]{}|;:,.<>?" if use_special else ''
18
+
19
+ # COMBINE ALL ALLOWED CHARACTERS
20
+ all_chars = lowercase + uppercase + numbers + special
21
+
22
+ # ENSURE MINIMUM REQUIREMENTS
23
+ password = []
24
+ if use_uppercase:
25
+ password.append(secrets.choice(uppercase))
26
+ if use_numbers:
27
+ password.extend(secrets.choice(numbers) for _ in range(min_numbers))
28
+ if use_special:
29
+ password.extend(secrets.choice(special) for _ in range(min_special))
30
+
31
+ # FILL REST OF PASSWORD
32
+ remaining_length = length - len(password)
33
+ password.extend(secrets.choice(all_chars) for _ in range(remaining_length))
34
+
35
+ random.shuffle(password) # SHUFFLE PASSWORD
36
+
37
+ return ''.join(password) ## RETURN PASSWORD
38
+
39
+ def generate_encryption_key(password=None, salt=None):
40
+ """Generate a strong encryption key using Fernet."""
41
+ if not password:
42
+ # GENERATE A RANDOM KEY
43
+ return Fernet.generate_key()
44
+
45
+ if not salt:
46
+ salt = secrets.token_bytes(16)
47
+
48
+ # DERIVE A KEY FROM PASSWORD AND SALT
49
+ kdf = PBKDF2HMAC(
50
+ algorithm=hashes.SHA256(),
51
+ length=32,
52
+ salt=salt,
53
+ iterations=100000,
54
+ )
55
+
56
+ # ENCODE KEY IN BASE64
57
+ key = base64.urlsafe_b64encode(kdf.derive(password.encode()))
58
+ return key, salt
59
+
60
+ def analyze_password_strength(password):
61
+ """Analyze password strength and return a score and suggestions."""
62
+ score = 0
63
+ suggestions = []
64
+
65
+ # CHECK LENGTH
66
+ if len(password) >= 12:
67
+ score += 2
68
+ elif len(password) >= 8:
69
+ score += 1
70
+ else:
71
+ suggestions.append("Password should be at least 8 characters long")
72
+
73
+ # CHECK FOR CHARACTER TYPES
74
+ if any(c.isupper() for c in password):
75
+ score += 1
76
+ else:
77
+ suggestions.append("Add uppercase letters")
78
+
79
+ # CHECK FOR CHARACTER TYPES
80
+ if any(c.islower() for c in password):
81
+ score += 1
82
+ else:
83
+ suggestions.append("Add lowercase letters")
84
+
85
+ # CHECK FOR CHARACTER TYPES
86
+ if any(c.isdigit() for c in password):
87
+ score += 1
88
+ else:
89
+ suggestions.append("Add numbers")
90
+
91
+ # CHECK FOR CHARACTER TYPES
92
+ if any(c in "!@#$%^&*()_+-=[]{}|;:,.<>?" for c in password):
93
+ score += 1
94
+ else:
95
+ suggestions.append("Add special characters")
96
+
97
+ # RETURN SCORE AND SUGGESTIONS
98
+ return {
99
+ 'score': score,
100
+ 'strength': ['Very Weak', 'Weak', 'Medium', 'Strong', 'Very Strong'][min(score, 4)],
101
+ 'suggestions': suggestions
102
+ }
@@ -1,31 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: Open-AutoTools
3
- Version: 0.0.1
4
- License-File: LICENSE
5
- Requires-Dist: Brotli==1.1.0
6
- Requires-Dist: certifi==2024.2.2
7
- Requires-Dist: charset-normalizer==3.3.2
8
- Requires-Dist: click==8.1.7
9
- Requires-Dist: idna==3.6
10
- Requires-Dist: importlib-metadata==7.0.1
11
- Requires-Dist: joblib==1.3.2
12
- Requires-Dist: Levenshtein==0.25.0
13
- Requires-Dist: mutagen==1.47.0
14
- Requires-Dist: nltk==3.8.1
15
- Requires-Dist: platformdirs==4.2.0
16
- Requires-Dist: pycryptodomex==3.20.0
17
- Requires-Dist: pyperclip==1.9.0
18
- Requires-Dist: python-dotenv==1.0.1
19
- Requires-Dist: python-Levenshtein==0.25.0
20
- Requires-Dist: rapidfuzz==3.6.1
21
- Requires-Dist: regex==2023.12.25
22
- Requires-Dist: requests==2.32.3
23
- Requires-Dist: textblob==0.18.0.post0
24
- Requires-Dist: tomli==2.0.1
25
- Requires-Dist: tqdm==4.66.2
26
- Requires-Dist: urllib3==2.2.1
27
- Requires-Dist: websockets==13.0.1
28
- Requires-Dist: yapf==0.40.2
29
- Requires-Dist: yt-dlp==2024.8.6
30
- Requires-Dist: zipp==3.17.0
31
-
@@ -1,16 +0,0 @@
1
- autotools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- autotools/cli.py,sha256=a510Nq8u3xUA_AGkkEDZSvnZ7DN28wKbpoyShlhU10k,2485
3
- autotools/autocaps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- autotools/autocaps/core.py,sha256=NnOacVp0kMoq__KHWi5UMcApSuq6Iyo5bFxN40dRw7U,253
5
- autotools/autocorrect/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- autotools/autocorrect/core.py,sha256=S0Sp1wAfuv2k9J9pvvuSJ4vpD_rNn08kcG-jMiXMxlw,1168
7
- autotools/autotranslate/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- autotools/autotranslate/core.py,sha256=qh_0marZKojHCMSuqJbeRZT5CyDwOxknWIygB-rkSXU,1159
9
- autotools/downloader/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
- autotools/downloader/core.py,sha256=Meyq0ABpHGziaFYXNYVfoewfZAONc-3stvPOzEzaBm0,6988
11
- Open_AutoTools-0.0.1.dist-info/LICENSE,sha256=SpbSRxNWos2l0-geleCa6d0L9G_bOsZRkY4rB9OduJ0,1069
12
- Open_AutoTools-0.0.1.dist-info/METADATA,sha256=PSTWsQQkC-lJVfHg1cZMpHICrUG6eJulQAJHm_OF_K4,925
13
- Open_AutoTools-0.0.1.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
14
- Open_AutoTools-0.0.1.dist-info/entry_points.txt,sha256=xpRGvz30QlP0wB7R64UdNzgwOVH7yQMkgtQX7GwwqOk,214
15
- Open_AutoTools-0.0.1.dist-info/top_level.txt,sha256=x5ZRvdQw7DQnVmR0YDqVSAuuS94KTHDmk6uIeW7YOPw,10
16
- Open_AutoTools-0.0.1.dist-info/RECORD,,
@@ -1,34 +0,0 @@
1
- import requests
2
- import os
3
- import pyperclip
4
-
5
- # AUTOCORRECT FUNCTION DEFINITION
6
- def autocorrect_text(text, language="en"):
7
- # API CALL TO REWRITER API
8
- url = "https://rewriter-paraphraser-text-changer-multi-language.p.rapidapi.com/rewrite"
9
-
10
- # PAYLOAD AND HEADERS FOR API CALL
11
- payload = {
12
- "language": language,
13
- "strength": 3, # STRENGTH OF REWRITING (STRENGTH 3 IS RECOMMENDED FOR BETTER RESULTS)
14
- "text": text
15
- }
16
- headers = {
17
- "content-type": "application/json",
18
- "X-RapidAPI-Key": os.getenv('RAPIDAPI_API_KEY'), # API KEY FROM ENVIRONMENT VARIABLE
19
- "X-RapidAPI-Host": "rewriter-paraphraser-text-changer-multi-language.p.rapidapi.com"
20
- }
21
-
22
- # RESPONSE FROM API CALL
23
- response = requests.post(url, json=payload, headers=headers)
24
-
25
- # RETURN REWRITTEN TEXT IF SUCCESSFUL ELSE RETURN ERROR MESSAGE
26
- if response.status_code == 200:
27
- corrected_text = response.json()['rewrite']
28
-
29
- # COPY CORRECTED TEXT TO CLIPBOARD
30
- pyperclip.copy(corrected_text)
31
-
32
- return corrected_text
33
- else:
34
- return "ERROR: CORRECTION FAILED - " + response.text + str(response.status_code)
File without changes