ytdl-sub/src/ytdl_sub/subscriptions/subscription_ytdl_options.py
Jesse Bannon 0497f2b749
[FEATURE] Perform match-filter on download, not metadata pull (#612)
* [FEATURE] Apply match-filter on download instead of metadata

* correct ytdl_option ordering

* lint

* test that downloads
2023-05-18 09:52:24 -07:00

143 lines
4.6 KiB
Python

from pathlib import Path
from typing import Dict
from typing import List
from typing import Optional
from typing import Type
from typing import TypeVar
from ytdl_sub.config.preset import Preset
from ytdl_sub.downloaders.base_downloader import BaseDownloader
from ytdl_sub.downloaders.ytdl_options_builder import YTDLOptionsBuilder
from ytdl_sub.plugins.audio_extract import AudioExtractPlugin
from ytdl_sub.plugins.chapters import ChaptersPlugin
from ytdl_sub.plugins.date_range import DateRangePlugin
from ytdl_sub.plugins.file_convert import FileConvertPlugin
from ytdl_sub.plugins.match_filters import MatchFiltersPlugin
from ytdl_sub.plugins.plugin import Plugin
from ytdl_sub.plugins.subtitles import SubtitlesPlugin
from ytdl_sub.utils.ffmpeg import FFMPEG
from ytdl_sub.ytdl_additions.enhanced_download_archive import EnhancedDownloadArchive
PluginT = TypeVar("PluginT", bound=Plugin)
class SubscriptionYTDLOptions:
def __init__(
self,
preset: Preset,
plugins: List[Plugin],
enhanced_download_archive: EnhancedDownloadArchive,
working_directory: str,
dry_run: bool,
):
self._preset = preset
self._plugins = plugins
self._enhanced_download_archive = enhanced_download_archive
self._working_directory = working_directory
self._dry_run = dry_run
def _get_plugin(self, plugin_type: Type[PluginT]) -> Optional[PluginT]:
for plugin in self._plugins:
if isinstance(plugin, plugin_type):
return plugin
return None
@property
def _downloader(self) -> Type[BaseDownloader]:
return self._preset.downloader
@property
def _global_options(self) -> Dict:
"""
Returns
-------
ytdl-options to apply to every run no matter what
"""
ytdl_options = {
# Download all files in the format of {id}.{ext}
"outtmpl": str(Path(self._working_directory) / "%(id)s.%(ext)s"),
# Always write thumbnails
"writethumbnail": True,
"ffmpeg_location": FFMPEG.ffmpeg_path(),
}
return ytdl_options
@property
def _dry_run_options(self) -> Dict:
return {
"skip_download": True,
"writethumbnail": False,
}
@property
def _info_json_only_options(self) -> Dict:
return {
"skip_download": True,
"writethumbnail": False,
"writeinfojson": True,
}
@property
def _download_only_options(self) -> Dict:
return {"break_on_reject": True}
@property
def _output_options(self) -> Dict:
ytdl_options = {}
if self._preset.output_options.maintain_download_archive:
ytdl_options["download_archive"] = str(
Path(self._working_directory) / self._enhanced_download_archive.archive_file_name
)
return ytdl_options
def _plugin_ytdl_options(self, plugin: Type[PluginT]) -> Dict:
if not (audio_extract_plugin := self._get_plugin(plugin)):
return {}
return audio_extract_plugin.ytdl_options()
@property
def _user_ytdl_options(self) -> Dict:
return self._preset.ytdl_options.dict
def metadata_builder(self) -> YTDLOptionsBuilder:
"""
Returns
-------
YTDLOptionsBuilder
Builder with values set for fetching metadata (.info.json) only
"""
return YTDLOptionsBuilder().add(
self._global_options,
self._output_options,
self._plugin_ytdl_options(DateRangePlugin),
self._user_ytdl_options, # user ytdl options...
self._info_json_only_options, # then info_json_only options
)
def download_builder(self) -> YTDLOptionsBuilder:
"""
Returns
-------
YTDLOptionsBuilder
Builder with values set based on the subscription for actual downloading
"""
ytdl_options_builder = YTDLOptionsBuilder().add(
self._global_options,
self._output_options,
self._plugin_ytdl_options(MatchFiltersPlugin),
self._plugin_ytdl_options(FileConvertPlugin),
self._plugin_ytdl_options(SubtitlesPlugin),
self._plugin_ytdl_options(ChaptersPlugin),
self._plugin_ytdl_options(AudioExtractPlugin),
self._user_ytdl_options, # user ytdl options...
self._download_only_options, # then download_only options
)
# Add dry run options last if enabled
if self._dry_run:
ytdl_options_builder.add(self._dry_run_options)
return ytdl_options_builder