✨ Do not process tracks with missing segments. Refactored some method to pathlib.Path.
This commit is contained in:
+46
-44
@@ -92,7 +92,7 @@ class Download:
|
|||||||
self,
|
self,
|
||||||
media: Track | Video,
|
media: Track | Video,
|
||||||
path_file: pathlib.Path,
|
path_file: pathlib.Path,
|
||||||
) -> pathlib.Path:
|
) -> (bool, pathlib.Path):
|
||||||
media_name: str = name_builder_item(media)
|
media_name: str = name_builder_item(media)
|
||||||
urls: [str]
|
urls: [str]
|
||||||
path_base: pathlib.Path = path_file.parent
|
path_base: pathlib.Path = path_file.parent
|
||||||
@@ -165,21 +165,20 @@ class Download:
|
|||||||
# mark the whole thing as corrupt.
|
# mark the whole thing as corrupt.
|
||||||
result_segments = False
|
result_segments = False
|
||||||
|
|
||||||
# Bring list into right order, so segments can be easily merged.
|
tmp_path_file_decrypted: pathlib.Path = path_file
|
||||||
dl_segment_results.sort(key=lambda x: x.id_segment)
|
|
||||||
# TODO: Implement error handling on corrupt segments (also in the following method.
|
|
||||||
reult_merge: bool = self._segments_merge(path_file, dl_segment_results)
|
|
||||||
tmp_path_file_decrypted: pathlib.Path = pathlib.Path("")
|
|
||||||
|
|
||||||
if reult_merge:
|
# Only if no error happened while downloading.
|
||||||
if isinstance(media, Track) and stream_manifest.is_encrypted:
|
if result_segments:
|
||||||
|
# Bring list into right order, so segments can be easily merged.
|
||||||
|
dl_segment_results.sort(key=lambda x: x.id_segment)
|
||||||
|
reult_merge: bool = self._segments_merge(path_file, dl_segment_results)
|
||||||
|
|
||||||
|
if reult_merge and isinstance(media, Track) and stream_manifest.is_encrypted:
|
||||||
key, nonce = decrypt_security_token(stream_manifest.encryption_key)
|
key, nonce = decrypt_security_token(stream_manifest.encryption_key)
|
||||||
tmp_path_file_decrypted = path_file + "_decrypted"
|
tmp_path_file_decrypted = path_file.with_suffix("_decrypted")
|
||||||
decrypt_file(path_file, tmp_path_file_decrypted, key, nonce)
|
decrypt_file(path_file, tmp_path_file_decrypted, key, nonce)
|
||||||
else:
|
|
||||||
tmp_path_file_decrypted = path_file
|
|
||||||
|
|
||||||
return tmp_path_file_decrypted
|
return result_segments, tmp_path_file_decrypted
|
||||||
|
|
||||||
def _segments_merge(self, path_file, dl_segment_results) -> bool:
|
def _segments_merge(self, path_file, dl_segment_results) -> bool:
|
||||||
result: bool
|
result: bool
|
||||||
@@ -229,7 +228,7 @@ class Download:
|
|||||||
except HTTPError as e:
|
except HTTPError as e:
|
||||||
error = e
|
error = e
|
||||||
self.progress.advance(p_task)
|
self.progress.advance(p_task)
|
||||||
self.fn_logger.exception(e.charachter_written)
|
self.fn_logger.exception(e)
|
||||||
|
|
||||||
# To send the progress to the GUI, we need to emit the percentage.
|
# To send the progress to the GUI, we need to emit the percentage.
|
||||||
if not progress_to_stdout:
|
if not progress_to_stdout:
|
||||||
@@ -281,12 +280,14 @@ class Download:
|
|||||||
# Create file name and path
|
# Create file name and path
|
||||||
file_extension_dummy: str = AudioExtensions.FLAC
|
file_extension_dummy: str = AudioExtensions.FLAC
|
||||||
file_name_relative = format_path_media(file_template, media)
|
file_name_relative = format_path_media(file_template, media)
|
||||||
path_media_dst = os.path.abspath(
|
path_media_dst: pathlib.Path = (
|
||||||
os.path.normpath(os.path.join(os.path.expanduser(self.path_base), file_name_relative))
|
(pathlib.Path(self.path_base).expanduser() / file_name_relative).resolve().absolute()
|
||||||
)
|
)
|
||||||
|
|
||||||
# Sanitize final path_file to fit into OS boundaries.
|
# Sanitize final path_file to fit into OS boundaries.
|
||||||
path_media_dst = path_file_sanitize(path_media_dst + file_extension_dummy, adapt=True)
|
path_media_dst = pathlib.Path(
|
||||||
|
path_file_sanitize(str(path_media_dst.with_suffix(file_extension_dummy)), adapt=True)
|
||||||
|
)
|
||||||
|
|
||||||
# Compute if and how downloads need to be skipped.
|
# Compute if and how downloads need to be skipped.
|
||||||
if self.skip_existing:
|
if self.skip_existing:
|
||||||
@@ -336,38 +337,39 @@ class Download:
|
|||||||
tmp_path_file.touch()
|
tmp_path_file.touch()
|
||||||
|
|
||||||
# Download media.
|
# Download media.
|
||||||
tmp_path_file = self._download(media=media, path_file=tmp_path_file)
|
result_download, tmp_path_file = self._download(media=media, path_file=tmp_path_file)
|
||||||
|
|
||||||
# Convert video from TS to MP4
|
if result_download:
|
||||||
if isinstance(media, Video) and self.settings.data.video_convert_mp4:
|
# Convert video from TS to MP4
|
||||||
# Convert `*.ts` file to `*.mp4` using ffmpeg
|
if isinstance(media, Video) and self.settings.data.video_convert_mp4:
|
||||||
tmp_path_file = self._video_convert(tmp_path_file)
|
# Convert `*.ts` file to `*.mp4` using ffmpeg
|
||||||
|
tmp_path_file = self._video_convert(tmp_path_file)
|
||||||
|
|
||||||
# Extract FLAC from MP4 container using ffmpeg
|
# Extract FLAC from MP4 container using ffmpeg
|
||||||
if isinstance(media, Track) and self.settings.data.extract_flac and do_flac_extract:
|
if isinstance(media, Track) and self.settings.data.extract_flac and do_flac_extract:
|
||||||
tmp_path_file = self._extract_flac(tmp_path_file)
|
tmp_path_file = self._extract_flac(tmp_path_file)
|
||||||
|
|
||||||
tmp_path_lyrics: pathlib.Path | None = None
|
tmp_path_lyrics: pathlib.Path | None = None
|
||||||
tmp_path_cover: pathlib.Path | None = None
|
tmp_path_cover: pathlib.Path | None = None
|
||||||
|
|
||||||
# Write metadata to file.
|
# Write metadata to file.
|
||||||
if not isinstance(media, Video):
|
if not isinstance(media, Video):
|
||||||
result_metadata, tmp_path_lyrics, tmp_path_cover = self.metadata_write(
|
result_metadata, tmp_path_lyrics, tmp_path_cover = self.metadata_write(
|
||||||
media, tmp_path_file, is_parent_album
|
media, tmp_path_file, is_parent_album
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Move lyrics file
|
||||||
|
if self.settings.data.lyrics_file and not isinstance(media, Video):
|
||||||
|
self._move_lyrics(tmp_path_lyrics, path_media_dst)
|
||||||
|
|
||||||
|
# Move cover file
|
||||||
|
if self.settings.data.cover_album_file:
|
||||||
|
self._move_cover(tmp_path_cover, path_media_dst)
|
||||||
|
|
||||||
# Move final file to the configured destination directory.
|
# Move final file to the configured destination directory.
|
||||||
os.makedirs(os.path.dirname(path_media_dst), exist_ok=True)
|
os.makedirs(path_media_dst.parent, exist_ok=True)
|
||||||
shutil.move(tmp_path_file, path_media_dst)
|
shutil.move(tmp_path_file, path_media_dst)
|
||||||
|
|
||||||
# Move lyrics file
|
|
||||||
if self.settings.data.lyrics_file and not isinstance(media, Video):
|
|
||||||
self._move_lyrics(tmp_path_lyrics, path_media_dst)
|
|
||||||
|
|
||||||
# Move cover file
|
|
||||||
if self.settings.data.cover_album_file:
|
|
||||||
self._move_cover(tmp_path_cover, path_media_dst)
|
|
||||||
|
|
||||||
if quality_audio:
|
if quality_audio:
|
||||||
# Set quality back to the global user value
|
# Set quality back to the global user value
|
||||||
self.adjust_quality_audio(quality_audio_old)
|
self.adjust_quality_audio(quality_audio_old)
|
||||||
@@ -418,16 +420,16 @@ class Download:
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def _move_lyrics(self, path_lyrics: pathlib.Path, file_media_dst: str) -> bool:
|
def _move_lyrics(self, path_lyrics: pathlib.Path, file_media_dst: pathlib.Path) -> bool:
|
||||||
# Build tmp lyrics filename
|
# Build tmp lyrics filename
|
||||||
path_file_lyrics: str = os.path.splitext(file_media_dst)[0] + EXTENSION_LYRICS
|
path_file_lyrics: pathlib.Path = file_media_dst.with_suffix(EXTENSION_LYRICS)
|
||||||
result: bool = self._move_file(path_lyrics, path_file_lyrics)
|
result: bool = self._move_file(path_lyrics, path_file_lyrics)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def _move_cover(self, path_cover: pathlib.Path, file_media_dst: str) -> bool:
|
def _move_cover(self, path_cover: pathlib.Path, file_media_dst: pathlib.Path) -> bool:
|
||||||
# Build tmp lyrics filename
|
# Build tmp lyrics filename
|
||||||
path_file_cover: pathlib.Path = pathlib.Path(file_media_dst).parent.absolute() / COVER_NAME
|
path_file_cover: pathlib.Path = file_media_dst.parent / COVER_NAME
|
||||||
result: bool = self._move_file(path_cover, path_file_cover)
|
result: bool = self._move_file(path_cover, path_file_cover)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import math
|
import math
|
||||||
import os
|
import os
|
||||||
|
import pathlib
|
||||||
import posixpath
|
import posixpath
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
from pathlib import Path, PosixPath
|
|
||||||
from urllib.parse import unquote, urlsplit
|
from urllib.parse import unquote, urlsplit
|
||||||
|
|
||||||
from pathvalidate import sanitize_filename, sanitize_filepath
|
from pathvalidate import sanitize_filename, sanitize_filepath
|
||||||
@@ -197,7 +197,7 @@ def get_format_template(
|
|||||||
def path_file_sanitize(path_file: str, adapt: bool = False, uniquify: bool = False) -> (bool, str):
|
def path_file_sanitize(path_file: str, adapt: bool = False, uniquify: bool = False) -> (bool, str):
|
||||||
# Split into path and filename
|
# Split into path and filename
|
||||||
pathname, filename = os.path.split(path_file)
|
pathname, filename = os.path.split(path_file)
|
||||||
file_extension: str = Path(path_file).suffix
|
file_extension: str = pathlib.Path(path_file).suffix
|
||||||
|
|
||||||
# Sanitize path
|
# Sanitize path
|
||||||
try:
|
try:
|
||||||
@@ -207,7 +207,7 @@ def path_file_sanitize(path_file: str, adapt: bool = False, uniquify: bool = Fal
|
|||||||
except ValidationError:
|
except ValidationError:
|
||||||
# If adaption of path is allowed in case of an error set path to HOME.
|
# If adaption of path is allowed in case of an error set path to HOME.
|
||||||
if adapt:
|
if adapt:
|
||||||
pathname_sanitized: str = Path.home()
|
pathname_sanitized: str = str(pathlib.Path.home())
|
||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
|
|
||||||
@@ -274,10 +274,10 @@ def file_unique_suffix(path_file: str, seperator: str = "_") -> str:
|
|||||||
return unique_suffix
|
return unique_suffix
|
||||||
|
|
||||||
|
|
||||||
def check_file_exists(path_file: str, extension_ignore: bool = False) -> bool:
|
def check_file_exists(path_file: pathlib.Path, extension_ignore: bool = False) -> bool:
|
||||||
if extension_ignore:
|
if extension_ignore:
|
||||||
path_file_stem: str = Path(path_file).stem
|
path_file_stem: str = pathlib.Path(path_file).stem
|
||||||
path_parent: PosixPath = Path(path_file).parent
|
path_parent: pathlib.Path = pathlib.Path(path_file).parent
|
||||||
path_files: [str] = []
|
path_files: [str] = []
|
||||||
|
|
||||||
for extension in AudioExtensions:
|
for extension in AudioExtensions:
|
||||||
|
|||||||
Reference in New Issue
Block a user