Open-AutoTools 0.0.3rc2__py3-none-any.whl → 0.0.3rc3__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.
- {Open_AutoTools-0.0.3rc2.dist-info → Open_AutoTools-0.0.3rc3.dist-info}/METADATA +58 -67
- {Open_AutoTools-0.0.3rc2.dist-info → Open_AutoTools-0.0.3rc3.dist-info}/RECORD +22 -9
- autotools/autocaps/commands.py +17 -0
- autotools/autodownload/commands.py +38 -0
- autotools/autodownload/core.py +138 -44
- autotools/autoip/commands.py +29 -0
- autotools/autolower/commands.py +17 -0
- autotools/autopassword/commands.py +76 -0
- autotools/autopassword/core.py +1 -0
- autotools/autospell/commands.py +123 -0
- autotools/autotranslate/commands.py +42 -0
- autotools/cli.py +30 -493
- autotools/test/__init__.py +3 -0
- autotools/test/commands.py +120 -0
- autotools/utils/__init__.py +5 -0
- autotools/utils/loading.py +16 -0
- autotools/utils/updates.py +30 -0
- autotools/utils/version.py +74 -0
- {Open_AutoTools-0.0.3rc2.dist-info → Open_AutoTools-0.0.3rc3.dist-info}/LICENSE +0 -0
- {Open_AutoTools-0.0.3rc2.dist-info → Open_AutoTools-0.0.3rc3.dist-info}/WHEEL +0 -0
- {Open_AutoTools-0.0.3rc2.dist-info → Open_AutoTools-0.0.3rc3.dist-info}/entry_points.txt +0 -0
- {Open_AutoTools-0.0.3rc2.dist-info → Open_AutoTools-0.0.3rc3.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: Open-AutoTools
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.3rc3
|
|
4
4
|
Summary: A suite of automated tools accessible via CLI with a simple `autotools` command
|
|
5
5
|
Home-page: https://github.com/BabylooPro/Open-AutoTools
|
|
6
6
|
Author: BabylooPro
|
|
@@ -49,6 +49,8 @@ Requires-Dist: setuptools>=40.8.0
|
|
|
49
49
|
Requires-Dist: language-tool-python>=2.7.1
|
|
50
50
|
Requires-Dist: spacy>=3.7.2
|
|
51
51
|
Requires-Dist: beautifulsoup4>=4.12.0
|
|
52
|
+
Requires-Dist: halo>=0.0.31
|
|
53
|
+
Requires-Dist: ffmpeg-python>=0.2.0
|
|
52
54
|
Provides-Extra: test
|
|
53
55
|
Requires-Dist: pytest>=7.4.0; extra == "test"
|
|
54
56
|
Requires-Dist: pytest-cov>=4.1.0; extra == "test"
|
|
@@ -66,7 +68,18 @@ Dynamic: summary
|
|
|
66
68
|
|
|
67
69
|
# Open-AutoTools
|
|
68
70
|
|
|
69
|
-
Open-AutoTools
|
|
71
|
+
[PYPI_BADGE]: https://badge.fury.io/py/Open-AutoTools.svg
|
|
72
|
+
[PYPI_URL]: https://pypi.org/project/Open-AutoTools/
|
|
73
|
+
[PYTHON_BADGE]: https://img.shields.io/badge/Python-3.11-blue.svg
|
|
74
|
+
[PYTHON_URL]: https://www.python.org/downloads/
|
|
75
|
+
[CHANGELOG_BADGE]: https://img.shields.io/badge/CHANGELOG-red.svg
|
|
76
|
+
[CHANGELOG_URL]: CHANGELOG.md
|
|
77
|
+
[TODO_BADGE]: https://img.shields.io/badge/TODO-purple.svg
|
|
78
|
+
[TODO_URL]: TODO.md
|
|
79
|
+
|
|
80
|
+
[![PyPI][PYPI_BADGE]][PYPI_URL] [![Python][PYTHON_BADGE]][PYTHON_URL] [![CHANGELOG][CHANGELOG_BADGE]][CHANGELOG_URL] [![TODO][TODO_BADGE]][TODO_URL]
|
|
81
|
+
|
|
82
|
+
Open-AutoTools is a comprehensive Python CLI toolkit that streamlines everyday developer tasks through a collection of powerful command-line utilities. Each tool is designed to enhance productivity directly from your terminal.
|
|
70
83
|
|
|
71
84
|
https://github.com/BabylooPro/Open-AutoTools/assets/35376790/d57f2b9d-55f8-4368-bb40-c0010eb9d49a
|
|
72
85
|
|
|
@@ -135,16 +148,14 @@ pip install -e .
|
|
|
135
148
|
```
|
|
136
149
|
- **Options:**
|
|
137
150
|
- `--length, -l`: Set password length (default: 12)
|
|
138
|
-
- `--no-uppercase`: Exclude uppercase letters
|
|
139
|
-
- `--no-numbers`: Exclude numbers
|
|
140
|
-
- `--no-special`: Exclude special characters
|
|
141
|
-
- `--min-special`: Minimum number of special characters (default: 1)
|
|
142
|
-
- `--min-numbers`: Minimum number of numbers (default: 1)
|
|
143
|
-
- `--
|
|
144
|
-
- `--
|
|
145
|
-
- `--
|
|
146
|
-
|
|
147
|
-
These examples demonstrate how the terminal will display the results after executing each command, providing a straightforward way for users to understand the immediate effects of these commands.
|
|
151
|
+
- `--no-uppercase, -u`: Exclude uppercase letters
|
|
152
|
+
- `--no-numbers, -n`: Exclude numbers
|
|
153
|
+
- `--no-special, -s`: Exclude special characters
|
|
154
|
+
- `--min-special, -m`: Minimum number of special characters (default: 1)
|
|
155
|
+
- `--min-numbers, -d`: Minimum number of numbers (default: 1)
|
|
156
|
+
- `--analyze, -a`: Show password strength analysis
|
|
157
|
+
- `--gen-key, -g`: Generate a random encryption key
|
|
158
|
+
- `--password-key, -p`: Generate an encryption key from password
|
|
148
159
|
|
|
149
160
|
### AutoTranslate
|
|
150
161
|
|
|
@@ -172,6 +183,7 @@ These examples demonstrate how the terminal will display the results after execu
|
|
|
172
183
|
- `--copy`: Copy translation to clipboard
|
|
173
184
|
- `--detect`: Show detected source language
|
|
174
185
|
- `--list-languages`: Show all supported language codes and names
|
|
186
|
+
- `--output, -o`: Save translation to file
|
|
175
187
|
|
|
176
188
|
### AutoSpell (unreleased)
|
|
177
189
|
|
|
@@ -180,14 +192,17 @@ These examples demonstrate how the terminal will display the results after execu
|
|
|
180
192
|
```
|
|
181
193
|
~ ❯ autospell "Your text with misspellings"
|
|
182
194
|
~ ❯ autospell --lang fr "Votre texte avec des fautes"
|
|
183
|
-
~ ❯ autospell --
|
|
195
|
+
~ ❯ autospell --fix "Text to autocorrect"
|
|
184
196
|
```
|
|
185
197
|
- **Options:**
|
|
186
|
-
- `--lang`: Language code (default:
|
|
187
|
-
- `--
|
|
188
|
-
- `--copy`: Copy
|
|
189
|
-
- `--
|
|
190
|
-
- `--
|
|
198
|
+
- `--lang, -l`: Language code (default: auto)
|
|
199
|
+
- `--fix, -f`: Auto-fix text and copy to clipboard
|
|
200
|
+
- `--copy, -c`: Copy result to clipboard
|
|
201
|
+
- `--list-languages`: Show supported languages
|
|
202
|
+
- `--json, -j`: Output results as JSON
|
|
203
|
+
- `--ignore, -i`: Error types to ignore (spelling/grammar/style/punctuation)
|
|
204
|
+
- `--interactive, -n`: Interactive mode - confirm each correction
|
|
205
|
+
- `--output, -o`: Save corrections to file
|
|
191
206
|
|
|
192
207
|
### AutoDownload
|
|
193
208
|
|
|
@@ -205,52 +220,30 @@ These examples demonstrate how the terminal will display the results after execu
|
|
|
205
220
|
|
|
206
221
|
- **Options:**
|
|
207
222
|
|
|
208
|
-
- `--format`: Choose output format (mp4 or mp3)
|
|
209
|
-
- `--quality`: Select video quality (best, 1440p, 1080p, 720p, 480p, 360p, 240p)
|
|
223
|
+
- `--format, -f`: Choose output format (mp4 or mp3)
|
|
224
|
+
- `--quality, -q`: Select video quality (best, 1440p, 1080p, 720p, 480p, 360p, 240p)
|
|
210
225
|
|
|
211
226
|
- **Features:**
|
|
212
227
|
|
|
213
228
|
- Automatic bot detection bypass
|
|
214
|
-
-
|
|
215
|
-
- Progress tracking
|
|
229
|
+
- Mobile API integration for better reliability
|
|
230
|
+
- Progress tracking with detailed status
|
|
216
231
|
- Multiple quality options
|
|
217
232
|
- MP3 audio extraction
|
|
218
233
|
- Downloads to user's Downloads folder
|
|
219
234
|
- Supports both YouTube and general file downloads
|
|
235
|
+
- File existence checks with user prompts
|
|
220
236
|
|
|
221
237
|
- **Setup Requirements:**
|
|
222
238
|
|
|
223
|
-
-
|
|
224
|
-
|
|
225
|
-
```bash
|
|
226
|
-
# First time setup:
|
|
227
|
-
1. Open Chrome and sign in to YouTube
|
|
228
|
-
2. Make sure you're logged into your Google account
|
|
229
|
-
3. Accept YouTube's terms of service in browser
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
- **Troubleshooting:**
|
|
233
|
-
|
|
234
|
-
- If downloads fail with "Sign in to confirm you're not a bot":
|
|
235
|
-
|
|
236
|
-
1. Open YouTube in Chrome
|
|
237
|
-
2. Sign in if not already
|
|
238
|
-
3. Solve any CAPTCHA if prompted
|
|
239
|
-
4. Try download again
|
|
240
|
-
|
|
241
|
-
- If you get cookie errors:
|
|
242
|
-
1. Clear Chrome cookies
|
|
243
|
-
2. Sign in to YouTube again
|
|
244
|
-
3. Wait a few minutes before downloading
|
|
245
|
-
|
|
239
|
+
- No special setup required
|
|
246
240
|
- **Technical Requirements:**
|
|
247
|
-
- Chrome browser (for cookie and session handling)
|
|
248
|
-
- Active YouTube/Google account
|
|
249
241
|
- Internet connection
|
|
250
242
|
- Sufficient storage space
|
|
251
243
|
- yt-dlp library (automatically installed)
|
|
244
|
+
- FFmpeg (required for format conversion)
|
|
252
245
|
|
|
253
|
-
> **Note:** The tool uses
|
|
246
|
+
> **Note:** The tool uses YouTube's mobile API for better compatibility and reliability.
|
|
254
247
|
|
|
255
248
|
### AutoIP
|
|
256
249
|
|
|
@@ -258,28 +251,9 @@ These examples demonstrate how the terminal will display the results after execu
|
|
|
258
251
|
- **Usage:**
|
|
259
252
|
|
|
260
253
|
```bash
|
|
261
|
-
# Display IP addresses
|
|
262
254
|
~ ❯ autoip
|
|
263
|
-
|
|
264
|
-
# Run speed test
|
|
265
255
|
~ ❯ autoip --speed
|
|
266
|
-
|
|
267
|
-
# Test connectivity
|
|
268
|
-
~ ❯ autoip --test
|
|
269
|
-
|
|
270
|
-
# Show location info
|
|
271
256
|
~ ❯ autoip --location
|
|
272
|
-
|
|
273
|
-
# Monitor network traffic
|
|
274
|
-
~ ❯ autoip --monitor
|
|
275
|
-
|
|
276
|
-
# Check common ports
|
|
277
|
-
~ ❯ autoip --ports
|
|
278
|
-
|
|
279
|
-
# Show DNS servers
|
|
280
|
-
~ ❯ autoip --dns
|
|
281
|
-
|
|
282
|
-
# Hide IP display and only show tests
|
|
283
257
|
~ ❯ autoip --no-ip --test --speed
|
|
284
258
|
```
|
|
285
259
|
|
|
@@ -288,6 +262,7 @@ These examples demonstrate how the terminal will display the results after execu
|
|
|
288
262
|
- `--test, -t`: Run connectivity tests to popular services
|
|
289
263
|
- `--speed, -s`: Run internet speed test
|
|
290
264
|
- `--monitor, -m`: Monitor real-time network traffic
|
|
265
|
+
- `--interval, -i`: Monitoring interval in seconds
|
|
291
266
|
- `--ports, -p`: Check status of common ports
|
|
292
267
|
- `--dns, -d`: Show DNS server configuration
|
|
293
268
|
- `--location, -l`: Show IP geolocation information
|
|
@@ -297,11 +272,27 @@ These examples demonstrate how the terminal will display the results after execu
|
|
|
297
272
|
- Local and public IP detection (IPv4 & IPv6)
|
|
298
273
|
- Internet speed testing
|
|
299
274
|
- Network connectivity checks
|
|
275
|
+
- Monitoring interval (10 seconds)
|
|
300
276
|
- Real-time traffic monitoring
|
|
301
277
|
- Port scanning
|
|
302
278
|
- DNS server information
|
|
303
279
|
- IP geolocation
|
|
304
280
|
|
|
281
|
+
### Test Suite (DEVELOPMENT ONLY)
|
|
282
|
+
|
|
283
|
+
- **Description:** Run the test suite for Open-AutoTools
|
|
284
|
+
- **Usage:**
|
|
285
|
+
```bash
|
|
286
|
+
~ ❯ autotools test
|
|
287
|
+
```
|
|
288
|
+
- **Options:**
|
|
289
|
+
|
|
290
|
+
- `--unit, -u`: Run only unit tests
|
|
291
|
+
- `--integration, -i`: Run only integration tests
|
|
292
|
+
- `--no-cov`: Disable coverage report
|
|
293
|
+
- `--html`: Generate HTML coverage report
|
|
294
|
+
- `--module, -m`: Test specific module (e.g., autocaps, autolower)
|
|
295
|
+
|
|
305
296
|
## License
|
|
306
297
|
|
|
307
298
|
This project is licensed under the MIT License. For more details, see the [LICENSE](LICENSE) file.
|
|
@@ -1,31 +1,44 @@
|
|
|
1
1
|
autotools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
autotools/cli.py,sha256=
|
|
2
|
+
autotools/cli.py,sha256=WBFH0NZwUW3QpoB_dOW-Ukpul_klc8PJSptfALewU04,3538
|
|
3
3
|
autotools/autocaps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
autotools/autocaps/commands.py,sha256=YIoSRTjfwpupbUl5r4P6LH6PXrTBcehf9gZwOOKxv9I,477
|
|
4
5
|
autotools/autocaps/core.py,sha256=NnOacVp0kMoq__KHWi5UMcApSuq6Iyo5bFxN40dRw7U,253
|
|
5
6
|
autotools/autocaps/tests/__init__.py,sha256=CckydfM7SZdXtW3pLgAeRdrC60sovNx_v59nyFvslFo,23
|
|
6
7
|
autotools/autocaps/tests/test_autocaps_core.py,sha256=fzpci_sK7L1fSf_IJ1paJ__bmnHwC9OUOD7ftd3w07c,1672
|
|
7
8
|
autotools/autocaps/tests/test_autocaps_integration.py,sha256=Qe2hzVEvzf0-INp14oTTrHi0RiRDCE2fxo9abVNcd_E,1435
|
|
8
9
|
autotools/autodownload/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
-
autotools/autodownload/
|
|
10
|
+
autotools/autodownload/commands.py,sha256=WBG4o5716zQ63t23k-qJLNv41L58RnL2XTvNl_TsK-w,1442
|
|
11
|
+
autotools/autodownload/core.py,sha256=z9SBQx0SUZbAcCRmVA4TWYI7BPPco79JpDWqi5X1FfU,12181
|
|
10
12
|
autotools/autoip/__init__.py,sha256=T_5hz9G4reFPXDucdzRoMFPYlAKwTPt9TejOpkRPgn0,23
|
|
13
|
+
autotools/autoip/commands.py,sha256=c4s22yb7aharRAwOmD37Kgbj6rm05XNBtCVyxU7rc7M,1425
|
|
11
14
|
autotools/autoip/core.py,sha256=Q3dzLstZQruwYkSbCSlKQNmKVGCyNpo1DGst5VFtHLU,10123
|
|
12
15
|
autotools/autoip/tests/__init__.py,sha256=CckydfM7SZdXtW3pLgAeRdrC60sovNx_v59nyFvslFo,23
|
|
13
16
|
autotools/autoip/tests/test_autoip_core.py,sha256=Q8865qqhopcGBzS4mIlDlEzxu-mTIbZxpgJyzIyuQXc,2153
|
|
14
17
|
autotools/autoip/tests/test_autoip_integration.py,sha256=-vS2gnY8ZfT-tfY2FRbUtTzY0lcIBtVZHbPbWsKyueo,2746
|
|
15
18
|
autotools/autolower/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
19
|
+
autotools/autolower/commands.py,sha256=Od_5hWGjFr8CLApmtMnoM5QhNRe1ttWy2qLi7S9hTts,480
|
|
16
20
|
autotools/autolower/core.py,sha256=vjM2ognA3tDCbv10a9vta9WPuAiqTPjOXZ1JHL_b-nk,260
|
|
17
21
|
autotools/autolower/tests/__init__.py,sha256=CckydfM7SZdXtW3pLgAeRdrC60sovNx_v59nyFvslFo,23
|
|
18
22
|
autotools/autolower/tests/test_autolower_core.py,sha256=ChkS3qZgXz75iLfC9EXVH_kMd-sjaxpRKFjaxKoBnxo,1694
|
|
19
23
|
autotools/autolower/tests/test_autolower_integration.py,sha256=M2yN1Ym7kGulys62-IwKq-uWn7CFvI3sCnoo-e3CTaA,1446
|
|
20
24
|
autotools/autopassword/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
21
|
-
autotools/autopassword/
|
|
25
|
+
autotools/autopassword/commands.py,sha256=lyNM833UXCcafqnBa0ojxpdgPPEUadO-t2HrAP4UIaM,3137
|
|
26
|
+
autotools/autopassword/core.py,sha256=3aeXJaF7yYvHAH0VkVxGxaKawxgZDlSoI5lUcDCu264,3193
|
|
22
27
|
autotools/autospell/__init__.py,sha256=jkpkiE7pksBgllXKfkNpYYvqtlm8vN0h4kXnQOqcb_U,60
|
|
28
|
+
autotools/autospell/commands.py,sha256=SG_kP9xAOj7H2jnXXq7auwRALt5ml6r0oz8dKnE5z04,5956
|
|
23
29
|
autotools/autospell/core.py,sha256=WPvi9Xs6uF3dte_g2I9oHfTjCV1-NasrJElLP9bbC8U,8103
|
|
24
30
|
autotools/autotranslate/__init__.py,sha256=6BxuZqhyQhfsZ5x7DkB1BAEpC08GT_5l5bl0AY_eLpU,64
|
|
31
|
+
autotools/autotranslate/commands.py,sha256=6M1D27mrk41uWTLgwGeO-HTUtq0iiHFrptIb1BM7A-s,1794
|
|
25
32
|
autotools/autotranslate/core.py,sha256=H2f90IWr_jNGiJD3XAv-20i5sRGM-VDYWrYt65EDEkI,1836
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
33
|
+
autotools/test/__init__.py,sha256=_xWAfk2kKSboEOW9fVUlmNfVHAx-qGYWFb8dxCz8g1w,48
|
|
34
|
+
autotools/test/commands.py,sha256=ZDSl-BCCeH1CsGjpQr_b6x3cMEGK8dSgNdPDqXgSxpw,4846
|
|
35
|
+
autotools/utils/__init__.py,sha256=2uAirI6ZbOwSFPSg5wuEjA0gMWf1XBJ4yP_WcGeND7M,183
|
|
36
|
+
autotools/utils/loading.py,sha256=cRh8rvNLT4B2aVgWq7flg8bNpnp1XlNBV3_cvxjfm8E,439
|
|
37
|
+
autotools/utils/updates.py,sha256=ZGS8pAVxvy5ORuey_zrBWdA0_hKNmEcwzJ-6c22x4Yo,1140
|
|
38
|
+
autotools/utils/version.py,sha256=sHwkZ8MNTKQdTntV1B-8QInbMnMtR7Xr3DAY5-wf5-0,3027
|
|
39
|
+
Open_AutoTools-0.0.3rc3.dist-info/LICENSE,sha256=SpbSRxNWos2l0-geleCa6d0L9G_bOsZRkY4rB9OduJ0,1069
|
|
40
|
+
Open_AutoTools-0.0.3rc3.dist-info/METADATA,sha256=ymNaYp1DaA28ufYkUDE3y3EMi8yXpEIrMAwqfukKGFU,9280
|
|
41
|
+
Open_AutoTools-0.0.3rc3.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
|
42
|
+
Open_AutoTools-0.0.3rc3.dist-info/entry_points.txt,sha256=QLIsUk6vHo0wAYDk1K74kIuYunJMwWe2xbwQhJXLoKo,312
|
|
43
|
+
Open_AutoTools-0.0.3rc3.dist-info/top_level.txt,sha256=x5ZRvdQw7DQnVmR0YDqVSAuuS94KTHDmk6uIeW7YOPw,10
|
|
44
|
+
Open_AutoTools-0.0.3rc3.dist-info/RECORD,,
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import click
|
|
2
|
+
from .core import autocaps_transform
|
|
3
|
+
from ..utils.loading import LoadingAnimation
|
|
4
|
+
from ..utils.updates import check_for_updates
|
|
5
|
+
|
|
6
|
+
@click.command()
|
|
7
|
+
@click.argument('text', nargs=-1)
|
|
8
|
+
def autocaps(text):
|
|
9
|
+
"""Convert text to UPPERCASE."""
|
|
10
|
+
with LoadingAnimation():
|
|
11
|
+
result = autocaps_transform(" ".join(text))
|
|
12
|
+
click.echo(result)
|
|
13
|
+
|
|
14
|
+
# UPDATE CHECK AT THE END
|
|
15
|
+
update_msg = check_for_updates()
|
|
16
|
+
if update_msg:
|
|
17
|
+
click.echo(update_msg)
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import click
|
|
2
|
+
import sys
|
|
3
|
+
from .core import download_youtube_video, download_file, validate_youtube_url
|
|
4
|
+
from ..utils.loading import LoadingAnimation
|
|
5
|
+
from ..utils.updates import check_for_updates
|
|
6
|
+
|
|
7
|
+
@click.command()
|
|
8
|
+
@click.argument('url')
|
|
9
|
+
@click.option('--format', '-f', type=click.Choice(['mp4', 'mp3'], case_sensitive=False),
|
|
10
|
+
default='mp4', help='Output file format (mp4 for video, mp3 for audio)')
|
|
11
|
+
@click.option('--quality', '-q', type=click.Choice(['best', '2160p', '1440p', '1080p', '720p', '480p', '360p', '240p'],
|
|
12
|
+
case_sensitive=False), default='best', help='Video quality (mp4 only)')
|
|
13
|
+
def autodownload(url, format, quality):
|
|
14
|
+
"""Download videos from YouTube or files from any URL.
|
|
15
|
+
|
|
16
|
+
Supports YouTube video download with quality selection and format conversion (mp4/mp3).
|
|
17
|
+
|
|
18
|
+
For non-YouTube URLs, downloads the file directly."""
|
|
19
|
+
|
|
20
|
+
loading = LoadingAnimation()
|
|
21
|
+
|
|
22
|
+
if "youtube.com" in url or "youtu.be" in url:
|
|
23
|
+
with loading:
|
|
24
|
+
if not validate_youtube_url(url):
|
|
25
|
+
click.echo("Invalid YouTube URL", err=True)
|
|
26
|
+
sys.exit(1)
|
|
27
|
+
|
|
28
|
+
if not download_youtube_video(url, format, quality):
|
|
29
|
+
sys.exit(1)
|
|
30
|
+
else:
|
|
31
|
+
with loading:
|
|
32
|
+
if not download_file(url):
|
|
33
|
+
sys.exit(1)
|
|
34
|
+
|
|
35
|
+
# UPDATE CHECK AT THE END
|
|
36
|
+
update_msg = check_for_updates()
|
|
37
|
+
if update_msg:
|
|
38
|
+
click.echo(update_msg)
|
autotools/autodownload/core.py
CHANGED
|
@@ -7,6 +7,8 @@ import yt_dlp
|
|
|
7
7
|
import platform
|
|
8
8
|
import subprocess
|
|
9
9
|
import json
|
|
10
|
+
from rich.progress import Progress
|
|
11
|
+
from ..utils.loading import LoadingAnimation
|
|
10
12
|
|
|
11
13
|
|
|
12
14
|
# FUNCTION TO GET DEFAULT DOWNLOAD DIRECTORY
|
|
@@ -44,17 +46,23 @@ def open_download_folder(path):
|
|
|
44
46
|
|
|
45
47
|
# FUNCTION TO VALIDATE YOUTUBE URL FORMAT
|
|
46
48
|
def validate_youtube_url(url):
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
49
|
+
"""BASIC URL VALIDATION WITH PROPER FORMAT CHECK"""
|
|
50
|
+
# CHECK IF URL CONTAINS YOUTUBE DOMAIN
|
|
51
|
+
is_youtube = any(domain in url for domain in ["youtube.com", "youtu.be", "music.youtube.com"])
|
|
52
|
+
|
|
53
|
+
# CHECK IF URL HAS PROPER VIDEO ID FORMAT
|
|
54
|
+
has_video_id = False
|
|
55
|
+
if "youtube.com/watch" in url and "v=" in url:
|
|
56
|
+
has_video_id = True
|
|
57
|
+
elif "youtu.be/" in url and len(url.split("youtu.be/")[1]) > 0:
|
|
58
|
+
has_video_id = True
|
|
59
|
+
elif any(pattern in url for pattern in ["/watch/", "/shorts/", "/live/"]):
|
|
60
|
+
path_parts = url.split("/")
|
|
61
|
+
has_video_id = len(path_parts[-1]) > 0
|
|
62
|
+
elif "attribution_link" in url and "watch?v=" in url:
|
|
63
|
+
has_video_id = True
|
|
64
|
+
|
|
65
|
+
return is_youtube and has_video_id
|
|
58
66
|
|
|
59
67
|
|
|
60
68
|
# FUNCTION TO DOWNLOAD FILES WITH REQUESTS, INCLUDING ERROR HANDLING AND PROGRESS BAR
|
|
@@ -85,40 +93,50 @@ def download_file(url):
|
|
|
85
93
|
# FUNCTION TO GET CONSENT FILE PATH
|
|
86
94
|
def get_consent_file_path():
|
|
87
95
|
"""GET PATH TO STORE CONSENT STATUS"""
|
|
96
|
+
# INFO: delete consent file with "rm -f ~/.autotools/consent.json" if you want to force new consent in local development
|
|
88
97
|
return Path.home() / '.autotools' / 'consent.json'
|
|
89
98
|
|
|
90
99
|
# FUNCTION TO LOAD CONSENT STATUS
|
|
91
100
|
def load_consent_status():
|
|
92
101
|
"""LOAD SAVED CONSENT STATUS"""
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
with open(consent_file) as f:
|
|
99
|
-
return json.load(f).get('youtube_consent', False)
|
|
100
|
-
except:
|
|
102
|
+
try:
|
|
103
|
+
consent_file = get_consent_file_path()
|
|
104
|
+
|
|
105
|
+
# FORCE NEW CONSENT IF FILE DOESN'T EXIST OR IS EMPTY
|
|
106
|
+
if not consent_file.exists():
|
|
101
107
|
return False
|
|
102
|
-
|
|
108
|
+
|
|
109
|
+
# READ CONSENT STATUS
|
|
110
|
+
with open(consent_file) as f:
|
|
111
|
+
data = json.load(f)
|
|
112
|
+
return data.get('youtube_consent', False)
|
|
113
|
+
except Exception:
|
|
114
|
+
# IF ANY ERROR OCCURS, FORCE NEW CONSENT
|
|
115
|
+
return False
|
|
103
116
|
|
|
104
117
|
# FUNCTION TO SAVE CONSENT STATUS
|
|
105
118
|
def save_consent_status(status):
|
|
106
119
|
"""SAVE CONSENT STATUS"""
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
120
|
+
try:
|
|
121
|
+
consent_file = get_consent_file_path()
|
|
122
|
+
consent_file.parent.mkdir(exist_ok=True)
|
|
123
|
+
|
|
124
|
+
# SAVE CONSENT STATUS TO FILE
|
|
125
|
+
with open(consent_file, 'w') as f:
|
|
126
|
+
json.dump({'youtube_consent': status}, f)
|
|
127
|
+
return True
|
|
128
|
+
except Exception:
|
|
129
|
+
# IF SAVING FAILS, RETURN FALSE TO FORCE NEW CONSENT NEXT TIME
|
|
130
|
+
return False
|
|
113
131
|
|
|
114
132
|
# FUNCTION TO GET USER CONSENT WITH INTERACTIVE PROMPT
|
|
115
133
|
def get_user_consent():
|
|
116
134
|
"""GET USER CONSENT WITH INTERACTIVE PROMPT"""
|
|
117
135
|
print("\n⚠️ Important Notice:")
|
|
118
136
|
print("This tool will:")
|
|
119
|
-
print("1.
|
|
120
|
-
print("2.
|
|
121
|
-
print("3.
|
|
137
|
+
print("1. Download video content from YouTube")
|
|
138
|
+
print("2. Save files to your local machine")
|
|
139
|
+
print("3. Use mobile API for better compatibility")
|
|
122
140
|
|
|
123
141
|
# GET USER CONSENT WITH INTERACTIVE PROMPT
|
|
124
142
|
while True:
|
|
@@ -132,40 +150,116 @@ def get_user_consent():
|
|
|
132
150
|
print("Please answer 'yes' or 'no'")
|
|
133
151
|
|
|
134
152
|
|
|
153
|
+
# FUNCTION TO CHECK IF VIDEO EXISTS AND GET USER CONSENT FOR REPLACEMENT
|
|
154
|
+
def check_existing_video(info, format='mp4'):
|
|
155
|
+
"""CHECK IF VIDEO EXISTS AND ASK FOR REPLACEMENT"""
|
|
156
|
+
download_dir = get_default_download_dir()
|
|
157
|
+
title = info.get('title', '').replace('/', '_') # SANITIZE TITLE
|
|
158
|
+
filename = f"{title}.{format}"
|
|
159
|
+
filepath = download_dir / filename
|
|
160
|
+
|
|
161
|
+
# CHECK IF FILE EXISTS AND ASK FOR REPLACEMENT
|
|
162
|
+
if filepath.exists():
|
|
163
|
+
print(f"\n⚠️ File already exists: {filename}")
|
|
164
|
+
while True:
|
|
165
|
+
response = input("Do you want to replace it? (yes/no): ").lower()
|
|
166
|
+
if response in ['yes', 'y']:
|
|
167
|
+
return True
|
|
168
|
+
elif response in ['no', 'n']:
|
|
169
|
+
# OPEN DOWNLOADS FOLDER TO SHOW EXISTING FILE
|
|
170
|
+
open_download_folder(download_dir)
|
|
171
|
+
return False
|
|
172
|
+
print("Please answer 'yes' or 'no'")
|
|
173
|
+
return True
|
|
174
|
+
|
|
175
|
+
|
|
135
176
|
# FUNCTION TO DOWNLOAD YOUTUBE VIDEOS WITH YT-DLP AND SPECIFIED FORMAT AND QUALITY
|
|
136
177
|
def download_youtube_video(url, format='mp4', quality='best'):
|
|
137
178
|
"""DOWNLOAD VIDEO WITH CONSENT CHECK"""
|
|
138
|
-
#
|
|
139
|
-
if not
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
179
|
+
# VALIDATE URL FIRST
|
|
180
|
+
if not validate_youtube_url(url):
|
|
181
|
+
print("\n❌ Invalid YouTube URL")
|
|
182
|
+
return False
|
|
183
|
+
|
|
184
|
+
# CHECK FOR SAVED CONSENT FIRST AND GET NEW CONSENT IF NEEDED
|
|
185
|
+
if not load_consent_status() and not get_user_consent():
|
|
186
|
+
print("\n❌ Download cancelled by user")
|
|
187
|
+
return False
|
|
188
|
+
|
|
189
|
+
# FIRST CHECK VIDEO INFO AND EXISTENCE
|
|
190
|
+
try:
|
|
191
|
+
with yt_dlp.YoutubeDL({
|
|
192
|
+
'quiet': True,
|
|
193
|
+
'no_warnings': True,
|
|
194
|
+
'extractor_args': {'youtube': {
|
|
195
|
+
'player_client': ['android'],
|
|
196
|
+
'formats': ['missing_pot'] # ALLOW FORMATS WITHOUT PO TOKEN
|
|
197
|
+
}}
|
|
198
|
+
}) as ydl:
|
|
199
|
+
info = ydl.extract_info(url, download=False)
|
|
200
|
+
formats = info.get('formats', [])
|
|
201
|
+
if not formats:
|
|
202
|
+
print("\n❌ No formats available for this video")
|
|
203
|
+
return False
|
|
204
|
+
|
|
205
|
+
# CHECK IF FILE EXISTS AND GET REPLACEMENT CONSENT
|
|
206
|
+
force_download = check_existing_video(info, format)
|
|
207
|
+
if not force_download:
|
|
208
|
+
print("\n❌ Download cancelled - file already exists")
|
|
209
|
+
return False
|
|
210
|
+
|
|
211
|
+
# OPEN DOWNLOADS FOLDER IF STARTING NEW DOWNLOAD OR REPLACING
|
|
212
|
+
download_dir = get_default_download_dir()
|
|
213
|
+
open_download_folder(download_dir)
|
|
214
|
+
|
|
215
|
+
except Exception as e:
|
|
216
|
+
print(f"\n❌ Error checking video: {str(e)}")
|
|
217
|
+
return False
|
|
218
|
+
|
|
219
|
+
loading = LoadingAnimation()
|
|
220
|
+
|
|
221
|
+
# START LOADING FOR DOWNLOAD PROCESS
|
|
222
|
+
with loading:
|
|
223
|
+
loading._spinner.start()
|
|
224
|
+
print("\n🔍 Starting download...")
|
|
143
225
|
|
|
144
226
|
print(f"\n🎥 Downloading video from: {url}")
|
|
145
227
|
print(f"📋 Format: {format}, Quality: {quality}\n")
|
|
146
228
|
|
|
229
|
+
# YT-DLP PERMISSION OPTIONS FOR DOWNLOADING YOUTUBE VIDEOS
|
|
147
230
|
ydl_opts = {
|
|
148
231
|
'format': 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best' if format == 'mp4' else 'bestaudio[ext=mp3]/best',
|
|
149
|
-
'quiet':
|
|
150
|
-
'no_warnings':
|
|
151
|
-
'
|
|
152
|
-
'
|
|
232
|
+
'quiet': True,
|
|
233
|
+
'no_warnings': True,
|
|
234
|
+
'progress': True,
|
|
235
|
+
'progress_hooks': [lambda d: print(f"⏳ {d['_percent_str']} of {d.get('_total_bytes_str', 'Unknown size')}") if d['status'] == 'downloading' else None],
|
|
236
|
+
'extractor_args': {
|
|
237
|
+
'youtube': {
|
|
238
|
+
'player_client': ['android'],
|
|
239
|
+
'formats': ['missing_pot'] # ALLOW FORMATS WITHOUT PO TOKEN
|
|
240
|
+
}
|
|
241
|
+
},
|
|
153
242
|
'http_headers': {
|
|
154
|
-
'User-Agent': 'Mozilla/5.0 (
|
|
155
|
-
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
|
|
156
|
-
'Accept-Language': 'en-us,en;q=0.5',
|
|
157
|
-
'Sec-Fetch-Mode': 'navigate'
|
|
243
|
+
'User-Agent': 'Mozilla/5.0 (Linux; Android 12; SM-S906N Build/QP1A.190711.020; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/80.0.3987.119 Mobile Safari/537.36'
|
|
158
244
|
},
|
|
159
|
-
'
|
|
245
|
+
'outtmpl': str(download_dir / '%(title)s.%(ext)s'), # SET OUTPUT TEMPLATE
|
|
246
|
+
'overwrites': True # FORCE OVERWRITE IF USER CONSENTED
|
|
160
247
|
}
|
|
161
248
|
|
|
162
249
|
try:
|
|
250
|
+
# THEN DOWNLOAD
|
|
163
251
|
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
|
|
164
252
|
ydl.download([url])
|
|
165
253
|
print("\n✅ Download completed successfully!")
|
|
166
254
|
return True
|
|
167
255
|
except Exception as e:
|
|
168
|
-
|
|
256
|
+
error_msg = str(e)
|
|
257
|
+
if "Requested format is not available" in error_msg:
|
|
258
|
+
print("\n❌ Format not available. Available formats are:")
|
|
259
|
+
for f in formats:
|
|
260
|
+
print(f"- {f.get('format_id', 'N/A')}: {f.get('ext', 'N/A')} ({f.get('format_note', 'N/A')})")
|
|
261
|
+
else:
|
|
262
|
+
print(f"\n❌ ERROR: {error_msg}")
|
|
169
263
|
return False
|
|
170
264
|
|
|
171
265
|
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import click
|
|
2
|
+
from .core import run
|
|
3
|
+
from ..utils.loading import LoadingAnimation
|
|
4
|
+
from ..utils.updates import check_for_updates
|
|
5
|
+
|
|
6
|
+
@click.command()
|
|
7
|
+
@click.option('--test', '-t', is_flag=True, help='Run connectivity tests')
|
|
8
|
+
@click.option('--speed', '-s', is_flag=True, help='Run internet speed test')
|
|
9
|
+
@click.option('--monitor', '-m', is_flag=True, help='Monitor network traffic')
|
|
10
|
+
@click.option('--interval', '-i', default=1, help='Monitoring interval in seconds')
|
|
11
|
+
@click.option('--ports', '-p', is_flag=True, help='Check common ports status')
|
|
12
|
+
@click.option('--dns', '-d', is_flag=True, help='Show DNS servers')
|
|
13
|
+
@click.option('--location', '-l', is_flag=True, help='Show IP location info')
|
|
14
|
+
@click.option('--no-ip', '-n', is_flag=True, help='Hide IP addresses')
|
|
15
|
+
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
|
+
with LoadingAnimation():
|
|
22
|
+
output = run(test=test, speed=speed, monitor=monitor, interval=interval,
|
|
23
|
+
ports=ports, dns=dns, location=location, no_ip=no_ip)
|
|
24
|
+
click.echo(output)
|
|
25
|
+
|
|
26
|
+
# UPDATE CHECK AT THE END
|
|
27
|
+
update_msg = check_for_updates()
|
|
28
|
+
if update_msg:
|
|
29
|
+
click.echo(update_msg)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import click
|
|
2
|
+
from .core import autolower_transform
|
|
3
|
+
from ..utils.loading import LoadingAnimation
|
|
4
|
+
from ..utils.updates import check_for_updates
|
|
5
|
+
|
|
6
|
+
@click.command()
|
|
7
|
+
@click.argument('text', nargs=-1)
|
|
8
|
+
def autolower(text):
|
|
9
|
+
"""Convert text to lowercase."""
|
|
10
|
+
with LoadingAnimation():
|
|
11
|
+
result = autolower_transform(" ".join(text))
|
|
12
|
+
click.echo(result)
|
|
13
|
+
|
|
14
|
+
# UPDATE CHECK AT THE END
|
|
15
|
+
update_msg = check_for_updates()
|
|
16
|
+
if update_msg:
|
|
17
|
+
click.echo(update_msg)
|