DDownloader 0.2.2__py3-none-any.whl → 0.2.3__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 CHANGED
@@ -2,8 +2,10 @@ import os
2
2
  import re
3
3
  import logging
4
4
  import coloredlogs
5
+ import time
6
+ from pathlib import Path
5
7
  from colorama import Fore, Style
6
- import platform, time # Added to detect platform
8
+ from DDownloader.modules.helper import download_binaries, detect_platform
7
9
  from DDownloader.modules.args_parser import parse_arguments
8
10
  from DDownloader.modules.banners import banners
9
11
  from DDownloader.modules.dash_downloader import DASH
@@ -14,23 +16,10 @@ logger = logging.getLogger("+ MAIN + ")
14
16
  coloredlogs.install(level='DEBUG', logger=logger)
15
17
 
16
18
  def validate_directories():
17
- """Ensure necessary directories exist."""
18
19
  downloads_dir = 'downloads'
19
20
  if not os.path.exists(downloads_dir):
20
21
  os.makedirs(downloads_dir)
21
- logger.debug(f"Created '{downloads_dir}' directory.")
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'
22
+ # logger.debug(f"Created '{downloads_dir}' directory.")
34
23
 
35
24
  def display_help():
36
25
  """Display custom help message with emoji."""
@@ -50,9 +39,16 @@ def main():
50
39
  banners()
51
40
  time.sleep(1)
52
41
  platform_name = detect_platform()
53
- logger.info(f"Running on platform: {platform_name}\n")
42
+ logger.info(f"Running on platform: {platform_name}")
54
43
  time.sleep(1)
55
44
 
45
+ logger.info(f"Downloading binaries... Please wait!")
46
+ bin_dir = Path(__file__).resolve().parent / "bin"
47
+ download_binaries(bin_dir)
48
+ logger.info(f"{Fore.GREEN}Downloading completed! Bye!{Fore.RESET}")
49
+ time.sleep(1)
50
+ banners()
51
+
56
52
  validate_directories()
57
53
  try:
58
54
  args = parse_arguments()
@@ -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.2] \n{Fore.RESET}")
23
+ print(f"{Fore.YELLOW}[DDownloader] - {Fore.GREEN}Download DASH or HLS streams with decryption keys. - {Fore.RED}[V0.2.3] \n{Fore.RESET}")
24
24
 
25
25
 
26
26
 
@@ -17,13 +17,24 @@ class DASH:
17
17
  self.binary_path = self._get_binary_path()
18
18
 
19
19
  def _get_binary_path(self):
20
- base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
21
- bin_dir = os.path.join(base_dir, 'bin')
20
+ """
21
+ Dynamically determine the path to the binary file in the 'bin' directory relative to the main module.
22
+ """
23
+ # Locate the base directory for the project (relative to main.py)
24
+ base_dir = os.path.dirname(os.path.abspath(__file__)) # Directory containing the current module
25
+ project_root = os.path.dirname(base_dir) # Go up one level to the project root
26
+ bin_dir = os.path.join(project_root, 'bin') # Bin directory is under the project root
27
+
28
+ # Determine the binary file name based on the platform
22
29
  binary_name = 'N_m3u8DL-RE.exe' if platform.system() == 'Windows' else 'N_m3u8DL-RE'
23
30
  binary = os.path.join(bin_dir, binary_name)
31
+
32
+ # Check if the binary exists
24
33
  if not os.path.isfile(binary):
25
34
  logger.error(f"Binary not found: {binary}")
26
35
  raise FileNotFoundError(f"Binary not found: {binary}")
36
+
37
+ # Ensure the binary is executable on Linux
27
38
  if platform.system() == 'Linux':
28
39
  chmod_command = ['chmod', '+x', binary]
29
40
  try:
@@ -32,6 +43,7 @@ class DASH:
32
43
  except subprocess.CalledProcessError as e:
33
44
  logger.error(Fore.RED + f"Failed to set executable permissions for: {binary}" + Fore.RESET)
34
45
  raise RuntimeError(f"Could not set executable permissions for: {binary}") from e
46
+
35
47
  return binary
36
48
 
37
49
  def dash_downloader(self):
@@ -0,0 +1,69 @@
1
+ import os
2
+ import requests
3
+ from tqdm import tqdm
4
+ from colorama import Fore
5
+ import logging
6
+ import coloredlogs
7
+ import platform
8
+
9
+ logger = logging.getLogger(Fore.GREEN + "+ HELPER + ")
10
+ coloredlogs.install(level='DEBUG', logger=logger)
11
+
12
+ binaries = [
13
+ "https://github.com/ThatNotEasy/DDownloader/raw/refs/heads/main/DDownloader/bin/N_m3u8DL-RE",
14
+ "https://github.com/ThatNotEasy/DDownloader/raw/refs/heads/main/DDownloader/bin/N_m3u8DL-RE.exe",
15
+ "https://github.com/ThatNotEasy/DDownloader/raw/refs/heads/main/DDownloader/bin/ffmpeg.exe",
16
+ "https://github.com/ThatNotEasy/DDownloader/raw/refs/heads/main/DDownloader/bin/aria2c.exe",
17
+ "https://github.com/ThatNotEasy/DDownloader/raw/refs/heads/main/DDownloader/bin/mp4decrypt.exe",
18
+ "https://github.com/ThatNotEasy/DDownloader/raw/refs/heads/main/DDownloader/bin/shaka-packager.exe",
19
+ "https://github.com/ThatNotEasy/DDownloader/raw/refs/heads/main/DDownloader/bin/yt-dl.exe",
20
+ "https://github.com/ThatNotEasy/DDownloader/raw/refs/heads/main/DDownloader/bin/mkvmerge.exe"
21
+ ]
22
+
23
+ def download_binaries(bin_dir):
24
+ os.makedirs(bin_dir, exist_ok=True)
25
+ # logger.info(f"Created or confirmed directory: {bin_dir}")
26
+
27
+ for binary_url in binaries:
28
+ try:
29
+ filename = binary_url.split("/")[-1]
30
+ filepath = os.path.join(bin_dir, filename)
31
+
32
+ if os.path.exists(filepath):
33
+ logger.info(f"Skipping {filename} (already exists).")
34
+ continue
35
+
36
+ logger.info(f"Downloading {filename} from {binary_url}...")
37
+ response = requests.get(binary_url, stream=True, timeout=30)
38
+ response.raise_for_status()
39
+
40
+ # Total size for progress bar
41
+ total_size = int(response.headers.get('content-length', 0))
42
+ with open(filepath, "wb") as file, tqdm(
43
+ total=total_size,
44
+ unit='B',
45
+ unit_scale=True,
46
+ desc=f"{Fore.CYAN}{filename}{Fore.RESET}",
47
+ dynamic_ncols=True,
48
+ bar_format="{l_bar}{bar} | {n_fmt}/{total_fmt} [{rate_fmt}]"
49
+ ) as progress_bar:
50
+ for chunk in response.iter_content(chunk_size=8192):
51
+ file.write(chunk)
52
+ progress_bar.update(len(chunk))
53
+
54
+ logger.info(f"{Fore.GREEN}Downloaded and saved: {filepath}{Fore.RESET}")
55
+ except requests.exceptions.RequestException as e:
56
+ logger.error(f"{Fore.RED}Failed to download {binary_url}: {e}{Fore.RESET}")
57
+ except Exception as e:
58
+ logger.error(f"{Fore.RED}Unexpected error for {binary_url}: {e}{Fore.RESET}")
59
+
60
+ def detect_platform():
61
+ system_platform = platform.system().lower()
62
+ if system_platform == 'windows':
63
+ return 'Windows'
64
+ elif system_platform == 'linux':
65
+ return 'Linux'
66
+ elif system_platform == 'darwin':
67
+ return 'MacOS'
68
+ else:
69
+ return 'Unknown'
@@ -17,13 +17,24 @@ class HLS:
17
17
  self.binary_path = self._get_binary_path()
18
18
 
19
19
  def _get_binary_path(self):
20
- base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
21
- bin_dir = os.path.join(base_dir, 'bin')
20
+ """
21
+ Dynamically determine the path to the binary file in the 'bin' directory relative to the main module.
22
+ """
23
+ # Locate the base directory for the project (relative to main.py)
24
+ base_dir = os.path.dirname(os.path.abspath(__file__)) # Directory containing the current module
25
+ project_root = os.path.dirname(base_dir) # Go up one level to the project root
26
+ bin_dir = os.path.join(project_root, 'bin') # Bin directory is under the project root
27
+
28
+ # Determine the binary file name based on the platform
22
29
  binary_name = 'N_m3u8DL-RE.exe' if platform.system() == 'Windows' else 'N_m3u8DL-RE'
23
30
  binary = os.path.join(bin_dir, binary_name)
31
+
32
+ # Check if the binary exists
24
33
  if not os.path.isfile(binary):
25
34
  logger.error(f"Binary not found: {binary}")
26
35
  raise FileNotFoundError(f"Binary not found: {binary}")
36
+
37
+ # Ensure the binary is executable on Linux
27
38
  if platform.system() == 'Linux':
28
39
  chmod_command = ['chmod', '+x', binary]
29
40
  try:
@@ -32,7 +43,7 @@ class HLS:
32
43
  except subprocess.CalledProcessError as e:
33
44
  logger.error(Fore.RED + f"Failed to set executable permissions for: {binary}" + Fore.RESET)
34
45
  raise RuntimeError(f"Could not set executable permissions for: {binary}") from e
35
- logger.debug(f"Binary path determined: {binary}")
46
+
36
47
  return binary
37
48
 
38
49
  def hls_downloader(self):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: DDownloader
3
- Version: 0.2.2
3
+ Version: 0.2.3
4
4
  Summary: A downloader for DRM-protected content.
5
5
  Author-email: ThatNotEasy <apidotmy@proton.me>
6
6
  License: MIT License
@@ -0,0 +1,15 @@
1
+ DDownloader/__init__.py,sha256=lVZwmZNId0Dai7XBQpxglmJtIxAtZplRHDsvobL2UNo,33
2
+ DDownloader/main.py,sha256=6nCcnznPLmo4TTz2plg1mNtsx7-osuutOXdls6cJ1nI,3563
3
+ DDownloader/modules/__init__.py,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
4
+ DDownloader/modules/args_parser.py,sha256=JsmemrQcxBSz8aWHWTpAO6I4BfGoK6GmJvJFuhRhZ7Y,919
5
+ DDownloader/modules/banners.py,sha256=_ZxH7nIyQhTV7iSW5lVsjN8BWKbDR_wMo8FZzCSw3nA,3989
6
+ DDownloader/modules/dash_downloader.py,sha256=EJhNl7hRSO085ra2c9y5UdDL3x67Nb1VtDeO4svmn0I,3766
7
+ DDownloader/modules/helper.py,sha256=DnyQa4HNlhatTOcq8tj6l6bhvql9d9bbaxn3wI4_KHo,2983
8
+ DDownloader/modules/hls_downloader.py,sha256=e-PdWdgi0msVcxBPOJl8xmPpRS2ItBX4AAkZpgtGw1M,3761
9
+ DDownloader/modules/streamlink.py,sha256=F8vneSkxgGgqxRBhCHxvID-KwltpDG2QerH6QsAHuxE,506
10
+ DDownloader-0.2.3.dist-info/LICENSE,sha256=cnjTim3BMjb9cVC_b3oS41FESKLuvuDsufVHa_ymZRw,1090
11
+ DDownloader-0.2.3.dist-info/METADATA,sha256=nrlEMfyUJDFAyZycHjYpfr_22-Bid55UCJFOXXdbpDg,3402
12
+ DDownloader-0.2.3.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
13
+ DDownloader-0.2.3.dist-info/entry_points.txt,sha256=tCZVr_SRONlWlMFsVKgcPj3lxe9gBtWD4GuWukMv75g,54
14
+ DDownloader-0.2.3.dist-info/top_level.txt,sha256=INZYgY1vEHV1MIWTPXKJL8j8-ZXjWb8u4XLuU3S8umY,12
15
+ DDownloader-0.2.3.dist-info/RECORD,,
@@ -1,14 +0,0 @@
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=_Ln7HObqHUYKTc5BJWMk42wy97m2kUUYoYDE_y7N4Bg,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.2.dist-info/LICENSE,sha256=cnjTim3BMjb9cVC_b3oS41FESKLuvuDsufVHa_ymZRw,1090
10
- DDownloader-0.2.2.dist-info/METADATA,sha256=8WyPTaXcxIM2_DbwepApMEbdT9eurg3C8WAcPYwTvjQ,3402
11
- DDownloader-0.2.2.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
12
- DDownloader-0.2.2.dist-info/entry_points.txt,sha256=tCZVr_SRONlWlMFsVKgcPj3lxe9gBtWD4GuWukMv75g,54
13
- DDownloader-0.2.2.dist-info/top_level.txt,sha256=INZYgY1vEHV1MIWTPXKJL8j8-ZXjWb8u4XLuU3S8umY,12
14
- DDownloader-0.2.2.dist-info/RECORD,,