DDownloader 0.1.6__py3-none-any.whl → 0.1.9__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/__init__.py CHANGED
@@ -1,11 +1 @@
1
- from .bin import *
2
- from .dash_downloader import DASH
3
- from .hls_downloader import HLS
4
- from .streamlink import STREAMLINK
5
-
6
- __all__ = [
7
- 'DDownloader',
8
- 'HLS',
9
- 'STREAMLINK',
10
- 'DASH'
11
- ]
1
+ from DDownloader.main import main
DDownloader/main.py ADDED
@@ -0,0 +1,57 @@
1
+ import argparse
2
+ import logging
3
+ import coloredlogs
4
+ from DDownloader.modules.banners import banners
5
+ from DDownloader.modules.dash_downloader import DASH
6
+ from DDownloader.modules.hls_downloader import HLS
7
+
8
+ logger = logging.getLogger("+ MAIN + ")
9
+ coloredlogs.install(level='DEBUG', logger=logger)
10
+
11
+ def parse_arguments():
12
+ """
13
+ Parse command-line arguments for the downloader.
14
+ """
15
+ parser = argparse.ArgumentParser(description="Download DASH or HLS streams with decryption keys.")
16
+ parser.add_argument("-u", "--url", required=True, help="Manifest URL pointing to the stream (.mpd or .m3u8).")
17
+ parser.add_argument("-k", "--key", action="append", help="Decryption keys in the format KID:KEY. Use multiple -k options for multiple keys.")
18
+ parser.add_argument("-o", "--output", required=True, help="Output file name.")
19
+ return parser.parse_args()
20
+
21
+ def main():
22
+ banners()
23
+ args = parse_arguments()
24
+
25
+ # Detect DASH or HLS based on URL extension
26
+ if args.url.endswith(".mpd"):
27
+ logger.info("DASH stream detected. Initializing DASH downloader...")
28
+ downloader = DASH()
29
+ elif args.url.endswith(".m3u8"):
30
+ logger.info("HLS stream detected. Initializing HLS downloader...")
31
+ downloader = HLS()
32
+ else:
33
+ logger.error("Unsupported URL format. Please provide a valid DASH (.mpd) or HLS (.m3u8) URL.")
34
+ return
35
+
36
+ # Set downloader properties
37
+ downloader.manifest_url = args.url
38
+ downloader.output_name = args.output
39
+ downloader.decryption_keys = args.key or [] # Default to an empty list if no keys provided
40
+
41
+ # Log decryption keys
42
+ if downloader.decryption_keys:
43
+ logger.info("Decryption key(s) provided:")
44
+ for key in downloader.decryption_keys:
45
+ logger.info(f"--key {key}")
46
+
47
+ # Start download
48
+ try:
49
+ if isinstance(downloader, DASH):
50
+ downloader.dash_downloader()
51
+ else:
52
+ downloader.hls_downloader()
53
+ except Exception as e:
54
+ logger.error(f"An error occurred: {e}")
55
+
56
+ if __name__ == "__main__":
57
+ main()
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,31 @@
1
+ import os
2
+ from sys import stdout
3
+ from colorama import Fore, Style
4
+
5
+ def clear_screen():
6
+ os.system('cls' if os.name == 'nt' else 'clear')
7
+
8
+ def banners():
9
+ clear_screen()
10
+ stdout.write(" \n")
11
+ stdout.write(""+Fore.LIGHTRED_EX +"██████╗ ██████╗ ██████╗ ██╗ ██╗███╗ ██╗██╗ ██████╗ █████╗ ██████╗ █████╗ ███████╗██████╗ \n")
12
+ stdout.write(""+Fore.LIGHTRED_EX +"██╔══██╗██╔══██╗██╔═══██╗██║ ██║████╗ ██║██║ ██╔═══██╗██╔══██╗██╔══██╗██╔══██╗██╔════╝██╔══██╗\n")
13
+ stdout.write(""+Fore.LIGHTRED_EX +"██║ ██║██║ ██║██║ ██║██║ █╗ ██║██╔██╗ ██║██║ ██║ ██║███████║██║ ██║███████║█████╗ ██████╔╝\n")
14
+ stdout.write(""+Fore.LIGHTRED_EX +"██║ ██║██║ ██║██║ ██║██║███╗██║██║╚██╗██║██║ ██║ ██║██╔══██║██║ ██║██╔══██║██╔══╝ ██╔══██╗\n")
15
+ stdout.write(""+Fore.LIGHTRED_EX +"██████╔╝██████╔╝╚██████╔╝╚███╔███╔╝██║ ╚████║███████╗╚██████╔╝██║ ██║██████╔╝██║ ██║███████╗██║ ██║\n")
16
+ stdout.write(""+Fore.LIGHTRED_EX +"╚═════╝ ╚═════╝ ╚═════╝ ╚══╝╚══╝ ╚═╝ ╚═══╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝╚═════╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝\n")
17
+ stdout.write(""+Fore.YELLOW +"═════════════╦═════════════════════════════════╦══════════════════════════════\n")
18
+ stdout.write(""+Fore.YELLOW +"╔════════════╩═════════════════════════════════╩═════════════════════════════╗\n")
19
+ stdout.write(""+Fore.YELLOW +"║ \x1b[38;2;255;20;147m• "+Fore.GREEN+"AUTHOR "+Fore.RED+" |"+Fore.LIGHTWHITE_EX+" PARI MALAM "+Fore.YELLOW+"║\n")
20
+ stdout.write(""+Fore.YELLOW +"╔════════════════════════════════════════════════════════════════════════════╝\n")
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
+ stdout.write(""+Fore.YELLOW +"╚════════════════════════════════════════════════════════════════════════════╝\n")
23
+ print(f"{Fore.YELLOW}[DDownloader] - {Fore.GREEN}Download DASH or HLS streams with decryption keys. - {Fore.RED}[V0.1.9] \n{Fore.RESET}")
24
+
25
+
26
+
27
+
28
+
29
+
30
+
31
+
@@ -1,11 +1,10 @@
1
1
  import os
2
2
  import subprocess
3
3
  import logging
4
- import platform # For platform detection
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.decryption_key = None # Default to None, making it optional
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 # Linux binaries usually have no extension
27
- elif platform.system() == 'Darwin': # macOS
28
- binary = base_path # Adjust if necessary for macOS-specific binaries
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, # Path to the binary
53
- self.manifest_url, # The manifest URL
48
+ self.binary_path,
49
+ self.manifest_url,
54
50
  '--auto-select',
55
51
  '-mt',
56
- '--thread-count', '12',
52
+ '-M', 'format=mp4',
57
53
  '--save-dir', 'downloads',
58
54
  '--tmp-dir', 'downloads',
59
- '--save-name', self.output_name # The output name
55
+ '--save-name', self.output_name
60
56
  ]
61
-
62
- # Only add decryption_key if it's provided
63
- if self.decryption_key:
64
- logger.debug(f"Decryption key provided: {self.decryption_key}")
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
- # Use os.system to run the command as a string
76
- result = os.system(command)
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 # For platform detection
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.decryption_key = None # Default to None, making it optional
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 # Linux binaries usually have no extension
24
+ binary = base_path
27
25
  elif platform.system() == 'Darwin': # macOS
28
- binary = base_path # Adjust if necessary for macOS-specific binaries
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, # Path to the binary
53
- self.manifest_url, # Manifest URL (no need for quotes)
47
+ self.binary_path,
48
+ self.manifest_url,
54
49
  '--auto-select',
55
50
  '-mt',
56
- '--thread-count', '12',
51
+ '-M', 'format=mp4',
57
52
  '--save-dir', 'downloads',
58
53
  '--tmp-dir', 'downloads',
59
- '--save-name', self.output_name # The output name (no quotes)
54
+ '--save-name', self.output_name
60
55
  ]
61
-
62
- # Only add decryption_key if it's provided
63
- if self.decryption_key:
64
- command.append(f'--key {self.decryption_key}') # Ensure correct format: KID:KEY
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
- # Use os.system to run the command as a string
75
- result = os.system(command)
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,20 +1,20 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: DDownloader
3
- Version: 0.1.6
3
+ Version: 0.1.9
4
4
  Summary: A downloader for DRM-protected content.
5
5
  Home-page: https://github.com/ThatNotEasy/DDownloader
6
6
  Author: ThatNotEasy
7
7
  Author-email: apidotmy@proton.me
8
8
  License: MIT
9
9
  Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.10
10
11
  Classifier: License :: OSI Approved :: MIT License
11
12
  Classifier: Operating System :: OS Independent
12
13
  Requires-Python: >=3.10
13
14
  Description-Content-Type: text/markdown
14
- Requires-Dist: requests
15
- Requires-Dist: coloredlogs
16
- Requires-Dist: loguru
17
- Requires-Dist: argparse
15
+ Requires-Dist: requests>=2.26.0
16
+ Requires-Dist: coloredlogs>=15.0
17
+ Requires-Dist: loguru>=0.6.0
18
18
 
19
19
  # DDownloader
20
20
  - DDownloader is a Python library to download HLS and DASH manifests and decrypt media files.
@@ -0,0 +1,12 @@
1
+ DDownloader/__init__.py,sha256=lVZwmZNId0Dai7XBQpxglmJtIxAtZplRHDsvobL2UNo,33
2
+ DDownloader/main.py,sha256=QEkNB9KPD7Ph4iERBsuX-sarxLfhcrszUXleZfEF_Ig,2132
3
+ DDownloader/modules/__init__.py,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
4
+ DDownloader/modules/banners.py,sha256=MbYTiLWce5GdbPzzo-wUkhDcd4gPlwqWtYCUYCTisJE,3989
5
+ DDownloader/modules/dash_downloader.py,sha256=kvnb6G45QvcZEgB6G7bVsqWx_GLub_xVr1Q4YGS8T54,2578
6
+ DDownloader/modules/hls_downloader.py,sha256=_veAQWmjiY4L277bl_EajQXhAVa9dUAEoGUkO8GRUfQ,2490
7
+ DDownloader/modules/streamlink.py,sha256=F8vneSkxgGgqxRBhCHxvID-KwltpDG2QerH6QsAHuxE,506
8
+ DDownloader-0.1.9.dist-info/METADATA,sha256=3VytT0L1RWKt1NGU9Oqe9oS8zA1ozmA834meV0Ux8hs,1877
9
+ DDownloader-0.1.9.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
10
+ DDownloader-0.1.9.dist-info/entry_points.txt,sha256=tCZVr_SRONlWlMFsVKgcPj3lxe9gBtWD4GuWukMv75g,54
11
+ DDownloader-0.1.9.dist-info/top_level.txt,sha256=INZYgY1vEHV1MIWTPXKJL8j8-ZXjWb8u4XLuU3S8umY,12
12
+ DDownloader-0.1.9.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.45.1)
2
+ Generator: setuptools (75.6.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ DDownloader = DDownloader.main:main
@@ -1,9 +0,0 @@
1
- DDownloader/__init__.py,sha256=2qcq67r0hzIQ5dYnX5c8da19aPqSYutZmwwIFdsW1JU,203
2
- DDownloader/dash_downloader.py,sha256=8iyOwbZIoEM-AM50UX2-jBjgHjbUvBHzemVLUDe4C74,3120
3
- DDownloader/hls_downloader.py,sha256=kOb4zh5-M6-N9zs63NCmpKoQrxjswCDAj1woH9-0TZo,3053
4
- DDownloader/streamlink.py,sha256=F8vneSkxgGgqxRBhCHxvID-KwltpDG2QerH6QsAHuxE,506
5
- DDownloader-0.1.6.dist-info/METADATA,sha256=AKOfG9T2o1qLSur-krUDJn4f4hnKQ5mITp9svU1scbk,1829
6
- DDownloader-0.1.6.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
7
- DDownloader-0.1.6.dist-info/entry_points.txt,sha256=1jTwDiTcHyA4otMMuIpIDnHclZ6k23GbIfKgp1zTGYw,54
8
- DDownloader-0.1.6.dist-info/top_level.txt,sha256=INZYgY1vEHV1MIWTPXKJL8j8-ZXjWb8u4XLuU3S8umY,12
9
- DDownloader-0.1.6.dist-info/RECORD,,
@@ -1,2 +0,0 @@
1
- [console_scripts]
2
- ddownloader = ddownloader.main:main
File without changes