DDownloader 0.2.0__py3-none-any.whl → 0.2.1__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.
- DDownloader/main.py +60 -18
- DDownloader/modules/args_parser.py +24 -0
- DDownloader/modules/banners.py +1 -1
- DDownloader/modules/dash_downloader.py +7 -0
- DDownloader/modules/hls_downloader.py +8 -1
- {DDownloader-0.2.0.dist-info → DDownloader-0.2.1.dist-info}/METADATA +1 -1
- DDownloader-0.2.1.dist-info/RECORD +13 -0
- DDownloader-0.2.0.dist-info/RECORD +0 -12
- {DDownloader-0.2.0.dist-info → DDownloader-0.2.1.dist-info}/WHEEL +0 -0
- {DDownloader-0.2.0.dist-info → DDownloader-0.2.1.dist-info}/entry_points.txt +0 -0
- {DDownloader-0.2.0.dist-info → DDownloader-0.2.1.dist-info}/top_level.txt +0 -0
DDownloader/main.py
CHANGED
@@ -1,31 +1,67 @@
|
|
1
|
-
import
|
1
|
+
import os
|
2
|
+
import re
|
2
3
|
import logging
|
3
4
|
import coloredlogs
|
5
|
+
from colorama import Fore, Style
|
6
|
+
import platform, time # Added to detect platform
|
7
|
+
from DDownloader.modules.args_parser import parse_arguments
|
4
8
|
from DDownloader.modules.banners import banners
|
5
9
|
from DDownloader.modules.dash_downloader import DASH
|
6
10
|
from DDownloader.modules.hls_downloader import HLS
|
7
|
-
import os, re
|
8
11
|
|
12
|
+
# Setup logger
|
9
13
|
logger = logging.getLogger("+ MAIN + ")
|
10
14
|
coloredlogs.install(level='DEBUG', logger=logger)
|
11
15
|
|
12
16
|
def validate_directories():
|
13
|
-
|
14
|
-
|
15
|
-
|
17
|
+
"""Ensure necessary directories exist."""
|
18
|
+
downloads_dir = 'downloads'
|
19
|
+
if not os.path.exists(downloads_dir):
|
20
|
+
os.makedirs(downloads_dir)
|
21
|
+
logger.debug(f"Created '{downloads_dir}' directory.")
|
16
22
|
|
17
|
-
def
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
+
def detect_platform():
|
24
|
+
"""Detect the platform the script is running on."""
|
25
|
+
system_platform = platform.system().lower()
|
26
|
+
if system_platform == 'windows':
|
27
|
+
return 'Windows'
|
28
|
+
elif system_platform == 'linux':
|
29
|
+
return 'Linux'
|
30
|
+
elif system_platform == 'darwin':
|
31
|
+
return 'MacOS'
|
32
|
+
else:
|
33
|
+
return 'Unknown'
|
34
|
+
|
35
|
+
def display_help():
|
36
|
+
"""Display custom help message with emoji."""
|
37
|
+
print(
|
38
|
+
f"{Fore.WHITE}+" + "=" * 80 + f"+{Style.RESET_ALL}\n"
|
39
|
+
f"{Fore.CYAN}{'Option':<40}{'Description':<90}{Style.RESET_ALL}\n"
|
40
|
+
f"{Fore.WHITE}+" + "=" * 80 + f"+{Style.RESET_ALL}\n"
|
41
|
+
f" {Fore.GREEN}-u, --url{' ' * 22}{Style.RESET_ALL}URL of the manifest (mpd/m3u8) 🌐\n"
|
42
|
+
f" {Fore.GREEN}-p, --proxy{' ' * 20}{Style.RESET_ALL}A proxy with protocol (http://ip:port) 🌍\n"
|
43
|
+
f" {Fore.GREEN}-o, --output{' ' * 19}{Style.RESET_ALL}Name of the output file 💾\n"
|
44
|
+
f" {Fore.GREEN}-k, --key{' ' * 22}{Style.RESET_ALL}Decryption key in KID:KEY format 🔑\n"
|
45
|
+
f" {Fore.GREEN}-h, --help{' ' * 21}{Style.RESET_ALL}Show this help message and exit ❓\n"
|
46
|
+
f"{Fore.WHITE}+" + "=" * 80 + f"+{Style.RESET_ALL}\n"
|
47
|
+
)
|
23
48
|
|
24
49
|
def main():
|
25
50
|
banners()
|
51
|
+
time.sleep(1)
|
52
|
+
platform_name = detect_platform()
|
53
|
+
logger.info(f"Running on platform: {platform_name}\n")
|
54
|
+
time.sleep(1)
|
55
|
+
|
26
56
|
validate_directories()
|
27
|
-
|
57
|
+
try:
|
58
|
+
args = parse_arguments()
|
59
|
+
except SystemExit:
|
60
|
+
display_help()
|
61
|
+
exit(1)
|
28
62
|
|
63
|
+
# Detect and initialize appropriate downloader
|
64
|
+
downloader = None
|
29
65
|
if re.search(r"\.mpd\b", args.url, re.IGNORECASE):
|
30
66
|
logger.info("DASH stream detected. Initializing DASH downloader...")
|
31
67
|
downloader = DASH()
|
@@ -34,24 +70,30 @@ def main():
|
|
34
70
|
downloader = HLS()
|
35
71
|
else:
|
36
72
|
logger.error("Unsupported URL format. Please provide a valid DASH (.mpd) or HLS (.m3u8) URL.")
|
37
|
-
|
73
|
+
exit(1)
|
38
74
|
|
75
|
+
# Configure downloader
|
39
76
|
downloader.manifest_url = args.url
|
40
77
|
downloader.output_name = args.output
|
41
78
|
downloader.decryption_keys = args.key or []
|
79
|
+
downloader.proxy = args.proxy # Add proxy if provided
|
42
80
|
|
81
|
+
# Log provided decryption keys
|
43
82
|
if downloader.decryption_keys:
|
83
|
+
logger.info("Decryption keys provided:")
|
44
84
|
for key in downloader.decryption_keys:
|
45
|
-
logger.info(f"
|
46
|
-
|
85
|
+
logger.info(f" --key {key}")
|
86
|
+
print(Fore.MAGENTA + "=" * 80 + Fore.RESET)
|
47
87
|
|
88
|
+
# Execute downloader
|
48
89
|
try:
|
49
90
|
if isinstance(downloader, DASH):
|
50
91
|
downloader.dash_downloader()
|
51
|
-
|
92
|
+
elif isinstance(downloader, HLS):
|
52
93
|
downloader.hls_downloader()
|
53
94
|
except Exception as e:
|
54
|
-
logger.error(f"An error occurred: {e}")
|
95
|
+
logger.error(f"An error occurred during the download process: {e}")
|
96
|
+
exit(1)
|
55
97
|
|
56
98
|
if __name__ == "__main__":
|
57
|
-
main()
|
99
|
+
main()
|
@@ -0,0 +1,24 @@
|
|
1
|
+
import argparse
|
2
|
+
from colorama import Fore, Style
|
3
|
+
|
4
|
+
def parse_arguments():
|
5
|
+
"""Parse and return command-line arguments."""
|
6
|
+
# Create the ArgumentParser with no default help and no description
|
7
|
+
parser = argparse.ArgumentParser(
|
8
|
+
add_help=False, # Disable default help
|
9
|
+
usage="", # Suppress the default usage message
|
10
|
+
)
|
11
|
+
|
12
|
+
# Add arguments (these will not include the default descriptions)
|
13
|
+
parser.add_argument("-u", "--url", required=True, help=argparse.SUPPRESS)
|
14
|
+
parser.add_argument("-p", "--proxy", help=argparse.SUPPRESS)
|
15
|
+
parser.add_argument("-o", "--output", required=True, help=argparse.SUPPRESS)
|
16
|
+
parser.add_argument("-k", "--key", action="append", help=argparse.SUPPRESS)
|
17
|
+
parser.add_argument(
|
18
|
+
"-h", "--help",
|
19
|
+
action="help",
|
20
|
+
default=argparse.SUPPRESS,
|
21
|
+
help=argparse.SUPPRESS
|
22
|
+
)
|
23
|
+
|
24
|
+
return parser.parse_args()
|
DDownloader/modules/banners.py
CHANGED
@@ -20,7 +20,7 @@ def banners():
|
|
20
20
|
stdout.write(""+Fore.YELLOW +"╔════════════════════════════════════════════════════════════════════════════╝\n")
|
21
21
|
stdout.write(""+Fore.YELLOW +"║ \x1b[38;2;255;20;147m• "+Fore.GREEN+"GITHUB "+Fore.RED+" |"+Fore.LIGHTWHITE_EX+" GITHUB.COM/THATNOTEASY "+Fore.YELLOW+"║\n")
|
22
22
|
stdout.write(""+Fore.YELLOW +"╚════════════════════════════════════════════════════════════════════════════╝\n")
|
23
|
-
print(f"{Fore.YELLOW}[DDownloader] - {Fore.GREEN}Download DASH or HLS streams with decryption keys. - {Fore.RED}[V0.2.
|
23
|
+
print(f"{Fore.YELLOW}[DDownloader] - {Fore.GREEN}Download DASH or HLS streams with decryption keys. - {Fore.RED}[V0.2.1] \n{Fore.RESET}")
|
24
24
|
|
25
25
|
|
26
26
|
|
@@ -12,6 +12,7 @@ class DASH:
|
|
12
12
|
def __init__(self):
|
13
13
|
self.manifest_url = None
|
14
14
|
self.output_name = None
|
15
|
+
self.proxy = None
|
15
16
|
self.decryption_keys = []
|
16
17
|
self.binary_path = self._get_binary_path()
|
17
18
|
|
@@ -53,8 +54,14 @@ class DASH:
|
|
53
54
|
'--del-after-done',
|
54
55
|
'--save-name', self.output_name
|
55
56
|
]
|
57
|
+
|
56
58
|
for key in self.decryption_keys:
|
57
59
|
command.extend(['--key', key])
|
60
|
+
|
61
|
+
if self.proxy:
|
62
|
+
if not self.proxy.startswith("http://"):
|
63
|
+
self.proxy = f"http://{self.proxy}"
|
64
|
+
command.extend(['--custom-proxy', self.proxy])
|
58
65
|
# logger.debug(f"Built command: {' '.join(command)}")
|
59
66
|
return command
|
60
67
|
|
@@ -12,6 +12,7 @@ class HLS:
|
|
12
12
|
def __init__(self):
|
13
13
|
self.manifest_url = None
|
14
14
|
self.output_name = None
|
15
|
+
self.proxy = None
|
15
16
|
self.decryption_keys = []
|
16
17
|
self.binary_path = self._get_binary_path()
|
17
18
|
|
@@ -44,7 +45,7 @@ class HLS:
|
|
44
45
|
def _build_command(self):
|
45
46
|
command = [
|
46
47
|
self.binary_path,
|
47
|
-
f'"{self.manifest_url}"',
|
48
|
+
f'"{self.manifest_url}"',
|
48
49
|
'--select-video', 'BEST',
|
49
50
|
'--select-audio', 'BEST',
|
50
51
|
'-mt',
|
@@ -54,8 +55,14 @@ class HLS:
|
|
54
55
|
'--del-after-done',
|
55
56
|
'--save-name', self.output_name
|
56
57
|
]
|
58
|
+
|
57
59
|
for key in self.decryption_keys:
|
58
60
|
command.extend(['--key', key])
|
61
|
+
|
62
|
+
if self.proxy:
|
63
|
+
if not self.proxy.startswith("http://"):
|
64
|
+
self.proxy = f"http://{self.proxy}"
|
65
|
+
command.extend(['--custom-proxy', self.proxy])
|
59
66
|
# logger.debug(f"Built command: {' '.join(command)}")
|
60
67
|
return command
|
61
68
|
|
@@ -0,0 +1,13 @@
|
|
1
|
+
DDownloader/__init__.py,sha256=lVZwmZNId0Dai7XBQpxglmJtIxAtZplRHDsvobL2UNo,33
|
2
|
+
DDownloader/main.py,sha256=9R2OW58YMZ4ECXbxIHhaZCmTY7ZJ3TU7Lk_S3eVslOI,3650
|
3
|
+
DDownloader/modules/__init__.py,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
|
4
|
+
DDownloader/modules/args_parser.py,sha256=JsmemrQcxBSz8aWHWTpAO6I4BfGoK6GmJvJFuhRhZ7Y,919
|
5
|
+
DDownloader/modules/banners.py,sha256=xgDGg8djkrbDBIuWefZPSEF_8iQ-WvX-vrZ2q43tZSs,3989
|
6
|
+
DDownloader/modules/dash_downloader.py,sha256=iJWs7qo4qG8vu-7ROFlrurVSo2uvjlOTAOeb_SaXbqo,3230
|
7
|
+
DDownloader/modules/hls_downloader.py,sha256=o7X6_w6gQNxot1NIHm7WYSfPwj7Q5Xbsvo1MCYzma1k,3284
|
8
|
+
DDownloader/modules/streamlink.py,sha256=F8vneSkxgGgqxRBhCHxvID-KwltpDG2QerH6QsAHuxE,506
|
9
|
+
DDownloader-0.2.1.dist-info/METADATA,sha256=fHkn3lPJDel63pvxyN9MGSdAO63STzGgPIlaC2Hj6xg,2016
|
10
|
+
DDownloader-0.2.1.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
11
|
+
DDownloader-0.2.1.dist-info/entry_points.txt,sha256=tCZVr_SRONlWlMFsVKgcPj3lxe9gBtWD4GuWukMv75g,54
|
12
|
+
DDownloader-0.2.1.dist-info/top_level.txt,sha256=INZYgY1vEHV1MIWTPXKJL8j8-ZXjWb8u4XLuU3S8umY,12
|
13
|
+
DDownloader-0.2.1.dist-info/RECORD,,
|
@@ -1,12 +0,0 @@
|
|
1
|
-
DDownloader/__init__.py,sha256=lVZwmZNId0Dai7XBQpxglmJtIxAtZplRHDsvobL2UNo,33
|
2
|
-
DDownloader/main.py,sha256=Fr16CMszpIaQnAYWa2404Zkq7lpDST79AkPLY3FC78o,2151
|
3
|
-
DDownloader/modules/__init__.py,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
|
4
|
-
DDownloader/modules/banners.py,sha256=qVx4D57E4bnHwu2t4eBgEN5Xnc5DsNn3CRtkipfjWBA,3989
|
5
|
-
DDownloader/modules/dash_downloader.py,sha256=9eigcmQXY3kYggf6vN5mik9q8OqT_5dgyzaZ4CJ4H6E,3008
|
6
|
-
DDownloader/modules/hls_downloader.py,sha256=0C3hyITZEbZOvGQhaWCZCguIIhThwlQYVduvxoHGCLA,3088
|
7
|
-
DDownloader/modules/streamlink.py,sha256=F8vneSkxgGgqxRBhCHxvID-KwltpDG2QerH6QsAHuxE,506
|
8
|
-
DDownloader-0.2.0.dist-info/METADATA,sha256=vLDqMrNYyzzgEZRYIWVbvA39s2QPGj2HTrDubZBSBO0,2016
|
9
|
-
DDownloader-0.2.0.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
10
|
-
DDownloader-0.2.0.dist-info/entry_points.txt,sha256=tCZVr_SRONlWlMFsVKgcPj3lxe9gBtWD4GuWukMv75g,54
|
11
|
-
DDownloader-0.2.0.dist-info/top_level.txt,sha256=INZYgY1vEHV1MIWTPXKJL8j8-ZXjWb8u4XLuU3S8umY,12
|
12
|
-
DDownloader-0.2.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|