maintain download archive
This commit is contained in:
parent
fb7993cf70
commit
55a462c71b
9 changed files with 56 additions and 14 deletions
|
|
@ -53,6 +53,7 @@ presets:
|
||||||
file_name: "{output_file_name}.{ext}"
|
file_name: "{output_file_name}.{ext}"
|
||||||
convert_thumbnail: "jpeg"
|
convert_thumbnail: "jpeg"
|
||||||
thumbnail_name: "{output_file_name}.jpeg"
|
thumbnail_name: "{output_file_name}.jpeg"
|
||||||
|
maintain_download_archive: True
|
||||||
metadata_options:
|
metadata_options:
|
||||||
nfo:
|
nfo:
|
||||||
nfo_name: "{output_file_name}.nfo"
|
nfo_name: "{output_file_name}.nfo"
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,12 @@ class Downloader:
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _configure_ytdl_options(cls, ytdl_options: Optional[Dict], working_directory: str) -> Dict:
|
def _configure_ytdl_options(
|
||||||
|
cls,
|
||||||
|
working_directory: str,
|
||||||
|
ytdl_options: Optional[Dict],
|
||||||
|
download_archive_file_name: Optional[str],
|
||||||
|
) -> Dict:
|
||||||
"""Configure the ytdl options for the downloader"""
|
"""Configure the ytdl options for the downloader"""
|
||||||
if ytdl_options is None:
|
if ytdl_options is None:
|
||||||
ytdl_options = {}
|
ytdl_options = {}
|
||||||
|
|
@ -35,14 +40,19 @@ class Downloader:
|
||||||
# Overwrite defaults + input with global options
|
# Overwrite defaults + input with global options
|
||||||
ytdl_options = dict(ytdl_options, **cls.ytdl_option_overrides())
|
ytdl_options = dict(ytdl_options, **cls.ytdl_option_overrides())
|
||||||
|
|
||||||
# Finally overwrite the output location with the specified working directory
|
# Overwrite the output location with the specified working directory
|
||||||
ytdl_options["outtmpl"] = str(Path(working_directory) / "%(id)s.%(ext)s")
|
ytdl_options["outtmpl"] = str(Path(working_directory) / "%(id)s.%(ext)s")
|
||||||
|
|
||||||
|
# If a download archive file name is provided, set it to that
|
||||||
|
ytdl_options["download_archive"] = str(Path(working_directory) / download_archive_file_name)
|
||||||
|
|
||||||
return ytdl_options
|
return ytdl_options
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
output_directory: str,
|
output_directory: str,
|
||||||
ytdl_options: Optional[Dict] = None,
|
ytdl_options: Optional[Dict] = None,
|
||||||
|
download_archive_file_name: Optional[str] = None,
|
||||||
):
|
):
|
||||||
self.output_directory = output_directory
|
self.output_directory = output_directory
|
||||||
if self.output_directory is None:
|
if self.output_directory is None:
|
||||||
|
|
@ -51,6 +61,7 @@ class Downloader:
|
||||||
self.ytdl_options = Downloader._configure_ytdl_options(
|
self.ytdl_options = Downloader._configure_ytdl_options(
|
||||||
ytdl_options=ytdl_options,
|
ytdl_options=ytdl_options,
|
||||||
working_directory=self.output_directory,
|
working_directory=self.output_directory,
|
||||||
|
download_archive_file_name=download_archive_file_name,
|
||||||
)
|
)
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,6 @@ class YoutubeDownloader(Downloader):
|
||||||
not fetch the metadata (maybe there is a way??)
|
not fetch the metadata (maybe there is a way??)
|
||||||
"""
|
"""
|
||||||
ytdl_metadata_override = {
|
ytdl_metadata_override = {
|
||||||
"download_archive": str(Path(self.output_directory) / "ytdl-download-archive.txt"),
|
|
||||||
"writeinfojson": True,
|
"writeinfojson": True,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
from collections import OrderedDict
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
|
@ -8,7 +7,6 @@ from sanitize_filename import sanitize
|
||||||
|
|
||||||
from ytdl_subscribe.validators.base.string_formatter_validators import StringFormatterValidator
|
from ytdl_subscribe.validators.base.string_formatter_validators import StringFormatterValidator
|
||||||
from ytdl_subscribe.validators.config.overrides.overrides_validator import OverridesValidator
|
from ytdl_subscribe.validators.config.overrides.overrides_validator import OverridesValidator
|
||||||
from ytdl_subscribe.validators.exceptions import ValidationException
|
|
||||||
|
|
||||||
|
|
||||||
class Entry:
|
class Entry:
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ if __name__ == "__main__":
|
||||||
)
|
)
|
||||||
|
|
||||||
for subscription in subscriptions:
|
for subscription in subscriptions:
|
||||||
subscription.to_subscription().extract_info()
|
subscription.to_subscription().download()
|
||||||
|
|
||||||
print("hi")
|
print("hi")
|
||||||
# for subscription_path in subscription_paths:
|
# for subscription_path in subscription_paths:
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ from ytdl_subscribe.validators.config.source_options.soundcloud_validators impor
|
||||||
class SoundcloudAlbumsAndSinglesSubscription(
|
class SoundcloudAlbumsAndSinglesSubscription(
|
||||||
Subscription[SoundcloudAlbumsAndSinglesSourceValidator]
|
Subscription[SoundcloudAlbumsAndSinglesSourceValidator]
|
||||||
):
|
):
|
||||||
def extract_info(self):
|
def _extract_info(self):
|
||||||
tracks: List[SoundcloudTrack] = []
|
tracks: List[SoundcloudTrack] = []
|
||||||
downloader = self.get_downloader(SoundcloudDownloader)
|
downloader = self.get_downloader(SoundcloudDownloader)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import os
|
import os
|
||||||
|
import shutil
|
||||||
from abc import ABC
|
from abc import ABC
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from shutil import copyfile
|
from shutil import copyfile
|
||||||
|
|
@ -61,13 +62,16 @@ class Subscription(Generic[S], ABC):
|
||||||
self, downloader_type: Type[D], source_ytdl_options: Optional[Dict] = None
|
self, downloader_type: Type[D], source_ytdl_options: Optional[Dict] = None
|
||||||
) -> D:
|
) -> D:
|
||||||
"""Returns the downloader that will be used to download media for this subscription"""
|
"""Returns the downloader that will be used to download media for this subscription"""
|
||||||
|
|
||||||
# if source_ytdl_options are present, override the ytdl_options with them
|
# if source_ytdl_options are present, override the ytdl_options with them
|
||||||
ytdl_options = self.__preset_options.ytdl_options.dict
|
ytdl_options = self.__preset_options.ytdl_options.dict
|
||||||
if source_ytdl_options:
|
if source_ytdl_options:
|
||||||
ytdl_options = dict(ytdl_options, **source_ytdl_options)
|
ytdl_options = dict(ytdl_options, **source_ytdl_options)
|
||||||
|
|
||||||
return downloader_type(output_directory=self.working_directory, ytdl_options=ytdl_options)
|
return downloader_type(
|
||||||
|
output_directory=self.working_directory,
|
||||||
|
ytdl_options=ytdl_options,
|
||||||
|
download_archive_file_name=self.download_archive_file_name,
|
||||||
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def output_options(self) -> OutputOptionsValidator:
|
def output_options(self) -> OutputOptionsValidator:
|
||||||
|
|
@ -89,6 +93,14 @@ class Subscription(Generic[S], ABC):
|
||||||
"""Returns the directory that the downloader saves files to"""
|
"""Returns the directory that the downloader saves files to"""
|
||||||
return str(Path(self.__config_options.working_directory.value) / Path(self.name))
|
return str(Path(self.__config_options.working_directory.value) / Path(self.name))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def output_directory(self):
|
||||||
|
return self._apply_formatter(formatter=self.output_options.output_directory)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def download_archive_file_name(self):
|
||||||
|
return f".ytdl-subscribe-{self.name}-download-archive.txt"
|
||||||
|
|
||||||
def _apply_formatter(
|
def _apply_formatter(
|
||||||
self, formatter: StringFormatterValidator, entry: Optional[Entry] = None
|
self, formatter: StringFormatterValidator, entry: Optional[Entry] = None
|
||||||
) -> str:
|
) -> str:
|
||||||
|
|
@ -139,7 +151,23 @@ class Subscription(Generic[S], ABC):
|
||||||
with open(nfo_file_path, "wb") as nfo_file:
|
with open(nfo_file_path, "wb") as nfo_file:
|
||||||
nfo_file.write(xml)
|
nfo_file.write(xml)
|
||||||
|
|
||||||
def extract_info(self):
|
def download(self):
|
||||||
|
"""
|
||||||
|
Performs the subscription download.
|
||||||
|
"""
|
||||||
|
existing_download_archive = Path(self.output_directory) / self.download_archive_file_name
|
||||||
|
working_directory_archive = Path(self.working_directory) / self.download_archive_file_name
|
||||||
|
|
||||||
|
if self.output_options.maintain_download_archive:
|
||||||
|
if os.path.exists(existing_download_archive):
|
||||||
|
shutil.copy(existing_download_archive, working_directory_archive)
|
||||||
|
|
||||||
|
self._extract_info()
|
||||||
|
|
||||||
|
if self.output_options.maintain_download_archive:
|
||||||
|
shutil.copy(working_directory_archive, existing_download_archive)
|
||||||
|
|
||||||
|
def _extract_info(self):
|
||||||
"""
|
"""
|
||||||
Extracts only the info of the source, does not download it
|
Extracts only the info of the source, does not download it
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ from ytdl_subscribe.validators.config.source_options.youtube_validators import (
|
||||||
|
|
||||||
|
|
||||||
class YoutubePlaylistSubscription(Subscription[YoutubePlaylistSourceValidator]):
|
class YoutubePlaylistSubscription(Subscription[YoutubePlaylistSourceValidator]):
|
||||||
def extract_info(self):
|
def _extract_info(self):
|
||||||
entries = self.get_downloader(YoutubeDownloader).download_playlist(
|
entries = self.get_downloader(YoutubeDownloader).download_playlist(
|
||||||
playlist_id=self.source_options.playlist_id.value
|
playlist_id=self.source_options.playlist_id.value
|
||||||
)
|
)
|
||||||
|
|
@ -24,7 +24,7 @@ class YoutubePlaylistSubscription(Subscription[YoutubePlaylistSourceValidator]):
|
||||||
|
|
||||||
|
|
||||||
class YoutubeChannelSubscription(Subscription[YoutubeChannelSourceValidator]):
|
class YoutubeChannelSubscription(Subscription[YoutubeChannelSourceValidator]):
|
||||||
def extract_info(self):
|
def _extract_info(self):
|
||||||
source_ytdl_options = {}
|
source_ytdl_options = {}
|
||||||
if self.source_options.before or self.source_options.after:
|
if self.source_options.before or self.source_options.after:
|
||||||
source_ytdl_options["daterange"] = DateRange(
|
source_ytdl_options["daterange"] = DateRange(
|
||||||
|
|
@ -40,7 +40,7 @@ class YoutubeChannelSubscription(Subscription[YoutubeChannelSourceValidator]):
|
||||||
|
|
||||||
|
|
||||||
class YoutubeVideoSubscription(Subscription[YoutubeVideoSourceValidator]):
|
class YoutubeVideoSubscription(Subscription[YoutubeVideoSourceValidator]):
|
||||||
def extract_info(self):
|
def _extract_info(self):
|
||||||
entry = self.get_downloader(YoutubeDownloader).download_video(
|
entry = self.get_downloader(YoutubeDownloader).download_video(
|
||||||
video_id=self.source_options.video_id.value
|
video_id=self.source_options.video_id.value
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ from ytdl_subscribe.validators.base.string_formatter_validators import (
|
||||||
)
|
)
|
||||||
from ytdl_subscribe.validators.base.string_formatter_validators import StringFormatterValidator
|
from ytdl_subscribe.validators.base.string_formatter_validators import StringFormatterValidator
|
||||||
from ytdl_subscribe.validators.base.string_select_validator import StringSelectValidator
|
from ytdl_subscribe.validators.base.string_select_validator import StringSelectValidator
|
||||||
|
from ytdl_subscribe.validators.base.validators import BoolValidator
|
||||||
|
|
||||||
|
|
||||||
class ConvertThumbnailValidator(StringSelectValidator):
|
class ConvertThumbnailValidator(StringSelectValidator):
|
||||||
|
|
@ -16,7 +17,7 @@ class OutputOptionsValidator(StrictDictValidator):
|
||||||
"""Where to output the final files and thumbnails"""
|
"""Where to output the final files and thumbnails"""
|
||||||
|
|
||||||
_required_keys = {"output_directory", "file_name"}
|
_required_keys = {"output_directory", "file_name"}
|
||||||
_optional_keys = {"convert_thumbnail", "thumbnail_name"}
|
_optional_keys = {"convert_thumbnail", "thumbnail_name", "maintain_download_archive"}
|
||||||
|
|
||||||
def __init__(self, name, value):
|
def __init__(self, name, value):
|
||||||
super().__init__(name, value)
|
super().__init__(name, value)
|
||||||
|
|
@ -37,3 +38,7 @@ class OutputOptionsValidator(StrictDictValidator):
|
||||||
self.thumbnail_name = self._validate_key_if_present(
|
self.thumbnail_name = self._validate_key_if_present(
|
||||||
key="thumbnail_name", validator=StringFormatterValidator
|
key="thumbnail_name", validator=StringFormatterValidator
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self.maintain_download_archive = self._validate_key_if_present(
|
||||||
|
key="maintain_download_archive", validator=BoolValidator
|
||||||
|
)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue