90 lines
3.1 KiB
Python
90 lines
3.1 KiB
Python
import os
|
|
import re
|
|
import subprocess
|
|
import logging
|
|
|
|
from aniworld.models import Anime
|
|
from aniworld.config import PROVIDER_HEADERS, INVALID_PATH_CHARS
|
|
from aniworld.parser import arguments
|
|
|
|
# Configure logging
|
|
logging.basicConfig(
|
|
filename="download.log",
|
|
level=logging.INFO,
|
|
format="%(asctime)s - %(levelname)s - %(message)s"
|
|
)
|
|
|
|
# Read timeout from environment variable, default to 600 seconds (10 minutes)
|
|
timeout = int(os.getenv("DOWNLOAD_TIMEOUT", 600))
|
|
|
|
def download(anime: Anime): # pylint: disable=too-many-branches
|
|
for episode in anime:
|
|
sanitized_anime_title = ''.join(
|
|
char for char in anime.title if char not in INVALID_PATH_CHARS
|
|
)
|
|
|
|
if episode.season == 0:
|
|
output_file = (
|
|
f"{sanitized_anime_title} - "
|
|
f"Movie {episode.episode:02} - "
|
|
f"({anime.language}).mp4"
|
|
)
|
|
else:
|
|
output_file = (
|
|
f"{sanitized_anime_title} - "
|
|
f"S{episode.season:02}E{episode.episode:03} - "
|
|
f"({anime.language}).mp4"
|
|
)
|
|
|
|
output_path = os.path.join(anime.output_directory, output_file)
|
|
os.makedirs(os.path.dirname(output_path), exist_ok=True)
|
|
|
|
logging.info(f"Preparing to download: {output_path}")
|
|
|
|
command = [
|
|
"yt-dlp",
|
|
episode.get_direct_link(anime.provider, anime.language),
|
|
"--fragment-retries", "infinite",
|
|
"--concurrent-fragments", "4",
|
|
"-o", output_path,
|
|
"--quiet",
|
|
"--no-warnings",
|
|
"--progress"
|
|
]
|
|
|
|
if anime.provider in PROVIDER_HEADERS:
|
|
for header in PROVIDER_HEADERS[anime.provider]:
|
|
command.extend(["--add-header", header])
|
|
|
|
if arguments.only_command:
|
|
logging.info(
|
|
f"{anime.title} - S{episode.season}E{episode.episode} - ({anime.language}): "
|
|
f"{' '.join(str(item) if item is not None else '' for item in command)}"
|
|
)
|
|
continue
|
|
|
|
try:
|
|
|
|
logging.info(f"Starting download to {output_path}...")
|
|
subprocess.run(command, check=True, timeout=timeout)
|
|
logging.info(f"Download completed: {output_path}")
|
|
except subprocess.TimeoutExpired:
|
|
logging.error(f"Download timed out after {timeout} seconds: {' '.join(str(item) for item in command)}")
|
|
except subprocess.CalledProcessError:
|
|
logging.error(f"Error running command: {' '.join(str(item) for item in command)}")
|
|
except KeyboardInterrupt:
|
|
logging.warning("Download interrupted by user.")
|
|
output_dir = os.path.dirname(output_path)
|
|
is_empty = True
|
|
|
|
for file_name in os.listdir(output_dir):
|
|
if re.search(r'\.(part|ytdl|part-Frag\d+)$', file_name):
|
|
os.remove(os.path.join(output_dir, file_name))
|
|
else:
|
|
is_empty = False
|
|
|
|
if is_empty or not os.listdir(output_dir):
|
|
os.rmdir(output_dir)
|
|
logging.info(f"Removed empty download directory: {output_dir}")
|
|
|