This commit is contained in:
Jesse Bannon 2023-07-28 00:04:39 -07:00
parent 6b46c648f3
commit 86a0fb0400
10 changed files with 84 additions and 14 deletions

View file

@ -84,7 +84,7 @@ class UrlDownloaderThumbnailPlugin(SourcePluginExtension):
if thumbnail_id == ThumbnailTypes.LATEST_ENTRY:
# always save in dry-run even if it doesn't exist...
if self.is_dry_run or entry.is_thumbnail_available():
if self.is_dry_run or entry.is_thumbnail_downloaded():
self.save_file(
file_name=entry.get_download_thumbnail_name(),
output_file_name=thumbnail_name,
@ -350,7 +350,7 @@ class MultiUrlDownloader(SourcePlugin[MultiUrlValidator]):
is_downloaded_fn=None if self.is_dry_run else entry.is_downloaded,
is_thumbnail_downloaded_fn=None
if (self.is_dry_run or not self.is_entry_thumbnails_enabled)
else entry.is_thumbnail_downloaded,
else entry.is_thumbnail_downloaded_via_ytdlp,
url=entry.webpage_url,
)
return Entry(download_entry_dict, working_directory=self.working_directory)

View file

@ -84,16 +84,16 @@ class Entry(EntryVariables, BaseEntry):
file.write(kwargs_json)
@final
def is_thumbnail_downloaded(self) -> bool:
def is_thumbnail_downloaded_via_ytdlp(self) -> bool:
"""
Returns
-------
True if the thumbnail file exist locally. False otherwise.
True if ANY thumbnail file exist locally. False otherwise.
"""
return self.get_ytdlp_download_thumbnail_path() is not None
@final
def is_thumbnail_available(self) -> bool:
def is_thumbnail_downloaded(self) -> bool:
"""
Returns
-------

View file

@ -89,12 +89,13 @@ class EmbedThumbnailPlugin(Plugin[EmbedThumbnailOptions]):
logger.warning("webm does not support embedded thumbnails, skipping")
return None
if not entry.is_thumbnail_downloaded():
logger.warning(
"Cannot embed thumbnail for '%s' because it is not available", entry.title
)
if not self.is_dry_run:
if not entry.is_thumbnail_downloaded():
logger.warning(
"Cannot embed thumbnail for '%s' because it is not available", entry.title
)
return None
if entry.ext in AUDIO_CODEC_EXTS:
self._embed_audio_file(entry)
else:

View file

@ -161,7 +161,7 @@ class MusicTagsPlugin(Plugin[MusicTagsOptions]):
)
setattr(audio_file, tag_name, tag_value[0])
if self.plugin_options.embed_thumbnail and entry.is_thumbnail_available():
if self.plugin_options.embed_thumbnail and entry.is_thumbnail_downloaded():
with open(entry.get_download_thumbnail_path(), "rb") as thumb:
mediafile_img = mediafile.Image(
data=thumb.read(), desc="cover", type=mediafile.ImageType.front

View file

@ -202,7 +202,7 @@ class SplitByChaptersPlugin(SplitPlugin[SplitByChaptersOptions]):
# Copy the original vid thumbnail to the working directory with the new uid. This so
# downstream logic thinks this split video has its own thumbnail
if entry.is_thumbnail_available():
if entry.is_thumbnail_downloaded():
FileHandler.copy(
src_file_path=entry.get_download_thumbnail_path(),
dst_file_path=Path(self.working_directory)

View file

@ -1,4 +1,5 @@
import contextlib
import logging
import os
import shutil
from abc import ABC
@ -21,6 +22,9 @@ from ytdl_sub.utils.exceptions import ValidationException
from ytdl_sub.utils.file_handler import FileHandler
from ytdl_sub.utils.file_handler import FileHandlerTransactionLog
from ytdl_sub.utils.file_handler import FileMetadata
from ytdl_sub.utils.logger import Logger
logger: logging.Logger = Logger.get()
def _get_split_plugin(plugins: List[Plugin]) -> Optional[SplitPlugin]:
@ -68,7 +72,7 @@ class SubscriptionDownload(BaseSubscription, ABC):
entry=entry,
)
if self.output_options.thumbnail_name and entry.is_thumbnail_available():
if self.output_options.thumbnail_name and entry.is_thumbnail_downloaded():
output_thumbnail_name = self.overrides.apply_formatter(
formatter=self.output_options.thumbnail_name, entry=entry
)
@ -80,6 +84,10 @@ class SubscriptionDownload(BaseSubscription, ABC):
entry=entry,
copy_file=True,
)
elif not entry.is_thumbnail_downloaded():
logger.warning(
"Cannot save thumbnail for '%s' because it is not available", entry.title
)
if self.output_options.info_json_name:
output_info_json_name = self.overrides.apply_formatter(

View file

@ -33,7 +33,7 @@ def try_convert_download_thumbnail(entry: Entry) -> None:
download_thumbnail_path_as_jpg = entry.get_download_thumbnail_path()
# If it was already converted, do not convert again
if os.path.isfile(download_thumbnail_path_as_jpg):
if entry.is_thumbnail_downloaded():
return
if not download_thumbnail_path:

View file

@ -1,10 +1,15 @@
from unittest.mock import patch
import pytest
from conftest import preset_dict_to_dl_args
from e2e.conftest import mock_run_from_cli
from expected_download import assert_expected_downloads
from expected_transaction_log import assert_transaction_log_matches
from ytdl_sub.downloaders.ytdlp import YTDLP
from ytdl_sub.entries.entry import Entry
from ytdl_sub.subscriptions.subscription import Subscription
from ytdl_sub.utils.file_handler import FileHandler
@pytest.fixture
@ -140,6 +145,43 @@ class TestYoutubeVideo:
expected_download_summary_file_name="youtube/test_video.json",
)
def test_single_video_download_missing_thumbnail(
self,
music_video_config,
single_video_preset_dict,
working_directory,
output_directory,
):
single_video_subscription = Subscription.from_dict(
config=music_video_config,
preset_name="music_video_single_video_test",
preset_dict=single_video_preset_dict,
)
def delete_entry_thumb(entry: Entry) -> None:
FileHandler.delete(entry.get_download_thumbnail_path())
# Pretend the thumbnail did not download via returning nothing for its downloaded path
with patch.object(YTDLP, "_EXTRACT_ENTRY_NUM_RETRIES", 1), patch.object(
Entry, "get_ytdlp_download_thumbnail_path"
) as mock_ytdlp_path, patch(
"ytdl_sub.downloaders.url.downloader.try_convert_download_thumbnail",
side_effect=delete_entry_thumb,
):
mock_ytdlp_path.return_value = None
transaction_log = single_video_subscription.download(dry_run=False)
assert_transaction_log_matches(
output_directory=output_directory,
transaction_log=transaction_log,
transaction_log_summary_file_name="youtube/test_video_missing_thumb.txt",
)
assert_expected_downloads(
output_directory=output_directory,
dry_run=False,
expected_download_summary_file_name="youtube/test_video_missing_thumb.json",
)
@pytest.mark.parametrize("dry_run", [True, False])
def test_single_video_download_from_cli_dl(
self,

View file

@ -0,0 +1,5 @@
{
"JMC/JMC - Oblivion Mod Falcor p.1.info.json": "4b361d0ab0220407731553dbe36f12a1",
"JMC/JMC - Oblivion Mod Falcor p.1.mp4": "3744c49f2e447bd7712a5aad5ed36be2",
"JMC/JMC - Oblivion Mod Falcor p.1.nfo": "24cc4e17d2bebc89b2759ce5471d403e"
}

View file

@ -0,0 +1,14 @@
Files created:
----------------------------------------
{output_directory}/JMC
JMC - Oblivion Mod Falcor p.1.info.json
JMC - Oblivion Mod Falcor p.1.mp4
Video Tags:
title: Oblivion Mod "Falcor" p.1
JMC - Oblivion Mod Falcor p.1.nfo
NFO tags:
musicvideo:
album: Music Videos
artist: JMC
title: Oblivion Mod "Falcor" p.1
year: 2010