DDownloader 0.1.6__tar.gz → 0.1.7__tar.gz
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-0.1.7/DDownloader/__init__.py +4 -0
- DDownloader-0.1.7/DDownloader/main.py +55 -0
- DDownloader-0.1.7/DDownloader/modules/__init__.py +1 -0
- {DDownloader-0.1.6/DDownloader → DDownloader-0.1.7/DDownloader/modules}/dash_downloader.py +19 -29
- {DDownloader-0.1.6/DDownloader → DDownloader-0.1.7/DDownloader/modules}/hls_downloader.py +18 -28
- {DDownloader-0.1.6 → DDownloader-0.1.7}/DDownloader.egg-info/PKG-INFO +1 -1
- {DDownloader-0.1.6 → DDownloader-0.1.7}/DDownloader.egg-info/SOURCES.txt +6 -4
- {DDownloader-0.1.6 → DDownloader-0.1.7}/PKG-INFO +1 -1
- {DDownloader-0.1.6 → DDownloader-0.1.7}/setup.py +1 -1
- DDownloader-0.1.6/DDownloader/__init__.py +0 -11
- {DDownloader-0.1.6/DDownloader → DDownloader-0.1.7/DDownloader/modules}/streamlink.py +0 -0
- {DDownloader-0.1.6 → DDownloader-0.1.7}/DDownloader.egg-info/dependency_links.txt +0 -0
- {DDownloader-0.1.6 → DDownloader-0.1.7}/DDownloader.egg-info/entry_points.txt +0 -0
- {DDownloader-0.1.6 → DDownloader-0.1.7}/DDownloader.egg-info/requires.txt +0 -0
- {DDownloader-0.1.6 → DDownloader-0.1.7}/DDownloader.egg-info/top_level.txt +0 -0
- {DDownloader-0.1.6 → DDownloader-0.1.7}/README.md +0 -0
- {DDownloader-0.1.6 → DDownloader-0.1.7}/setup.cfg +0 -0
@@ -0,0 +1,55 @@
|
|
1
|
+
import argparse
|
2
|
+
import logging
|
3
|
+
from modules.dash_downloader import DASH
|
4
|
+
from modules.hls_downloader import HLS
|
5
|
+
|
6
|
+
logger = logging.getLogger("+ MAIN + ")
|
7
|
+
coloredlogs.install(level='DEBUG', logger=logger)
|
8
|
+
|
9
|
+
def parse_arguments():
|
10
|
+
"""
|
11
|
+
Parse command-line arguments for the downloader.
|
12
|
+
"""
|
13
|
+
parser = argparse.ArgumentParser(description="Download DASH or HLS streams with decryption keys.")
|
14
|
+
parser.add_argument("-u", "--url", required=True, help="Manifest URL pointing to the stream (.mpd or .m3u8).")
|
15
|
+
parser.add_argument("-k", "--key", action="append", help="Decryption keys in the format KID:KEY. Use multiple -k options for multiple keys.")
|
16
|
+
parser.add_argument("-o", "--output", required=True, help="Output file name.")
|
17
|
+
return parser.parse_args()
|
18
|
+
|
19
|
+
def main():
|
20
|
+
# Parse arguments
|
21
|
+
args = parse_arguments()
|
22
|
+
|
23
|
+
# Detect DASH or HLS based on URL extension
|
24
|
+
if args.url.endswith(".mpd"):
|
25
|
+
logger.info("DASH stream detected. Initializing DASH downloader...")
|
26
|
+
downloader = DASH()
|
27
|
+
elif args.url.endswith(".m3u8"):
|
28
|
+
logger.info("HLS stream detected. Initializing HLS downloader...")
|
29
|
+
downloader = HLS()
|
30
|
+
else:
|
31
|
+
logger.error("Unsupported URL format. Please provide a valid DASH (.mpd) or HLS (.m3u8) URL.")
|
32
|
+
return
|
33
|
+
|
34
|
+
# Set downloader properties
|
35
|
+
downloader.manifest_url = args.url
|
36
|
+
downloader.output_name = args.output
|
37
|
+
downloader.decryption_keys = args.key or [] # Default to an empty list if no keys provided
|
38
|
+
|
39
|
+
# Log decryption keys
|
40
|
+
if downloader.decryption_keys:
|
41
|
+
logger.info("Decryption key(s) provided:")
|
42
|
+
for key in downloader.decryption_keys:
|
43
|
+
logger.info(f"--key {key}")
|
44
|
+
|
45
|
+
# Start download
|
46
|
+
try:
|
47
|
+
if isinstance(downloader, DASH):
|
48
|
+
downloader.dash_downloader()
|
49
|
+
else:
|
50
|
+
downloader.hls_downloader()
|
51
|
+
except Exception as e:
|
52
|
+
logger.error(f"An error occurred: {e}")
|
53
|
+
|
54
|
+
if __name__ == "__main__":
|
55
|
+
main()
|
@@ -0,0 +1 @@
|
|
1
|
+
|
@@ -1,11 +1,10 @@
|
|
1
1
|
import os
|
2
2
|
import subprocess
|
3
3
|
import logging
|
4
|
-
import platform
|
4
|
+
import platform
|
5
5
|
import coloredlogs
|
6
6
|
from colorama import Fore
|
7
7
|
|
8
|
-
# Set up logging
|
9
8
|
logger = logging.getLogger("+ DASH + ")
|
10
9
|
coloredlogs.install(level='DEBUG', logger=logger)
|
11
10
|
|
@@ -13,7 +12,7 @@ class DASH:
|
|
13
12
|
def __init__(self):
|
14
13
|
self.manifest_url = None
|
15
14
|
self.output_name = None
|
16
|
-
self.
|
15
|
+
self.decryption_keys = [] # Store multiple keys as a list
|
17
16
|
self.binary_path = self._get_binary_path()
|
18
17
|
|
19
18
|
def _get_binary_path(self):
|
@@ -23,9 +22,9 @@ class DASH:
|
|
23
22
|
if platform.system() == 'Windows':
|
24
23
|
binary = f"{base_path}.exe"
|
25
24
|
elif platform.system() == 'Linux':
|
26
|
-
binary = base_path
|
27
|
-
elif platform.system() == 'Darwin':
|
28
|
-
binary = base_path
|
25
|
+
binary = base_path
|
26
|
+
elif platform.system() == 'Darwin':
|
27
|
+
binary = base_path
|
29
28
|
else:
|
30
29
|
logger.error(f"Unsupported platform: {platform.system()}")
|
31
30
|
raise OSError(f"Unsupported platform: {platform.system()}")
|
@@ -42,43 +41,34 @@ class DASH:
|
|
42
41
|
return
|
43
42
|
|
44
43
|
command = self._build_command()
|
45
|
-
|
46
|
-
# logger.debug(f"Running command: {command}")
|
47
44
|
self._execute_command(command)
|
48
45
|
|
49
46
|
def _build_command(self):
|
50
|
-
# Build the basic command without extra quotes
|
51
47
|
command = [
|
52
|
-
self.binary_path,
|
53
|
-
self.manifest_url,
|
48
|
+
self.binary_path,
|
49
|
+
self.manifest_url,
|
54
50
|
'--auto-select',
|
55
51
|
'-mt',
|
56
|
-
'
|
52
|
+
'-M', 'format=mp4',
|
57
53
|
'--save-dir', 'downloads',
|
58
54
|
'--tmp-dir', 'downloads',
|
59
|
-
'--save-name', self.output_name
|
55
|
+
'--save-name', self.output_name
|
60
56
|
]
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
command.append(f'--key {self.decryption_key}') # Ensure correct format: KID:KEY
|
66
|
-
|
67
|
-
# Join the command as a single string for system execution
|
68
|
-
command_str = ' '.join(command)
|
69
|
-
# logger.debug(f"Command string: {command_str}")
|
70
|
-
|
71
|
-
return command_str
|
57
|
+
for key in self.decryption_keys:
|
58
|
+
command.extend(['--key', key])
|
59
|
+
logger.debug(f"Built command: {' '.join(command)}")
|
60
|
+
return command
|
72
61
|
|
73
62
|
def _execute_command(self, command):
|
74
63
|
try:
|
75
|
-
|
76
|
-
result
|
77
|
-
|
78
|
-
if result == 0:
|
64
|
+
result = subprocess.run(command, check=True)
|
65
|
+
if result.returncode == 0:
|
79
66
|
logger.info("Downloaded using N_m3u8DL-RE successfully.")
|
80
67
|
else:
|
81
|
-
logger.error(f"Download failed with result code: {result}")
|
68
|
+
logger.error(f"Download failed with result code: {result.returncode}")
|
82
69
|
|
70
|
+
except subprocess.CalledProcessError as e:
|
71
|
+
logger.error(f"Command failed: {e}")
|
72
|
+
raise RuntimeError(f"Download process failed: {e}")
|
83
73
|
except Exception as e:
|
84
74
|
logger.error(f"An unexpected error occurred: {e}")
|
@@ -1,11 +1,10 @@
|
|
1
1
|
import os
|
2
2
|
import subprocess
|
3
3
|
import logging
|
4
|
-
import platform
|
4
|
+
import platform
|
5
5
|
import coloredlogs
|
6
6
|
from colorama import Fore
|
7
7
|
|
8
|
-
# Set up logging
|
9
8
|
logger = logging.getLogger(Fore.RED + "+ HLS + ")
|
10
9
|
coloredlogs.install(level='DEBUG', logger=logger)
|
11
10
|
|
@@ -13,19 +12,18 @@ class HLS:
|
|
13
12
|
def __init__(self):
|
14
13
|
self.manifest_url = None
|
15
14
|
self.output_name = None
|
16
|
-
self.
|
15
|
+
self.decryption_keys = []
|
17
16
|
self.binary_path = self._get_binary_path()
|
18
17
|
|
19
18
|
def _get_binary_path(self):
|
20
|
-
"""Determine the correct binary path based on the platform."""
|
21
19
|
base_path = os.path.join(os.path.dirname(__file__), 'bin', 'N_m3u8DL-RE')
|
22
20
|
|
23
21
|
if platform.system() == 'Windows':
|
24
22
|
binary = f"{base_path}.exe"
|
25
23
|
elif platform.system() == 'Linux':
|
26
|
-
binary = base_path
|
24
|
+
binary = base_path
|
27
25
|
elif platform.system() == 'Darwin': # macOS
|
28
|
-
binary = base_path
|
26
|
+
binary = base_path
|
29
27
|
else:
|
30
28
|
logger.error(f"Unsupported platform: {platform.system()}")
|
31
29
|
raise OSError(f"Unsupported platform: {platform.system()}")
|
@@ -42,42 +40,34 @@ class HLS:
|
|
42
40
|
return
|
43
41
|
|
44
42
|
command = self._build_command()
|
45
|
-
|
46
|
-
# logger.debug(f"Running command: {command}")
|
47
43
|
self._execute_command(command)
|
48
44
|
|
49
45
|
def _build_command(self):
|
50
|
-
# Build the command to pass to os.system()
|
51
46
|
command = [
|
52
|
-
self.binary_path,
|
53
|
-
self.manifest_url,
|
47
|
+
self.binary_path,
|
48
|
+
self.manifest_url,
|
54
49
|
'--auto-select',
|
55
50
|
'-mt',
|
56
|
-
'
|
51
|
+
'-M', 'format=mp4',
|
57
52
|
'--save-dir', 'downloads',
|
58
53
|
'--tmp-dir', 'downloads',
|
59
|
-
'--save-name', self.output_name
|
54
|
+
'--save-name', self.output_name
|
60
55
|
]
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
# Join the command as a single string for system execution
|
67
|
-
command_str = ' '.join(command)
|
68
|
-
# logger.debug(f"Command string: {command_str}")
|
69
|
-
|
70
|
-
return command_str
|
56
|
+
for key in self.decryption_keys:
|
57
|
+
command.extend(['--key', key])
|
58
|
+
logger.debug(f"Built command: {' '.join(command)}")
|
59
|
+
return command
|
71
60
|
|
72
61
|
def _execute_command(self, command):
|
73
62
|
try:
|
74
|
-
|
75
|
-
result
|
76
|
-
|
77
|
-
if result == 0:
|
63
|
+
result = subprocess.run(command, check=True)
|
64
|
+
if result.returncode == 0:
|
78
65
|
logger.info("Downloaded using N_m3u8DL-RE successfully.")
|
79
66
|
else:
|
80
|
-
logger.error(f"Download failed with result code: {result}")
|
67
|
+
logger.error(f"Download failed with result code: {result.returncode}")
|
81
68
|
|
69
|
+
except subprocess.CalledProcessError as e:
|
70
|
+
logger.error(f"Command failed: {e}")
|
71
|
+
raise RuntimeError(f"Download process failed: {e}")
|
82
72
|
except Exception as e:
|
83
73
|
logger.error(f"An unexpected error occurred: {e}")
|
@@ -1,12 +1,14 @@
|
|
1
1
|
README.md
|
2
2
|
setup.py
|
3
3
|
DDownloader/__init__.py
|
4
|
-
DDownloader/
|
5
|
-
DDownloader/hls_downloader.py
|
6
|
-
DDownloader/streamlink.py
|
4
|
+
DDownloader/main.py
|
7
5
|
DDownloader.egg-info/PKG-INFO
|
8
6
|
DDownloader.egg-info/SOURCES.txt
|
9
7
|
DDownloader.egg-info/dependency_links.txt
|
10
8
|
DDownloader.egg-info/entry_points.txt
|
11
9
|
DDownloader.egg-info/requires.txt
|
12
|
-
DDownloader.egg-info/top_level.txt
|
10
|
+
DDownloader.egg-info/top_level.txt
|
11
|
+
DDownloader/modules/__init__.py
|
12
|
+
DDownloader/modules/dash_downloader.py
|
13
|
+
DDownloader/modules/hls_downloader.py
|
14
|
+
DDownloader/modules/streamlink.py
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|